From 484450009a152bdbd2e1edf141abbc91acf4e45b Mon Sep 17 00:00:00 2001 From: Bohdan Siryk Date: Tue, 23 Jan 2024 13:46:59 +0200 Subject: [PATCH] dev --- apis/clusters/v1beta1/generic_structs.go | 30 +-- apis/clusters/v1beta1/opensearch_types.go | 6 +- .../clusters/v1beta1/opensearch_types_test.go | 182 ++++++++++++++++++ .../samples/clusters_v1beta1_opensearch.yaml | 59 ++++++ controllers/clusters/opensearch_controller.go | 44 +---- pkg/instaclustr/client.go | 4 + 6 files changed, 268 insertions(+), 57 deletions(-) create mode 100644 apis/clusters/v1beta1/opensearch_types_test.go diff --git a/apis/clusters/v1beta1/generic_structs.go b/apis/clusters/v1beta1/generic_structs.go index 79d8c834f..bc5a0abad 100644 --- a/apis/clusters/v1beta1/generic_structs.go +++ b/apis/clusters/v1beta1/generic_structs.go @@ -4,24 +4,15 @@ import "github.com/instaclustr/operator/apis/clusterresources/v1beta1" type GenericStatus struct { ID string `json:"id,omitempty"` - MaintenanceEvents []*v1beta1.ClusteredMaintenanceEventStatus `json:"maintenanceEvents,omitempty"` State string `json:"state,omitempty"` CurrentClusterOperationStatus string `json:"currentClusterOperationStatus,omitempty"` + MaintenanceEvents []*v1beta1.ClusteredMaintenanceEventStatus `json:"maintenanceEvents,omitempty"` } func (s *GenericStatus) Equals(o *GenericStatus) bool { - return false -} - -type GenericDataCentreStatus struct { - Name string `json:"name,omitempty"` - ID string `json:"id,omitempty"` - Status string `json:"status,omitempty"` - ResizeOperations []*ResizeOperation `json:"resizeOperations,omitempty"` -} - -func (s *GenericDataCentreStatus) Equals(o *GenericDataCentreStatus) bool { - return false + return s.ID == o.ID && + s.State == o.State && + s.CurrentClusterOperationStatus == o.CurrentClusterOperationStatus } func (s *GenericStatus) MaintenanceEventsEqual(events []*v1beta1.ClusteredMaintenanceEventStatus) bool { @@ -37,3 +28,16 @@ func (s *GenericStatus) MaintenanceEventsEqual(events []*v1beta1.ClusteredMainte return true } + +type GenericDataCentreStatus struct { + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Status string `json:"status,omitempty"` + ResizeOperations []*ResizeOperation `json:"resizeOperations,omitempty"` +} + +func (s *GenericDataCentreStatus) Equals(o *GenericDataCentreStatus) bool { + return s.Name == o.Name && + s.Status == o.Status && + s.ID == o.ID +} diff --git a/apis/clusters/v1beta1/opensearch_types.go b/apis/clusters/v1beta1/opensearch_types.go index 27a0ab1ff..a4c15e306 100644 --- a/apis/clusters/v1beta1/opensearch_types.go +++ b/apis/clusters/v1beta1/opensearch_types.go @@ -615,7 +615,7 @@ func (s *OpenSearchDataCentreStatus) Equals(o *OpenSearchDataCentreStatus) bool for _, k8sNode := range s.Nodes { for _, instaNode := range o.Nodes { - if !k8sNode.Equals(&instaNode) { + if k8sNode.ID == instaNode.ID && !k8sNode.Equals(&instaNode) { return false } } @@ -635,7 +635,7 @@ func (oss *OpenSearchStatus) DataCentreEquals(s *OpenSearchStatus) bool { for _, k8sDC := range oss.DataCentres { for _, iDC := range s.DataCentres { - if !k8sDC.Equals(&iDC) { + if k8sDC.ID == iDC.ID && !k8sDC.Equals(&iDC) { return false } } @@ -645,7 +645,7 @@ func (oss *OpenSearchStatus) DataCentreEquals(s *OpenSearchStatus) bool { } func (oss *OpenSearchStatus) Equals(o *OpenSearchStatus) bool { - return oss.ID != o.ID && + return oss.ID == o.ID && oss.State == o.State && oss.CurrentClusterOperationStatus == o.CurrentClusterOperationStatus && oss.PublicEndpoint == o.PublicEndpoint && diff --git a/apis/clusters/v1beta1/opensearch_types_test.go b/apis/clusters/v1beta1/opensearch_types_test.go new file mode 100644 index 000000000..0f7cd357b --- /dev/null +++ b/apis/clusters/v1beta1/opensearch_types_test.go @@ -0,0 +1,182 @@ +package v1beta1 + +import ( + "testing" +) + +func TestOpenSearchStatus_Equals(t *testing.T) { + tests := map[string]struct { + fields OpenSearchStatus + args OpenSearchStatus + want bool + }{ + "Equal Empty Objects": { + fields: OpenSearchStatus{}, + args: OpenSearchStatus{}, + want: true, + }, + "Different LoadBalancerConnectionURL": { + fields: OpenSearchStatus{LoadBalancerConnectionURL: ""}, + args: OpenSearchStatus{LoadBalancerConnectionURL: "http://loadbalancer1"}, + want: false, + }, + "Different PrivateEndpoint": { + fields: OpenSearchStatus{PrivateEndpoint: ""}, + args: OpenSearchStatus{PrivateEndpoint: "http://private1"}, + want: false, + }, + "Different PublicEndpoint": { + fields: OpenSearchStatus{PublicEndpoint: ""}, + args: OpenSearchStatus{PublicEndpoint: "http://public1"}, + want: false, + }, + "Different IngestNodesLoadBalancerConnectionURL": { + fields: OpenSearchStatus{IngestNodesLoadBalancerConnectionURL: ""}, + args: OpenSearchStatus{IngestNodesLoadBalancerConnectionURL: "http://ingest1"}, + want: false, + }, + + "Different GenericStatus ID": { + fields: OpenSearchStatus{GenericStatus: GenericStatus{ID: ""}}, + args: OpenSearchStatus{GenericStatus: GenericStatus{ID: "1"}}, + want: false, + }, + "Different GenericStatus State": { + fields: OpenSearchStatus{GenericStatus: GenericStatus{State: "PROVISIONING"}}, + args: OpenSearchStatus{GenericStatus: GenericStatus{State: "RUNNING"}}, + want: false, + }, + "Different GenericStatus CurrentClusterOperationStatus": { + fields: OpenSearchStatus{GenericStatus: GenericStatus{CurrentClusterOperationStatus: "NO_OPERATION"}}, + args: OpenSearchStatus{GenericStatus: GenericStatus{CurrentClusterOperationStatus: "OPERATION_IN_PROGRESS"}}, + want: false, + }, + + "Different DataCentre ID": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{GenericDataCentreStatus: GenericDataCentreStatus{ID: ""}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{GenericDataCentreStatus: GenericDataCentreStatus{ID: "dc1"}}}}, + want: false, + }, + "Different DataCentre Name": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{GenericDataCentreStatus: GenericDataCentreStatus{Name: ""}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{GenericDataCentreStatus: GenericDataCentreStatus{Name: "DataCentre1"}}}}, + want: false, + }, + "Different DataCentre Status": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{GenericDataCentreStatus: GenericDataCentreStatus{Status: "PROVISIONING"}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{GenericDataCentreStatus: GenericDataCentreStatus{Status: "RUNNING"}}}}, + want: false, + }, + + "Different Node PublicEndpoint": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{PublicEndpoint: ""}}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{PublicEndpoint: "http://public.node1"}}}}}, + want: false, + }, + "Different Node PrivateEndpoint": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{PrivateEndpoint: ""}}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{PrivateEndpoint: "http://private.node1"}}}}}, + want: false, + }, + "Different Node PrivateLinkConnectionURL": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{PrivateLinkConnectionURL: ""}}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{PrivateLinkConnectionURL: "http://privatelink.node1"}}}}}, + want: false, + }, + + "Different Node ID": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{ID: "node1"}}}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{ID: "node2"}}}}}}, + want: false, + }, + "Different Node Size": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{Size: "large"}}}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{Size: "small"}}}}}}, + want: false, + }, + "Different Node PublicAddress": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{PublicAddress: ""}}}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{PublicAddress: "192.168.1.2"}}}}}}, + want: false, + }, + "Different Node PrivateAddress": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{PrivateAddress: ""}}}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{PrivateAddress: "10.0.0.2"}}}}}}, + want: false, + }, + "Different Node Status": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{Status: "PROVISIONING"}}}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{Status: "RUNNING"}}}}}}, + want: false, + }, + "Different Node Roles": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{Roles: []string{""}}}}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{Roles: []string{"MASTER"}}}}}}}, + want: false, + }, + "Different Node Rack": { + fields: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{Rack: ""}}}}}}, + args: OpenSearchStatus{DataCentres: []OpenSearchDataCentreStatus{{Nodes: []OpenSearchNodeStatus{{Node: Node{Rack: "rack1"}}}}}}, + want: false, + }, + + "Different OpenSearchNodeStatus PublicEndpoint": { + fields: OpenSearchStatus{ + DataCentres: []OpenSearchDataCentreStatus{ + {Nodes: []OpenSearchNodeStatus{{PublicEndpoint: ""}}}, + }, + }, + args: OpenSearchStatus{ + DataCentres: []OpenSearchDataCentreStatus{ + {Nodes: []OpenSearchNodeStatus{{PublicEndpoint: "http://public.node1"}}}, + }, + }, + want: false, + }, + "Different OpenSearchNodeStatus PrivateEndpoint": { + fields: OpenSearchStatus{ + DataCentres: []OpenSearchDataCentreStatus{ + {Nodes: []OpenSearchNodeStatus{{PrivateEndpoint: ""}}}, + }, + }, + args: OpenSearchStatus{ + DataCentres: []OpenSearchDataCentreStatus{ + {Nodes: []OpenSearchNodeStatus{{PrivateEndpoint: "http://private.node1"}}}, + }, + }, + want: false, + }, + "Different OpenSearchNodeStatus PrivateLinkConnectionURL": { + fields: OpenSearchStatus{ + DataCentres: []OpenSearchDataCentreStatus{ + {Nodes: []OpenSearchNodeStatus{{PrivateLinkConnectionURL: ""}}}, + }, + }, + args: OpenSearchStatus{ + DataCentres: []OpenSearchDataCentreStatus{ + {Nodes: []OpenSearchNodeStatus{{PrivateLinkConnectionURL: "http://privatelink.node1"}}}, + }, + }, + want: false, + }, + } + + for name, tt := range tests { + tt := tt + + t.Run(name, func(t *testing.T) { + //t.Parallel() + oss := &OpenSearchStatus{ + GenericStatus: tt.fields.GenericStatus, + DataCentres: tt.fields.DataCentres, + LoadBalancerConnectionURL: tt.fields.LoadBalancerConnectionURL, + PrivateEndpoint: tt.fields.PrivateEndpoint, + PublicEndpoint: tt.fields.PublicEndpoint, + IngestNodesLoadBalancerConnectionURL: tt.fields.IngestNodesLoadBalancerConnectionURL, + } + if got := oss.Equals(&tt.args); got != tt.want { + t.Errorf("Equals() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/config/samples/clusters_v1beta1_opensearch.yaml b/config/samples/clusters_v1beta1_opensearch.yaml index e60317a99..49b96daa9 100644 --- a/config/samples/clusters_v1beta1_opensearch.yaml +++ b/config/samples/clusters_v1beta1_opensearch.yaml @@ -55,4 +55,63 @@ spec: sqlPlugin: false # resizeSettings: # - notifySupportContacts: false +# concurrency: 3 +--- +#apiVersion: clusters.instaclustr.com/v1beta1 +#kind: OpenSearch +#metadata: +# labels: +# app.kubernetes.io/name: opensearch +# app.kubernetes.io/instance: opensearch-sample +# app.kubernetes.io/part-of: operator +# app.kuberentes.io/managed-by: kustomize +# app.kubernetes.io/created-by: operator +# name: opensearch-sample2 +# annotations: +# test.annotation/first: testAnnotation +#spec: +# name: bohdan-test-2 +# alertingPlugin: false +# anomalyDetectionPlugin: false +# asynchronousSearchPlugin: false +# # userRefs: +# # - name: "test-user-1" +# # namespace: "default" +# # - name: "test-user-2" +# # namespace: "default" +# clusterManagerNodes: +# - dedicatedManager: false +# nodeSize: SRH-DEV-t4g.small-5 +## nodeSize: SRH-PRD-c5d.2xlarge-200 +# dataCentres: +# - cloudProvider: AWS_VPC +# name: AWS_VPC_US_EAST_1 +# network: 10.0.0.0/16 +# replicationFactor: 3 +# privateLink: false +# region: US_EAST_1 +# # ingestNodes: +# ## - nodeSize: SRH-DI-PRD-m6g.large-10 +# # - nodeSize: SRH-DI-PRD-m6g.xlarge-10 +# # nodeCount: 3 +# # dataNodes: +# # - nodeNumber: 3 +# # nodeSize: SRH-DEV-t4g.small-5 +# icuPlugin: false +# indexManagementPlugin: true +# knnPlugin: false +# loadBalancer: true +# notificationsPlugin: false +# # opensearchDashboards: +# # - nodeSize: SRH-DEV-t4g.small-5 +# # oidcProvider: '' +# # version: opensearch-dashboards:2.5.0 +# version: 2.11.1 +# pciCompliance: false +# privateNetworkCluster: false +# reportingPlugin: false +# slaTier: NON_PRODUCTION +# sqlPlugin: false +## resizeSettings: +## - notifySupportContacts: false # concurrency: 3 \ No newline at end of file diff --git a/controllers/clusters/opensearch_controller.go b/controllers/clusters/opensearch_controller.go index 396fea6fb..aca8e90ef 100644 --- a/controllers/clusters/opensearch_controller.go +++ b/controllers/clusters/opensearch_controller.go @@ -608,7 +608,7 @@ func (r *OpenSearchReconciler) startUsersCreationJob(cluster *v1beta1.OpenSearch } func (r *OpenSearchReconciler) newWatchStatusJob(o *v1beta1.OpenSearch) scheduler.Job { - l := log.Log.WithValues("component", "openSearchStatusClusterJob") + l := log.Log.WithValues("openSearchStatusJob", o.GetJobID(scheduler.StatusChecker)) return func() error { namespacedName := client.ObjectKeyFromObject(o) err := r.Get(context.Background(), namespacedName, o) @@ -651,7 +651,8 @@ func (r *OpenSearchReconciler) newWatchStatusJob(o *v1beta1.OpenSearch) schedule return err } - + o.Status.MaintenanceEvents = nil + //if !reflect.DeepEqual(&iO.Status, &o.Status) { if !iO.Status.Equals(&o.Status) { l.Info("Updating OpenSearch cluster status", "old", o.Status, "new", iO.Status) @@ -697,45 +698,6 @@ func (r *OpenSearchReconciler) newWatchStatusJob(o *v1beta1.OpenSearch) schedule } } - //if !areStatusesEqual(&iO.Status.ClusterStatus, &o.Status.ClusterStatus) { - // l.Info("Updating OpenSearch cluster status", - // "new status", iO.Status.ClusterStatus, - // "old status", o.Status.ClusterStatus, - // ) - // - // areDCsEqual := areDataCentresEqual(iO.Status.ClusterStatus.DataCentres, o.Status.ClusterStatus.DataCentres) - // - // patch := o.NewPatch() - // o.Status.ClusterStatus = iO.Status.ClusterStatus - // err = r.Status().Patch(context.Background(), o, patch) - // if err != nil { - // l.Error(err, "Cannot patch OpenSearch cluster", - // "cluster name", o.Spec.Name, - // "status", o.Status.State, - // ) - // - // return err - // } - // - // if !areDCsEqual { - // var nodes []*v1beta1.Node - // - // for _, dc := range iO.Status.ClusterStatus.DataCentres { - // nodes = append(nodes, dc.Nodes...) - // } - // - // err = exposeservice.Create(r.Client, - // o.Name, - // o.Namespace, - // o.Spec.PrivateNetworkCluster, - // nodes, - // models.OpenSearchConnectionPort) - // if err != nil { - // return err - // } - // } - //} - if iO.Status.CurrentClusterOperationStatus == models.NoOperation && o.Annotations[models.UpdateQueuedAnnotation] != models.True && !o.Spec.IsEqual(iO.Spec) { diff --git a/pkg/instaclustr/client.go b/pkg/instaclustr/client.go index 80a0ba746..dd93f00b1 100644 --- a/pkg/instaclustr/client.go +++ b/pkg/instaclustr/client.go @@ -1533,6 +1533,10 @@ func (c *Client) FetchMaintenanceEventStatuses( return nil, err } + if len(inProgressMEStatus) == 0 && len(pastMEStatus) == 0 && len(upcomingMEStatus) == 0 { + return nil, nil + } + iMEStatuses := []*clusterresourcesv1beta1.ClusteredMaintenanceEventStatus{ { InProgress: inProgressMEStatus,