Skip to content

ERA-60185 : Add ConfigMap defaults support for Database CR#208

Open
sasikanthmasini wants to merge 6 commits intomainfrom
configmap-defaults
Open

ERA-60185 : Add ConfigMap defaults support for Database CR#208
sasikanthmasini wants to merge 6 commits intomainfrom
configmap-defaults

Conversation

@sasikanthmasini
Copy link
Contributor

@sasikanthmasini sasikanthmasini commented Feb 25, 2026

ConfigMap Defaults for Database Resources

Overview

Enables administrators to pre-configure default database settings in a Kubernetes ConfigMap, allowing developers to create Database CRs with minimal required inputs. The operator automatically resolves missing values from the referenced ConfigMap.

Why?

  • Reduces CR complexity: Developers only specify database name, type, and credentials
  • Centralized configuration: Admins manage default profiles, cluster, timezone, and Time Machine settings in one place
  • No sensitive data: ConfigMap stores only non-sensitive defaults; credentials remain in Secrets
  • Backward compatible: Existing CRs without ConfigMap references work unchanged

Key Changes

API Changes (api/v1alpha1/database_types.go)

  • Added defaultsConfigMapRef field to DatabaseSpec
  • Added clusterName, sourceDatabaseName, snapshotName fields for name-based resolution
  • Made corresponding ID fields omitempty to support both UUID and name-based workflows

ConfigMap Defaults (controller_adapters/configmap_defaults.go)

  • New module to fetch ConfigMap and apply defaults to Database CR
  • Supports database-specific keys (e.g., postgres.profiles.dbParam.name) and generic keys
  • Applied during reconciliation before name resolution

Auto-Snapshot Selection (controller_adapters/name_resolution.go & ndb_api/snapshots.go)

  • New feature: Automatically selects latest snapshot when both snapshotId and snapshotName are omitted during cloning
  • Added GetLatestSnapshotForTM() to fetch most recent snapshot by timestamp
  • Works seamlessly with ConfigMap defaults

Webhook Validation (api/v1alpha1/webhook_helpers.go)

  • Relaxed validation for clusterId, timezone, and snapshot fields when defaultsConfigMapRef is present
  • Allows auto-snapshot (both snapshotId and snapshotName empty) with ConfigMap
  • Maintains strict validation for traditional CRs without ConfigMap

RBAC (config/rbac/)

  • Added ConfigMap read permissions to operator's ClusterRole
  • Fixed ClusterRoleBinding ServiceAccount reference

ConfigMap Structure Used

apiVersion: v1
kind: ConfigMap
metadata:
  name: ndb-163-defaults
  namespace: default
data:
  timezone: "UTC"
  clusterName: "auto_cluster_nested_697cec1c92fce9da8fbb8668"
  
  # PostgreSQL-specific profiles
  postgres.profiles.software.name: "POSTGRES_14.13_OOB"
  postgres.profiles.network.name: "DEFAULT_OOB_POSTGRESQL_NETWORK"
  postgres.profiles.dbParam.name: "DEFAULT_POSTGRES_PARAMS"
  postgres.profiles.compute.name: "DEFAULT_OOB_COMPUTE"
  postgres.size: "10"
  
  # MySQL-specific profiles
  mysql.profiles.software.name: "MYSQL_8.0.37_OOB"
  mysql.profiles.network.name: "DEFAULT_OOB_MYSQL_NETWORK"
  mysql.profiles.dbParam.name: "DEFAULT_MYSQL_PARAMS"
  mysql.profiles.compute.name: "DEFAULT_OOB_COMPUTE"
  mysql.size: "10"
  
  # Time Machine settings (shared)
  timeMachine.sla: "DEFAULT_OOB_BRASS_SLA"
  timeMachine.dailySnapshotTime: "12:00:00"
  timeMachine.snapshotsPerDay: "1"
  timeMachine.logCatchUpFrequency: "30"
  timeMachine.weeklySnapshotDay: "MONDAY"
  timeMachine.monthlySnapshotDay: "1"

Example Usage

ConfigMap with Defaults

apiVersion: v1
kind: ConfigMap
metadata:
  name: ndb-defaults
data:
  timezone: "UTC"
  clusterName: "prod-cluster"
  postgres.profiles.software.name: "POSTGRES_14.13_OOB"
  postgres.profiles.network.name: "DEFAULT_OOB_POSTGRESQL_NETWORK"
  postgres.profiles.dbParam.name: "DEFAULT_POSTGRES_PARAMS"
  postgres.profiles.compute.name: "DEFAULT_OOB_COMPUTE"
  postgres.size: "10"
  timeMachine.sla: "DEFAULT_OOB_BRASS_SLA"
  timeMachine.dailySnapshotTime: "12:00:00"
  timeMachine.snapshotsPerDay: "1"
  # ... additional settings

Minimal Database CR (Provisioning)

apiVersion: ndb.nutanix.com/v1alpha1
kind: Database
metadata:
  name: my-postgres
spec:
  ndbRef: ndb-server
  defaultsConfigMapRef: ndb-defaults  # ← References ConfigMap
  isClone: false
  databaseInstance:
    type: postgres
    name: my-postgres
    databaseNames: ["app_db"]
    credentialSecret: postgres-creds

Minimal Clone CR (Auto-snapshot)

apiVersion: ndb.nutanix.com/v1alpha1
kind: Database
metadata:
  name: my-clone
spec:
  ndbRef: ndb-server
  defaultsConfigMapRef: ndb-defaults
  isClone: true
  clone:
    type: postgres
    name: my-clone
    sourceDatabaseName: "my-postgres"  # ← Name-based resolution
    # No snapshotName/snapshotId → auto-selects latest
    credentialSecret: clone-creds

Testing

Test Coverage: 20/20 Tests Passed

Category Tests Status
Functionality PostgreSQL & MySQL provisioning with ConfigMap defaults
Cloning with auto-snapshot, explicit name, and explicit ID
5/5
Backward Compatibility Provisioning & cloning without ConfigMap (traditional flow)
Webhook validation for non-ConfigMap CRs
4/4
Override Behavior Explicit CR values override ConfigMap defaults
Verified with size, timezone, and profile overrides
4/4
Error Handling Missing ConfigMap, empty ConfigMap, invalid profiles
Invalid source DB, invalid snapshot, Time Machine not ready
7/7

Key Validations

  • ConfigMap integration working correctly
  • Database-specific profiles (postgres vs mysql) applied correctly
  • Name-based resolution for cluster, database, and snapshot
  • Auto-snapshot selection for latest snapshot
  • Explicit CR values override ConfigMap defaults
  • Backward compatibility: traditional flows unchanged
  • Error handling: all errors reported via Kubernetes events with clear messages
  • RBAC permissions configured correctly

Breaking Changes

None. This feature is fully backward compatible. Existing Database CRs without defaultsConfigMapRef continue to work unchanged.

Documentation

  • Updated README.md with ConfigMap usage examples and auto-snapshot documentation

Testing Summary and Logs

1. Functionality Testing

1.1 PostgreSQL Provisioning with ConfigMap Defaults

Test File: test-pgsi-1.yaml

Minimal CR:

apiVersion: ndb.nutanix.com/v1alpha1
kind: Database
metadata:
  name: pgsi-1
spec:
  ndbRef: ndb-test-163
  defaultsConfigMapRef: ndb-163-defaults  # Reference to ConfigMap
  isClone: false
  databaseInstance:
    type: postgres
    name: pgsi-1
    databaseNames: ["testdb"]
    credentialSecret: pgsi-1-secret

ConfigMap Defaults Applied:

  • Cluster: auto_cluster_nested_697cec1c92fce9da8fbb8668
  • Timezone: UTC
  • Software Profile: POSTGRES_14.13_OOB
  • Network Profile: DEFAULT_OOB_POSTGRESQL_NETWORK
  • DbParam Profile: DEFAULT_POSTGRES_PARAMS
  • Compute Profile: DEFAULT_OOB_COMPUTE
  • Size: 10 GB
  • Time Machine SLA: DEFAULT_OOB_BRASS_SLA

Operator Logs:

INFO    Fetching ConfigMap defaults    {"namespace": "default", "configMapName": "ndb-163-defaults"}
INFO    ConfigMap defaults fetched successfully
INFO    Applying defaults from ConfigMap to Database CR
INFO    Applied default value from ConfigMap    {"key": "clusterName", "value": "auto_cluster_nested_697cec1c92fce9da8fbb8668"}
INFO    Applied default value from ConfigMap    {"key": "postgres.profiles.software.name", "value": "POSTGRES_14.13_OOB"}
INFO    Applied default value from ConfigMap    {"key": "postgres.profiles.network.name", "value": "DEFAULT_OOB_POSTGRESQL_NETWORK"}
INFO    Applied default value from ConfigMap    {"key": "postgres.profiles.dbParam.name", "value": "DEFAULT_POSTGRES_PARAMS"}

Result: Database pgsi-1 successfully created on NDB with all defaults properly applied.


1.2 MySQL Provisioning with ConfigMap Defaults

Test File: test-mysql-1.yaml

Minimal CR:

apiVersion: ndb.nutanix.com/v1alpha1
kind: Database
metadata:
  name: mysql-1
spec:
  ndbRef: ndb-test-163
  defaultsConfigMapRef: ndb-163-defaults
  isClone: false
  databaseInstance:
    type: mysql
    name: mysql-1
    databaseNames: ["testdb"]
    credentialSecret: mysql-1-secret

ConfigMap Defaults Applied:

  • Software Profile: MYSQL_8.0.37_OOB
  • Network Profile: DEFAULT_OOB_MYSQL_NETWORK
  • DbParam Profile: DEFAULT_MYSQL_PARAMS
  • All other defaults same as PostgreSQL

Operator Logs:

INFO    Applied default value from ConfigMap    {"key": "mysql.profiles.software.name", "value": "MYSQL_8.0.37_OOB"}
INFO    Applied default value from ConfigMap    {"key": "mysql.profiles.network.name", "value": "DEFAULT_OOB_MYSQL_NETWORK"}
INFO    Applied default value from ConfigMap    {"key": "mysql.profiles.dbParam.name", "value": "DEFAULT_MYSQL_PARAMS"}

Result: Database mysql-1 successfully created with database-specific MySQL profiles.


1.3 Cloning with Auto-Snapshot Selection

Test File: test-clone-pgsi-auto-snapshot.yaml

Minimal Clone CR (no snapshot specified):

apiVersion: ndb.nutanix.com/v1alpha1
kind: Database
metadata:
  name: clone-pgsi-auto
spec:
  ndbRef: ndb-test-163
  defaultsConfigMapRef: ndb-163-defaults
  isClone: true
  clone:
    type: postgres
    name: clone-pgsi-auto
    sourceDatabaseName: "pgsi-1"
    # No snapshotName or snapshotId - operator auto-selects latest
    credentialSecret: clone-pgsi-auto-secret

Operator Logs:

INFO    Both snapshotId and snapshotName are empty, auto-selecting latest snapshot
INFO    Fetching source database to get timeMachineId
INFO    Source database found    {"databaseId": "xxx", "timeMachineId": "e9e70cbf-8a42-4059-8298-be9126004e69"}
INFO    Fetching all snapshots for time machine
INFO    Found 3 snapshots, selecting latest by timestamp
INFO    Auto-selected latest snapshot    {"snapshotId": "db842c71-1ca3-4a5f-9ab5-c66c3644436b", "snapshotName": "snapthot1"}

Result: Clone successfully created using auto-selected latest snapshot.


1.4 Cloning with Explicit Snapshot Name

Test File: test-clone-pgsi-with-name.yaml

spec:
  clone:
    sourceDatabaseName: "pgsi-1"
    snapshotName: "snapthot1"  # Explicit snapshot name

Operator Logs:

INFO    Resolving snapshot name 'snapthot1' to UUID
INFO    Snapshot resolved successfully    {"snapshotName": "snapthot1", "snapshotId": "db842c71-1ca3-4a5f-9ab5-c66c3644436b"}

Result: Clone created successfully using explicit snapshot name.


1.5 Cloning with Explicit Snapshot ID

Test File: test-clone-pgsi-with-id.yaml

spec:
  clone:
    sourceDatabaseName: "pgsi-1"
    snapshotId: "db842c71-1ca3-4a5f-9ab5-c66c3644436b"  # Explicit UUID

Result: Clone created successfully using explicit snapshot UUID (no name resolution needed).


2. Backward Compatibility Testing

2.1 Provisioning WITHOUT ConfigMap (Traditional Flow)

Test File: test-pgsi-2-backward-compat.yaml

Traditional CR (no ConfigMap reference):

apiVersion: ndb.nutanix.com/v1alpha1
kind: Database
metadata:
  name: pgsi-2
spec:
  ndbRef: ndb-test-163
  # No defaultsConfigMapRef
  isClone: false
  databaseInstance:
    type: postgres
    name: pgsi-2
    databaseNames: ["testdb"]
    credentialSecret: pgsi-2-secret
    clusterId: "697cec1c-92fc-e9da-8fbb-8668b54a1639"
    timezone: "UTC"
    profiles:
      software:
        id: "e0038090-fd0b-4b0f-87b4-8c992a9620d9"
      network:
        id: "3e8d0bd0-da1b-49ef-b1e5-ed72cf8d53ee"
      dbParam:
        id: "24fb5e63-b3d3-418e-b27d-d2bc4a572be9"
      compute:
        id: "d3b16b1c-eaea-4a74-91b9-6865a42c3e48"
    size: 10
    timeMachine:
      sla: "DEFAULT_OOB_BRASS_SLA"
      # ... all other fields explicitly provided

Result: Database pgsi-2 successfully created. Traditional provisioning flow works unchanged.

Verification:

$ kubectl get database pgsi-2
NAME     STATUS    DATABASE-ID
pgsi-2   READY     <uuid>

2.2 Cloning WITHOUT ConfigMap (Traditional Flow)

Test File: test-clone-pgsi-1-backward-compat.yaml

Traditional Clone CR:

apiVersion: ndb.nutanix.com/v1alpha1
kind: Database
metadata:
  name: clone-pgsi-1-noconfig
spec:
  ndbRef: ndb-test-163
  # No defaultsConfigMapRef
  isClone: true
  clone:
    type: postgres
    name: clone-pgsi-1-noconfig
    sourceDatabaseId: "<uuid>"
    snapshotId: "<uuid>"
    clusterId: "<uuid>"
    timezone: "UTC"
    # ... all fields explicitly provided
    credentialSecret: clone-pgsi-1-noconfig-secret

Result: Clone clone-pgsi-1-noconfig successfully created. Traditional cloning flow works unchanged.


2.3 Webhook Validation for Traditional Flow

Webhook Behavior:

  • When defaultsConfigMapRef is NOT present, webhook enforces strict validation
  • Required fields: clusterId (or clusterName), timezone, profiles, size, etc.
  • Snapshot fields: At least one of snapshotId or snapshotName must be provided for cloning

Test: Created CR without ConfigMap and without required fields

Webhook Response:

Error from server: admission webhook "vdatabase.kb.io" denied the request: 
spec.Instance.clusterId: Invalid value: "": Either clusterId or clusterName must be provided
spec.Instance.timezone: Invalid value: "": timezone is a required field

Result: Webhook correctly enforces validation when ConfigMap is not used.


3. Override Behavior Testing

3.1 Provisioning with Overrides

Test File: test-pgsi-3-override.yaml

CR with Overrides:

apiVersion: ndb.nutanix.com/v1alpha1
kind: Database
metadata:
  name: pgsi-3
spec:
  ndbRef: ndb-test-163
  defaultsConfigMapRef: ndb-163-defaults
  isClone: false
  databaseInstance:
    type: postgres
    name: pgsi-3
    databaseNames: ["testdb"]
    credentialSecret: pgsi-3-secret
    size: 20          # Override: ConfigMap has 10
    timezone: "Asia/Kolkata"  # Override: ConfigMap has UTC

Operator Logs (NDB API request):

{
  "databaseServer": {
    "name": "pgsi-3",
    "newDbServerTimeZone": "Asia/Kolkata"
  },
  "createDbserver": true,
  "nodeCount": 1,
  "nodes": [{
    "properties": [{
      "name": "listener_port",
      "value": "5432"
    }],
    "vmName": "pgsi-3"
  }],
  "databaseParameterProfileId": "24fb5e63-b3d3-418e-b27d-d2bc4a572be9",
  "dbserverId": "",
  "timeMachineInfo": {
    "name": "pgsi-3_TM",
    "slaId": "16f89219-a307-4470-9b79-7f7853a4edb6"
  },
  "actionArguments": [{
    "name": "vm_name",
    "value": "pgsi-3"
  }, {
    "name": "working_dir",
    "value": "/tmp"
  }, {
    "name": "dbserver_description",
    "value": "pgsi-3"
  }, {
    "name": "db_password",
    "value": "***"
  }, {
    "name": "db_size",
    "value": "20"  #  Override applied
  }]
}

Verification:

  • ConfigMap has size: "10" and timezone: "UTC"
  • CR specifies size: 20 and timezone: "Asia/Kolkata"
  • Operator correctly uses 20 and "Asia/Kolkata" in NDB request

Result: Explicit CR values correctly override ConfigMap defaults.


3.2 Cloning with Overrides

Test File: test-pgsi-3-cloning-override.yaml

CR with Override:

spec:
  clone:
    name: pgsi-3-cloning
    sourceDatabaseName: "pgsi-1"
    timezone: "Europe/London"  # Override: ConfigMap has UTC

Operator Logs (NDB API request):

{
  "name": "pgsi-3-cloning",
  "createDbserver": true,
  "clustered": false,
  "nxClusterId": "697cec1c-92fc-e9da-8fbb-8668b54a1639",
  "sshPublicKey": "ssh-rsa ...",
  "dbserverId": "",
  "dbserverClusterId": "",
  "dbserverLogicalClusterId": "",
  "timeMachineId": "e9e70cbf-8a42-4059-8298-be9126004e69",
  "snapshotId": "db842c71-1ca3-4a5f-9ab5-c66c3644436b",
  "userPitrTimestamp": "",
  "timeZone": "Europe/London",  #  Override applied
  "latestSnapshot": false
}

Result: Explicit timezone in clone CR overrides ConfigMap default.


4. Edge Cases and Error Handling

4.1 Non-existent ConfigMap ❌ → Handled

Test: Reference a ConfigMap that doesn't exist

Events:

Warning  ConfigMapError  Failed to fetch defaults ConfigMap 'this-configmap-does-not-exist': 
                         ConfigMap "this-configmap-does-not-exist" not found

Result: Error properly detected and reported via Kubernetes event.


4.2 Empty ConfigMap → Handled

Test: ConfigMap exists but has data: {}

Events:

Normal   RequestGenerated  Generated database provisioning request
Warning  NDBRequestFailed  Error: Failed to create database on NDB. 
                          POST databases/provision error...

Result: Operator attempts to generate request, but NDB rejects due to missing required fields. Error properly reported.


4.3 Invalid Profile Names → Handled

Test: ConfigMap has postgres.profiles.software.name: "THIS_PROFILE_DOES_NOT_EXIST"

Events:

Warning  RequestGenerationFailed  Error: Could not generate database provisioning request. 
                                  could not resolve profile using the provided name=THIS_PROFILE_DOES_NOT_EXIST
Warning  NDBRequestFailed         Error: Failed to create database on NDB. 
                                  could not resolve profile using the provided name=THIS_PROFILE_DOES_NOT_EXIST

Result: Profile resolution fails with clear error message indicating which profile name is invalid.


4.4 Invalid Source Database Name → Handled

Test: Clone CR with sourceDatabaseName: "this-database-does-not-exist"

Events:

Warning  RequestGenerationFailed  Error: Failed to resolve names to UUIDs. 
                                  failed to resolve source database name 'this-database-does-not-exist': 
                                  database with name 'this-database-does-not-exist' not found

Result: Name resolution properly detects missing database with clear error.


4.5 Invalid Snapshot Name → Handled

Test: Clone CR with snapshotName: "this-snapshot-does-not-exist"

Events:

Warning  RequestGenerationFailed  Error: Failed to resolve names to UUIDs. 
                                  failed to resolve snapshot name 'this-snapshot-does-not-exist': 
                                  snapshot with name 'this-snapshot-does-not-exist' not found in 
                                  time machine 'e9e70cbf-8a42-4059-8298-be9126004e69'

Result: Snapshot name resolution checks time machine and reports which snapshot name is invalid.


4.6 Time Machine Not Ready → Handled

Test: Clone from database whose Time Machine is in NOT_YET_ACTIVATED state (no snapshots available)

Events:

Normal   RequestGenerated  Generated database cloning request
Warning  NDBRequestFailed  Error: Failed to make database cloning request to NDB. 
                          POST tms/aaba68a2-b9ad-46a7-9c5d-8479abef8d9c/clones error
                          ndb api error response status: 500, 
                          response body: {
                            "errorCode":"ERA-IVS-0000001",
                            "Reason":"TimeMachine (id:aaba68a2-b9ad-46a7-9c5d-8479abef8d9c) is in 'NOT_YET_ACTIVATED' state",
                            "remedy":"TimeMachine must be in either 'READY', 'PAUSED' or 'FROZEN' state 
                                     in order to create/refresh a clone or to restore a database"
                          }

Result: Operator forwards detailed NDB error message explaining Time Machine state.


4.7 Webhook Relaxed Validation

Test: Create minimal CR with ConfigMap reference but missing clusterId, timezone, snapshotId

Webhook Logs:

INFO  DefaultsConfigMapRef is set, relaxing validation for fields that can come from ConfigMap

Result: CR passes webhook validation. Fields will be resolved from ConfigMap during reconciliation.


Key Validations

ConfigMap Integration: Operator successfully reads and applies ConfigMap defaults
Database-specific Profiles: PostgreSQL and MySQL use correct database-specific profiles
Name Resolution: Cluster, database, and snapshot names resolve to UUIDs correctly
Auto-snapshot Selection: Latest snapshot automatically selected when both ID and name omitted
Override Mechanism: Explicit CR values override ConfigMap defaults
Backward Compatibility: Traditional flows (without ConfigMap) work unchanged
Webhook Validation: Relaxes validation when ConfigMap referenced, strict otherwise
Error Handling: All errors detected and reported via Kubernetes events with clear messages
RBAC: Operator has correct permissions to read ConfigMaps


Allow developers to specify minimal inputs in Database CR with admin-provided defaults via ConfigMap.
Values in CR take precedence over ConfigMap defaults.
…ecified

This commit adds the critical logic to skip validation for fields that
can be provided via ConfigMap defaults (cluster, size, profiles, timeMachine).

Key changes:
- Webhook detects when defaultsConfigMapRef is set
- Passes hasDefaultsConfigMap flag to validation handlers
- Validation handlers skip cluster/size/TM checks when ConfigMap ref is present
- Allows minimal Database CRs to pass validation successfully

Tested: Successfully provisioned databases using minimal CRs with ConfigMap defaults.
…iles

- Add postgres.profiles.dbParam.name for PostgreSQL-specific defaults
- Add mysql.profiles.dbParam.name for MySQL-specific defaults
- Add MySQL-specific example section in ConfigMap
- Clarify that dbParam profiles should be database-type-specific
- Updated webhook validation to allow omitting both snapshotId and snapshotName when defaultsConfigMapRef is set
- Added automatic selection of latest snapshot when both snapshot fields are empty
- Implemented GetLatestSnapshotForTM() in ndb_api to fetch most recent snapshot by timestamp
- Updated README with documentation on auto-snapshot feature

Testing: Verified with PostgreSQL and MySQL clones, backward compatibility maintained
Changes:
- Removed ConfigMap requirement for auto-snapshot feature
- Auto-snapshot now works when both snapshotId and snapshotName are omitted
- Updated webhook validation: removed hasDefaultsConfigMap check
- Updated test: changed from expecting error to expecting success
- Updated documentation: clarified auto-snapshot works in any scenario

This makes features orthogonal:
- ConfigMap defaults = provide default configuration values
- Auto-snapshot = automatically select latest snapshot

Benefits:
- Better UX: no need for ConfigMap just to get auto-snapshot
- More flexible: supports common "clone latest" use case
- Simpler mental model: omit snapshot = latest

Testing:
-  All 7 webhook validation scenarios pass
-  Auto-snapshot works without ConfigMap (new behavior)
-  Backward compatibility maintained
-  ConfigMap + auto-snapshot still works
Copy link
Contributor

@shivaprasadmb shivaprasadmb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few suggesions:

  1. Document all supported ConfigMap keys
    README already has a good example. Adding a short “Supported keys” subsection (e.g. clusterName, size, timezone, profiles., timeMachine., type-specific keys like postgres.size) would help admins.

  2. Validation after applying defaults
    Optional: after ApplyDefaultsToDatabase, run a quick check (e.g. for provisioning: cluster set, size >= 10, required TM fields) and emit a clear event or set a condition if something required is still missing, so “ConfigMap missing required key” is easier to diagnose.

  3. ConfigMap namespace
    Restricting the ConfigMap to the Database’s namespace is simple and consistent with RBAC. If you ever need cross-namespace defaults, you could add an optional defaultsConfigMapNamespace (or a small struct ref) later; not necessary for the current design.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants