diff --git a/apis/rds/v1beta1/zz_cluster_terraformed.go b/apis/rds/v1beta1/zz_cluster_terraformed.go index 9ed1982838..a004162076 100755 --- a/apis/rds/v1beta1/zz_cluster_terraformed.go +++ b/apis/rds/v1beta1/zz_cluster_terraformed.go @@ -25,7 +25,7 @@ func (mg *Cluster) GetTerraformResourceType() string { // GetConnectionDetailsMapping for this Cluster func (tr *Cluster) GetConnectionDetailsMapping() map[string]string { - return map[string]string{"master_password": "spec.forProvider.masterPasswordSecretRef", "password": "spec.forProvider.passwordSecretRef"} + return map[string]string{"master_password": "spec.forProvider.masterPasswordSecretRef"} } // GetObservation of this Cluster diff --git a/apis/rds/v1beta1/zz_cluster_types.go b/apis/rds/v1beta1/zz_cluster_types.go index 46953ff75a..f11fce2992 100755 --- a/apis/rds/v1beta1/zz_cluster_types.go +++ b/apis/rds/v1beta1/zz_cluster_types.go @@ -580,10 +580,6 @@ type ClusterParameters struct { // +kubebuilder:validation:Optional NetworkType *string `json:"networkType,omitempty" tf:"network_type,omitempty"` - // Password for the master DB user. If you set autoGeneratePassword to true, the Secret referenced here will be created or updated with generated password if it does not already contain one. - // +kubebuilder:validation:Optional - PasswordSecretRef *v1.SecretKeySelector `json:"passwordSecretRef,omitempty" tf:"-"` - // Port on which the DB accepts connections // +kubebuilder:validation:Optional Port *float64 `json:"port,omitempty" tf:"port,omitempty"` diff --git a/apis/rds/v1beta1/zz_generated.deepcopy.go b/apis/rds/v1beta1/zz_generated.deepcopy.go index 6f140d4a10..b0de7e7c47 100644 --- a/apis/rds/v1beta1/zz_generated.deepcopy.go +++ b/apis/rds/v1beta1/zz_generated.deepcopy.go @@ -2875,11 +2875,6 @@ func (in *ClusterParameters) DeepCopyInto(out *ClusterParameters) { *out = new(string) **out = **in } - if in.PasswordSecretRef != nil { - in, out := &in.PasswordSecretRef, &out.PasswordSecretRef - *out = new(v1.SecretKeySelector) - **out = **in - } if in.Port != nil { in, out := &in.Port, &out.Port *out = new(float64) diff --git a/config/common/common_test.go b/config/common/common_test.go index a9cd392bbb..4f2f6f4bec 100644 --- a/config/common/common_test.go +++ b/config/common/common_test.go @@ -9,11 +9,11 @@ import ( "testing" "time" - "github.com/crossplane/crossplane-runtime/pkg/errors" "github.com/crossplane/crossplane-runtime/pkg/resource" "github.com/crossplane/crossplane-runtime/pkg/resource/fake" "github.com/crossplane/crossplane-runtime/pkg/test" "github.com/google/go-cmp/cmp" + "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -85,6 +85,35 @@ func TestPasswordGenerator(t *testing.T) { }, }, }, + "ClusterSecretAlreadyFull": { + reason: "Should be no-op if the Secret already has password.", + args: args{ + kube: &test.MockClient{ + MockGet: func(ctx context.Context, key client.ObjectKey, obj client.Object) error { + s, ok := obj.(*corev1.Secret) + if !ok { + return errors.New("needs to be secret") + } + s.Data = map[string][]byte{ + "password": []byte("foo"), + } + return nil + }, + }, + secretRefFieldPath: "parameterizable.parameters.masterPasswordSecretRef", + mg: &ujfake.Terraformed{ + Parameterizable: ujfake.Parameterizable{ + Parameters: map[string]any{ + "masterPasswordSecretRef": map[string]any{ + "name": "foo", + "namespace": "bar", + "key": "password", + }, + }, + }, + }, + }, + }, "NoSecretReference": { reason: "Should be no-op if the secret reference is not given.", args: args{ @@ -98,6 +127,19 @@ func TestPasswordGenerator(t *testing.T) { }, }, }, + "NoClusterSecretReference": { + reason: "Should be no-op if the secret reference is not given.", + args: args{ + secretRefFieldPath: "parameterizable.parameters.masterPasswordSecretRef", + mg: &ujfake.Terraformed{ + Parameterizable: ujfake.Parameterizable{ + Parameters: map[string]any{ + "another": "field", + }, + }, + }, + }, + }, "ToggleNotSet": { reason: "Should be no-op if the toggle is not set at all.", args: args{ @@ -119,6 +161,27 @@ func TestPasswordGenerator(t *testing.T) { }, }, }, + "ClusterToggleNotSet": { + reason: "Should be no-op if the toggle is not set at all.", + args: args{ + kube: &test.MockClient{ + MockGet: test.NewMockGetFn(nil), + }, + secretRefFieldPath: "parameterizable.parameters.masterPasswordSecretRef", + toggleFieldPath: "parameterizable.parameters.autoGeneratePassword", + mg: &ujfake.Terraformed{ + Parameterizable: ujfake.Parameterizable{ + Parameters: map[string]any{ + "masterPasswordSecretRef": map[string]any{ + "name": "foo", + "namespace": "bar", + "key": "password", + }, + }, + }, + }, + }, + }, "ToggleFalse": { reason: "Should be no-op if the toggle is set to false.", args: args{ @@ -141,6 +204,28 @@ func TestPasswordGenerator(t *testing.T) { }, }, }, + "ClusterToggleFalse": { + reason: "Should be no-op if the toggle is set to false.", + args: args{ + kube: &test.MockClient{ + MockGet: test.NewMockGetFn(nil), + }, + secretRefFieldPath: "parameterizable.parameters.masterPasswordSecretRef", + toggleFieldPath: "parameterizable.parameters.autoGeneratePassword", + mg: &ujfake.Terraformed{ + Parameterizable: ujfake.Parameterizable{ + Parameters: map[string]any{ + "masterPasswordSecretRef": map[string]any{ + "name": "foo", + "namespace": "bar", + "key": "password", + }, + "autoGeneratePassword": false, + }, + }, + }, + }, + }, "GenerateAndApply": { reason: "Should apply if we generate, set the content of an already existing secret.", args: args{ @@ -183,6 +268,48 @@ func TestPasswordGenerator(t *testing.T) { }, }, }, + "ClusterSecretGenerateAndApply": { + reason: "Should apply if we generate, set the content of an already existing secret.", + args: args{ + kube: &test.MockClient{ + MockGet: func(ctx context.Context, key client.ObjectKey, obj client.Object) error { + s, ok := obj.(*corev1.Secret) + if !ok { + return errors.New("needs to be secret") + } + s.CreationTimestamp = metav1.Time{Time: time.Now()} + return nil + }, + MockPatch: func(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { + s, ok := obj.(*corev1.Secret) + if !ok { + return errors.New("needs to be secret") + } + if len(s.Data["password"]) == 0 { + return errors.New("password is not set") + } + if len(s.OwnerReferences) != 0 { + return errors.New("owner references should not be set if secret already exists") + } + return nil + }, + }, + secretRefFieldPath: "parameterizable.parameters.masterPasswordSecretRef", + toggleFieldPath: "parameterizable.parameters.autoGeneratePassword", + mg: &ujfake.Terraformed{ + Parameterizable: ujfake.Parameterizable{ + Parameters: map[string]any{ + "masterPasswordSecretRef": map[string]any{ + "name": "foo", + "namespace": "bar", + "key": "password", + }, + "autoGeneratePassword": true, + }, + }, + }, + }, + }, "GenerateAndCreate": { reason: "Should create if we generate, set the content and there is no secret in place.", args: args{ @@ -224,6 +351,47 @@ func TestPasswordGenerator(t *testing.T) { }, }, }, + "ClusterSecretGenerateAndCreate": { + reason: "Should create if we generate, set the content and there is no secret in place.", + args: args{ + kube: &test.MockClient{ + MockGet: test.NewMockGetFn(kerrors.NewNotFound(schema.GroupResource{}, "")), + MockCreate: func(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { + s, ok := obj.(*corev1.Secret) + if !ok { + return errors.New("needs to be secret") + } + if len(s.Data["password"]) == 0 { + return errors.New("password is not set") + } + if len(s.OwnerReferences) == 1 && + s.OwnerReferences[0].Name == "foo-mgd" { + return nil + } + return errors.New("owner references should be set if secret is created") + }, + }, + secretRefFieldPath: "parameterizable.parameters.masterPasswordSecretRef", + toggleFieldPath: "parameterizable.parameters.autoGeneratePassword", + mg: &ujfake.Terraformed{ + Managed: fake.Managed{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo-mgd", + }, + }, + Parameterizable: ujfake.Parameterizable{ + Parameters: map[string]any{ + "masterPasswordSecretRef": map[string]any{ + "name": "foo", + "namespace": "bar", + "key": "password", + }, + "autoGeneratePassword": true, + }, + }, + }, + }, + }, } for name, tc := range cases { t.Run(name, func(t *testing.T) { diff --git a/package/crds/rds.aws.upbound.io_clusters.yaml b/package/crds/rds.aws.upbound.io_clusters.yaml index de87357205..b3fa4e9e8e 100644 --- a/package/crds/rds.aws.upbound.io_clusters.yaml +++ b/package/crds/rds.aws.upbound.io_clusters.yaml @@ -486,25 +486,6 @@ spec: description: 'Network type of the cluster. Valid values: IPV4, DUAL.' type: string - passwordSecretRef: - description: Password for the master DB user. If you set autoGeneratePassword - to true, the Secret referenced here will be created or updated - with generated password if it does not already contain one. - properties: - key: - description: The key to select. - type: string - name: - description: Name of the secret. - type: string - namespace: - description: Namespace of the secret. - type: string - required: - - key - - name - - namespace - type: object port: description: Port on which the DB accepts connections type: number