diff --git a/api/v1/verticadb_types.go b/api/v1/verticadb_types.go index 1ced856e4..fa71c94a4 100644 --- a/api/v1/verticadb_types.go +++ b/api/v1/verticadb_types.go @@ -18,6 +18,7 @@ limitations under the License. package v1 import ( + "github.com/vertica/vcluster/vclusterops" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -847,7 +848,7 @@ type VerticaDBStatus struct { // +operator-sdk:csv:customresourcedefinitions:type=status // +optional // The details about the last created restore point - RestorePoint *RestorePointInfo `json:"restorePoint"` + RestorePoint *RestorePointInfo `json:"restorePoint,omitempty"` } type RestorePointInfo struct { @@ -855,9 +856,18 @@ type RestorePointInfo struct { // Name of the archive that this restore point was created in. Archive string `json:"archive"` // +operator-sdk:csv:customresourcedefinitions:type=status + // The timestamp when the save restore point api call started. This is helpful + // to manually query the restore point after its creation in case the operator could + // not retrieve all of the restore point info. StartTimestamp string `json:"startTimestamp"` // +operator-sdk:csv:customresourcedefinitions:type=status + // The timestamp when the save restore point api call ended. This is helpful + // to manually query the restore point after its creation in case the operator could + // not retrieve all of the restore point info. EndTimestamp string `json:"endTimestamp"` + // +operator-sdk:csv:customresourcedefinitions:type=status + // This contains the result of the restore points query. + Details *vclusterops.RestorePoint `json:"details"` } type SandboxUpgradeState struct { diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index a566822ff..d9132291c 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ limitations under the License. package v1 import ( + "github.com/vertica/vcluster/vclusterops" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -112,6 +113,11 @@ func (in *LocalStorage) DeepCopy() *LocalStorage { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RestorePointInfo) DeepCopyInto(out *RestorePointInfo) { *out = *in + if in.Details != nil { + in, out := &in.Details, &out.Details + *out = new(vclusterops.RestorePoint) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestorePointInfo. @@ -533,7 +539,7 @@ func (in *VerticaDBStatus) DeepCopyInto(out *VerticaDBStatus) { if in.RestorePoint != nil { in, out := &in.RestorePoint, &out.RestorePoint *out = new(RestorePointInfo) - **out = **in + (*in).DeepCopyInto(*out) } } diff --git a/api/v1beta1/verticadb_types.go b/api/v1beta1/verticadb_types.go index 53d01a22b..f07a243e8 100644 --- a/api/v1beta1/verticadb_types.go +++ b/api/v1beta1/verticadb_types.go @@ -20,6 +20,7 @@ import ( "fmt" "regexp" + "github.com/vertica/vcluster/vclusterops" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -928,7 +929,7 @@ type VerticaDBStatus struct { // +operator-sdk:csv:customresourcedefinitions:type=status // +optional // The details about the last created restore point - RestorePoint *RestorePointInfo `json:"restorePoint"` + RestorePoint *RestorePointInfo `json:"restorePoint,omitempty"` } type RestorePointInfo struct { @@ -936,9 +937,18 @@ type RestorePointInfo struct { // Name of the archive that this restore point was created in. Archive string `json:"archive"` // +operator-sdk:csv:customresourcedefinitions:type=status + // The timestamp when the save restore point api call started. This is helpful + // to manually query the restore point after its creation in case the operator could + // not retrieve all of the restore point info. StartTimestamp string `json:"startTimestamp"` // +operator-sdk:csv:customresourcedefinitions:type=status + // The timestamp when the save restore point api call ended. This is helpful + // to manually query the restore point after its creation in case the operator could + // not retrieve all of the restore point info. EndTimestamp string `json:"endTimestamp"` + // +operator-sdk:csv:customresourcedefinitions:type=status + // This contains the result of the restore points query. + Details *vclusterops.RestorePoint `json:"details"` } type SandboxUpgradeState struct { diff --git a/pkg/controllers/vdb/saverestorepoint_reconciler.go b/pkg/controllers/vdb/saverestorepoint_reconciler.go index f799a519c..f62f5595a 100644 --- a/pkg/controllers/vdb/saverestorepoint_reconciler.go +++ b/pkg/controllers/vdb/saverestorepoint_reconciler.go @@ -34,27 +34,23 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" ) // SaveRestorePointReconciler saves a restore point to an archive, and create the archive if it doesn't exist type SaveRestorePointReconciler struct { - VRec *VerticaDBReconciler - Vdb *vapi.VerticaDB - Log logr.Logger - client.Client - Dispatcher vadmin.Dispatcher - PFacts *PodFacts - InitiatorIP string // The IP of the pod that we run vclusterOps from + VRec *VerticaDBReconciler + Vdb *vapi.VerticaDB + Log logr.Logger + Dispatcher vadmin.Dispatcher + PFacts *PodFacts } func MakeSaveRestorePointReconciler(r *VerticaDBReconciler, vdb *vapi.VerticaDB, log logr.Logger, - pfacts *PodFacts, dispatcher vadmin.Dispatcher, cli client.Client) controllers.ReconcileActor { + pfacts *PodFacts, dispatcher vadmin.Dispatcher) controllers.ReconcileActor { return &SaveRestorePointReconciler{ VRec: r, Log: log.WithName("SaveRestorePointReconciler"), Vdb: vdb, - Client: cli, Dispatcher: dispatcher, PFacts: pfacts, } @@ -215,6 +211,8 @@ func (s *SaveRestorePointReconciler) updateVDB(ctx context.Context, start, end t vdb.Status.RestorePoint.Archive = s.Vdb.Spec.RestorePoint.Archive vdb.Status.RestorePoint.StartTimestamp = start.Format("2006-01-02 15:04:05.000000000") vdb.Status.RestorePoint.EndTimestamp = end.Format("2006-01-02 15:04:05.000000000") + // A separate reconciler will handle this + vdb.Status.RestorePoint.Details = nil return nil } // Clear the condition and add a status after restore point creation. diff --git a/pkg/controllers/vdb/saverestorepoint_reconciler_test.go b/pkg/controllers/vdb/saverestorepoint_reconciler_test.go index cc7a500a9..c2d9111d2 100644 --- a/pkg/controllers/vdb/saverestorepoint_reconciler_test.go +++ b/pkg/controllers/vdb/saverestorepoint_reconciler_test.go @@ -41,7 +41,7 @@ var _ = Describe("saverestorepoint_reconciler", func() { Expect(k8sClient.Status().Update(ctx, vdb)).Should(Succeed()) fpr := &cmds.FakePodRunner{} dispatcher := vdbRec.makeDispatcher(logger, vdb, fpr, TestPassword) - r := MakeSaveRestorePointReconciler(vdbRec, vdb, logger, &PodFacts{}, dispatcher, k8sClient) + r := MakeSaveRestorePointReconciler(vdbRec, vdb, logger, &PodFacts{}, dispatcher) res, err := r.Reconcile(ctx, &ctrl.Request{}) Expect(err).Should(Succeed()) Expect(res.Requeue).Should(BeFalse()) diff --git a/pkg/controllers/vdb/showrestorepoint_reconciler.go b/pkg/controllers/vdb/showrestorepoint_reconciler.go new file mode 100644 index 000000000..2d2cc5fca --- /dev/null +++ b/pkg/controllers/vdb/showrestorepoint_reconciler.go @@ -0,0 +1,155 @@ +/* + (c) Copyright [2021-2024] Open Text. + Licensed under the Apache License, Version 2.0 (the "License"); + You may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package vdb + +import ( + "context" + "time" + + "github.com/go-logr/logr" + "github.com/vertica/vcluster/vclusterops" + vapi "github.com/vertica/vertica-kubernetes/api/v1" + "github.com/vertica/vertica-kubernetes/pkg/controllers" + "github.com/vertica/vertica-kubernetes/pkg/events" + "github.com/vertica/vertica-kubernetes/pkg/iter" + "github.com/vertica/vertica-kubernetes/pkg/vadmin" + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/showrestorepoints" + config "github.com/vertica/vertica-kubernetes/pkg/vdbconfig" + "github.com/vertica/vertica-kubernetes/pkg/vdbstatus" + "github.com/vertica/vertica-kubernetes/pkg/vk8s" + corev1 "k8s.io/api/core/v1" + ctrl "sigs.k8s.io/controller-runtime" +) + +// ShowRestorePointReconciler will query a restore point and update the status +type ShowRestorePointReconciler struct { + VRec *VerticaDBReconciler + Vdb *vapi.VerticaDB + Log logr.Logger + Dispatcher vadmin.Dispatcher + PFacts *PodFacts + config.ConfigParamsGenerator +} + +func MakeShowRestorePointReconciler(r *VerticaDBReconciler, vdb *vapi.VerticaDB, log logr.Logger, + pfacts *PodFacts, dispatcher vadmin.Dispatcher) controllers.ReconcileActor { + return &ShowRestorePointReconciler{ + VRec: r, + Log: log.WithName("ShowRestorePointReconciler"), + Vdb: vdb, + Dispatcher: dispatcher, + PFacts: pfacts, + ConfigParamsGenerator: config.ConfigParamsGenerator{ + VRec: r, + Vdb: vdb, + Log: log.WithName("ShowRestorePointReconciler"), + }, + } +} + +func (s *ShowRestorePointReconciler) Reconcile(ctx context.Context, _ *ctrl.Request) (ctrl.Result, error) { + if shouldEarlyExit(s.Vdb) { + return ctrl.Result{}, nil + } + + restorePoints, requeue, err := s.runShowRestorePoints(ctx) + if err != nil || requeue { + return ctrl.Result{Requeue: requeue}, err + } + return ctrl.Result{}, s.saveRestorePointDetailsInVDB(ctx, restorePoints) +} + +// runShowRestorePoints call the vclusterOps API to get the restore points +func (s *ShowRestorePointReconciler) runShowRestorePoints(ctx context.Context) ([]vclusterops.RestorePoint, bool, error) { + finder := iter.MakeSubclusterFinder(s.VRec.GetClient(), s.Vdb) + pods, err := finder.FindPods(ctx, iter.FindExisting, vapi.MainCluster) + if err != nil { + return nil, false, err + } + + // find a pod to execute the vclusterops API + podIP := vk8s.FindRunningPodWithNMAContainer(pods) + if podIP == "" { + s.Log.Info("couldn't find any pod to run the query") + return nil, true, nil + } + + // extract out the communal and config information to pass down to the vclusterops API. + opts := []showrestorepoints.Option{} + opts = append(opts, + showrestorepoints.WithInitiator(podIP), + showrestorepoints.WithCommunalPath(s.Vdb.GetCommunalPath()), + showrestorepoints.WithConfigurationParams(s.ConfigurationParams.GetMap()), + showrestorepoints.WithArchiveNameFilter(s.Vdb.Status.RestorePoint.Archive), + showrestorepoints.WithStartTimestampFilter(s.Vdb.Status.RestorePoint.StartTimestamp), + showrestorepoints.WithEndTimestampFilter(s.Vdb.Status.RestorePoint.EndTimestamp), + ) + + // call showRestorePoints vcluster API + s.VRec.Eventf(s.Vdb, corev1.EventTypeNormal, events.ShowRestorePointsStarted, + "Starting show restore points") + start := time.Now() + restorePoints, err := s.Dispatcher.ShowRestorePoints(ctx, opts...) + if err != nil { + return nil, false, err + } + + s.VRec.Eventf(s.Vdb, corev1.EventTypeNormal, events.ShowRestorePointsSucceeded, + "Successfully queried restore points in %s", time.Since(start).Truncate(time.Second)) + return restorePoints, false, nil +} + +// saveRestorePointDetailsInVDB saves the last created restore point info in the status. +func (s *ShowRestorePointReconciler) saveRestorePointDetailsInVDB(ctx context.Context, restorePoints []vclusterops.RestorePoint) error { + // This is very unlikely to happen + if len(restorePoints) == 0 { + s.Log.Info("No restore point found.") + return nil + } + // We should normally only be getting the restore point that was just created + // so if there are more that one restore point we will randomly pick the first one + if len(restorePoints) > 1 { + s.Log.Info("Multiple restore points were found, only the first one will be saved in the status.") + } + restorePoint := restorePoints[0] + return s.updateRestorePointDetails(ctx, &restorePoint) +} + +func (s *ShowRestorePointReconciler) updateRestorePointDetails(ctx context.Context, restorePoint *vclusterops.RestorePoint) error { + refreshStatusInPlace := func(vdb *vapi.VerticaDB) error { + if vdb.Status.RestorePoint == nil { + vdb.Status.RestorePoint = new(vapi.RestorePointInfo) + } + if vdb.Status.RestorePoint.Details == nil { + vdb.Status.RestorePoint.Details = new(vclusterops.RestorePoint) + } + vdb.Status.RestorePoint.Details.Archive = restorePoint.Archive + vdb.Status.RestorePoint.Details.Index = restorePoint.Index + vdb.Status.RestorePoint.Details.ID = restorePoint.ID + vdb.Status.RestorePoint.Details.Timestamp = restorePoint.Timestamp + vdb.Status.RestorePoint.Details.VerticaVersion = restorePoint.VerticaVersion + return nil + } + return vdbstatus.Update(ctx, s.VRec.Client, s.Vdb, refreshStatusInPlace) +} + +func shouldEarlyExit(vdb *vapi.VerticaDB) bool { + return vdb.Status.RestorePoint == nil || + vdb.Status.RestorePoint.Archive == "" || + vdb.Status.RestorePoint.StartTimestamp == "" || + vdb.Status.RestorePoint.EndTimestamp == "" || + vdb.Status.RestorePoint.Details != nil +} diff --git a/pkg/controllers/vdb/showrestorepoint_reconciler_test.go b/pkg/controllers/vdb/showrestorepoint_reconciler_test.go new file mode 100644 index 000000000..686c49fa4 --- /dev/null +++ b/pkg/controllers/vdb/showrestorepoint_reconciler_test.go @@ -0,0 +1,77 @@ +/* + (c) Copyright [2021-2024] Open Text. + Licensed under the Apache License, Version 2.0 (the "License"); + You may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package vdb + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/vertica/vcluster/vclusterops" + vapi "github.com/vertica/vertica-kubernetes/api/v1" + "github.com/vertica/vertica-kubernetes/pkg/test" +) + +var _ = Describe("showrestorepoint_reconciler", func() { + ctx := context.Background() + const archive = "arch" + + It("should exit early", func() { + vdb := vapi.MakeVDB() + vdb.Status = vapi.VerticaDBStatus{} + // should exit because status.restorePoint is nil + Expect(shouldEarlyExit(vdb)).Should(BeTrue()) + vdb.Status.RestorePoint = &vapi.RestorePointInfo{ + Archive: archive, + StartTimestamp: "start", + } + // should exit because at least one of archive, startTimeStamp, + // endTimeStamp is not set + Expect(shouldEarlyExit(vdb)).Should(BeTrue()) + vdb.Status.RestorePoint.EndTimestamp = "end" + // should not exit + Expect(shouldEarlyExit(vdb)).Should(BeFalse()) + vdb.Status.RestorePoint.Details = &vclusterops.RestorePoint{} + // should exit because status.restorePoint.details is already set + Expect(shouldEarlyExit(vdb)).Should(BeTrue()) + }) + + It("should update status with restore point info", func() { + vdb := vapi.MakeVDB() + test.CreateVDB(ctx, k8sClient, vdb) + defer test.DeleteVDB(ctx, k8sClient, vdb) + + s := &ShowRestorePointReconciler{ + Vdb: vdb, + VRec: vdbRec, + Log: logger, + } + const id = "abcdef" + rpts := []vclusterops.RestorePoint{ + { + Archive: archive, + ID: id, + Index: 1, + }, + } + Expect(s.saveRestorePointDetailsInVDB(ctx, rpts)).Should(Succeed()) + fetchedVdb := &vapi.VerticaDB{} + Expect(k8sClient.Get(ctx, vdb.ExtractNamespacedName(), fetchedVdb)).Should(Succeed()) + Expect(fetchedVdb.Status.RestorePoint.Details.Archive).Should(Equal(archive)) + Expect(fetchedVdb.Status.RestorePoint.Details.ID).Should(Equal(id)) + Expect(fetchedVdb.Status.RestorePoint.Details.Index).Should(Equal(1)) + }) +}) diff --git a/pkg/controllers/vdb/verticadb_controller.go b/pkg/controllers/vdb/verticadb_controller.go index 1acf08e9c..b12506d97 100644 --- a/pkg/controllers/vdb/verticadb_controller.go +++ b/pkg/controllers/vdb/verticadb_controller.go @@ -268,7 +268,9 @@ func (r *VerticaDBReconciler) constructActors(log logr.Logger, vdb *vapi.Vertica // Add the label after update the sandbox subcluster status field MakeObjReconciler(r, log, vdb, pfacts, ObjReconcileModeAll), // Handle calls to create a restore point - MakeSaveRestorePointReconciler(r, vdb, log, pfacts, dispatcher, r.Client), + MakeSaveRestorePointReconciler(r, vdb, log, pfacts, dispatcher), + // Update the status with the restore point info + MakeShowRestorePointReconciler(r, vdb, log, pfacts, dispatcher), // Resize any PVs if the local data size changed in the vdb MakeResizePVReconciler(r, log, vdb, prunner, pfacts), // This must be the last reconciler. It makes sure that all dependent diff --git a/pkg/controllers/vrpq/query_reconciler.go b/pkg/controllers/vrpq/query_reconciler.go index 19134ab27..d4a466e74 100644 --- a/pkg/controllers/vrpq/query_reconciler.go +++ b/pkg/controllers/vrpq/query_reconciler.go @@ -45,7 +45,6 @@ const ( stateQuerying = "Querying" stateSuccessQuery = "Query successful" stateFailedQuery = "Query failed" - podRunning = "Running" ) type QueryReconciler struct { @@ -107,7 +106,7 @@ func (q *QueryReconciler) Reconcile(ctx context.Context, _ *ctrl.Request) (ctrl. // extract out the communal and config information to pass down to the vclusterops API. opts := []showrestorepoints.Option{} opts = append(opts, - showrestorepoints.WithInitiator(q.Vrpq.ExtractNamespacedName(), podIP), + showrestorepoints.WithInitiator(podIP), showrestorepoints.WithCommunalPath(q.Vdb.GetCommunalPath()), showrestorepoints.WithConfigurationParams(q.ConfigurationParams.GetMap()), ) @@ -179,16 +178,12 @@ func (q *QueryReconciler) runShowRestorePoints(ctx context.Context, dispatcher v // findRunningPodWithNMAContainer finds a pod to execute the vclusterops API. // The pod should be running and the NMA container should be ready func (q *QueryReconciler) findRunningPodWithNMAContainer(pods *corev1.PodList) (string, ctrl.Result) { - for i := range pods.Items { - pod := &pods.Items[i] - if pod.Status.Phase == podRunning { - if vk8s.IsNMAContainerReady(pod) { - return pod.Status.PodIP, ctrl.Result{} - } - } + podIP := vk8s.FindRunningPodWithNMAContainer(pods) + if podIP == "" { + q.Log.Info("couldn't find any pod to run the query") + return "", ctrl.Result{Requeue: true} } - q.Log.Info("couldn't find any pod to run the query") - return "", ctrl.Result{Requeue: true} + return podIP, ctrl.Result{} } // makeDispatcher will create a Dispatcher object based on the feature flags set. diff --git a/pkg/controllers/vrpq/query_reconciler_test.go b/pkg/controllers/vrpq/query_reconciler_test.go index 0a679e461..acce0e2f1 100644 --- a/pkg/controllers/vrpq/query_reconciler_test.go +++ b/pkg/controllers/vrpq/query_reconciler_test.go @@ -223,7 +223,7 @@ func constructVrpqDispatcher(ctx context.Context, vrpq *v1beta1.VerticaRestorePo } opts := []showrestorepoints.Option{} opts = append(opts, - showrestorepoints.WithInitiator(vrpq.ExtractNamespacedName(), "192.168.0.1"), + showrestorepoints.WithInitiator("192.168.0.1"), showrestorepoints.WithCommunalPath("/communal"), ) err := g.runShowRestorePoints(ctx, dispatcher, opts) diff --git a/pkg/events/event.go b/pkg/events/event.go index e7e90a6d1..1a17b0d92 100644 --- a/pkg/events/event.go +++ b/pkg/events/event.go @@ -18,102 +18,104 @@ package events // Constants for VerticaDB reconciler const ( - AddNodeStart = "AddNodeStart" - AddNodeSucceeded = "AddNodeSucceeded" - AddNodeLicenseFail = "AddNodeLicenseFail" - AddNodeFailed = "AddNodeFailed" - CreateDBStart = "CreateDBStart" - CreateDBSucceeded = "CreateDBSucceeded" - CreateDBFailed = "CreateDBFailed" - ReviveDBStart = "ReviveDBStart" - ReviveDBSucceeded = "ReviveDBSucceeded" - ReviveDBFailed = "ReviveDBFailed" - ReviveDBClusterInUse = "ReviveDBClusterInUse" - ReviveDBNotFound = "ReviveDBNotFound" - ReviveDBPermissionDenied = "ReviveDBPermissionDenied" - ReviveDBNodeCountMismatch = "ReviveDBNodeCountMismatch" - ReviveDBRestoreUnsupported = "ReviveDBRestoreUnsupported" - ReviveDBRestorePointNotFound = "ReviveDBRestorePointNotFound" - ReviveOrderBad = "ReviveOrderBad" - ObjectNotFound = "ObjectNotFound" - CommunalCredsWrongKey = "CommunalCredsWrongKey" - CommunalEndpointIssue = "CommunalEndpointIssue" - S3BucketDoesNotExist = "S3BucketDoesNotExist" - S3WrongRegion = "S3WrongRegion" - S3SseCustomerWrongKey = "S3SseCustomerWrongKey" - InvalidS3SseCustomerKey = "InvalidS3SseCustomerKey" - InvalidConfigParm = "InvalidConfigParm" - CommunalPathIsNotEmpty = "CommunalPathIsNotEmpty" - RemoveNodesStart = "RemoveNodesStart" - RemoveNodesSucceeded = "RemoveNodesSucceeded" - RemoveNodesFailed = "RemoveNodesFailed" - NodeRestartStarted = "NodeRestartStarted" - NodeRestartSucceeded = "NodeRestartSucceeded" - NodeRestartFailed = "NodeRestartFailed" - ClusterRestartStarted = "ClusterRestartStarted" - ClusterRestartSucceeded = "ClusterRestartSucceeded" - SandboxSubclusterFailed = "SandboxSubclusterFailed" - SandboxSubclusterStart = "SandboxSubclusterStart" - SandboxSubclusterSucceeded = "SandboxSubclusterSucceeded" - PromoteSandboxToMainFailed = "PromoteSandboxSubclusterToMainFailed" - PromoteSandboxToMainStart = "PromoteSandboxSubclusterToMainStart" - PromoteSandboxToSucceeded = "PromoteSandboxSubclusterToMainSucceeded" - UnsandboxSubclusterFailed = "UnsandboxSubclusterFailed" - UnsandboxSubclusterStart = "UnsandboxSubclusterStart" - UnsandboxSubclusterSucceeded = "UnsandboxSubclusterSucceeded" - CreateArchiveStart = "CreateArchiveStart" - CreateArchiveSucceeded = "CreateArchiveSucceeded" - ArchiveExists = "ArchiveExists" - CreateArchiveFailed = "CreateArchiveFailed" - SaveRestorePointStart = "SaveRestorePointStart" - SaveRestorePointSucceeded = "SaveRestorePointSucceeded" - SaveRestorePointFailed = "SaveRestorePointFailed" - SlowRestartDetected = "SlowRestartDetected" - SubclusterAdded = "SubclusterAdded" - SubclusterRemoved = "SubclusterRemoved" - AlterSubclusterStart = "AlterSubclusterStart" - AlterSubclusterFailed = "AlterSubclusterFailed" - AlterSubclusterSucceeded = "AlterSubclusterSucceeded" - SuperuserPasswordSecretNotFound = "SuperuserPasswordSecretNotFound" - UnsupportedVerticaVersion = "UnsupportedVerticaVersion" - ATConfPartiallyCopied = "ATConfPartiallyCopied" - AuthParmsCopyFailed = "AuthParmsCopyFailed" - UpgradeStart = "UpgradeStart" - UpgradeSucceeded = "UpgradeSucceeded" - IncompatibleUpgradeRequested = "IncompatibleUpgradeRequested" - ClusterShutdownStarted = "ClusterShutdownStarted" - ClusterShutdownFailed = "ClusterShutdownFailed" - ClusterShutdownSucceeded = "ClusterShutdownSucceeded" - ReipFailed = "ReipFailed" - MissingSecretKeys = "MissingSecretKeys" - HTTPServerNotSetup = "HTTPServerNotSetup" - HTTPServerStartStarted = "HTTPServerStartStarted" - HTTPServerStartFailed = "HTTPServerStartFailed" - KerberosAuthError = "KerberosAuthError" - OperatorUpgrade = "OperatorUpgrade" - InvalidUpgradePath = "InvalidUpgradePath" - RebalanceShards = "RebalanceShards" - DrainNodeRetry = "DrainNodeRetry" - DrainSubclusterRetry = "DrainSubclusterRetry" - SuboptimalNodeCount = "SuboptimalNodeCount" - StopDBStart = "StopDBStart" - StopDBSucceeded = "StopDBSucceeded" - StopDBFailed = "StopDBFailed" - DepotResized = "DepotResized" - MgmtFailed = "MgmtFailed" - MgmtFailedDiskFull = "MgmtFailedDiskfull" - LowLocalDataAvailSpace = "LowLocalDataAvailSpace" - WrongImage = "WrongImage" - MonolithicContainerNotSupported = "MonolithicContainerNotSupported" - InstallPackagesStarted = "InstallPackagesStarted" - InstallPackagesFailed = "InstallPackagesFailed" - InstallPackagesFinished = "InstallPackagesFinished" - RenameSubclusterFailed = "RenameSubclusterFailed" - RenameSubclusterStart = "RenameSubclusterStart" - RenameSubclusterSucceeded = "RenameSubclusterSucceeded" - InDBSaveRestorePointNotSupported = "InDBSaveRestorePointNotSupported" - PauseConnectionsRetry = "PauseConnectionsRetry" - UpgradeFailed = "UpgradeFailed" + AddNodeStart = "AddNodeStart" + AddNodeSucceeded = "AddNodeSucceeded" + AddNodeLicenseFail = "AddNodeLicenseFail" + AddNodeFailed = "AddNodeFailed" + CreateDBStart = "CreateDBStart" + CreateDBSucceeded = "CreateDBSucceeded" + CreateDBFailed = "CreateDBFailed" + ReviveDBStart = "ReviveDBStart" + ReviveDBSucceeded = "ReviveDBSucceeded" + ReviveDBFailed = "ReviveDBFailed" + ReviveDBClusterInUse = "ReviveDBClusterInUse" + ReviveDBNotFound = "ReviveDBNotFound" + ReviveDBPermissionDenied = "ReviveDBPermissionDenied" + ReviveDBNodeCountMismatch = "ReviveDBNodeCountMismatch" + ReviveDBRestoreUnsupported = "ReviveDBRestoreUnsupported" + ReviveDBRestorePointNotFound = "ReviveDBRestorePointNotFound" + ReviveOrderBad = "ReviveOrderBad" + ObjectNotFound = "ObjectNotFound" + CommunalCredsWrongKey = "CommunalCredsWrongKey" + CommunalEndpointIssue = "CommunalEndpointIssue" + S3BucketDoesNotExist = "S3BucketDoesNotExist" + S3WrongRegion = "S3WrongRegion" + S3SseCustomerWrongKey = "S3SseCustomerWrongKey" + InvalidS3SseCustomerKey = "InvalidS3SseCustomerKey" + InvalidConfigParm = "InvalidConfigParm" + CommunalPathIsNotEmpty = "CommunalPathIsNotEmpty" + RemoveNodesStart = "RemoveNodesStart" + RemoveNodesSucceeded = "RemoveNodesSucceeded" + RemoveNodesFailed = "RemoveNodesFailed" + NodeRestartStarted = "NodeRestartStarted" + NodeRestartSucceeded = "NodeRestartSucceeded" + NodeRestartFailed = "NodeRestartFailed" + ClusterRestartStarted = "ClusterRestartStarted" + ClusterRestartSucceeded = "ClusterRestartSucceeded" + SandboxSubclusterFailed = "SandboxSubclusterFailed" + SandboxSubclusterStart = "SandboxSubclusterStart" + SandboxSubclusterSucceeded = "SandboxSubclusterSucceeded" + PromoteSandboxToMainFailed = "PromoteSandboxSubclusterToMainFailed" + PromoteSandboxToMainStart = "PromoteSandboxSubclusterToMainStart" + PromoteSandboxToSucceeded = "PromoteSandboxSubclusterToMainSucceeded" + UnsandboxSubclusterFailed = "UnsandboxSubclusterFailed" + UnsandboxSubclusterStart = "UnsandboxSubclusterStart" + UnsandboxSubclusterSucceeded = "UnsandboxSubclusterSucceeded" + CreateArchiveStart = "CreateArchiveStart" + CreateArchiveSucceeded = "CreateArchiveSucceeded" + ArchiveExists = "ArchiveExists" + CreateArchiveFailed = "CreateArchiveFailed" + SaveRestorePointStart = "SaveRestorePointStart" + SaveRestorePointSucceeded = "SaveRestorePointSucceeded" + SaveRestorePointFailed = "SaveRestorePointFailed" + CreateRestorePointsQueryFailed = "CreateRestorePointsQueryFailed" + CreateRestorePointsQuerySucceeded = "CreateRestorePointsQuerySucceeded" + SlowRestartDetected = "SlowRestartDetected" + SubclusterAdded = "SubclusterAdded" + SubclusterRemoved = "SubclusterRemoved" + AlterSubclusterStart = "AlterSubclusterStart" + AlterSubclusterFailed = "AlterSubclusterFailed" + AlterSubclusterSucceeded = "AlterSubclusterSucceeded" + SuperuserPasswordSecretNotFound = "SuperuserPasswordSecretNotFound" + UnsupportedVerticaVersion = "UnsupportedVerticaVersion" + ATConfPartiallyCopied = "ATConfPartiallyCopied" + AuthParmsCopyFailed = "AuthParmsCopyFailed" + UpgradeStart = "UpgradeStart" + UpgradeSucceeded = "UpgradeSucceeded" + IncompatibleUpgradeRequested = "IncompatibleUpgradeRequested" + ClusterShutdownStarted = "ClusterShutdownStarted" + ClusterShutdownFailed = "ClusterShutdownFailed" + ClusterShutdownSucceeded = "ClusterShutdownSucceeded" + ReipFailed = "ReipFailed" + MissingSecretKeys = "MissingSecretKeys" + HTTPServerNotSetup = "HTTPServerNotSetup" + HTTPServerStartStarted = "HTTPServerStartStarted" + HTTPServerStartFailed = "HTTPServerStartFailed" + KerberosAuthError = "KerberosAuthError" + OperatorUpgrade = "OperatorUpgrade" + InvalidUpgradePath = "InvalidUpgradePath" + RebalanceShards = "RebalanceShards" + DrainNodeRetry = "DrainNodeRetry" + DrainSubclusterRetry = "DrainSubclusterRetry" + SuboptimalNodeCount = "SuboptimalNodeCount" + StopDBStart = "StopDBStart" + StopDBSucceeded = "StopDBSucceeded" + StopDBFailed = "StopDBFailed" + DepotResized = "DepotResized" + MgmtFailed = "MgmtFailed" + MgmtFailedDiskFull = "MgmtFailedDiskfull" + LowLocalDataAvailSpace = "LowLocalDataAvailSpace" + WrongImage = "WrongImage" + MonolithicContainerNotSupported = "MonolithicContainerNotSupported" + InstallPackagesStarted = "InstallPackagesStarted" + InstallPackagesFailed = "InstallPackagesFailed" + InstallPackagesFinished = "InstallPackagesFinished" + RenameSubclusterFailed = "RenameSubclusterFailed" + RenameSubclusterStart = "RenameSubclusterStart" + RenameSubclusterSucceeded = "RenameSubclusterSucceeded" + InDBSaveRestorePointNotSupported = "InDBSaveRestorePointNotSupported" + PauseConnectionsRetry = "PauseConnectionsRetry" + UpgradeFailed = "UpgradeFailed" ) // Constants for VerticaAutoscaler reconciler diff --git a/pkg/vadmin/opts/showrestorepoints/opts.go b/pkg/vadmin/opts/showrestorepoints/opts.go index aae99a07b..f6fd86852 100644 --- a/pkg/vadmin/opts/showrestorepoints/opts.go +++ b/pkg/vadmin/opts/showrestorepoints/opts.go @@ -17,12 +17,10 @@ package showrestorepoints import ( vops "github.com/vertica/vcluster/vclusterops" - "k8s.io/apimachinery/pkg/types" ) // Parms holds all of the option for a restore point invocation. type Parms struct { - InitiatorName types.NamespacedName InitiatorIP string Hosts []string CommunalPath string @@ -39,9 +37,8 @@ func (s *Parms) Make(opts ...Option) { } } -func WithInitiator(nm types.NamespacedName, ip string) Option { +func WithInitiator(ip string) Option { return func(s *Parms) { - s.InitiatorName = nm s.InitiatorIP = ip } } diff --git a/pkg/vadmin/restore_points_query_vc_test.go b/pkg/vadmin/restore_points_query_vc_test.go index b3a3b217b..2c0ea881e 100644 --- a/pkg/vadmin/restore_points_query_vc_test.go +++ b/pkg/vadmin/restore_points_query_vc_test.go @@ -78,7 +78,7 @@ var _ = Describe("restore_points_vc", func() { defer test.DeleteSecret(ctx, dispatcher.Client, dispatcher.VDB.Spec.NMATLSSecret) showRestorePoints, err := dispatcher.ShowRestorePoints(ctx, - showrestorepoints.WithInitiator(dispatcher.VDB.ExtractNamespacedName(), nodeIPs[0]), + showrestorepoints.WithInitiator(nodeIPs[0]), showrestorepoints.WithCommunalPath(TestCommunalPath), showrestorepoints.WithConfigurationParams(TestCommunalStorageParams), showrestorepoints.WithArchiveNameFilter(TestArchiveName), diff --git a/pkg/vk8s/container.go b/pkg/vk8s/container.go index 79d1875f7..e0aaff9f7 100644 --- a/pkg/vk8s/container.go +++ b/pkg/vk8s/container.go @@ -87,6 +87,19 @@ func FindServerContainerStatus(pod *corev1.Pod) *corev1.ContainerStatus { return findContainerStatus(pod.Status.ContainerStatuses, names.ServerContainer) } +// FindRunningPodWithNMAContainer finds a running pod with NMA ready. +func FindRunningPodWithNMAContainer(pods *corev1.PodList) string { + for i := range pods.Items { + pod := &pods.Items[i] + if pod.Status.Phase == corev1.PodRunning { + if IsNMAContainerReady(pod) { + return pod.Status.PodIP + } + } + } + return "" +} + // FindScrutinizeInitContainerStatus will return the status of the scrutinize // init container func FindScrutinizeInitContainerStatus(pod *corev1.Pod) *corev1.ContainerStatus { diff --git a/tests/e2e-leg-6/save-restore-point/10-assert.yaml b/tests/e2e-leg-6/save-restore-point/10-assert.yaml index ebebbc121..d6dec7221 100644 --- a/tests/e2e-leg-6/save-restore-point/10-assert.yaml +++ b/tests/e2e-leg-6/save-restore-point/10-assert.yaml @@ -21,6 +21,16 @@ involvedObject: kind: VerticaDB name: v-restore-point --- +apiVersion: v1 +kind: Event +reason: ShowRestorePointsSucceeded +source: + component: verticadb-operator +involvedObject: + apiVersion: vertica.com/v1 + kind: VerticaDB + name: v-restore-point +--- apiVersion: vertica.com/v1 kind: VerticaDB metadata: @@ -28,3 +38,6 @@ metadata: status: restorePoint: archive: test + details: + archive: test + index: 1 diff --git a/tests/e2e-leg-6/save-restore-point/20-assert.yaml b/tests/e2e-leg-6/save-restore-point/20-assert.yaml index ebebbc121..9210556ec 100644 --- a/tests/e2e-leg-6/save-restore-point/20-assert.yaml +++ b/tests/e2e-leg-6/save-restore-point/20-assert.yaml @@ -28,3 +28,6 @@ metadata: status: restorePoint: archive: test + details: + archive: test + index: 2