Skip to content

Commit

Permalink
only use custom config when enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
datdao committed Dec 24, 2024
1 parent 3cd7c8e commit c010f24
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 15 deletions.
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,51 @@ To configure the operator, you can set the following values in the `values.yaml`

- `prewarmDevDB`: The Operator always keeps devdb resources around to speed up the migration process. Set this to `false` to disable this feature.

- `allowCustomConfig`: Enable this to allow custom `atlas.hcl` configuration. To use this feature, you can set the `config` field in the `AtlasSchema` or `AtlasMigration` resource.

```yaml
spec:
envName: myenv
config: |
env myenv {}
# config from secretKeyRef
# configFrom:
# secretKeyRef:
# key: config
# name: my-secret
```

To use variables in the `config` field:

```yaml
spec:
envName: myenv
variables:
- name: db_url
value: "mysql://root"
# variables from secretKeyRef
# - name: db_url
# valueFrom:
# secretKeyRef:
# key: db_url
# name: my-secret
# variables from configMapKeyRef
# - name: db_url
# valueFrom:
# configMapKeyRef:
# key: db_url
# name: my-configmap
config: |
variable "db_url" {
type = string
}
env myenv {
url = var.db_url
}
```
> Note: Allowing custom configuration can elevate privileges of the operator. Use this feature with caution.
- `extraEnvs`: Used to set environment variables for the operator

```yaml
Expand Down
2 changes: 2 additions & 0 deletions charts/atlas-operator/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ spec:
env:
- name: PREWARM_DEVDB
value: "{{ .Values.prewarmDevDB }}"
- name: ALLOW_CUSTOM_CONFIG
value: "{{ .Values.allowCustomConfig }}"
{{- with .Values.extraEnvs }}
{{- toYaml . | nindent 8 }}
{{- end }}
Expand Down
4 changes: 4 additions & 0 deletions charts/atlas-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ affinity: {}
# Set this to true to keep the devdb pods around.
prewarmDevDB: true

# Enable this to allow custom project configuration
# Warning: This action will elevate the privileges of the operator
allowCustomConfig: false

# -- Additional environment variables to set
extraEnvs: []
# extraEnvs:
Expand Down
36 changes: 32 additions & 4 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ const (
vercheckURL = "https://vercheck.ariga.io"
// prewarmDevDB when disabled it deletes the devDB pods after the schema is created
prewarmDevDB = "PREWARM_DEVDB"
// allowCustomConfig when enabled it allows the use of custom config
allowsCustomConfig = "ALLOW_CUSTOM_CONFIG"
)

func init() {
Expand Down Expand Up @@ -141,13 +143,24 @@ func main() {
os.Exit(1)
}
prewarmDevDB := getPrewarmDevDBEnv()
if err = controller.NewAtlasSchemaReconciler(mgr, controller.NewAtlasExec, prewarmDevDB).
SetupWithManager(mgr); err != nil {
allowCustomConfig := getAllowCustomConfigEnv()
// Setup controller for AtlasSchema
schemaController := controller.NewAtlasSchemaReconciler(mgr, prewarmDevDB)
schemaController.SetAtlasClient(controller.NewAtlasExec)
if allowCustomConfig {
schemaController.AllowCustomConfig()
}
if err := schemaController.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "AtlasSchema")
os.Exit(1)
}
if err = controller.NewAtlasMigrationReconciler(mgr, controller.NewAtlasExec, prewarmDevDB).
SetupWithManager(mgr); err != nil {
// Setup controller for AtlasMigration
migrationController := controller.NewAtlasMigrationReconciler(mgr, prewarmDevDB)
migrationController.SetAtlasClient(controller.NewAtlasExec)
if allowCustomConfig {
migrationController.AllowCustomConfig()
}
if err = migrationController.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "AtlasMigration")
os.Exit(1)
}
Expand Down Expand Up @@ -219,3 +232,18 @@ func getPrewarmDevDBEnv() bool {
}
return prewarmDevDB
}

// getAllowCustomConfigEnv returns the value of the env var ALLOW_CUSTOM_CONFIG.
// if the env var is not set, it returns false.
func getAllowCustomConfigEnv() bool {
env := os.Getenv(allowsCustomConfig)
if env == "" {
return false
}
allowsCustomConfig, err := strconv.ParseBool(env)
if err != nil {
setupLog.Error(err, "invalid value for env var ALLOW_CUSTOM_CONFIG, expected true or false")
os.Exit(1)
}
return allowsCustomConfig
}
18 changes: 16 additions & 2 deletions internal/controller/atlasmigration_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ type (
secretWatcher *watch.ResourceWatcher
recorder record.EventRecorder
devDB *devDBReconciler
// AllowCustomConfig allows the controller to use custom atlas.hcl config.
allowCustomConfig bool
}
// migrationData is the data used to render the HCL template
// that will be used for Atlas CLI
Expand All @@ -82,12 +84,11 @@ type (
}
)

func NewAtlasMigrationReconciler(mgr Manager, atlas AtlasExecFn, prewarmDevDB bool) *AtlasMigrationReconciler {
func NewAtlasMigrationReconciler(mgr Manager, prewarmDevDB bool) *AtlasMigrationReconciler {
r := mgr.GetEventRecorderFor("atlasmigration-controller")
return &AtlasMigrationReconciler{
Client: mgr.GetClient(),
scheme: mgr.GetScheme(),
atlasClient: atlas,
configMapWatcher: watch.New(),
secretWatcher: watch.New(),
recorder: r,
Expand Down Expand Up @@ -211,6 +212,16 @@ func (r *AtlasMigrationReconciler) SetupWithManager(mgr ctrl.Manager) error {
Complete(r)
}

// SetAtlasClient sets the Atlas client for the reconciler.
func (r *AtlasMigrationReconciler) SetAtlasClient(fn AtlasExecFn) {
r.atlasClient = fn
}

// AllowCustomConfig allows the controller to use custom atlas.hcl config.
func (r *AtlasMigrationReconciler) AllowCustomConfig() {
r.allowCustomConfig = true
}

func (r *AtlasMigrationReconciler) watchRefs(res *dbv1alpha1.AtlasMigration) {
if c := res.Spec.Dir.ConfigMapRef; c != nil {
r.configMapWatcher.Watch(
Expand Down Expand Up @@ -429,6 +440,9 @@ func (r *AtlasMigrationReconciler) extractData(ctx context.Context, res *dbv1alp
if err != nil {
return nil, transient(err)
}
if !r.allowCustomConfig && data.Config != nil {
return nil, errors.New("install the operator with \"--set allowCustomConfig=true\" to use custom atlas.hcl config")
}
hasConfig := data.Config != nil
if hasConfig && data.EnvName == "" {
return nil, errors.New("env name must be set when using custom atlas.hcl config")
Expand Down
18 changes: 18 additions & 0 deletions internal/controller/atlasmigration_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,23 @@ func TestWatcher_enabled(t *testing.T) {
}, watched)
}

func TestCustomConfig_disabled(t *testing.T) {
tt := migrationCliTest(t)
tt.r.allowCustomConfig = false
_, err := tt.r.extractData(context.Background(), &dbv1alpha1.AtlasMigration{
ObjectMeta: migrationObjmeta(),
Spec: dbv1alpha1.AtlasMigrationSpec{
TargetSpec: dbv1alpha1.TargetSpec{URL: tt.dburl},
EnvName: "test",
ProjectConfigSpec: dbv1alpha1.ProjectConfigSpec{
Config: `env "test" {}`,
},
},
})
require.Error(t, err)
require.Contains(t, err.Error(), "install the operator with \"--set allowCustomConfig=true\" to use custom atlas.hcl config")
}

func TestDefaultTemplate(t *testing.T) {
migrate := &migrationData{
EnvName: defaultEnvName,
Expand Down Expand Up @@ -1276,6 +1293,7 @@ func newMigrationTest(t *testing.T) *migrationTest {
scheme: scheme,
recorder: r,
},
allowCustomConfig: true,
},
}
}
Expand Down
27 changes: 21 additions & 6 deletions internal/controller/atlasschema_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ type (
secretWatcher *watch.ResourceWatcher
recorder record.EventRecorder
devDB *devDBReconciler
// AllowCustomConfig allows the controller to use custom atlas.hcl config.
allowCustomConfig bool
}
// managedData contains information about the managed database and its desired state.
managedData struct {
Expand All @@ -85,17 +87,17 @@ type (

const sqlLimitSize = 1024

func NewAtlasSchemaReconciler(mgr Manager, atlas AtlasExecFn, prewarmDevDB bool) *AtlasSchemaReconciler {
r := mgr.GetEventRecorderFor("atlasschema-controller")
return &AtlasSchemaReconciler{
func NewAtlasSchemaReconciler(mgr Manager, prewarmDevDB bool) *AtlasSchemaReconciler {
rec := mgr.GetEventRecorderFor("atlasschema-controller")
r := &AtlasSchemaReconciler{
Client: mgr.GetClient(),
scheme: mgr.GetScheme(),
atlasClient: atlas,
configMapWatcher: watch.New(),
secretWatcher: watch.New(),
recorder: r,
devDB: newDevDB(mgr, r, prewarmDevDB),
recorder: rec,
devDB: newDevDB(mgr, rec, prewarmDevDB),
}
return r
}

// Reconcile is part of the main kubernetes reconciliation loop which aims to
Expand Down Expand Up @@ -517,6 +519,16 @@ func (r *AtlasSchemaReconciler) watchRefs(res *dbv1alpha1.AtlasSchema) {
}
}

// SetAtlasClient sets the Atlas client function.
func (r *AtlasSchemaReconciler) SetAtlasClient(fn AtlasExecFn) {
r.atlasClient = fn
}

// AllowCustomConfig allows the controller to use custom atlas.hcl config.
func (r *AtlasSchemaReconciler) AllowCustomConfig() {
r.allowCustomConfig = true
}

// extractData extracts the info about the managed database and its desired state.
func (r *AtlasSchemaReconciler) extractData(ctx context.Context, res *dbv1alpha1.AtlasSchema) (_ *managedData, err error) {
var (
Expand All @@ -535,6 +547,9 @@ func (r *AtlasSchemaReconciler) extractData(ctx context.Context, res *dbv1alpha1
if err != nil {
return nil, transient(err)
}
if !r.allowCustomConfig && data.Config != nil {
return nil, errors.New("install the operator with \"--set allowCustomConfig=true\" to use custom atlas.hcl config")
}
hasConfig := data.Config != nil
if hasConfig && data.EnvName == "" {
return nil, errors.New("env name must be set when using custom atlas.hcl config")
Expand Down
15 changes: 15 additions & 0 deletions internal/controller/atlasschema_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,20 @@ env "kubernetes" {
require.True(t, hasTargets)
}

func TestExtractData_DisabledCustomConfig(t *testing.T) {
sc := conditionReconciling()
sc.Spec.DevURL = "mysql://dev"
sc.Spec.EnvName = "kubernetes"
sc.Spec.Config = `
env "kubernetes" {}
`
tt := newTest(t)
tt.r.allowCustomConfig = false
_, err := tt.r.extractData(context.Background(), sc)
require.Error(t, err)
require.Contains(t, err.Error(), "install the operator with \"--set allowCustomConfig=true\" to use custom atlas.hcl config")
}

func TestReconcile_Credentials_BadPassSecret(t *testing.T) {
tt := newTest(t)
sc := conditionReconciling()
Expand Down Expand Up @@ -635,6 +649,7 @@ func newTest(t *testing.T) *test {
scheme: scheme,
recorder: r,
},
allowCustomConfig: true,
},
}
}
Expand Down
10 changes: 7 additions & 3 deletions internal/controller/testhelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ func (m *mockAtlasExec) MigrateStatus(context.Context, *atlasexec.MigrateStatusP
}

// newRunner returns a runner that can be used to test a reconcile.Reconciler.
func newRunner[T reconcile.Reconciler](fn func(Manager, AtlasExecFn, bool) T, modify func(*fake.ClientBuilder), mock *mockAtlasExec) (*helper, runner) {
func newRunner[T interface {
Reconcile(context.Context, reconcile.Request) (reconcile.Result, error)
SetAtlasClient(AtlasExecFn)
}](fn func(Manager, bool) T, modify func(*fake.ClientBuilder), mock *mockAtlasExec) (*helper, runner) {
scheme := runtime.NewScheme()
clientgoscheme.AddToScheme(scheme)
dbv1alpha1.AddToScheme(scheme)
Expand All @@ -132,12 +135,13 @@ func newRunner[T reconcile.Reconciler](fn func(Manager, AtlasExecFn, bool) T, mo
client: c,
recorder: r,
scheme: scheme,
}, func(s string, c *Cloud) (AtlasExec, error) {
}, true)
a.SetAtlasClient(func(s string, c *Cloud) (AtlasExec, error) {
if mock == nil {
return NewAtlasExec(s, c)
}
return mock, nil
}, true)
})
h := &helper{client: c, recorder: r}
return h, func(obj client.Object, fn check) {
fn(a.Reconcile(context.Background(), request(obj)))
Expand Down
1 change: 1 addition & 0 deletions test/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ func TestOperator(t *testing.T) {
e.Setenv("ATLAS_TOKEN", os.Getenv("ATLAS_TOKEN"))
// Ensure the test in running in the right kube context
e.Setenv("KUBECONFIG", kubeconfig)
e.Setenv("ALLOW_CUSTOM_CONFIG", "true")
// Creating a namespace for the test
ns := fmt.Sprintf("e2e-%s-%d", strings.ToLower(t.Name()), time.Now().UnixMicro())
e.Setenv("NAMESPACE", ns)
Expand Down

0 comments on commit c010f24

Please sign in to comment.