From 3cb77a81fb6f919b225d8614073c53f73bd97a20 Mon Sep 17 00:00:00 2001 From: Rotem Tamir Date: Sun, 6 Aug 2023 16:12:45 +0300 Subject: [PATCH] api: add dev url from secret (#76) --- api/v1alpha1/atlasschema_types.go | 3 ++ api/v1alpha1/zz_generated.deepcopy.go | 1 + charts/atlas-operator/templates/crds/crd.yaml | 25 ++++++++++++++++ .../crd/bases/db.atlasgo.io_atlasschemas.yaml | 25 ++++++++++++++++ controllers/atlasschema_controller.go | 25 +++++++++++++++- controllers/atlasschema_controller_test.go | 29 +++++++++++++++++++ 6 files changed, 107 insertions(+), 1 deletion(-) diff --git a/api/v1alpha1/atlasschema_types.go b/api/v1alpha1/atlasschema_types.go index 409c6ee5..255c7f6b 100644 --- a/api/v1alpha1/atlasschema_types.go +++ b/api/v1alpha1/atlasschema_types.go @@ -71,6 +71,9 @@ type ( // DevURL is the URL of the database to use for normalization and calculations. // If not specified, the operator will spin up a temporary database container to use for these operations. DevURL string `json:"devURL"` + // DevURLFrom is a reference to a secret containing the URL of the database to use for normalization and calculations. + // +optional + DevURLFrom URLFrom `json:"devURLFrom,omitempty"` // Exclude a list of glob patterns used to filter existing resources being taken into account. Exclude []string `json:"exclude,omitempty"` // Policy defines the policies to apply when managing the schema change lifecycle. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 2f959c31..ecc0200b 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -190,6 +190,7 @@ func (in *AtlasSchemaSpec) DeepCopyInto(out *AtlasSchemaSpec) { *out = *in in.TargetSpec.DeepCopyInto(&out.TargetSpec) in.Schema.DeepCopyInto(&out.Schema) + in.DevURLFrom.DeepCopyInto(&out.DevURLFrom) if in.Exclude != nil { in, out := &in.Exclude, &out.Exclude *out = make([]string, len(*in)) diff --git a/charts/atlas-operator/templates/crds/crd.yaml b/charts/atlas-operator/templates/crds/crd.yaml index 876cf135..ff2299d3 100644 --- a/charts/atlas-operator/templates/crds/crd.yaml +++ b/charts/atlas-operator/templates/crds/crd.yaml @@ -377,6 +377,31 @@ spec: and calculations. If not specified, the operator will spin up a temporary database container to use for these operations. type: string + devURLFrom: + description: DevURLFrom is a reference to a secret containing the + URL of the database to use for normalization and calculations. + properties: + secretKeyRef: + description: SecretKeyRef references to the key of a secret in + the same namespace. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object exclude: description: Exclude a list of glob patterns used to filter existing resources being taken into account. diff --git a/config/crd/bases/db.atlasgo.io_atlasschemas.yaml b/config/crd/bases/db.atlasgo.io_atlasschemas.yaml index c59ddeb3..c59236a8 100644 --- a/config/crd/bases/db.atlasgo.io_atlasschemas.yaml +++ b/config/crd/bases/db.atlasgo.io_atlasschemas.yaml @@ -92,6 +92,31 @@ spec: and calculations. If not specified, the operator will spin up a temporary database container to use for these operations. type: string + devURLFrom: + description: DevURLFrom is a reference to a secret containing the + URL of the database to use for normalization and calculations. + properties: + secretKeyRef: + description: SecretKeyRef references to the key of a secret in + the same namespace. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object exclude: description: Exclude a list of glob patterns used to filter existing resources being taken into account. diff --git a/controllers/atlasschema_controller.go b/controllers/atlasschema_controller.go index 683fa8dd..b82787be 100644 --- a/controllers/atlasschema_controller.go +++ b/controllers/atlasschema_controller.go @@ -273,6 +273,12 @@ func (r *AtlasSchemaReconciler) watch(sc *dbv1alpha1.AtlasSchema) { sc.NamespacedName(), ) } + if s := sc.Spec.DevURLFrom.SecretKeyRef; s != nil { + r.secretWatcher.Watch( + types.NamespacedName{Name: s.Name, Namespace: sc.Namespace}, + sc.NamespacedName(), + ) + } } // Clean up any resources created by the controller @@ -434,11 +440,21 @@ func (r *AtlasSchemaReconciler) extractManaged(ctx context.Context, sc *dbv1alph r.recorder.Eventf(sc, corev1.EventTypeWarning, "DatabaseURL", err.Error()) return nil, transient(err) } - if sc.Spec.DevURL != "" { + switch spec := sc.Spec; { + case spec.DevURL != "": devURL, err = url.Parse(sc.Spec.DevURL) if err != nil { return nil, err } + case spec.DevURLFrom.SecretKeyRef != nil: + v, err := getSecretValue(ctx, r, sc.Namespace, *spec.DevURLFrom.SecretKeyRef) + if err != nil { + return nil, err + } + devURL, err = url.Parse(v) + if err != nil { + return nil, err + } } return &managed{ desired: string(data), @@ -479,6 +495,13 @@ func (d *managed) schemaBound() bool { // This value is false if the target database is sqlite or if the the user explicitly // provided a url to a dev database. func (d *managed) needsDevDB() bool { + switch { + case d.driver == "sqlite": + return false + case d.devURL != nil: + return false + + } if d.driver == "sqlite" { return false } diff --git a/controllers/atlasschema_controller_test.go b/controllers/atlasschema_controller_test.go index 11cba824..5a261efd 100644 --- a/controllers/atlasschema_controller_test.go +++ b/controllers/atlasschema_controller_test.go @@ -131,6 +131,35 @@ func TestReconcile_CustomDevURL(t *testing.T) { require.EqualValues(t, "mysql://dev", runs[1].DevURL) } +func TestReconcile_CustomDevURL_Secret(t *testing.T) { + tt := newTest(t) + sc := conditionReconciling() + tt.k8s.put(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "devdb", + Namespace: "test", + }, + Data: map[string][]byte{ + "url": []byte("mysql://dev"), + }, + }) + sc.Spec.DevURLFrom = dbv1alpha1.URLFrom{ + SecretKeyRef: &corev1.SecretKeySelector{ + Key: "url", + LocalObjectReference: corev1.LocalObjectReference{ + Name: "devdb", + }, + }, + } + tt.k8s.put(sc) + request := req() + _, err := tt.r.Reconcile(context.Background(), request) + require.NoError(t, err) + runs := tt.mockCLI().applyRuns + require.EqualValues(t, "mysql://dev", runs[0].DevURL) + require.EqualValues(t, "mysql://dev", runs[1].DevURL) +} + func TestReconcile_HasSchemaAndDB(t *testing.T) { tt := newTest(t) sc := conditionReconciling()