From a0be9711323caf748ebaed29fe56f4a22ec9df1c Mon Sep 17 00:00:00 2001 From: ivanauth Date: Fri, 22 May 2026 11:51:12 -0400 Subject: [PATCH] feat: warn when version/channel are placed under .spec.config --- pkg/config/config.go | 7 ++ pkg/config/config_test.go | 185 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) diff --git a/pkg/config/config.go b/pkg/config/config.go index 59f63ba3..d6826659 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -202,6 +202,13 @@ func NewConfig(cluster *v1alpha1.SpiceDBCluster, globalConfig *OperatorConfig, s errs := make([]error, 0) warnings := make([]error, 0) + for _, k := range []string{"version", "channel"} { + if _, ok := config[k]; ok { + warnings = append(warnings, fmt.Errorf(".spec.config.%s is ignored; use .spec.%s instead", k, k)) + delete(config, k) + } + } + spiceConfig := SpiceConfig{ Name: cluster.Name, Namespace: cluster.Namespace, diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 74e3f3ab..113cdb41 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -2138,6 +2138,191 @@ func TestNewConfig(t *testing.T) { }, wantPortCount: 4, }, + { + name: "warns when version/channel are misplaced under .spec.config", + args: args{ + cluster: v1alpha1.ClusterSpec{ + SecretRef: "test-secret", + Config: json.RawMessage(` + { + "datastoreEngine": "cockroachdb", + "version": "ignored-version", + "channel": "ignored-channel" + } + `), + }, + globalConfig: OperatorConfig{ + ImageName: "image", + UpdateGraph: updates.UpdateGraph{ + Channels: []updates.Channel{ + { + Name: "cockroachdb", + Metadata: map[string]string{"datastore": "cockroachdb", "default": "true"}, + Nodes: []updates.State{ + {ID: "v1", Tag: "v1"}, + }, + Edges: map[string][]string{"v1": {}}, + }, + }, + }, + }, + secret: &corev1.Secret{Data: map[string][]byte{ + "datastore_uri": []byte("uri"), + "preshared_key": []byte("psk"), + }}, + }, + wantWarnings: []error{ + fmt.Errorf(".spec.config.version is ignored; use .spec.version instead"), + fmt.Errorf(".spec.config.channel is ignored; use .spec.channel instead"), + fmt.Errorf("no TLS configured, consider setting \"tlsSecretName\""), + }, + want: &Config{ + MigrationConfig: MigrationConfig{ + MigrationLogLevel: "debug", + DatastoreEngine: "cockroachdb", + DatastoreURI: "uri", + TargetSpiceDBImage: "image:v1", + EnvPrefix: "SPICEDB", + SpiceDBCmd: "spicedb", + TargetMigration: "head", + SpiceDBVersion: &v1alpha1.SpiceDBVersion{ + Name: "v1", + Channel: "cockroachdb", + Attributes: []v1alpha1.SpiceDBVersionAttributes{ + v1alpha1.SpiceDBVersionAttributesMigration, + }, + }, + }, + SpiceConfig: SpiceConfig{ + LogLevel: "info", + Name: "test", + Namespace: "test", + UID: "1", + Replicas: 2, + PresharedKey: "psk", + EnvPrefix: "SPICEDB", + SpiceDBCmd: "spicedb", + ServiceAccountName: "test", + DispatchEnabled: true, + DispatchUpstreamCASecretPath: "tls.crt", + DatastoreURIRef: ResolvedCredentialRef{SecretName: "test-secret", Key: "datastore_uri"}, + PresharedKeyRef: ResolvedCredentialRef{SecretName: "test-secret", Key: "preshared_key"}, + MigrationSecretsRef: ResolvedCredentialRef{SecretName: "test-secret", Key: "migration_secrets"}, + ProjectLabels: true, + ProjectAnnotations: true, + Passthrough: map[string]string{ + "datastoreEngine": "cockroachdb", + "dispatchClusterEnabled": "true", + "terminationLogPath": "/dev/termination-log", + }, + }, + }, + wantEnvs: []string{ + "SPICEDB_POD_NAME=FIELD_REF=metadata.name", + "SPICEDB_LOG_LEVEL=info", + "SPICEDB_GRPC_PRESHARED_KEY=preshared_key", + "SPICEDB_DATASTORE_CONN_URI=datastore_uri", + "SPICEDB_DISPATCH_UPSTREAM_ADDR=kubernetes:///test.test:dispatch", + "SPICEDB_DATASTORE_ENGINE=cockroachdb", + "SPICEDB_DISPATCH_CLUSTER_ENABLED=true", + "SPICEDB_TERMINATION_LOG_PATH=/dev/termination-log", + }, + wantPortCount: 4, + }, + { + name: "misplaced version/channel are ignored when correctly set at .spec", + args: args{ + cluster: v1alpha1.ClusterSpec{ + SecretRef: "test-secret", + Version: "v1", + Channel: "cockroachdb", + Config: json.RawMessage(` + { + "datastoreEngine": "cockroachdb", + "version": "v2", + "channel": "wrongchannel" + } + `), + }, + globalConfig: OperatorConfig{ + ImageName: "image", + UpdateGraph: updates.UpdateGraph{ + Channels: []updates.Channel{ + { + Name: "cockroachdb", + Metadata: map[string]string{"datastore": "cockroachdb", "default": "true"}, + Nodes: []updates.State{ + {ID: "v2", Tag: "v2"}, + {ID: "v1", Tag: "v1"}, + }, + Edges: map[string][]string{"v1": {"v2"}}, + }, + }, + }, + }, + secret: &corev1.Secret{Data: map[string][]byte{ + "datastore_uri": []byte("uri"), + "preshared_key": []byte("psk"), + }}, + }, + wantWarnings: []error{ + fmt.Errorf(".spec.config.version is ignored; use .spec.version instead"), + fmt.Errorf(".spec.config.channel is ignored; use .spec.channel instead"), + fmt.Errorf("no TLS configured, consider setting \"tlsSecretName\""), + }, + want: &Config{ + MigrationConfig: MigrationConfig{ + MigrationLogLevel: "debug", + DatastoreEngine: "cockroachdb", + DatastoreURI: "uri", + TargetSpiceDBImage: "image:v1", + EnvPrefix: "SPICEDB", + SpiceDBCmd: "spicedb", + TargetMigration: "head", + SpiceDBVersion: &v1alpha1.SpiceDBVersion{ + Name: "v1", + Channel: "cockroachdb", + Attributes: []v1alpha1.SpiceDBVersionAttributes{ + v1alpha1.SpiceDBVersionAttributesMigration, + }, + }, + }, + SpiceConfig: SpiceConfig{ + LogLevel: "info", + Name: "test", + Namespace: "test", + UID: "1", + Replicas: 2, + PresharedKey: "psk", + EnvPrefix: "SPICEDB", + SpiceDBCmd: "spicedb", + ServiceAccountName: "test", + DispatchEnabled: true, + DispatchUpstreamCASecretPath: "tls.crt", + DatastoreURIRef: ResolvedCredentialRef{SecretName: "test-secret", Key: "datastore_uri"}, + PresharedKeyRef: ResolvedCredentialRef{SecretName: "test-secret", Key: "preshared_key"}, + MigrationSecretsRef: ResolvedCredentialRef{SecretName: "test-secret", Key: "migration_secrets"}, + ProjectLabels: true, + ProjectAnnotations: true, + Passthrough: map[string]string{ + "datastoreEngine": "cockroachdb", + "dispatchClusterEnabled": "true", + "terminationLogPath": "/dev/termination-log", + }, + }, + }, + wantEnvs: []string{ + "SPICEDB_POD_NAME=FIELD_REF=metadata.name", + "SPICEDB_LOG_LEVEL=info", + "SPICEDB_GRPC_PRESHARED_KEY=preshared_key", + "SPICEDB_DATASTORE_CONN_URI=datastore_uri", + "SPICEDB_DISPATCH_UPSTREAM_ADDR=kubernetes:///test.test:dispatch", + "SPICEDB_DATASTORE_ENGINE=cockroachdb", + "SPICEDB_DISPATCH_CLUSTER_ENABLED=true", + "SPICEDB_TERMINATION_LOG_PATH=/dev/termination-log", + }, + wantPortCount: 4, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {