Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions api/v1/database_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,21 @@ import (
)

// DatabaseSpec defines the desired state of Database
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.mode)",message="config.mode is only valid when spec.type is redis"
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.sync)",message="config.sync is only valid when spec.type is redis"
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.copy)",message="config.copy is only valid when spec.type is redis"
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.invoke_save)",message="config.invoke_save is only valid when spec.type is redis"
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.rdb_path)",message="config.rdb_path is only valid when spec.type is redis"
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.args_redis)",message="config.args_redis is only valid when spec.type is redis"
// +kubebuilder:validation:XValidation:rule="self.type == 'mongodb' || !has(self.config.auth_db)",message="config.auth_db is only valid when spec.type is mongodb"
// +kubebuilder:validation:XValidation:rule="self.type == 'mongodb' || !has(self.config.oplog)",message="config.oplog is only valid when spec.type is mongodb"
// +kubebuilder:validation:XValidation:rule="self.type == 'mssql' || !has(self.config.trust_server_certificate)",message="config.trust_server_certificate is only valid when spec.type is mssql"
// +kubebuilder:validation:XValidation:rule="self.type == 'influxdb' || !has(self.config.token)",message="config.token is only valid when spec.type is influxdb"
// +kubebuilder:validation:XValidation:rule="self.type == 'influxdb' || !has(self.config.bucket)",message="config.bucket is only valid when spec.type is influxdb"
// +kubebuilder:validation:XValidation:rule="self.type == 'influxdb' || !has(self.config.org)",message="config.org is only valid when spec.type is influxdb"
// +kubebuilder:validation:XValidation:rule="self.type == 'etcd' || !has(self.config.endpoints)",message="config.endpoints is only valid when spec.type is etcd"
// +kubebuilder:validation:XValidation:rule="self.type in ['postgresql', 'mysql', 'mariadb', 'mssql'] || !has(self.config.tables)",message="config.tables is only valid for SQL databases (postgresql, mysql, mariadb, mssql)"
// +kubebuilder:validation:XValidation:rule="self.type in ['postgresql', 'mysql', 'mariadb', 'mssql'] || !has(self.config.exclude_tables)",message="config.exclude_tables is only valid for SQL databases (postgresql, mysql, mariadb, mssql)"
type DatabaseSpec struct {
// Type is the database backend type
// +kubebuilder:validation:Enum=postgresql;mysql;mariadb;mongodb;redis;mssql;influxdb;etcd
Expand Down
34 changes: 34 additions & 0 deletions charts/gobackup-operator/crds/gobackup.io_databases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,40 @@ spec:
- config
- type
type: object
x-kubernetes-validations:
- message: config.mode is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.mode)
- message: config.sync is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.sync)
- message: config.copy is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.copy)
- message: config.invoke_save is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.invoke_save)
- message: config.rdb_path is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.rdb_path)
- message: config.args_redis is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.args_redis)
- message: config.auth_db is only valid when spec.type is mongodb
rule: self.type == 'mongodb' || !has(self.config.auth_db)
- message: config.oplog is only valid when spec.type is mongodb
rule: self.type == 'mongodb' || !has(self.config.oplog)
- message: config.trust_server_certificate is only valid when spec.type
is mssql
rule: self.type == 'mssql' || !has(self.config.trust_server_certificate)
- message: config.token is only valid when spec.type is influxdb
rule: self.type == 'influxdb' || !has(self.config.token)
- message: config.bucket is only valid when spec.type is influxdb
rule: self.type == 'influxdb' || !has(self.config.bucket)
- message: config.org is only valid when spec.type is influxdb
rule: self.type == 'influxdb' || !has(self.config.org)
- message: config.endpoints is only valid when spec.type is etcd
rule: self.type == 'etcd' || !has(self.config.endpoints)
- message: config.tables is only valid for SQL databases (postgresql,
mysql, mariadb, mssql)
rule: self.type in ['postgresql', 'mysql', 'mariadb', 'mssql'] || !has(self.config.tables)
- message: config.exclude_tables is only valid for SQL databases (postgresql,
mysql, mariadb, mssql)
rule: self.type in ['postgresql', 'mysql', 'mariadb', 'mssql'] || !has(self.config.exclude_tables)
status:
description: DatabaseStatus defines the observed state of Database
type: object
Expand Down
34 changes: 34 additions & 0 deletions config/crd/bases/gobackup.io_databases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,40 @@ spec:
- config
- type
type: object
x-kubernetes-validations:
- message: config.mode is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.mode)
- message: config.sync is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.sync)
- message: config.copy is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.copy)
- message: config.invoke_save is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.invoke_save)
- message: config.rdb_path is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.rdb_path)
- message: config.args_redis is only valid when spec.type is redis
rule: self.type == 'redis' || !has(self.config.args_redis)
- message: config.auth_db is only valid when spec.type is mongodb
rule: self.type == 'mongodb' || !has(self.config.auth_db)
- message: config.oplog is only valid when spec.type is mongodb
rule: self.type == 'mongodb' || !has(self.config.oplog)
- message: config.trust_server_certificate is only valid when spec.type
is mssql
rule: self.type == 'mssql' || !has(self.config.trust_server_certificate)
- message: config.token is only valid when spec.type is influxdb
rule: self.type == 'influxdb' || !has(self.config.token)
- message: config.bucket is only valid when spec.type is influxdb
rule: self.type == 'influxdb' || !has(self.config.bucket)
- message: config.org is only valid when spec.type is influxdb
rule: self.type == 'influxdb' || !has(self.config.org)
- message: config.endpoints is only valid when spec.type is etcd
rule: self.type == 'etcd' || !has(self.config.endpoints)
- message: config.tables is only valid for SQL databases (postgresql,
mysql, mariadb, mssql)
rule: self.type in ['postgresql', 'mysql', 'mariadb', 'mssql'] || !has(self.config.tables)
- message: config.exclude_tables is only valid for SQL databases (postgresql,
mysql, mariadb, mssql)
rule: self.type in ['postgresql', 'mysql', 'mariadb', 'mssql'] || !has(self.config.exclude_tables)
status:
description: DatabaseStatus defines the observed state of Database
type: object
Expand Down
28 changes: 28 additions & 0 deletions config/crd/bases/gobackup.io_storages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ spec:
a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
Expand Down Expand Up @@ -106,8 +110,12 @@ spec:
a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
Expand Down Expand Up @@ -143,8 +151,12 @@ spec:
a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
Expand Down Expand Up @@ -195,8 +207,12 @@ spec:
a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
Expand All @@ -222,8 +238,12 @@ spec:
a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
Expand Down Expand Up @@ -259,8 +279,12 @@ spec:
a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
Expand Down Expand Up @@ -296,8 +320,12 @@ spec:
a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
Expand Down
9 changes: 7 additions & 2 deletions pkg/k8sutil/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ func (k *K8s) CreateSecret(ctx context.Context, backup *backupv1.Backup) error {

// Process database references
for _, database := range model.DatabaseRefs {
dbType := strings.ToLower(database.Type)
// Resource name is always "databases" (plural of Database kind), not type-specific
resource := "databases"

Expand All @@ -60,7 +59,7 @@ func (k *K8s) CreateSecret(ctx context.Context, backup *backupv1.Backup) error {
// Fetch the database CRD
databaseCRD, err := k.GetCRD(ctx, apiGroup, "v1", resource, namespace, database.Name)
if err != nil {
return fmt.Errorf("failed to get %s database: %w", dbType, err)
return fmt.Errorf("failed to get database %s: %w", database.Name, err)
}

// Extract the database spec
Expand All @@ -69,6 +68,12 @@ func (k *K8s) CreateSecret(ctx context.Context, backup *backupv1.Backup) error {
return fmt.Errorf("database spec for %s is not a valid map", database.Name)
}

rawType, ok := specMap["type"].(string)
if !ok || strings.TrimSpace(rawType) == "" {
return fmt.Errorf("database type for %s is missing or invalid", database.Name)
}
dbType := strings.ToLower(strings.TrimSpace(rawType))

// Extract config if it exists
configMap, ok := specMap["config"].(map[string]interface{})
if !ok {
Expand Down