From 292c50764d3fce841e11c957f13865266639255c Mon Sep 17 00:00:00 2001 From: Mikalai Radchuk <509198+m1kola@users.noreply.github.com> Date: Tue, 28 Oct 2025 16:31:00 +0100 Subject: [PATCH] Add `.spec.clusterSpecList` field to `MongoDB` --- api/v1/mdb/mongodb_types.go | 7 + api/v1/mdbmulti/mongodb_multi_types.go | 2 - config/crd/bases/mongodb.com_mongodb.yaml | 145 +++++++++++++++++ .../mongodb.com_mongodbmulticluster.yaml | 5 + .../multicluster_replicaset_test.go | 10 +- helm_chart/crds/mongodb.com_mongodb.yaml | 145 +++++++++++++++++ .../crds/mongodb.com_mongodbmulticluster.yaml | 5 + pkg/telemetry/collector_test.go | 154 +++++++++--------- public/crds.yaml | 150 +++++++++++++++++ 9 files changed, 539 insertions(+), 84 deletions(-) diff --git a/api/v1/mdb/mongodb_types.go b/api/v1/mdb/mongodb_types.go index a009deaa3..00818fe43 100644 --- a/api/v1/mdb/mongodb_types.go +++ b/api/v1/mdb/mongodb_types.go @@ -421,6 +421,13 @@ type DbCommonSpec struct { // +kubebuilder:validation:Enum=SingleCluster;MultiCluster // +optional Topology string `json:"topology,omitempty"` + + // ClusterSpecList defines the configuration for MongoDB instances across multiple Kubernetes clusters. + // This field is used when Topology is set to "MultiCluster" and specifies how MongoDB members + // are distributed across different clusters, including member counts, service configurations, + // and external access settings for each cluster. + // +optional + ClusterSpecList ClusterSpecList `json:"clusterSpecList,omitempty"` } type MongoDbSpec struct { diff --git a/api/v1/mdbmulti/mongodb_multi_types.go b/api/v1/mdbmulti/mongodb_multi_types.go index fa88b6082..a1e139013 100644 --- a/api/v1/mdbmulti/mongodb_multi_types.go +++ b/api/v1/mdbmulti/mongodb_multi_types.go @@ -227,8 +227,6 @@ type MongoDBMultiSpec struct { // +kubebuilder:pruning:PreserveUnknownFields mdbv1.DbCommonSpec `json:",inline"` - ClusterSpecList mdbv1.ClusterSpecList `json:"clusterSpecList,omitempty"` - // Mapping stores the deterministic index for a given cluster-name. Mapping map[string]int `json:"-"` } diff --git a/config/crd/bases/mongodb.com_mongodb.yaml b/config/crd/bases/mongodb.com_mongodb.yaml index d421d8837..065d1271f 100644 --- a/config/crd/bases/mongodb.com_mongodb.yaml +++ b/config/crd/bases/mongodb.com_mongodb.yaml @@ -396,6 +396,151 @@ spec: clusterDomain: format: hostname type: string + clusterSpecList: + description: |- + ClusterSpecList defines the configuration for MongoDB instances across multiple Kubernetes clusters. + This field is used when Topology is set to "MultiCluster" and specifies how MongoDB members + are distributed across different clusters, including member counts, service configurations, + and external access settings for each cluster. + items: + description: |- + ClusterSpecItem is the mongodb multi-cluster spec that is specific to a + particular Kubernetes cluster, this maps to the statefulset created in each cluster + properties: + clusterName: + description: |- + ClusterName is name of the cluster where the MongoDB Statefulset will be scheduled, the + name should have a one on one mapping with the service-account created in the central cluster + to talk to the workload clusters. + type: string + externalAccess: + description: ExternalAccessConfiguration provides external access + configuration for Multi-Cluster. + properties: + externalDomain: + description: An external domain that is used for exposing + MongoDB to the outside world. + type: string + externalService: + description: Provides a way to override the default (NodePort) + Service + properties: + annotations: + additionalProperties: + type: string + description: A map of annotations that shall be added + to the externally available Service. + type: object + spec: + description: A wrapper for the Service spec object. + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + memberConfig: + description: MemberConfig allows to specify votes, priorities + and tags for each of the mongodb process. + items: + properties: + priority: + type: string + tags: + additionalProperties: + type: string + type: object + votes: + type: integer + type: object + type: array + members: + description: Amount of members for this MongoDB Replica Set + type: integer + podSpec: + properties: + persistence: + description: Note, that this field is used by MongoDB resources + only, let's keep it here for simplicity + properties: + multiple: + properties: + data: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + journal: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + logs: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + type: object + single: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + type: object + podTemplate: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + service: + description: this is an optional service, it will get the name + "-service" in case not provided + type: string + statefulSet: + description: |- + StatefulSetConfiguration holds the optional custom StatefulSet + that should be merged into the operator created one. + properties: + metadata: + description: StatefulSetMetadataWrapper is a wrapper around + Labels and Annotations + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + required: + - members + type: object + type: array configServerCount: type: integer configSrv: diff --git a/config/crd/bases/mongodb.com_mongodbmulticluster.yaml b/config/crd/bases/mongodb.com_mongodbmulticluster.yaml index 3f1fa05c9..1236c015d 100644 --- a/config/crd/bases/mongodb.com_mongodbmulticluster.yaml +++ b/config/crd/bases/mongodb.com_mongodbmulticluster.yaml @@ -388,6 +388,11 @@ spec: format: hostname type: string clusterSpecList: + description: |- + ClusterSpecList defines the configuration for MongoDB instances across multiple Kubernetes clusters. + This field is used when Topology is set to "MultiCluster" and specifies how MongoDB members + are distributed across different clusters, including member counts, service configurations, + and external access settings for each cluster. items: description: |- ClusterSpecItem is the mongodb multi-cluster spec that is specific to a diff --git a/controllers/operator/construct/multicluster/multicluster_replicaset_test.go b/controllers/operator/construct/multicluster/multicluster_replicaset_test.go index 8086ed554..9532865d5 100644 --- a/controllers/operator/construct/multicluster/multicluster_replicaset_test.go +++ b/controllers/operator/construct/multicluster/multicluster_replicaset_test.go @@ -46,11 +46,11 @@ func getMultiClusterMongoDB() mdbmulti.MongoDBMultiCluster { }, Roles: []mdb.MongoDBRole{}, }, - }, - ClusterSpecList: mdb.ClusterSpecList{ - { - ClusterName: "foo", - Members: 3, + ClusterSpecList: mdb.ClusterSpecList{ + { + ClusterName: "foo", + Members: 3, + }, }, }, } diff --git a/helm_chart/crds/mongodb.com_mongodb.yaml b/helm_chart/crds/mongodb.com_mongodb.yaml index d421d8837..065d1271f 100644 --- a/helm_chart/crds/mongodb.com_mongodb.yaml +++ b/helm_chart/crds/mongodb.com_mongodb.yaml @@ -396,6 +396,151 @@ spec: clusterDomain: format: hostname type: string + clusterSpecList: + description: |- + ClusterSpecList defines the configuration for MongoDB instances across multiple Kubernetes clusters. + This field is used when Topology is set to "MultiCluster" and specifies how MongoDB members + are distributed across different clusters, including member counts, service configurations, + and external access settings for each cluster. + items: + description: |- + ClusterSpecItem is the mongodb multi-cluster spec that is specific to a + particular Kubernetes cluster, this maps to the statefulset created in each cluster + properties: + clusterName: + description: |- + ClusterName is name of the cluster where the MongoDB Statefulset will be scheduled, the + name should have a one on one mapping with the service-account created in the central cluster + to talk to the workload clusters. + type: string + externalAccess: + description: ExternalAccessConfiguration provides external access + configuration for Multi-Cluster. + properties: + externalDomain: + description: An external domain that is used for exposing + MongoDB to the outside world. + type: string + externalService: + description: Provides a way to override the default (NodePort) + Service + properties: + annotations: + additionalProperties: + type: string + description: A map of annotations that shall be added + to the externally available Service. + type: object + spec: + description: A wrapper for the Service spec object. + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + memberConfig: + description: MemberConfig allows to specify votes, priorities + and tags for each of the mongodb process. + items: + properties: + priority: + type: string + tags: + additionalProperties: + type: string + type: object + votes: + type: integer + type: object + type: array + members: + description: Amount of members for this MongoDB Replica Set + type: integer + podSpec: + properties: + persistence: + description: Note, that this field is used by MongoDB resources + only, let's keep it here for simplicity + properties: + multiple: + properties: + data: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + journal: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + logs: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + type: object + single: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + type: object + podTemplate: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + service: + description: this is an optional service, it will get the name + "-service" in case not provided + type: string + statefulSet: + description: |- + StatefulSetConfiguration holds the optional custom StatefulSet + that should be merged into the operator created one. + properties: + metadata: + description: StatefulSetMetadataWrapper is a wrapper around + Labels and Annotations + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + required: + - members + type: object + type: array configServerCount: type: integer configSrv: diff --git a/helm_chart/crds/mongodb.com_mongodbmulticluster.yaml b/helm_chart/crds/mongodb.com_mongodbmulticluster.yaml index 3f1fa05c9..1236c015d 100644 --- a/helm_chart/crds/mongodb.com_mongodbmulticluster.yaml +++ b/helm_chart/crds/mongodb.com_mongodbmulticluster.yaml @@ -388,6 +388,11 @@ spec: format: hostname type: string clusterSpecList: + description: |- + ClusterSpecList defines the configuration for MongoDB instances across multiple Kubernetes clusters. + This field is used when Topology is set to "MultiCluster" and specifies how MongoDB members + are distributed across different clusters, including member counts, service configurations, + and external access settings for each cluster. items: description: |- ClusterSpecItem is the mongodb multi-cluster spec that is specific to a diff --git a/pkg/telemetry/collector_test.go b/pkg/telemetry/collector_test.go index f0ca25986..6e31263cd 100644 --- a/pkg/telemetry/collector_test.go +++ b/pkg/telemetry/collector_test.go @@ -353,19 +353,19 @@ func TestCollectDeploymentsSnapshot(t *testing.T) { Spec: mdbmulti.MongoDBMultiSpec{ DbCommonSpec: mdbv1.DbCommonSpec{ ResourceType: mdbv1.ReplicaSet, - }, - ClusterSpecList: []mdbv1.ClusterSpecItem{ - { - ClusterName: "cluster1", - Members: 1, - }, - { - ClusterName: "cluster2", - Members: 3, - }, - { - ClusterName: "cluster3", - Members: 3, + ClusterSpecList: []mdbv1.ClusterSpecItem{ + { + ClusterName: "cluster1", + Members: 1, + }, + { + ClusterName: "cluster2", + Members: 3, + }, + { + ClusterName: "cluster3", + Members: 3, + }, }, }, }, ObjectMeta: metav1.ObjectMeta{ @@ -582,19 +582,19 @@ func TestCollectDeploymentsSnapshot(t *testing.T) { Spec: mdbmulti.MongoDBMultiSpec{ DbCommonSpec: mdbv1.DbCommonSpec{ ResourceType: mdbv1.ReplicaSet, - }, - ClusterSpecList: []mdbv1.ClusterSpecItem{ - { - ClusterName: "cluster1", - Members: 1, - }, - { - ClusterName: "cluster2", - Members: 3, - }, - { - ClusterName: "cluster3", - Members: 3, + ClusterSpecList: []mdbv1.ClusterSpecItem{ + { + ClusterName: "cluster1", + Members: 1, + }, + { + ClusterName: "cluster2", + Members: 3, + }, + { + ClusterName: "cluster3", + Members: 3, + }, }, }, }, ObjectMeta: metav1.ObjectMeta{ @@ -609,19 +609,19 @@ func TestCollectDeploymentsSnapshot(t *testing.T) { ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ ExternalDomain: ptr.To("some.default.domain"), }, - }, - ClusterSpecList: []mdbv1.ClusterSpecItem{ - { - ClusterName: "cluster1", - Members: 1, - }, - { - ClusterName: "cluster2", - Members: 3, - }, - { - ClusterName: "cluster3", - Members: 3, + ClusterSpecList: []mdbv1.ClusterSpecItem{ + { + ClusterName: "cluster1", + Members: 1, + }, + { + ClusterName: "cluster2", + Members: 3, + }, + { + ClusterName: "cluster3", + Members: 3, + }, }, }, }, ObjectMeta: metav1.ObjectMeta{ @@ -636,27 +636,27 @@ func TestCollectDeploymentsSnapshot(t *testing.T) { ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ ExternalDomain: ptr.To("some.default.domain"), }, - }, - ClusterSpecList: []mdbv1.ClusterSpecItem{ - { - ClusterName: "cluster1", - Members: 1, - ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ - ExternalDomain: ptr.To("cluster1.domain"), + ClusterSpecList: []mdbv1.ClusterSpecItem{ + { + ClusterName: "cluster1", + Members: 1, + ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ + ExternalDomain: ptr.To("cluster1.domain"), + }, }, - }, - { - ClusterName: "cluster2", - Members: 3, - ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ - ExternalDomain: ptr.To("cluster2.domain"), + { + ClusterName: "cluster2", + Members: 3, + ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ + ExternalDomain: ptr.To("cluster2.domain"), + }, }, - }, - { - ClusterName: "cluster3", - Members: 3, - ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ - ExternalDomain: ptr.To("cluster3.domain"), + { + ClusterName: "cluster3", + Members: 3, + ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ + ExternalDomain: ptr.To("cluster3.domain"), + }, }, }, }, @@ -669,27 +669,27 @@ func TestCollectDeploymentsSnapshot(t *testing.T) { Spec: mdbmulti.MongoDBMultiSpec{ DbCommonSpec: mdbv1.DbCommonSpec{ ResourceType: mdbv1.ReplicaSet, - }, - ClusterSpecList: []mdbv1.ClusterSpecItem{ - { - ClusterName: "cluster1", - Members: 1, - ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ - ExternalDomain: ptr.To("cluster1.domain"), + ClusterSpecList: []mdbv1.ClusterSpecItem{ + { + ClusterName: "cluster1", + Members: 1, + ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ + ExternalDomain: ptr.To("cluster1.domain"), + }, }, - }, - { - ClusterName: "cluster2", - Members: 3, - ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ - ExternalDomain: ptr.To("cluster2.domain"), + { + ClusterName: "cluster2", + Members: 3, + ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ + ExternalDomain: ptr.To("cluster2.domain"), + }, }, - }, - { - ClusterName: "cluster3", - Members: 3, - ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ - ExternalDomain: ptr.To("cluster3.domain"), + { + ClusterName: "cluster3", + Members: 3, + ExternalAccessConfiguration: &mdbv1.ExternalAccessConfiguration{ + ExternalDomain: ptr.To("cluster3.domain"), + }, }, }, }, diff --git a/public/crds.yaml b/public/crds.yaml index beeaf741d..058c2a0ac 100644 --- a/public/crds.yaml +++ b/public/crds.yaml @@ -504,6 +504,151 @@ spec: clusterDomain: format: hostname type: string + clusterSpecList: + description: |- + ClusterSpecList defines the configuration for MongoDB instances across multiple Kubernetes clusters. + This field is used when Topology is set to "MultiCluster" and specifies how MongoDB members + are distributed across different clusters, including member counts, service configurations, + and external access settings for each cluster. + items: + description: |- + ClusterSpecItem is the mongodb multi-cluster spec that is specific to a + particular Kubernetes cluster, this maps to the statefulset created in each cluster + properties: + clusterName: + description: |- + ClusterName is name of the cluster where the MongoDB Statefulset will be scheduled, the + name should have a one on one mapping with the service-account created in the central cluster + to talk to the workload clusters. + type: string + externalAccess: + description: ExternalAccessConfiguration provides external access + configuration for Multi-Cluster. + properties: + externalDomain: + description: An external domain that is used for exposing + MongoDB to the outside world. + type: string + externalService: + description: Provides a way to override the default (NodePort) + Service + properties: + annotations: + additionalProperties: + type: string + description: A map of annotations that shall be added + to the externally available Service. + type: object + spec: + description: A wrapper for the Service spec object. + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + memberConfig: + description: MemberConfig allows to specify votes, priorities + and tags for each of the mongodb process. + items: + properties: + priority: + type: string + tags: + additionalProperties: + type: string + type: object + votes: + type: integer + type: object + type: array + members: + description: Amount of members for this MongoDB Replica Set + type: integer + podSpec: + properties: + persistence: + description: Note, that this field is used by MongoDB resources + only, let's keep it here for simplicity + properties: + multiple: + properties: + data: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + journal: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + logs: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + type: object + single: + properties: + labelSelector: + type: object + x-kubernetes-preserve-unknown-fields: true + storage: + type: string + storageClass: + type: string + type: object + type: object + podTemplate: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + service: + description: this is an optional service, it will get the name + "-service" in case not provided + type: string + statefulSet: + description: |- + StatefulSetConfiguration holds the optional custom StatefulSet + that should be merged into the operator created one. + properties: + metadata: + description: StatefulSetMetadataWrapper is a wrapper around + Labels and Annotations + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + type: object + x-kubernetes-preserve-unknown-fields: true + required: + - spec + type: object + required: + - members + type: object + type: array configServerCount: type: integer configSrv: @@ -3247,6 +3392,11 @@ spec: format: hostname type: string clusterSpecList: + description: |- + ClusterSpecList defines the configuration for MongoDB instances across multiple Kubernetes clusters. + This field is used when Topology is set to "MultiCluster" and specifies how MongoDB members + are distributed across different clusters, including member counts, service configurations, + and external access settings for each cluster. items: description: |- ClusterSpecItem is the mongodb multi-cluster spec that is specific to a