Skip to content

Commit b616df1

Browse files
Add validation in crds to avoid unrelated schema
1 parent 56f4c3d commit b616df1

5 files changed

Lines changed: 118 additions & 2 deletions

File tree

api/v1/database_types.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ import (
2121
)
2222

2323
// DatabaseSpec defines the desired state of Database
24+
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.mode)",message="config.mode is only valid when spec.type is redis"
25+
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.sync)",message="config.sync is only valid when spec.type is redis"
26+
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.copy)",message="config.copy is only valid when spec.type is redis"
27+
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.invoke_save)",message="config.invoke_save is only valid when spec.type is redis"
28+
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.rdb_path)",message="config.rdb_path is only valid when spec.type is redis"
29+
// +kubebuilder:validation:XValidation:rule="self.type == 'redis' || !has(self.config.args_redis)",message="config.args_redis is only valid when spec.type is redis"
30+
// +kubebuilder:validation:XValidation:rule="self.type == 'mongodb' || !has(self.config.auth_db)",message="config.auth_db is only valid when spec.type is mongodb"
31+
// +kubebuilder:validation:XValidation:rule="self.type == 'mongodb' || !has(self.config.oplog)",message="config.oplog is only valid when spec.type is mongodb"
32+
// +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"
33+
// +kubebuilder:validation:XValidation:rule="self.type == 'influxdb' || !has(self.config.token)",message="config.token is only valid when spec.type is influxdb"
34+
// +kubebuilder:validation:XValidation:rule="self.type == 'influxdb' || !has(self.config.bucket)",message="config.bucket is only valid when spec.type is influxdb"
35+
// +kubebuilder:validation:XValidation:rule="self.type == 'influxdb' || !has(self.config.org)",message="config.org is only valid when spec.type is influxdb"
36+
// +kubebuilder:validation:XValidation:rule="self.type == 'etcd' || !has(self.config.endpoints)",message="config.endpoints is only valid when spec.type is etcd"
37+
// +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)"
38+
// +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)"
2439
type DatabaseSpec struct {
2540
// Type is the database backend type
2641
// +kubebuilder:validation:Enum=postgresql;mysql;mariadb;mongodb;redis;mssql;influxdb;etcd

charts/gobackup-operator/crds/gobackup.io_databases.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,40 @@ spec:
155155
- config
156156
- type
157157
type: object
158+
x-kubernetes-validations:
159+
- message: config.mode is only valid when spec.type is redis
160+
rule: self.type == 'redis' || !has(self.config.mode)
161+
- message: config.sync is only valid when spec.type is redis
162+
rule: self.type == 'redis' || !has(self.config.sync)
163+
- message: config.copy is only valid when spec.type is redis
164+
rule: self.type == 'redis' || !has(self.config.copy)
165+
- message: config.invoke_save is only valid when spec.type is redis
166+
rule: self.type == 'redis' || !has(self.config.invoke_save)
167+
- message: config.rdb_path is only valid when spec.type is redis
168+
rule: self.type == 'redis' || !has(self.config.rdb_path)
169+
- message: config.args_redis is only valid when spec.type is redis
170+
rule: self.type == 'redis' || !has(self.config.args_redis)
171+
- message: config.auth_db is only valid when spec.type is mongodb
172+
rule: self.type == 'mongodb' || !has(self.config.auth_db)
173+
- message: config.oplog is only valid when spec.type is mongodb
174+
rule: self.type == 'mongodb' || !has(self.config.oplog)
175+
- message: config.trust_server_certificate is only valid when spec.type
176+
is mssql
177+
rule: self.type == 'mssql' || !has(self.config.trust_server_certificate)
178+
- message: config.token is only valid when spec.type is influxdb
179+
rule: self.type == 'influxdb' || !has(self.config.token)
180+
- message: config.bucket is only valid when spec.type is influxdb
181+
rule: self.type == 'influxdb' || !has(self.config.bucket)
182+
- message: config.org is only valid when spec.type is influxdb
183+
rule: self.type == 'influxdb' || !has(self.config.org)
184+
- message: config.endpoints is only valid when spec.type is etcd
185+
rule: self.type == 'etcd' || !has(self.config.endpoints)
186+
- message: config.tables is only valid for SQL databases (postgresql,
187+
mysql, mariadb, mssql)
188+
rule: self.type in ['postgresql', 'mysql', 'mariadb', 'mssql'] || !has(self.config.tables)
189+
- message: config.exclude_tables is only valid for SQL databases (postgresql,
190+
mysql, mariadb, mssql)
191+
rule: self.type in ['postgresql', 'mysql', 'mariadb', 'mssql'] || !has(self.config.exclude_tables)
158192
status:
159193
description: DatabaseStatus defines the observed state of Database
160194
type: object

config/crd/bases/gobackup.io_databases.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,40 @@ spec:
156156
- config
157157
- type
158158
type: object
159+
x-kubernetes-validations:
160+
- message: config.mode is only valid when spec.type is redis
161+
rule: self.type == 'redis' || !has(self.config.mode)
162+
- message: config.sync is only valid when spec.type is redis
163+
rule: self.type == 'redis' || !has(self.config.sync)
164+
- message: config.copy is only valid when spec.type is redis
165+
rule: self.type == 'redis' || !has(self.config.copy)
166+
- message: config.invoke_save is only valid when spec.type is redis
167+
rule: self.type == 'redis' || !has(self.config.invoke_save)
168+
- message: config.rdb_path is only valid when spec.type is redis
169+
rule: self.type == 'redis' || !has(self.config.rdb_path)
170+
- message: config.args_redis is only valid when spec.type is redis
171+
rule: self.type == 'redis' || !has(self.config.args_redis)
172+
- message: config.auth_db is only valid when spec.type is mongodb
173+
rule: self.type == 'mongodb' || !has(self.config.auth_db)
174+
- message: config.oplog is only valid when spec.type is mongodb
175+
rule: self.type == 'mongodb' || !has(self.config.oplog)
176+
- message: config.trust_server_certificate is only valid when spec.type
177+
is mssql
178+
rule: self.type == 'mssql' || !has(self.config.trust_server_certificate)
179+
- message: config.token is only valid when spec.type is influxdb
180+
rule: self.type == 'influxdb' || !has(self.config.token)
181+
- message: config.bucket is only valid when spec.type is influxdb
182+
rule: self.type == 'influxdb' || !has(self.config.bucket)
183+
- message: config.org is only valid when spec.type is influxdb
184+
rule: self.type == 'influxdb' || !has(self.config.org)
185+
- message: config.endpoints is only valid when spec.type is etcd
186+
rule: self.type == 'etcd' || !has(self.config.endpoints)
187+
- message: config.tables is only valid for SQL databases (postgresql,
188+
mysql, mariadb, mssql)
189+
rule: self.type in ['postgresql', 'mysql', 'mariadb', 'mssql'] || !has(self.config.tables)
190+
- message: config.exclude_tables is only valid for SQL databases (postgresql,
191+
mysql, mariadb, mssql)
192+
rule: self.type in ['postgresql', 'mysql', 'mariadb', 'mssql'] || !has(self.config.exclude_tables)
159193
status:
160194
description: DatabaseStatus defines the observed state of Database
161195
type: object

config/crd/bases/gobackup.io_storages.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,12 @@ spec:
5959
a valid secret key.
6060
type: string
6161
name:
62+
default: ""
6263
description: |-
6364
Name of the referent.
65+
This field is effectively required, but due to backwards compatibility is
66+
allowed to be empty. Instances of this type with an empty value here are
67+
almost certainly wrong.
6468
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
6569
type: string
6670
optional:
@@ -106,8 +110,12 @@ spec:
106110
a valid secret key.
107111
type: string
108112
name:
113+
default: ""
109114
description: |-
110115
Name of the referent.
116+
This field is effectively required, but due to backwards compatibility is
117+
allowed to be empty. Instances of this type with an empty value here are
118+
almost certainly wrong.
111119
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
112120
type: string
113121
optional:
@@ -143,8 +151,12 @@ spec:
143151
a valid secret key.
144152
type: string
145153
name:
154+
default: ""
146155
description: |-
147156
Name of the referent.
157+
This field is effectively required, but due to backwards compatibility is
158+
allowed to be empty. Instances of this type with an empty value here are
159+
almost certainly wrong.
148160
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
149161
type: string
150162
optional:
@@ -195,8 +207,12 @@ spec:
195207
a valid secret key.
196208
type: string
197209
name:
210+
default: ""
198211
description: |-
199212
Name of the referent.
213+
This field is effectively required, but due to backwards compatibility is
214+
allowed to be empty. Instances of this type with an empty value here are
215+
almost certainly wrong.
200216
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
201217
type: string
202218
optional:
@@ -222,8 +238,12 @@ spec:
222238
a valid secret key.
223239
type: string
224240
name:
241+
default: ""
225242
description: |-
226243
Name of the referent.
244+
This field is effectively required, but due to backwards compatibility is
245+
allowed to be empty. Instances of this type with an empty value here are
246+
almost certainly wrong.
227247
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
228248
type: string
229249
optional:
@@ -259,8 +279,12 @@ spec:
259279
a valid secret key.
260280
type: string
261281
name:
282+
default: ""
262283
description: |-
263284
Name of the referent.
285+
This field is effectively required, but due to backwards compatibility is
286+
allowed to be empty. Instances of this type with an empty value here are
287+
almost certainly wrong.
264288
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
265289
type: string
266290
optional:
@@ -296,8 +320,12 @@ spec:
296320
a valid secret key.
297321
type: string
298322
name:
323+
default: ""
299324
description: |-
300325
Name of the referent.
326+
This field is effectively required, but due to backwards compatibility is
327+
allowed to be empty. Instances of this type with an empty value here are
328+
almost certainly wrong.
301329
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
302330
type: string
303331
optional:

pkg/k8sutil/secret.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ func (k *K8s) CreateSecret(ctx context.Context, backup *backupv1.Backup) error {
4747

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

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

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

71+
rawType, ok := specMap["type"].(string)
72+
if !ok || strings.TrimSpace(rawType) == "" {
73+
return fmt.Errorf("database type for %s is missing or invalid", database.Name)
74+
}
75+
dbType := strings.ToLower(strings.TrimSpace(rawType))
76+
7277
// Extract config if it exists
7378
configMap, ok := specMap["config"].(map[string]interface{})
7479
if !ok {

0 commit comments

Comments
 (0)