From d2ec9ae37e1d25dca33f1a246b07d00d540eace0 Mon Sep 17 00:00:00 2001 From: testisnullus Date: Wed, 13 Sep 2023 13:29:03 +0300 Subject: [PATCH] Maintenance Events resource was transfered to APIv2 --- .../v1beta1/maintenanceevents_types.go | 60 ++--- .../v1beta1/maintenanceevents_webhook.go | 16 +- .../v1beta1/zz_generated.deepcopy.go | 74 ++++-- apis/clusters/v1beta1/structs.go | 119 +++++----- .../clusters/v1beta1/zz_generated.deepcopy.go | 70 ++++-- ...ces.instaclustr.com_maintenanceevents.yaml | 36 ++- .../clusters.instaclustr.com_cadences.yaml | 101 +++++++-- .../clusters.instaclustr.com_cassandras.yaml | 99 ++++++-- ...lusters.instaclustr.com_kafkaconnects.yaml | 99 ++++++-- .../clusters.instaclustr.com_kafkas.yaml | 100 +++++++-- ...clusters.instaclustr.com_opensearches.yaml | 99 ++++++-- .../clusters.instaclustr.com_postgresqls.yaml | 99 ++++++-- .../bases/clusters.instaclustr.com_redis.yaml | 99 ++++++-- .../clusters.instaclustr.com_zookeepers.yaml | 99 ++++++-- ...erresources_v1beta1_maintenanceevents.yaml | 14 +- .../samples/clusters_v1beta1_postgresql.yaml | 2 +- .../maintenanceevents_controller.go | 212 ++++-------------- controllers/clusters/cadence_controller.go | 50 +++-- controllers/clusters/cassandra_controller.go | 50 +++-- controllers/clusters/kafka_controller.go | 50 +++-- .../clusters/kafkaconnect_controller.go | 50 +++-- controllers/clusters/opensearch_controller.go | 56 ++--- controllers/clusters/postgresql_controller.go | 56 ++--- controllers/clusters/redis_controller.go | 50 +++-- controllers/clusters/zookeeper_controller.go | 50 +++-- pkg/instaclustr/client.go | 67 +++--- pkg/instaclustr/config.go | 6 +- pkg/instaclustr/interfaces.go | 6 +- pkg/instaclustr/mock/client.go | 14 +- pkg/models/operator.go | 6 + 30 files changed, 1237 insertions(+), 672 deletions(-) diff --git a/apis/clusterresources/v1beta1/maintenanceevents_types.go b/apis/clusterresources/v1beta1/maintenanceevents_types.go index 60fd1dfa5..2c59bd541 100644 --- a/apis/clusterresources/v1beta1/maintenanceevents_types.go +++ b/apis/clusterresources/v1beta1/maintenanceevents_types.go @@ -17,27 +17,24 @@ limitations under the License. package v1beta1 import ( - "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/instaclustr/operator/pkg/validation" ) -type MaintenanceEventRescheduleSpec struct { - ScheduledStartTime string `json:"scheduledStartTime"` - ScheduleID string `json:"scheduleId"` -} - // MaintenanceEventsSpec defines the desired state of MaintenanceEvents type MaintenanceEventsSpec struct { - ClusterID string `json:"clusterId"` - MaintenanceEventsReschedules []*MaintenanceEventRescheduleSpec `json:"maintenanceEventsReschedule,omitempty"` + ClusterID string `json:"clusterId"` + MaintenanceEventsReschedules []*MaintenanceEventReschedule `json:"maintenanceEventsReschedule"` } // MaintenanceEventsStatus defines the observed state of MaintenanceEvents type MaintenanceEventsStatus struct { - EventsStatuses []*MaintenanceEventStatus `json:"eventsStatuses,omitempty"` + CurrentRescheduledEvent MaintenanceEventReschedule `json:"currentRescheduledEvent"` +} + +type MaintenanceEventReschedule struct { + ScheduledStartTime string `json:"scheduledStartTime"` + MaintenanceEventID string `json:"maintenanceEventId"` } type MaintenanceEventStatus struct { @@ -47,7 +44,16 @@ type MaintenanceEventStatus struct { ScheduledEndTime string `json:"scheduledEndTime,omitempty"` ScheduledStartTimeMin string `json:"scheduledStartTimeMin,omitempty"` ScheduledStartTimeMax string `json:"scheduledStartTimeMax,omitempty"` - IsFinalized bool `json:"isFinalized,omitempty"` + IsFinalized bool `json:"isFinalized"` + StartTime string `json:"startTime,omitempty"` + EndTime string `json:"endTime,omitempty"` + Outcome string `json:"outcome,omitempty"` +} + +type ClusteredMaintenanceEventStatus struct { + InProgress []*MaintenanceEventStatus `json:"inProgress"` + Past []*MaintenanceEventStatus `json:"past"` + Upcoming []*MaintenanceEventStatus `json:"upcoming"` } //+kubebuilder:object:root=true @@ -80,36 +86,6 @@ func (me *MaintenanceEvents) NewPatch() client.Patch { return client.MergeFrom(old) } -func (me *MaintenanceEvents) AreMEventsStatusesEqual(instMEventsStatuses []*MaintenanceEventStatus) bool { - if len(instMEventsStatuses) != len(me.Status.EventsStatuses) { - return false - } - - for _, instMEvent := range instMEventsStatuses { - for _, k8sMEvent := range me.Status.EventsStatuses { - if instMEvent.ID == k8sMEvent.ID { - if *instMEvent != *k8sMEvent { - return false - } - - break - } - } - } - - return true -} - -func (mes *MaintenanceEventsSpec) ValidateMaintenanceEventsReschedules() error { - for _, event := range mes.MaintenanceEventsReschedules { - if dateValid, err := validation.ValidateISODate(event.ScheduledStartTime); err != nil || !dateValid { - return fmt.Errorf("scheduledStartTime must be provided in an ISO-8601 formatted UTC string: %v", err) - } - } - - return nil -} - func init() { SchemeBuilder.Register(&MaintenanceEvents{}, &MaintenanceEventsList{}) } diff --git a/apis/clusterresources/v1beta1/maintenanceevents_webhook.go b/apis/clusterresources/v1beta1/maintenanceevents_webhook.go index 5c7f8f7a4..ab5314a3c 100644 --- a/apis/clusterresources/v1beta1/maintenanceevents_webhook.go +++ b/apis/clusterresources/v1beta1/maintenanceevents_webhook.go @@ -23,6 +23,8 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + + "github.com/instaclustr/operator/pkg/validation" ) var maintenanceeventslog = logf.Log.WithName("maintenanceevents-resource") @@ -42,7 +44,7 @@ var _ webhook.Validator = &MaintenanceEvents{} func (r *MaintenanceEvents) ValidateCreate() error { maintenanceeventslog.Info("validate create", "name", r.Name) - if err := r.Spec.ValidateMaintenanceEventsReschedules(); err != nil { + if err := r.ValidateMaintenanceEventsReschedules(); err != nil { return fmt.Errorf("maintenance events reschedules validation failed: %v", err) } @@ -57,7 +59,7 @@ func (r *MaintenanceEvents) ValidateUpdate(old runtime.Object) error { return nil } - if err := r.Spec.ValidateMaintenanceEventsReschedules(); err != nil { + if err := r.ValidateMaintenanceEventsReschedules(); err != nil { return fmt.Errorf("maintenance events reschedules validation failed: %v", err) } @@ -71,3 +73,13 @@ func (r *MaintenanceEvents) ValidateDelete() error { // TODO(user): fill in your validation logic upon object deletion. return nil } + +func (r *MaintenanceEvents) ValidateMaintenanceEventsReschedules() error { + for _, event := range r.Spec.MaintenanceEventsReschedules { + if dateValid, err := validation.ValidateISODate(event.ScheduledStartTime); err != nil || !dateValid { + return fmt.Errorf("scheduledStartTime must be provided in an ISO-8601 formatted UTC string: %v", err) + } + } + + return nil +} diff --git a/apis/clusterresources/v1beta1/zz_generated.deepcopy.go b/apis/clusterresources/v1beta1/zz_generated.deepcopy.go index 27a8b69cc..8d51fc7e7 100644 --- a/apis/clusterresources/v1beta1/zz_generated.deepcopy.go +++ b/apis/clusterresources/v1beta1/zz_generated.deepcopy.go @@ -758,6 +758,54 @@ func (in *ClusterNetworkFirewallRuleStatus) DeepCopy() *ClusterNetworkFirewallRu return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusteredMaintenanceEventStatus) DeepCopyInto(out *ClusteredMaintenanceEventStatus) { + *out = *in + if in.InProgress != nil { + in, out := &in.InProgress, &out.InProgress + *out = make([]*MaintenanceEventStatus, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(MaintenanceEventStatus) + **out = **in + } + } + } + if in.Past != nil { + in, out := &in.Past, &out.Past + *out = make([]*MaintenanceEventStatus, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(MaintenanceEventStatus) + **out = **in + } + } + } + if in.Upcoming != nil { + in, out := &in.Upcoming, &out.Upcoming + *out = make([]*MaintenanceEventStatus, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(MaintenanceEventStatus) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusteredMaintenanceEventStatus. +func (in *ClusteredMaintenanceEventStatus) DeepCopy() *ClusteredMaintenanceEventStatus { + if in == nil { + return nil + } + out := new(ClusteredMaintenanceEventStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExclusionWindow) DeepCopyInto(out *ExclusionWindow) { *out = *in @@ -969,16 +1017,16 @@ func (in *GCPVPCPeeringStatus) DeepCopy() *GCPVPCPeeringStatus { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MaintenanceEventRescheduleSpec) DeepCopyInto(out *MaintenanceEventRescheduleSpec) { +func (in *MaintenanceEventReschedule) DeepCopyInto(out *MaintenanceEventReschedule) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MaintenanceEventRescheduleSpec. -func (in *MaintenanceEventRescheduleSpec) DeepCopy() *MaintenanceEventRescheduleSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MaintenanceEventReschedule. +func (in *MaintenanceEventReschedule) DeepCopy() *MaintenanceEventReschedule { if in == nil { return nil } - out := new(MaintenanceEventRescheduleSpec) + out := new(MaintenanceEventReschedule) in.DeepCopyInto(out) return out } @@ -1004,7 +1052,7 @@ func (in *MaintenanceEvents) DeepCopyInto(out *MaintenanceEvents) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) + out.Status = in.Status } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MaintenanceEvents. @@ -1062,11 +1110,11 @@ func (in *MaintenanceEventsSpec) DeepCopyInto(out *MaintenanceEventsSpec) { *out = *in if in.MaintenanceEventsReschedules != nil { in, out := &in.MaintenanceEventsReschedules, &out.MaintenanceEventsReschedules - *out = make([]*MaintenanceEventRescheduleSpec, len(*in)) + *out = make([]*MaintenanceEventReschedule, len(*in)) for i := range *in { if (*in)[i] != nil { in, out := &(*in)[i], &(*out)[i] - *out = new(MaintenanceEventRescheduleSpec) + *out = new(MaintenanceEventReschedule) **out = **in } } @@ -1086,17 +1134,7 @@ func (in *MaintenanceEventsSpec) DeepCopy() *MaintenanceEventsSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MaintenanceEventsStatus) DeepCopyInto(out *MaintenanceEventsStatus) { *out = *in - if in.EventsStatuses != nil { - in, out := &in.EventsStatuses, &out.EventsStatuses - *out = make([]*MaintenanceEventStatus, len(*in)) - for i := range *in { - if (*in)[i] != nil { - in, out := &(*in)[i], &(*out)[i] - *out = new(MaintenanceEventStatus) - **out = **in - } - } - } + out.CurrentRescheduledEvent = in.CurrentRescheduledEvent } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MaintenanceEventsStatus. diff --git a/apis/clusters/v1beta1/structs.go b/apis/clusters/v1beta1/structs.go index da46ff1f8..8f302eac6 100644 --- a/apis/clusters/v1beta1/structs.go +++ b/apis/clusters/v1beta1/structs.go @@ -20,6 +20,7 @@ import ( "encoding/json" "net" + clusterresource "github.com/instaclustr/operator/apis/clusterresources/v1beta1" "github.com/instaclustr/operator/pkg/models" ) @@ -90,24 +91,20 @@ type Cluster struct { } type ClusterStatus struct { - ID string `json:"id,omitempty"` - State string `json:"state,omitempty"` - DataCentres []*DataCentreStatus `json:"dataCentres,omitempty"` - CDCID string `json:"cdcid,omitempty"` - TwoFactorDeleteEnabled bool `json:"twoFactorDeleteEnabled,omitempty"` - Options *Options `json:"options,omitempty"` - CurrentClusterOperationStatus string `json:"currentClusterOperationStatus,omitempty"` - MaintenanceEvents []*MaintenanceEvent `json:"maintenanceEvents,omitempty"` -} - -type MaintenanceEvent struct { - ID string `json:"id,omitempty"` - Description string `json:"description,omitempty"` - ScheduledStartTime string `json:"scheduledStartTime,omitempty"` - ScheduledEndTime string `json:"scheduledEndTime,omitempty"` - ScheduledStartTimeMin string `json:"scheduledStartTimeMin,omitempty"` - ScheduledStartTimeMax string `json:"scheduledStartTimeMax,omitempty"` - IsFinalized bool `json:"isFinalized,omitempty"` + ID string `json:"id,omitempty"` + State string `json:"state,omitempty"` + DataCentres []*DataCentreStatus `json:"dataCentres,omitempty"` + CDCID string `json:"cdcid,omitempty"` + TwoFactorDeleteEnabled bool `json:"twoFactorDeleteEnabled,omitempty"` + Options *Options `json:"options,omitempty"` + CurrentClusterOperationStatus string `json:"currentClusterOperationStatus,omitempty"` + MaintenanceEvents []*clusterresource.ClusteredMaintenanceEventStatus `json:"maintenanceEvents,omitempty"` +} + +type ClusteredMaintenanceEvent struct { + InProgress []*clusterresource.MaintenanceEventStatus `json:"inProgress"` + Past []*clusterresource.MaintenanceEventStatus `json:"past"` + Upcoming []*clusterresource.MaintenanceEventStatus `json:"upcoming"` } type TwoFactorDelete struct { @@ -418,26 +415,70 @@ func (c *Cluster) newImmutableFields() immutableCluster { } } -func (cs *ClusterStatus) AreMaintenanceEventsEqual(iEvents []*MaintenanceEvent) bool { - if len(cs.MaintenanceEvents) != len(iEvents) { +func (cs *ClusterStatus) AreMaintenanceEventStatusesEqual( + iEventStatuses []*clusterresource.ClusteredMaintenanceEventStatus, +) bool { + if len(cs.MaintenanceEvents) != len(iEventStatuses) { return false } - for _, iEvent := range iEvents { - for _, k8sEvent := range cs.MaintenanceEvents { - if iEvent.ID == k8sEvent.ID { - if *iEvent != *k8sEvent { - return false - } + for i := range iEventStatuses { + if !areEventStatusesEqual(iEventStatuses[i], cs.MaintenanceEvents[i]) { + return false + } + } - break - } + return true +} + +func areEventStatusesEqual(a, b *clusterresource.ClusteredMaintenanceEventStatus) bool { + if len(a.Past) != len(b.Past) || + len(a.InProgress) != len(b.InProgress) || + len(a.Upcoming) != len(b.Upcoming) { + return false + } + + for i := range a.Past { + if a.Past[i].ID != b.Past[i].ID { + continue + } + if !areClusteredMaintenanceEventStatusEqual(a.Past[i], b.Past[i]) { + return false + } + } + + for i := range a.InProgress { + if a.InProgress[i].ID != b.InProgress[i].ID { + continue + } + if !areClusteredMaintenanceEventStatusEqual(a.InProgress[i], b.InProgress[i]) { + return false } } + for i := range a.Upcoming { + if a.Upcoming[i].ID != b.Upcoming[i].ID { + continue + } + if !areClusteredMaintenanceEventStatusEqual(a.Upcoming[i], b.Upcoming[i]) { + return false + } + } return true } +func areClusteredMaintenanceEventStatusEqual(a, b *clusterresource.MaintenanceEventStatus) bool { + return a.Description == b.Description && + a.ScheduledStartTime == b.ScheduledStartTime && + a.ScheduledEndTime == b.ScheduledEndTime && + a.ScheduledStartTimeMax == b.ScheduledStartTimeMax && + a.ScheduledStartTimeMin == b.ScheduledStartTimeMin && + a.IsFinalized == b.IsFinalized && + a.StartTime == b.StartTime && + a.EndTime == b.EndTime && + a.Outcome == b.Outcome +} + func (cs *ClusterStatus) DCFromInstAPI(iDC models.DataCentre) *DataCentreStatus { return &DataCentreStatus{ ID: iDC.ID, @@ -535,28 +576,6 @@ func isCloudProviderSettingsEmpty(iDC models.DataCentre) bool { return true } -func (c *Cluster) CloudProviderSettingsFromInstAPIv1(iProviders []*models.ClusterProviderV1) (accountName string, settings []*CloudProviderSettings) { - for _, iProvider := range iProviders { - accountName = iProvider.AccountName - switch iProvider.Name { - case models.AWSVPC: - settings = append(settings, &CloudProviderSettings{ - CustomVirtualNetworkID: iProvider.CustomVirtualNetworkID, - DiskEncryptionKey: iProvider.DiskEncryptionKey, - }) - case models.GCP: - settings = append(settings, &CloudProviderSettings{ - CustomVirtualNetworkID: iProvider.CustomVirtualNetworkID, - }) - case models.AZUREAZ: - settings = append(settings, &CloudProviderSettings{ - ResourceGroup: iProvider.ResourceGroup, - }) - } - } - return -} - func (cs *ClusterStatus) NodesFromInstAPI(iNodes []*models.Node) (nodes []*Node) { for _, iNode := range iNodes { nodes = append(nodes, &Node{ diff --git a/apis/clusters/v1beta1/zz_generated.deepcopy.go b/apis/clusters/v1beta1/zz_generated.deepcopy.go index aeedbf2bb..742eb349a 100644 --- a/apis/clusters/v1beta1/zz_generated.deepcopy.go +++ b/apis/clusters/v1beta1/zz_generated.deepcopy.go @@ -23,6 +23,7 @@ package v1beta1 import ( "encoding/json" + clusterresourcesv1beta1 "github.com/instaclustr/operator/apis/clusterresources/v1beta1" "k8s.io/apimachinery/pkg/runtime" ) @@ -593,12 +594,12 @@ func (in *ClusterStatus) DeepCopyInto(out *ClusterStatus) { } if in.MaintenanceEvents != nil { in, out := &in.MaintenanceEvents, &out.MaintenanceEvents - *out = make([]*MaintenanceEvent, len(*in)) + *out = make([]*clusterresourcesv1beta1.ClusteredMaintenanceEventStatus, len(*in)) for i := range *in { if (*in)[i] != nil { in, out := &(*in)[i], &(*out)[i] - *out = new(MaintenanceEvent) - **out = **in + *out = new(clusterresourcesv1beta1.ClusteredMaintenanceEventStatus) + (*in).DeepCopyInto(*out) } } } @@ -614,6 +615,54 @@ func (in *ClusterStatus) DeepCopy() *ClusterStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusteredMaintenanceEvent) DeepCopyInto(out *ClusteredMaintenanceEvent) { + *out = *in + if in.InProgress != nil { + in, out := &in.InProgress, &out.InProgress + *out = make([]*clusterresourcesv1beta1.MaintenanceEventStatus, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(clusterresourcesv1beta1.MaintenanceEventStatus) + **out = **in + } + } + } + if in.Past != nil { + in, out := &in.Past, &out.Past + *out = make([]*clusterresourcesv1beta1.MaintenanceEventStatus, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(clusterresourcesv1beta1.MaintenanceEventStatus) + **out = **in + } + } + } + if in.Upcoming != nil { + in, out := &in.Upcoming, &out.Upcoming + *out = make([]*clusterresourcesv1beta1.MaintenanceEventStatus, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(clusterresourcesv1beta1.MaintenanceEventStatus) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusteredMaintenanceEvent. +func (in *ClusteredMaintenanceEvent) DeepCopy() *ClusteredMaintenanceEvent { + if in == nil { + return nil + } + out := new(ClusteredMaintenanceEvent) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CustomConnectors) DeepCopyInto(out *CustomConnectors) { *out = *in @@ -1198,21 +1247,6 @@ func (in *Kraft) DeepCopy() *Kraft { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MaintenanceEvent) DeepCopyInto(out *MaintenanceEvent) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MaintenanceEvent. -func (in *MaintenanceEvent) DeepCopy() *MaintenanceEvent { - if in == nil { - return nil - } - out := new(MaintenanceEvent) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ManagedCluster) DeepCopyInto(out *ManagedCluster) { *out = *in diff --git a/config/crd/bases/clusterresources.instaclustr.com_maintenanceevents.yaml b/config/crd/bases/clusterresources.instaclustr.com_maintenanceevents.yaml index 248a0492c..e7a5ce71c 100644 --- a/config/crd/bases/clusterresources.instaclustr.com_maintenanceevents.yaml +++ b/config/crd/bases/clusterresources.instaclustr.com_maintenanceevents.yaml @@ -40,40 +40,34 @@ spec: maintenanceEventsReschedule: items: properties: - scheduleId: + maintenanceEventId: type: string scheduledStartTime: type: string required: - - scheduleId + - maintenanceEventId - scheduledStartTime type: object type: array required: - clusterId + - maintenanceEventsReschedule type: object status: description: MaintenanceEventsStatus defines the observed state of MaintenanceEvents properties: - eventsStatuses: - items: - properties: - description: - type: string - id: - type: string - isFinalized: - type: boolean - scheduledEndTime: - type: string - scheduledStartTime: - type: string - scheduledStartTimeMax: - type: string - scheduledStartTimeMin: - type: string - type: object - type: array + currentRescheduledEvent: + properties: + maintenanceEventId: + type: string + scheduledStartTime: + type: string + required: + - maintenanceEventId + - scheduledStartTime + type: object + required: + - currentRescheduledEvent type: object type: object served: true diff --git a/config/crd/bases/clusters.instaclustr.com_cadences.yaml b/config/crd/bases/clusters.instaclustr.com_cadences.yaml index f87d635d0..ee4025880 100644 --- a/config/crd/bases/clusters.instaclustr.com_cadences.yaml +++ b/config/crd/bases/clusters.instaclustr.com_cadences.yaml @@ -104,6 +104,8 @@ spec: - nodesNumber - region type: object + maxItems: 1 + minItems: 1 type: array description: type: string @@ -334,20 +336,91 @@ spec: maintenanceEvents: items: properties: - description: - type: string - id: - type: string - isFinalized: - type: boolean - scheduledEndTime: - type: string - scheduledStartTime: - type: string - scheduledStartTimeMax: - type: string - scheduledStartTimeMin: - type: string + inProgress: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + past: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + upcoming: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + required: + - inProgress + - past + - upcoming type: object type: array options: diff --git a/config/crd/bases/clusters.instaclustr.com_cassandras.yaml b/config/crd/bases/clusters.instaclustr.com_cassandras.yaml index a53b68e77..cf26549e0 100644 --- a/config/crd/bases/clusters.instaclustr.com_cassandras.yaml +++ b/config/crd/bases/clusters.instaclustr.com_cassandras.yaml @@ -248,20 +248,91 @@ spec: maintenanceEvents: items: properties: - description: - type: string - id: - type: string - isFinalized: - type: boolean - scheduledEndTime: - type: string - scheduledStartTime: - type: string - scheduledStartTimeMax: - type: string - scheduledStartTimeMin: - type: string + inProgress: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + past: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + upcoming: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + required: + - inProgress + - past + - upcoming type: object type: array options: diff --git a/config/crd/bases/clusters.instaclustr.com_kafkaconnects.yaml b/config/crd/bases/clusters.instaclustr.com_kafkaconnects.yaml index 7b1ef9981..d762b6512 100644 --- a/config/crd/bases/clusters.instaclustr.com_kafkaconnects.yaml +++ b/config/crd/bases/clusters.instaclustr.com_kafkaconnects.yaml @@ -303,20 +303,91 @@ spec: maintenanceEvents: items: properties: - description: - type: string - id: - type: string - isFinalized: - type: boolean - scheduledEndTime: - type: string - scheduledStartTime: - type: string - scheduledStartTimeMax: - type: string - scheduledStartTimeMin: - type: string + inProgress: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + past: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + upcoming: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + required: + - inProgress + - past + - upcoming type: object type: array options: diff --git a/config/crd/bases/clusters.instaclustr.com_kafkas.yaml b/config/crd/bases/clusters.instaclustr.com_kafkas.yaml index 07c923f6c..01dd6a5d3 100644 --- a/config/crd/bases/clusters.instaclustr.com_kafkas.yaml +++ b/config/crd/bases/clusters.instaclustr.com_kafkas.yaml @@ -95,6 +95,7 @@ spec: - region type: object maxItems: 1 + minItems: 1 type: array dedicatedZookeeper: description: Provision additional dedicated nodes for Apache Zookeeper @@ -296,20 +297,91 @@ spec: maintenanceEvents: items: properties: - description: - type: string - id: - type: string - isFinalized: - type: boolean - scheduledEndTime: - type: string - scheduledStartTime: - type: string - scheduledStartTimeMax: - type: string - scheduledStartTimeMin: - type: string + inProgress: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + past: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + upcoming: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + required: + - inProgress + - past + - upcoming type: object type: array options: diff --git a/config/crd/bases/clusters.instaclustr.com_opensearches.yaml b/config/crd/bases/clusters.instaclustr.com_opensearches.yaml index e250c4814..fa871171d 100644 --- a/config/crd/bases/clusters.instaclustr.com_opensearches.yaml +++ b/config/crd/bases/clusters.instaclustr.com_opensearches.yaml @@ -282,20 +282,91 @@ spec: maintenanceEvents: items: properties: - description: - type: string - id: - type: string - isFinalized: - type: boolean - scheduledEndTime: - type: string - scheduledStartTime: - type: string - scheduledStartTimeMax: - type: string - scheduledStartTimeMin: - type: string + inProgress: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + past: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + upcoming: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + required: + - inProgress + - past + - upcoming type: object type: array options: diff --git a/config/crd/bases/clusters.instaclustr.com_postgresqls.yaml b/config/crd/bases/clusters.instaclustr.com_postgresqls.yaml index 2d0fa3286..53c25232f 100644 --- a/config/crd/bases/clusters.instaclustr.com_postgresqls.yaml +++ b/config/crd/bases/clusters.instaclustr.com_postgresqls.yaml @@ -246,20 +246,91 @@ spec: maintenanceEvents: items: properties: - description: - type: string - id: - type: string - isFinalized: - type: boolean - scheduledEndTime: - type: string - scheduledStartTime: - type: string - scheduledStartTimeMax: - type: string - scheduledStartTimeMin: - type: string + inProgress: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + past: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + upcoming: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + required: + - inProgress + - past + - upcoming type: object type: array options: diff --git a/config/crd/bases/clusters.instaclustr.com_redis.yaml b/config/crd/bases/clusters.instaclustr.com_redis.yaml index 82ff9c2fd..8ede95292 100644 --- a/config/crd/bases/clusters.instaclustr.com_redis.yaml +++ b/config/crd/bases/clusters.instaclustr.com_redis.yaml @@ -245,20 +245,91 @@ spec: maintenanceEvents: items: properties: - description: - type: string - id: - type: string - isFinalized: - type: boolean - scheduledEndTime: - type: string - scheduledStartTime: - type: string - scheduledStartTimeMax: - type: string - scheduledStartTimeMin: - type: string + inProgress: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + past: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + upcoming: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + required: + - inProgress + - past + - upcoming type: object type: array options: diff --git a/config/crd/bases/clusters.instaclustr.com_zookeepers.yaml b/config/crd/bases/clusters.instaclustr.com_zookeepers.yaml index 0dbff225b..0b96113b3 100644 --- a/config/crd/bases/clusters.instaclustr.com_zookeepers.yaml +++ b/config/crd/bases/clusters.instaclustr.com_zookeepers.yaml @@ -180,20 +180,91 @@ spec: maintenanceEvents: items: properties: - description: - type: string - id: - type: string - isFinalized: - type: boolean - scheduledEndTime: - type: string - scheduledStartTime: - type: string - scheduledStartTimeMax: - type: string - scheduledStartTimeMin: - type: string + inProgress: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + past: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + upcoming: + items: + properties: + description: + type: string + endTime: + type: string + id: + type: string + isFinalized: + type: boolean + outcome: + type: string + scheduledEndTime: + type: string + scheduledStartTime: + type: string + scheduledStartTimeMax: + type: string + scheduledStartTimeMin: + type: string + startTime: + type: string + required: + - isFinalized + type: object + type: array + required: + - inProgress + - past + - upcoming type: object type: array options: diff --git a/config/samples/clusterresources_v1beta1_maintenanceevents.yaml b/config/samples/clusterresources_v1beta1_maintenanceevents.yaml index a4eb00a14..307734950 100644 --- a/config/samples/clusterresources_v1beta1_maintenanceevents.yaml +++ b/config/samples/clusterresources_v1beta1_maintenanceevents.yaml @@ -3,11 +3,9 @@ kind: MaintenanceEvents metadata: name: maintenanceevents-sample spec: - clusterId: "2ae611cf-ac91-4325-941c-a35c043f9c34" - exclusionWindows: - - dayOfWeek: "MONDAY" - startHour: 1 - durationInHours: 1 -# maintenanceEventsReschedule: -# - scheduledStartTime: "2023-03-08T00:00:00Z" -# scheduleId: "0585598f-e672-4bd2-806a-673ba521665c" + clusterId: "9cf09a53-a09e-450a-ba7d-e98b3c724911" + maintenanceEventsReschedule: + - scheduledStartTime: "2023-11-09T04:30:00Z" + maintenanceEventId: "0d25b466-bc22-44a8-b15d-8f92e815cb6e" + - scheduledStartTime: "2023-11-15T06:00:00Z" + maintenanceEventId: "d4806381-cd1e-48df-b9ba-70f9b0829c72" diff --git a/config/samples/clusters_v1beta1_postgresql.yaml b/config/samples/clusters_v1beta1_postgresql.yaml index b92140b4b..30dbb6195 100644 --- a/config/samples/clusters_v1beta1_postgresql.yaml +++ b/config/samples/clusters_v1beta1_postgresql.yaml @@ -7,7 +7,7 @@ metadata: # testAnnotation: test spec: name: "username-test" - version: "14.6.0" + version: "15.4.0" dataCentres: - region: "US_WEST_2" network: "10.1.0.0/16" diff --git a/controllers/clusterresources/maintenanceevents_controller.go b/controllers/clusterresources/maintenanceevents_controller.go index 26afd2e54..01eca05d5 100644 --- a/controllers/clusterresources/maintenanceevents_controller.go +++ b/controllers/clusterresources/maintenanceevents_controller.go @@ -21,12 +21,10 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" @@ -69,204 +67,82 @@ func (r *MaintenanceEventsReconciler) Reconcile(ctx context.Context, req ctrl.Re l.Info("Maintenance Event resource is not found", "request", req, ) - return models.ExitReconcile, nil } - l.Error(err, "Cannot get Maintenance Event resource", "request", req, ) - return models.ReconcileRequeue, nil } - patch := me.NewPatch() - if me.DeletionTimestamp != nil { - r.EventRecorder.Eventf( - me, models.Normal, models.DeletionStarted, - "Exclusion windows deletion request is sent to the Instaclustr API.", - ) - - r.Scheduler.RemoveJob(me.GetJobID(scheduler.StatusChecker)) - controllerutil.RemoveFinalizer(me, models.DeletionFinalizer) - err = r.Patch(ctx, me, patch) + if len(me.Spec.MaintenanceEventsReschedules) == 0 { + err = r.Client.Delete(ctx, me) if err != nil { - l.Error(err, "Cannot patch Maintenance Event resource", - "resource", me, + l.Error(err, + "Cannot delete Maintenance Events resource from K8s cluster", + "Maintenance Events spec", me.Spec, ) - r.EventRecorder.Eventf( - me, models.Warning, models.PatchFailed, - "Resource patch is failed. Reason: %v", + me, models.Warning, models.DeletionFailed, + "Resource deletion is failed. Reason: %v", err, ) return models.ReconcileRequeue, nil } - - return models.ExitReconcile, nil - } - - err = r.reconcileMaintenanceEventsReschedules(me) - if err != nil { - l.Error(err, "Cannot reconcile Maintenance Events Reschedules", - "spec", me.Spec, - ) - r.EventRecorder.Eventf( - me, models.Warning, models.UpdateFailed, - "Maintenance events update is failed. Reason: %v", - err, - ) - return models.ReconcileRequeue, nil - } - - err = r.Status().Patch(ctx, me, patch) - if err != nil { - l.Error(err, "Cannot patch Maintenance Event status", - "status", me.Status, - ) - - r.EventRecorder.Eventf( - me, models.Warning, models.PatchFailed, - "Resource status patch is failed. Reason: %v", - err, - ) - return models.ReconcileRequeue, nil - } - - controllerutil.AddFinalizer(me, models.DeletionFinalizer) - err = r.Patch(ctx, me, patch) - if err != nil { - l.Error(err, "Cannot patch Maintenance Event status", - "status", me.Status, - ) - - r.EventRecorder.Eventf( - me, models.Warning, models.PatchFailed, - "Resource patch is failed. Reason: %v", - err, + me, models.Normal, models.DeletionStarted, + "Resource is deleted.", ) - return models.ReconcileRequeue, nil - } - - err = r.startMaintenanceEventStatusJob(me) - if err != nil { - l.Error(err, "Cannot start Maintenance Event status job", - "spec", me.Spec, + l.Info( + "Maintenance Events were rescheduled, resource was deleted", + "Maintenance Events status", me.Status, ) - - r.EventRecorder.Eventf( - me, models.Warning, models.CreationFailed, - "Resource status check job is failed. Reason: %v", - err, - ) - return models.ReconcileRequeue, nil - } - - r.EventRecorder.Eventf( - me, models.Normal, models.Created, - "Cluster maintenance events check job is started", - ) - - l.Info("Maintenance Event resource was reconciled", - "spec", me.Spec, - "status", me.Status, - ) - - return models.ExitReconcile, nil -} - -func (r *MaintenanceEventsReconciler) startMaintenanceEventStatusJob(me *v1beta1.MaintenanceEvents) error { - job := r.newWatchStatusJob(me) - - err := r.Scheduler.ScheduleJob(me.GetJobID(scheduler.StatusChecker), scheduler.ClusterStatusInterval, job) - if err != nil { - return err + return models.ExitReconcile, nil } - return nil -} + if me.Status.CurrentRescheduledEvent.MaintenanceEventID == "" { + meReschedule := &v1beta1.MaintenanceEventReschedule{ + MaintenanceEventID: me.Spec.MaintenanceEventsReschedules[len(me.Spec.MaintenanceEventsReschedules)-1].MaintenanceEventID, + ScheduledStartTime: me.Spec.MaintenanceEventsReschedules[len(me.Spec.MaintenanceEventsReschedules)-1].ScheduledStartTime, + } -func (r *MaintenanceEventsReconciler) newWatchStatusJob(me *v1beta1.MaintenanceEvents) scheduler.Job { - l := log.Log.WithValues("component", "MaintenanceEventStatusJob") - return func() error { - err := r.Get(context.TODO(), types.NamespacedName{ - Name: me.Name, - Namespace: me.Namespace, - }, me) + err = r.API.RescheduleMaintenanceEvent(meReschedule) if err != nil { - l.Error(err, "Cannot get Maintenance Events resource", - "resource", me, + l.Error(err, + "Cannot start Maintenance Event reschedule process", + "Maintenance Event ID", meReschedule.MaintenanceEventID, ) - - return err + r.EventRecorder.Eventf( + me, models.Warning, models.CreationFailed, + "Resource creation on the Instaclustr is failed. Reason: %v", + err, + ) + return models.ReconcileRequeue, nil } - var updated bool + r.EventRecorder.Eventf( + me, models.Normal, models.Created, + "Resource reschedule request is sent. Maintenance Event ID: %s", + me.Spec.MaintenanceEventsReschedules[len(me.Spec.MaintenanceEventsReschedules)-1].MaintenanceEventID, + ) + patch := me.NewPatch() - instMEventsStatuses, err := r.API.GetMaintenanceEventsStatuses(me.Spec.ClusterID) + me.Spec.MaintenanceEventsReschedules = me.Spec.MaintenanceEventsReschedules[:len(me.Spec.MaintenanceEventsReschedules)-1] + err = r.Patch(ctx, me, patch) if err != nil { - l.Error(err, "Cannot get Maintenance Events statuses", - "resource", me, + l.Error(err, "Cannot patch Maintenance Event", + "spec", me.Spec, ) - - return err - } - - if !me.AreMEventsStatusesEqual(instMEventsStatuses) { - me.Status.EventsStatuses = instMEventsStatuses - updated = true - } - - if updated { - err = r.Status().Patch(context.TODO(), me, patch) - if err != nil { - l.Error(err, "Cannot get Maintenance Events resource status", - "resource", me, - ) - - return err - } - - l.Info("Maintenance Events resource status was updated", - "resource", me, + r.EventRecorder.Eventf( + me, models.Warning, models.PatchFailed, + "Resource patch is failed. Reason: %v", + err, ) + return models.ReconcileRequeue, nil } - return nil - } -} - -func (r *MaintenanceEventsReconciler) reconcileMaintenanceEventsReschedules(mEvents *v1beta1.MaintenanceEvents) error { - var updatedMEventsStatuses []*v1beta1.MaintenanceEventStatus - instMEvents, err := r.API.GetMaintenanceEventsStatuses(mEvents.Spec.ClusterID) - if err != nil { - return err } - - for _, k8sMEvent := range mEvents.Spec.MaintenanceEventsReschedules { - for _, instMEvent := range instMEvents { - if instMEvent.IsFinalized { - updatedMEventsStatuses = append(updatedMEventsStatuses, instMEvent) - - break - } - - if k8sMEvent.ScheduleID == instMEvent.ID && - (k8sMEvent.ScheduledStartTime != instMEvent.ScheduledStartTime) { - updatedMEventStatus, err := r.API.UpdateMaintenanceEvent(*k8sMEvent) - if err != nil { - return err - } - - updatedMEventsStatuses = append(updatedMEventsStatuses, updatedMEventStatus) - } - } - } - - mEvents.Status.EventsStatuses = updatedMEventsStatuses - - return nil + return models.ExitReconcile, nil } // SetupWithManager sets up the controller with the Manager. diff --git a/controllers/clusters/cadence_controller.go b/controllers/clusters/cadence_controller.go index 250f3f691..de4f282f5 100644 --- a/controllers/clusters/cadence_controller.go +++ b/controllers/clusters/cadence_controller.go @@ -904,35 +904,16 @@ func (r *CadenceReconciler) newWatchStatusJob(cadence *v1beta1.Cadence) schedule r.EventRecorder.Eventf(cadence, models.Warning, models.ExternalChanges, msgDiffSpecs) } - maintEvents, err := r.API.GetMaintenanceEvents(cadence.Status.ID) + //TODO: change all context.Background() and context.TODO() to ctx from Reconcile + err = r.reconcileMaintenanceEvents(context.Background(), cadence) if err != nil { - l.Error(err, "Cannot get Cadence cluster maintenance events", + l.Error(err, "Cannot reconcile cluster maintenance events", "cluster name", cadence.Spec.Name, "cluster ID", cadence.Status.ID, ) - return err } - if !cadence.Status.AreMaintenanceEventsEqual(maintEvents) { - patch := cadence.NewPatch() - cadence.Status.MaintenanceEvents = maintEvents - err = r.Status().Patch(context.TODO(), cadence, patch) - if err != nil { - l.Error(err, "Cannot patch Cadence cluster maintenance events", - "cluster name", cadence.Spec.Name, - "cluster ID", cadence.Status.ID, - ) - - return err - } - - l.Info("Cadence cluster maintenance events were updated", - "cluster ID", cadence.Status.ID, - "events", cadence.Status.MaintenanceEvents, - ) - } - return nil } } @@ -1241,3 +1222,28 @@ func (r *CadenceReconciler) SetupWithManager(mgr ctrl.Manager) error { })). Complete(r) } + +func (r *CadenceReconciler) reconcileMaintenanceEvents(ctx context.Context, c *v1beta1.Cadence) error { + l := log.FromContext(ctx) + + iMEStatuses, err := r.API.FetchMaintenanceEventStatuses(c.Status.ID) + if err != nil { + return err + } + + if !c.Status.AreMaintenanceEventStatusesEqual(iMEStatuses) { + patch := c.NewPatch() + c.Status.MaintenanceEvents = iMEStatuses + err = r.Status().Patch(ctx, c, patch) + if err != nil { + return err + } + + l.Info("Cluster maintenance events were reconciled", + "cluster ID", c.Status.ID, + "events", c.Status.MaintenanceEvents, + ) + } + + return nil +} diff --git a/controllers/clusters/cassandra_controller.go b/controllers/clusters/cassandra_controller.go index 42c8a0576..c4c832618 100644 --- a/controllers/clusters/cassandra_controller.go +++ b/controllers/clusters/cassandra_controller.go @@ -994,35 +994,16 @@ func (r *CassandraReconciler) newWatchStatusJob(cassandra *v1beta1.Cassandra) sc r.EventRecorder.Eventf(cassandra, models.Warning, models.ExternalChanges, msgDiffSpecs) } - maintEvents, err := r.API.GetMaintenanceEvents(cassandra.Status.ID) + //TODO: change all context.Background() and context.TODO() to ctx from Reconcile + err = r.reconcileMaintenanceEvents(context.Background(), cassandra) if err != nil { - l.Error(err, "Cannot get cluster maintenance events", + l.Error(err, "Cannot reconcile cluster maintenance events", "cluster name", cassandra.Spec.Name, "cluster ID", cassandra.Status.ID, ) - return err } - if !cassandra.Status.AreMaintenanceEventsEqual(maintEvents) { - patch := cassandra.NewPatch() - cassandra.Status.MaintenanceEvents = maintEvents - err = r.Status().Patch(context.TODO(), cassandra, patch) - if err != nil { - l.Error(err, "Cannot patch cluster maintenance events", - "cluster name", cassandra.Spec.Name, - "cluster ID", cassandra.Status.ID, - ) - - return err - } - - l.Info("Cluster maintenance events were updated", - "cluster ID", cassandra.Status.ID, - "events", cassandra.Status.MaintenanceEvents, - ) - } - return nil } } @@ -1224,6 +1205,31 @@ func (r *CassandraReconciler) deleteBackups(ctx context.Context, clusterID, name return nil } +func (r *CassandraReconciler) reconcileMaintenanceEvents(ctx context.Context, c *v1beta1.Cassandra) error { + l := log.FromContext(ctx) + + iMEStatuses, err := r.API.FetchMaintenanceEventStatuses(c.Status.ID) + if err != nil { + return err + } + + if !c.Status.AreMaintenanceEventStatusesEqual(iMEStatuses) { + patch := c.NewPatch() + c.Status.MaintenanceEvents = iMEStatuses + err = r.Status().Patch(ctx, c, patch) + if err != nil { + return err + } + + l.Info("Cluster maintenance events were reconciled", + "cluster ID", c.Status.ID, + "events", c.Status.MaintenanceEvents, + ) + } + + return nil +} + // SetupWithManager sets up the controller with the Manager. func (r *CassandraReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). diff --git a/controllers/clusters/kafka_controller.go b/controllers/clusters/kafka_controller.go index 9af9c5954..5d552ae2b 100644 --- a/controllers/clusters/kafka_controller.go +++ b/controllers/clusters/kafka_controller.go @@ -753,35 +753,16 @@ func (r *KafkaReconciler) newWatchStatusJob(kafka *v1beta1.Kafka) scheduler.Job r.EventRecorder.Eventf(kafka, models.Warning, models.ExternalChanges, msgDiffSpecs) } - maintEvents, err := r.API.GetMaintenanceEvents(kafka.Status.ID) + //TODO: change all context.Background() and context.TODO() to ctx from Reconcile + err = r.reconcileMaintenanceEvents(context.Background(), kafka) if err != nil { - l.Error(err, "Cannot get cluster maintenance events", + l.Error(err, "Cannot reconcile cluster maintenance events", "cluster name", kafka.Spec.Name, "cluster ID", kafka.Status.ID, ) - return err } - if !kafka.Status.AreMaintenanceEventsEqual(maintEvents) { - patch := kafka.NewPatch() - kafka.Status.MaintenanceEvents = maintEvents - err = r.Status().Patch(context.TODO(), kafka, patch) - if err != nil { - l.Error(err, "Cannot patch cluster maintenance events", - "cluster name", kafka.Spec.Name, - "cluster ID", kafka.Status.ID, - ) - - return err - } - - l.Info("Cluster maintenance events were updated", - "cluster ID", kafka.Status.ID, - "events", kafka.Status.MaintenanceEvents, - ) - } - return nil } } @@ -945,3 +926,28 @@ func (r *KafkaReconciler) SetupWithManager(mgr ctrl.Manager) error { }, })).Complete(r) } + +func (r *KafkaReconciler) reconcileMaintenanceEvents(ctx context.Context, k *v1beta1.Kafka) error { + l := log.FromContext(ctx) + + iMEStatuses, err := r.API.FetchMaintenanceEventStatuses(k.Status.ID) + if err != nil { + return err + } + + if !k.Status.AreMaintenanceEventStatusesEqual(iMEStatuses) { + patch := k.NewPatch() + k.Status.MaintenanceEvents = iMEStatuses + err = r.Status().Patch(ctx, k, patch) + if err != nil { + return err + } + + l.Info("Cluster maintenance events were reconciled", + "cluster ID", k.Status.ID, + "events", k.Status.MaintenanceEvents, + ) + } + + return nil +} diff --git a/controllers/clusters/kafkaconnect_controller.go b/controllers/clusters/kafkaconnect_controller.go index 3af39fb4b..f5915eade 100644 --- a/controllers/clusters/kafkaconnect_controller.go +++ b/controllers/clusters/kafkaconnect_controller.go @@ -572,35 +572,16 @@ func (r *KafkaConnectReconciler) newWatchStatusJob(kc *v1beta1.KafkaConnect) sch r.EventRecorder.Eventf(kc, models.Warning, models.ExternalChanges, msgDiffSpecs) } - maintEvents, err := r.API.GetMaintenanceEvents(kc.Status.ID) + //TODO: change all context.Background() and context.TODO() to ctx from Reconcile + err = r.reconcileMaintenanceEvents(context.Background(), kc) if err != nil { - l.Error(err, "Cannot get Kafka Connect cluster maintenance events", + l.Error(err, "Cannot reconcile cluster maintenance events", "cluster name", kc.Spec.Name, "cluster ID", kc.Status.ID, ) - return err } - if !kc.Status.AreMaintenanceEventsEqual(maintEvents) { - patch := kc.NewPatch() - kc.Status.MaintenanceEvents = maintEvents - err = r.Status().Patch(context.TODO(), kc, patch) - if err != nil { - l.Error(err, "Cannot patch Kafka Connect cluster maintenance events", - "cluster name", kc.Spec.Name, - "cluster ID", kc.Status.ID, - ) - - return err - } - - l.Info("Kafka Connect cluster maintenance events were updated", - "cluster ID", kc.Status.ID, - "events", kc.Status.MaintenanceEvents, - ) - } - return nil } } @@ -644,3 +625,28 @@ func (r *KafkaConnectReconciler) SetupWithManager(mgr ctrl.Manager) error { }, })).Complete(r) } + +func (r *KafkaConnectReconciler) reconcileMaintenanceEvents(ctx context.Context, kc *v1beta1.KafkaConnect) error { + l := log.FromContext(ctx) + + iMEStatuses, err := r.API.FetchMaintenanceEventStatuses(kc.Status.ID) + if err != nil { + return err + } + + if !kc.Status.AreMaintenanceEventStatusesEqual(iMEStatuses) { + patch := kc.NewPatch() + kc.Status.MaintenanceEvents = iMEStatuses + err = r.Status().Patch(ctx, kc, patch) + if err != nil { + return err + } + + l.Info("Cluster maintenance events were reconciled", + "cluster ID", kc.Status.ID, + "events", kc.Status.MaintenanceEvents, + ) + } + + return nil +} diff --git a/controllers/clusters/opensearch_controller.go b/controllers/clusters/opensearch_controller.go index dcbcd887b..c28508794 100644 --- a/controllers/clusters/opensearch_controller.go +++ b/controllers/clusters/opensearch_controller.go @@ -682,16 +682,6 @@ func (r *OpenSearchReconciler) newWatchStatusJob(o *v1beta1.OpenSearch) schedule } } - maintEvents, err := r.API.GetMaintenanceEvents(o.Status.ID) - if err != nil { - l.Error(err, "Cannot get OpenSearch cluster maintenance events", - "cluster name", o.Spec.Name, - "cluster ID", o.Status.ID, - ) - - return err - } - if iO.Status.CurrentClusterOperationStatus == models.NoOperation && o.Annotations[models.UpdateQueuedAnnotation] != models.True && !o.Spec.IsEqual(iO.Spec) { @@ -717,23 +707,14 @@ func (r *OpenSearchReconciler) newWatchStatusJob(o *v1beta1.OpenSearch) schedule r.EventRecorder.Eventf(o, models.Warning, models.ExternalChanges, msgDiffSpecs) } - if !o.Status.AreMaintenanceEventsEqual(maintEvents) { - patch := o.NewPatch() - o.Status.MaintenanceEvents = maintEvents - err = r.Status().Patch(context.TODO(), o, patch) - if err != nil { - l.Error(err, "Cannot patch OpenSearch cluster maintenance events", - "cluster name", o.Spec.Name, - "cluster ID", o.Status.ID, - ) - - return err - } - - l.Info("OpenSearch cluster maintenance events were updated", + //TODO: change all context.Background() and context.TODO() to ctx from Reconcile + err = r.reconcileMaintenanceEvents(context.Background(), o) + if err != nil { + l.Error(err, "Cannot reconcile cluster maintenance events", + "cluster name", o.Spec.Name, "cluster ID", o.Status.ID, - "events", o.Status.MaintenanceEvents, ) + return err } return nil @@ -1206,3 +1187,28 @@ func (r *OpenSearchReconciler) SetupWithManager(mgr ctrl.Manager) error { })). Complete(r) } + +func (r *OpenSearchReconciler) reconcileMaintenanceEvents(ctx context.Context, o *v1beta1.OpenSearch) error { + l := log.FromContext(ctx) + + iMEStatuses, err := r.API.FetchMaintenanceEventStatuses(o.Status.ID) + if err != nil { + return err + } + + if !o.Status.AreMaintenanceEventStatusesEqual(iMEStatuses) { + patch := o.NewPatch() + o.Status.MaintenanceEvents = iMEStatuses + err = r.Status().Patch(ctx, o, patch) + if err != nil { + return err + } + + l.Info("Cluster maintenance events were reconciled", + "cluster ID", o.Status.ID, + "events", o.Status.MaintenanceEvents, + ) + } + + return nil +} diff --git a/controllers/clusters/postgresql_controller.go b/controllers/clusters/postgresql_controller.go index 64e538d5e..c0dbc60f3 100644 --- a/controllers/clusters/postgresql_controller.go +++ b/controllers/clusters/postgresql_controller.go @@ -901,16 +901,6 @@ func (r *PostgreSQLReconciler) newWatchStatusJob(pg *v1beta1.PostgreSQL) schedul } } - maintEvents, err := r.API.GetMaintenanceEvents(pg.Status.ID) - if err != nil { - l.Error(err, "Cannot get PostgreSQL cluster maintenance events", - "cluster name", pg.Spec.Name, - "cluster ID", pg.Status.ID, - ) - - return err - } - if iPg.Status.CurrentClusterOperationStatus == models.NoOperation && pg.Annotations[models.UpdateQueuedAnnotation] != models.True && !pg.Spec.IsEqual(iPg.Spec) { @@ -935,23 +925,14 @@ func (r *PostgreSQLReconciler) newWatchStatusJob(pg *v1beta1.PostgreSQL) schedul r.EventRecorder.Eventf(pg, models.Warning, models.ExternalChanges, msgDiffSpecs) } - if !pg.Status.AreMaintenanceEventsEqual(maintEvents) { - patch := pg.NewPatch() - pg.Status.MaintenanceEvents = maintEvents - err = r.Status().Patch(context.TODO(), pg, patch) - if err != nil { - l.Error(err, "Cannot patch PostgreSQL cluster maintenance events", - "cluster name", pg.Spec.Name, - "cluster ID", pg.Status.ID, - ) - - return err - } - - l.Info("PostgreSQL cluster maintenance events were updated", + //TODO: change all context.Background() and context.TODO() to ctx from Reconcile + err = r.reconcileMaintenanceEvents(context.Background(), pg) + if err != nil { + l.Error(err, "Cannot reconcile cluster maintenance events", + "cluster name", pg.Spec.Name, "cluster ID", pg.Status.ID, - "events", pg.Status.MaintenanceEvents, ) + return err } return nil @@ -1394,3 +1375,28 @@ func (r *PostgreSQLReconciler) SetupWithManager(mgr ctrl.Manager) error { ). Complete(r) } + +func (r *PostgreSQLReconciler) reconcileMaintenanceEvents(ctx context.Context, pg *v1beta1.PostgreSQL) error { + l := log.FromContext(ctx) + + iMEStatuses, err := r.API.FetchMaintenanceEventStatuses(pg.Status.ID) + if err != nil { + return err + } + + if !pg.Status.AreMaintenanceEventStatusesEqual(iMEStatuses) { + patch := pg.NewPatch() + pg.Status.MaintenanceEvents = iMEStatuses + err = r.Status().Patch(ctx, pg, patch) + if err != nil { + return err + } + + l.Info("Cluster maintenance events were reconciled", + "cluster ID", pg.Status.ID, + "events", pg.Status.MaintenanceEvents, + ) + } + + return nil +} diff --git a/controllers/clusters/redis_controller.go b/controllers/clusters/redis_controller.go index 239bee6e5..d059bdda1 100644 --- a/controllers/clusters/redis_controller.go +++ b/controllers/clusters/redis_controller.go @@ -1007,35 +1007,16 @@ func (r *RedisReconciler) newWatchStatusJob(redis *v1beta1.Redis) scheduler.Job r.EventRecorder.Eventf(redis, models.Warning, models.ExternalChanges, msgDiffSpecs) } - maintEvents, err := r.API.GetMaintenanceEvents(redis.Status.ID) + //TODO: change all context.Background() and context.TODO() to ctx from Reconcile + err = r.reconcileMaintenanceEvents(context.Background(), redis) if err != nil { - l.Error(err, "Cannot get Redis cluster maintenance events", + l.Error(err, "Cannot reconcile cluster maintenance events", "cluster name", redis.Spec.Name, "cluster ID", redis.Status.ID, ) - return err } - if !redis.Status.AreMaintenanceEventsEqual(maintEvents) { - patch := redis.NewPatch() - redis.Status.MaintenanceEvents = maintEvents - err = r.Status().Patch(context.TODO(), redis, patch) - if err != nil { - l.Error(err, "Cannot patch Redis cluster maintenance events", - "cluster name", redis.Spec.Name, - "cluster ID", redis.Status.ID, - ) - - return err - } - - l.Info("Redis cluster maintenance events were updated", - "cluster ID", redis.Status.ID, - "events", redis.Status.MaintenanceEvents, - ) - } - return nil } } @@ -1242,3 +1223,28 @@ func (r *RedisReconciler) SetupWithManager(mgr ctrl.Manager) error { })). Complete(r) } + +func (r *RedisReconciler) reconcileMaintenanceEvents(ctx context.Context, redis *v1beta1.Redis) error { + l := log.FromContext(ctx) + + iMEStatuses, err := r.API.FetchMaintenanceEventStatuses(redis.Status.ID) + if err != nil { + return err + } + + if !redis.Status.AreMaintenanceEventStatusesEqual(iMEStatuses) { + patch := redis.NewPatch() + redis.Status.MaintenanceEvents = iMEStatuses + err = r.Status().Patch(ctx, redis, patch) + if err != nil { + return err + } + + l.Info("Cluster maintenance events were reconciled", + "cluster ID", redis.Status.ID, + "events", redis.Status.MaintenanceEvents, + ) + } + + return nil +} diff --git a/controllers/clusters/zookeeper_controller.go b/controllers/clusters/zookeeper_controller.go index 977945b3b..b832054ca 100644 --- a/controllers/clusters/zookeeper_controller.go +++ b/controllers/clusters/zookeeper_controller.go @@ -493,35 +493,16 @@ func (r *ZookeeperReconciler) newWatchStatusJob(zook *v1beta1.Zookeeper) schedul r.EventRecorder.Eventf(zook, models.Warning, models.ExternalChanges, msgDiffSpecs) } - maintEvents, err := r.API.GetMaintenanceEvents(zook.Status.ID) + //TODO: change all context.Background() and context.TODO() to ctx from Reconcile + err = r.reconcileMaintenanceEvents(context.Background(), zook) if err != nil { - l.Error(err, "Cannot get Zookeeper cluster maintenance events", + l.Error(err, "Cannot reconcile cluster maintenance events", "cluster name", zook.Spec.Name, "cluster ID", zook.Status.ID, ) - return err } - if !zook.Status.AreMaintenanceEventsEqual(maintEvents) { - patch := zook.NewPatch() - zook.Status.MaintenanceEvents = maintEvents - err = r.Status().Patch(context.TODO(), zook, patch) - if err != nil { - l.Error(err, "Cannot patch Zookeeper cluster maintenance events", - "cluster name", zook.Spec.Name, - "cluster ID", zook.Status.ID, - ) - - return err - } - - l.Info("Zookeeper cluster maintenance events were updated", - "cluster ID", zook.Status.ID, - "events", zook.Status.MaintenanceEvents, - ) - } - return nil } } @@ -614,3 +595,28 @@ func (r *ZookeeperReconciler) SetupWithManager(mgr ctrl.Manager) error { }, })).Complete(r) } + +func (r *ZookeeperReconciler) reconcileMaintenanceEvents(ctx context.Context, z *v1beta1.Zookeeper) error { + l := log.FromContext(ctx) + + iMEStatuses, err := r.API.FetchMaintenanceEventStatuses(z.Status.ID) + if err != nil { + return err + } + + if !z.Status.AreMaintenanceEventStatusesEqual(iMEStatuses) { + patch := z.NewPatch() + z.Status.MaintenanceEvents = iMEStatuses + err = r.Status().Patch(ctx, z, patch) + if err != nil { + return err + } + + l.Info("Cluster maintenance events were reconciled", + "cluster ID", z.Status.ID, + "events", z.Status.MaintenanceEvents, + ) + } + + return nil +} diff --git a/pkg/instaclustr/client.go b/pkg/instaclustr/client.go index 16d837a60..95b7b6899 100644 --- a/pkg/instaclustr/client.go +++ b/pkg/instaclustr/client.go @@ -1360,8 +1360,8 @@ func (c *Client) DeleteExclusionWindow(id string) error { return nil } -func (c *Client) GetMaintenanceEventsStatuses(clusterID string) ([]*clusterresourcesv1beta1.MaintenanceEventStatus, error) { - url := c.serverHostname + MaintenanceEventStatusEndpoint + clusterID +func (c *Client) GetMaintenanceEvents(clusterID, eventType string) ([]*clusterresourcesv1beta1.MaintenanceEventStatus, error) { + url := fmt.Sprintf(MaintenanceEventStatusEndpoint, c.serverHostname, clusterID, eventType) resp, err := c.DoRequest(url, http.MethodGet, nil) if err != nil { @@ -1382,52 +1382,51 @@ func (c *Client) GetMaintenanceEventsStatuses(clusterID string) ([]*clusterresou return nil, fmt.Errorf("status code: %d, message: %s", resp.StatusCode, body) } - statuses := &struct { + holder := []struct { MaintenanceEvents []*clusterresourcesv1beta1.MaintenanceEventStatus `json:"maintenanceEvents"` }{} - err = json.Unmarshal(body, statuses) + + err = json.Unmarshal(body, &holder) if err != nil { return nil, err } - return statuses.MaintenanceEvents, nil + return holder[0].MaintenanceEvents, nil } -func (c *Client) GetMaintenanceEvents(clusterID string) ([]*v1beta1.MaintenanceEvent, error) { - url := c.serverHostname + MaintenanceEventStatusEndpoint + clusterID +func (c *Client) FetchMaintenanceEventStatuses( + clusterID string, +) ([]*clusterresourcesv1beta1.ClusteredMaintenanceEventStatus, + error) { - resp, err := c.DoRequest(url, http.MethodGet, nil) + inProgressMEStatus, err := c.GetMaintenanceEvents(clusterID, models.InProgressME) if err != nil { return nil, err } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) + pastMEStatus, err := c.GetMaintenanceEvents(clusterID, models.PastME) if err != nil { return nil, err } - if resp.StatusCode == http.StatusNotFound { - return nil, NotFound - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("status code: %d, message: %s", resp.StatusCode, body) - } - - status := &struct { - MaintenanceEvents []*v1beta1.MaintenanceEvent `json:"maintenanceEvents"` - }{} - err = json.Unmarshal(body, status) + upcomingMEStatus, err := c.GetMaintenanceEvents(clusterID, models.UpcomingME) if err != nil { return nil, err } - return status.MaintenanceEvents, nil + iMEStatuses := []*clusterresourcesv1beta1.ClusteredMaintenanceEventStatus{ + { + InProgress: inProgressMEStatus, + Past: pastMEStatus, + Upcoming: upcomingMEStatus, + }, + } + + return iMEStatuses, nil } -func (c *Client) UpdateMaintenanceEvent(me clusterresourcesv1beta1.MaintenanceEventRescheduleSpec) (*clusterresourcesv1beta1.MaintenanceEventStatus, error) { - url := c.serverHostname + MaintenanceEventEndpoint + me.ScheduleID +func (c *Client) RescheduleMaintenanceEvent(me *clusterresourcesv1beta1.MaintenanceEventReschedule) error { + url := fmt.Sprintf(MaintenanceEventRescheduleEndpoint, c.serverHostname, me.MaintenanceEventID) requestBody := &struct { ScheduledStartTime string `json:"scheduledStartTime,omitempty"` @@ -1437,31 +1436,25 @@ func (c *Client) UpdateMaintenanceEvent(me clusterresourcesv1beta1.MaintenanceEv data, err := json.Marshal(requestBody) if err != nil { - return nil, err + return err } resp, err := c.DoRequest(url, http.MethodPut, data) if err != nil { - return nil, err + return err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("me code: %d, message: %s", resp.StatusCode, body) + return err } - response := &clusterresourcesv1beta1.MaintenanceEventStatus{} - err = json.Unmarshal(body, response) - if err != nil { - return nil, err + if resp.StatusCode != http.StatusAccepted { + return fmt.Errorf("status code: %d, message: %s", resp.StatusCode, body) } - return response, nil + return nil } func (c *Client) CreateNodeReload(nr *clusterresourcesv1beta1.Node) error { diff --git a/pkg/instaclustr/config.go b/pkg/instaclustr/config.go index f2c768abf..1c0fabb82 100644 --- a/pkg/instaclustr/config.go +++ b/pkg/instaclustr/config.go @@ -66,9 +66,9 @@ const ( APIv1RestoreEndpoint = "%s/provisioning/v1/%s/backups/restore" - ExclusionWindowEndpoint = "/cluster-management/v2/resources/exclusion-windows/v2/" - MaintenanceEventEndpoint = "/v1/maintenance-events/events/" - MaintenanceEventStatusEndpoint = "/v1/maintenance-events/events?clusterId=" + ExclusionWindowEndpoint = "/cluster-management/v2/resources/exclusion-windows/v2/" + MaintenanceEventRescheduleEndpoint = "%s/cluster-management/v2/operations/maintenance-events/%s/v2/reschedule-maintenance-event/v2/" + MaintenanceEventStatusEndpoint = "%s/cluster-management/v2/data-sources/cluster/%s/maintenance-events/v2/%s/v2/" ) const ( diff --git a/pkg/instaclustr/interfaces.go b/pkg/instaclustr/interfaces.go index 53f4fbf19..448508ae3 100644 --- a/pkg/instaclustr/interfaces.go +++ b/pkg/instaclustr/interfaces.go @@ -59,10 +59,10 @@ type API interface { TriggerClusterBackup(url, clusterID string) error CreateExclusionWindow(clusterID string, window *clusterresourcesv1beta1.ExclusionWindowSpec) (string, error) GetExclusionWindowsStatus(windowID string) (string, error) - GetMaintenanceEventsStatuses(clusterID string) ([]*clusterresourcesv1beta1.MaintenanceEventStatus, error) - GetMaintenanceEvents(clusterID string) ([]*v1beta1.MaintenanceEvent, error) DeleteExclusionWindow(id string) error - UpdateMaintenanceEvent(me clusterresourcesv1beta1.MaintenanceEventRescheduleSpec) (*clusterresourcesv1beta1.MaintenanceEventStatus, error) + GetMaintenanceEvents(clusterID, eventType string) ([]*clusterresourcesv1beta1.MaintenanceEventStatus, error) + FetchMaintenanceEventStatuses(clusterID string) ([]*clusterresourcesv1beta1.ClusteredMaintenanceEventStatus, error) + RescheduleMaintenanceEvent(me *clusterresourcesv1beta1.MaintenanceEventReschedule) error RestorePgCluster(restoreData *v1beta1.PgRestoreFrom) (string, error) RestoreRedisCluster(restoreData *v1beta1.RedisRestoreFrom) (string, error) RestoreOpenSearchCluster(restoreData *v1beta1.OpenSearchRestoreFrom) (string, error) diff --git a/pkg/instaclustr/mock/client.go b/pkg/instaclustr/mock/client.go index b595dafc3..dc0d8d876 100644 --- a/pkg/instaclustr/mock/client.go +++ b/pkg/instaclustr/mock/client.go @@ -212,20 +212,20 @@ func (c *mockClient) GetExclusionWindowsStatus(windowID string) (string, error) panic("GetExclusionWindowsStatus: is not implemented") } -func (c *mockClient) GetMaintenanceEventsStatuses(clusterID string) ([]*clusterresourcesv1beta1.MaintenanceEventStatus, error) { - panic("GetMaintenanceEventsStatuses: is not implemented") +func (c *mockClient) DeleteExclusionWindow(id string) error { + panic("DeleteExclusionWindow: is not implemented") } -func (c *mockClient) GetMaintenanceEvents(clusterID string) ([]*clustersv1beta1.MaintenanceEvent, error) { +func (c *mockClient) GetMaintenanceEvents(clusterID, eventType string) ([]*clusterresourcesv1beta1.MaintenanceEventStatus, error) { panic("GetMaintenanceEvents: is not implemented") } -func (c *mockClient) DeleteExclusionWindow(id string) error { - panic("DeleteExclusionWindow: is not implemented") +func (c *mockClient) FetchMaintenanceEventStatuses(clusterID string) ([]*clusterresourcesv1beta1.ClusteredMaintenanceEventStatus, error) { + panic("FetchMaintenanceEventStatuses: is not implemented") } -func (c *mockClient) UpdateMaintenanceEvent(me clusterresourcesv1beta1.MaintenanceEventRescheduleSpec) (*clusterresourcesv1beta1.MaintenanceEventStatus, error) { - panic("UpdateMaintenanceEvent: is not implemented") +func (c *mockClient) RescheduleMaintenanceEvent(me *clusterresourcesv1beta1.MaintenanceEventReschedule) error { + panic("RescheduleMaintenanceEvent: is not implemented") } func (c *mockClient) RestorePgCluster(restoreData *clustersv1beta1.PgRestoreFrom) (string, error) { diff --git a/pkg/models/operator.go b/pkg/models/operator.go index 8fb93e50a..2712b5b82 100644 --- a/pkg/models/operator.go +++ b/pkg/models/operator.go @@ -143,6 +143,12 @@ const ( Password = "password" ) +const ( + InProgressME = "in-progress" + PastME = "past" + UpcomingME = "upcoming" +) + const Requeue60 = time.Second * 60 var (