From 4b58e23e34106f39174f48b1ec69be59f585d392 Mon Sep 17 00:00:00 2001 From: Bohdan Siryk Date: Tue, 16 Jan 2024 15:29:47 +0200 Subject: [PATCH] issue-676, added immutability for replicationFactor and replicaNodes for redis resource --- apis/clusters/v1beta1/redis_types.go | 7 +++++-- apis/clusters/v1beta1/redis_webhook.go | 13 +++++++++++++ apis/clusters/v1beta1/structs.go | 12 ++++++------ .../clusters.instaclustr.com_cadences.yaml | 4 ++-- .../clusters.instaclustr.com_cassandras.yaml | 4 ++-- .../clusters.instaclustr.com_kafkaconnects.yaml | 4 ++-- .../bases/clusters.instaclustr.com_kafkas.yaml | 4 ++-- .../clusters.instaclustr.com_opensearches.yaml | 4 ++-- .../clusters.instaclustr.com_postgresqls.yaml | 4 ++-- .../bases/clusters.instaclustr.com_redis.yaml | 8 ++++++-- .../clusters.instaclustr.com_zookeepers.yaml | 4 ++-- controllers/clusters/helpers.go | 2 +- .../clusters/kafkaconnect_controller_test.go | 5 +++-- controllers/clusters/redis_controller.go | 17 +++++++++++++++-- pkg/models/operator.go | 2 +- 15 files changed, 64 insertions(+), 30 deletions(-) diff --git a/apis/clusters/v1beta1/redis_types.go b/apis/clusters/v1beta1/redis_types.go index fb7e640a8..03585665c 100644 --- a/apis/clusters/v1beta1/redis_types.go +++ b/apis/clusters/v1beta1/redis_types.go @@ -31,11 +31,14 @@ import ( ) type RedisDataCentre struct { - DataCentre `json:",inline"` + DataCentre `json:",inline"` + MasterNodes int `json:"masterNodes"` //+kubebuilder:validation:Minimum:=0 //+kubebuilder:validation:Maximum:=5 + // ReplicationFactor defines how many replica nodes (aka nodesNumber) should be created for each master node + // (e.a. if there are 3 masterNodes and replicationFactor 1 then it creates 1 replicaNode for each accordingly). ReplicationFactor int `json:"replicationFactor,omitempty"` //+kubebuilder:validation:MaxItems:=1 @@ -303,7 +306,7 @@ func (rs *RedisStatus) DCsFromInstAPI(iDCs []*models.RedisDataCentre) (dcs []*Da for _, iDC := range iDCs { dc := rs.ClusterStatus.DCFromInstAPI(iDC.DataCentre) dc.PrivateLink = privateLinkStatusesFromInstAPI(iDC.PrivateLink) - + dc.NodesNumber += iDC.MasterNodes dcs = append(dcs, dc) } return diff --git a/apis/clusters/v1beta1/redis_webhook.go b/apis/clusters/v1beta1/redis_webhook.go index 58c2c1813..19b4bf14d 100644 --- a/apis/clusters/v1beta1/redis_webhook.go +++ b/apis/clusters/v1beta1/redis_webhook.go @@ -64,6 +64,17 @@ func (r *Redis) Default() { for _, dataCentre := range r.Spec.DataCentres { dataCentre.SetDefaultValues() + + fmt.Println("DEFAULTER") + fmt.Println("nodes number", dataCentre.NodesNumber) + + if dataCentre.MasterNodes != 0 { + if dataCentre.ReplicationFactor > 0 { + dataCentre.NodesNumber = dataCentre.MasterNodes * dataCentre.ReplicationFactor + } else { + dataCentre.ReplicationFactor = dataCentre.NodesNumber / dataCentre.MasterNodes + } + } } } @@ -234,6 +245,7 @@ type specificRedisFields struct { type immutableRedisDCFields struct { immutableDC + ReplicationFactor int } func (rs *RedisSpec) ValidateUpdate(oldSpec RedisSpec) error { @@ -332,6 +344,7 @@ func (rdc *RedisDataCentre) newImmutableFields() *immutableRedisDCFields { ProviderAccountName: rdc.ProviderAccountName, Network: rdc.Network, }, + ReplicationFactor: rdc.ReplicationFactor, } } diff --git a/apis/clusters/v1beta1/structs.go b/apis/clusters/v1beta1/structs.go index 118b9d346..09e7b2ae3 100644 --- a/apis/clusters/v1beta1/structs.go +++ b/apis/clusters/v1beta1/structs.go @@ -48,7 +48,7 @@ type DataCentreStatus struct { ID string `json:"id,omitempty"` Status string `json:"status,omitempty"` Nodes []*Node `json:"nodes,omitempty"` - NodeNumber int `json:"nodeNumber,omitempty"` + NodesNumber int `json:"nodesNumber,omitempty"` EncryptionKeyID string `json:"encryptionKeyId,omitempty"` PrivateLink PrivateLinkStatuses `json:"privateLink,omitempty"` ResizeOperations []*ResizeOperation `json:"resizeOperations,omitempty"` @@ -569,11 +569,11 @@ func areClusteredMaintenanceEventStatusEqual(a, b *clusterresource.MaintenanceEv func (cs *ClusterStatus) DCFromInstAPI(iDC models.DataCentre) *DataCentreStatus { return &DataCentreStatus{ - Name: iDC.Name, - ID: iDC.ID, - Status: iDC.Status, - Nodes: cs.NodesFromInstAPI(iDC.Nodes), - NodeNumber: iDC.NumberOfNodes, + Name: iDC.Name, + ID: iDC.ID, + Status: iDC.Status, + Nodes: cs.NodesFromInstAPI(iDC.Nodes), + NodesNumber: iDC.NumberOfNodes, } } diff --git a/config/crd/bases/clusters.instaclustr.com_cadences.yaml b/config/crd/bases/clusters.instaclustr.com_cadences.yaml index 80e094b4d..e48e9fbd0 100644 --- a/config/crd/bases/clusters.instaclustr.com_cadences.yaml +++ b/config/crd/bases/clusters.instaclustr.com_cadences.yaml @@ -357,8 +357,6 @@ spec: type: string name: type: string - nodeNumber: - type: integer nodes: items: properties: @@ -380,6 +378,8 @@ spec: type: string type: object type: array + nodesNumber: + type: integer privateLink: items: properties: diff --git a/config/crd/bases/clusters.instaclustr.com_cassandras.yaml b/config/crd/bases/clusters.instaclustr.com_cassandras.yaml index e393d6da2..5c3e0226c 100644 --- a/config/crd/bases/clusters.instaclustr.com_cassandras.yaml +++ b/config/crd/bases/clusters.instaclustr.com_cassandras.yaml @@ -314,8 +314,6 @@ spec: type: string name: type: string - nodeNumber: - type: integer nodes: items: properties: @@ -337,6 +335,8 @@ spec: type: string type: object type: array + nodesNumber: + type: integer privateLink: items: properties: diff --git a/config/crd/bases/clusters.instaclustr.com_kafkaconnects.yaml b/config/crd/bases/clusters.instaclustr.com_kafkaconnects.yaml index 4d7245ad1..ae49cf00a 100644 --- a/config/crd/bases/clusters.instaclustr.com_kafkaconnects.yaml +++ b/config/crd/bases/clusters.instaclustr.com_kafkaconnects.yaml @@ -323,8 +323,6 @@ spec: type: string name: type: string - nodeNumber: - type: integer nodes: items: properties: @@ -346,6 +344,8 @@ spec: type: string type: object type: array + nodesNumber: + type: integer privateLink: items: properties: diff --git a/config/crd/bases/clusters.instaclustr.com_kafkas.yaml b/config/crd/bases/clusters.instaclustr.com_kafkas.yaml index 025541c8a..9219e02b9 100644 --- a/config/crd/bases/clusters.instaclustr.com_kafkas.yaml +++ b/config/crd/bases/clusters.instaclustr.com_kafkas.yaml @@ -331,8 +331,6 @@ spec: type: string name: type: string - nodeNumber: - type: integer nodes: items: properties: @@ -354,6 +352,8 @@ spec: type: string type: object type: array + nodesNumber: + type: integer privateLink: items: properties: diff --git a/config/crd/bases/clusters.instaclustr.com_opensearches.yaml b/config/crd/bases/clusters.instaclustr.com_opensearches.yaml index ed677bd58..7ba8cc888 100644 --- a/config/crd/bases/clusters.instaclustr.com_opensearches.yaml +++ b/config/crd/bases/clusters.instaclustr.com_opensearches.yaml @@ -293,8 +293,6 @@ spec: type: string name: type: string - nodeNumber: - type: integer nodes: items: properties: @@ -316,6 +314,8 @@ spec: type: string type: object type: array + nodesNumber: + type: integer privateLink: items: properties: diff --git a/config/crd/bases/clusters.instaclustr.com_postgresqls.yaml b/config/crd/bases/clusters.instaclustr.com_postgresqls.yaml index 0b7913821..4d1939e66 100644 --- a/config/crd/bases/clusters.instaclustr.com_postgresqls.yaml +++ b/config/crd/bases/clusters.instaclustr.com_postgresqls.yaml @@ -304,8 +304,6 @@ spec: type: string name: type: string - nodeNumber: - type: integer nodes: items: properties: @@ -327,6 +325,8 @@ spec: type: string type: object type: array + nodesNumber: + type: integer privateLink: items: properties: diff --git a/config/crd/bases/clusters.instaclustr.com_redis.yaml b/config/crd/bases/clusters.instaclustr.com_redis.yaml index 069ca7989..a07b793a4 100644 --- a/config/crd/bases/clusters.instaclustr.com_redis.yaml +++ b/config/crd/bases/clusters.instaclustr.com_redis.yaml @@ -93,6 +93,10 @@ spec: region: type: string replicationFactor: + description: ReplicationFactor defines how many replica nodes + (aka nodesNumber) should be created for each master node (e.a. + if there are 3 masterNodes and replicationFactor 1 then it + creates 1 replicaNode for each accordingly). maximum: 5 minimum: 0 type: integer @@ -285,8 +289,6 @@ spec: type: string name: type: string - nodeNumber: - type: integer nodes: items: properties: @@ -308,6 +310,8 @@ spec: type: string type: object type: array + nodesNumber: + type: integer privateLink: items: properties: diff --git a/config/crd/bases/clusters.instaclustr.com_zookeepers.yaml b/config/crd/bases/clusters.instaclustr.com_zookeepers.yaml index 07c7cec53..b622048cb 100644 --- a/config/crd/bases/clusters.instaclustr.com_zookeepers.yaml +++ b/config/crd/bases/clusters.instaclustr.com_zookeepers.yaml @@ -150,8 +150,6 @@ spec: type: string name: type: string - nodeNumber: - type: integer nodes: items: properties: @@ -173,6 +171,8 @@ spec: type: string type: object type: array + nodesNumber: + type: integer privateLink: items: properties: diff --git a/controllers/clusters/helpers.go b/controllers/clusters/helpers.go index d40e95967..f4d9f0c97 100644 --- a/controllers/clusters/helpers.go +++ b/controllers/clusters/helpers.go @@ -102,7 +102,7 @@ func areDataCentresEqual(a, b []*v1beta1.DataCentreStatus) bool { } if a[i].Status != b[i].Status || - a[i].NodeNumber != b[i].NodeNumber || + a[i].NodesNumber != b[i].NodesNumber || a[i].EncryptionKeyID != b[i].EncryptionKeyID { return false } diff --git a/controllers/clusters/kafkaconnect_controller_test.go b/controllers/clusters/kafkaconnect_controller_test.go index c099d66c5..8fa6e945b 100644 --- a/controllers/clusters/kafkaconnect_controller_test.go +++ b/controllers/clusters/kafkaconnect_controller_test.go @@ -18,9 +18,10 @@ package clusters import ( "context" - openapi "github.com/instaclustr/operator/pkg/instaclustr/mock/server/go" "os" + openapi "github.com/instaclustr/operator/pkg/instaclustr/mock/server/go" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" k8serrors "k8s.io/apimachinery/pkg/api/errors" @@ -103,7 +104,7 @@ var _ = Describe("Kafka Connect Controller", func() { return false } - return kafkaConnect.Status.DataCentres[0].NodeNumber == newKafkaConnectNodeNumbers + return kafkaConnect.Status.DataCentres[0].NodesNumber == newKafkaConnectNodeNumbers }, timeout, interval).Should(BeTrue()) }) }) diff --git a/controllers/clusters/redis_controller.go b/controllers/clusters/redis_controller.go index ef1296507..98197d8dc 100644 --- a/controllers/clusters/redis_controller.go +++ b/controllers/clusters/redis_controller.go @@ -869,9 +869,22 @@ func (r *RedisReconciler) newWatchStatusJob(redis *v1beta1.Redis) scheduler.Job } } - if iRedis.Status.CurrentClusterOperationStatus == models.NoOperation && + equals := redis.Spec.IsEqual(iRedis.Spec) + + if equals && redis.Annotations[models.ExternalChangesAnnotation] == models.True { + patch := redis.NewPatch() + delete(redis.Annotations, models.ExternalChangesAnnotation) + err := r.Patch(context.Background(), redis, patch) + if err != nil { + return err + } + + r.EventRecorder.Event(redis, models.Normal, models.ExternalChanges, + "External changes were automatically reconciled", + ) + } else if iRedis.Status.CurrentClusterOperationStatus == models.NoOperation && redis.Annotations[models.UpdateQueuedAnnotation] != models.True && - !redis.Spec.IsEqual(iRedis.Spec) { + !equals { k8sData, err := removeRedundantFieldsFromSpec(redis.Spec, "userRefs") if err != nil { diff --git a/pkg/models/operator.go b/pkg/models/operator.go index 638ecf93a..7411d10f2 100644 --- a/pkg/models/operator.go +++ b/pkg/models/operator.go @@ -186,5 +186,5 @@ const ( const ( ExternalChangesBaseMessage = "There are external changes on the Instaclustr console. Please reconcile the specification manually." - SpecPath = "path" + SpecPath = "spec" )