From d390bebb45796e69b8ae80e50163d7b765071841 Mon Sep 17 00:00:00 2001 From: roypaulin Date: Tue, 1 Oct 2024 18:27:37 +0200 Subject: [PATCH 1/4] Create a vrpq after saving a restore point --- .../vdb/saverestorepoint_reconciler.go | 49 ++++- pkg/events/event.go | 194 +++++++++--------- pkg/meta/annotations.go | 11 + .../save-restore-point/10-errors.yaml | 15 ++ .../12-enable-vrpq-creation.yaml | 20 ++ .../save-restore-point/20-assert.yaml | 10 + .../25-wait-for-vrpq-creation.yaml | 20 ++ 7 files changed, 222 insertions(+), 97 deletions(-) create mode 100644 tests/e2e-leg-6/save-restore-point/10-errors.yaml create mode 100644 tests/e2e-leg-6/save-restore-point/12-enable-vrpq-creation.yaml create mode 100644 tests/e2e-leg-6/save-restore-point/25-wait-for-vrpq-creation.yaml diff --git a/pkg/controllers/vdb/saverestorepoint_reconciler.go b/pkg/controllers/vdb/saverestorepoint_reconciler.go index f799a519c..198260359 100644 --- a/pkg/controllers/vdb/saverestorepoint_reconciler.go +++ b/pkg/controllers/vdb/saverestorepoint_reconciler.go @@ -18,11 +18,13 @@ package vdb import ( "context" "errors" + "fmt" "strings" "time" "github.com/go-logr/logr" vapi "github.com/vertica/vertica-kubernetes/api/v1" + "github.com/vertica/vertica-kubernetes/api/v1beta1" "github.com/vertica/vertica-kubernetes/pkg/controllers" "github.com/vertica/vertica-kubernetes/pkg/events" vmeta "github.com/vertica/vertica-kubernetes/pkg/meta" @@ -122,12 +124,57 @@ func (s *SaveRestorePointReconciler) Reconcile(ctx context.Context, _ *ctrl.Requ } // Once save restore point, change condition // params: context, host, archive-name, sandbox, num of restore point(0 is unlimited) - return ctrl.Result{}, s.runSaveRestorePointVclusterAPI(ctx, hostIP, vapi.MainCluster) + err := s.runSaveRestorePointVclusterAPI(ctx, hostIP, vapi.MainCluster) + if err != nil { + return ctrl.Result{}, err + } + if !vmeta.GetSkipVRPQCreation(s.Vdb.Annotations) { + s.createVRPQ(ctx) + } + return ctrl.Result{}, nil } // archive name param not set correctly, return an error return ctrl.Result{}, errors.New("create archive failed, archive name not set in restorePoint spec") } +// createVRPQ creates a VerticaRestorePointsQuery to fetch the restore point info. +func (s *SaveRestorePointReconciler) createVRPQ(ctx context.Context) { + rpq := &v1beta1.VerticaRestorePointsQuery{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1beta1.GroupVersion.String(), + Kind: v1beta1.RestorePointsQueryKind, + }, + ObjectMeta: metav1.ObjectMeta{ + GenerateName: fmt.Sprintf("%s-", s.Vdb.Name), + Namespace: s.Vdb.Namespace, + OwnerReferences: []metav1.OwnerReference{s.Vdb.GenerateOwnerReference()}, + }, + Spec: v1beta1.VerticaRestorePointsQuerySpec{ + VerticaDBName: s.Vdb.Name, + FilterOptions: &v1beta1.VerticaRestorePointQueryFilterOptions{ + ArchiveName: s.Vdb.Spec.RestorePoint.Archive, + StartTimestamp: s.Vdb.Status.RestorePoint.StartTimestamp, + EndTimestamp: s.Vdb.Status.RestorePoint.EndTimestamp, + }, + }, + } + s.Log.Info("Creating a VerticaRestorePointsQuery to show the restore point info") + // We will try this only once, if the operator cannot create the object the user will + // be asked to do it manually. This is because we don't want to fail the reconciler + // just because of it and the users have a few ways to easily get the restore point info + // like creating a vrpq themselves or using vsql. + err := s.VRec.Client.Create(ctx, rpq) + if err != nil { + s.VRec.Eventf(s.Vdb, corev1.EventTypeWarning, events.CreateRestorePointsQueryFailed, + "Failed to create the VerticaRestorePointsQuery %q. Manually create one with filter options from vdb.status.restorepoint"+ + " or query archive_restore_points to get the restore point details.", + rpq.GenerateName) + return + } + s.VRec.Eventf(s.Vdb, corev1.EventTypeNormal, events.CreateRestorePointsQuerySucceeded, + "VerticaRestorePointsQuery %s created.", "name", rpq.Name) +} + // runCreateArchiveVclusterAPI will do the actual execution of creating archive. // This handles logging of necessary events. func (s *SaveRestorePointReconciler) runCreateArchiveVclusterAPI(ctx context.Context, 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/meta/annotations.go b/pkg/meta/annotations.go index 36c9947c9..ae6f05949 100644 --- a/pkg/meta/annotations.go +++ b/pkg/meta/annotations.go @@ -300,6 +300,11 @@ const ( OnlineUpgradeArchiveBeforeReplicationAnnotation = "vertica.com/online-upgrade-archive-before-replication" SaveRestorePointAnnotation = "vertica.com/save-restore-point-on-upgrade" + // Allow users to skip the creation of a VerticaRestorePointsQuery object after saving + // a restore point. When this is false, after saving a restore point, the operator + // will create a VerticaRestorePointsQuery in order to expose the restore point info + // the user. + SkipVRPQCreationAnnotation = "vertica.com/skip-restore-points-query-creation" // This will be set in a sandbox configMap by the vdb controller to wake up the sandbox // controller for upgrading the sandboxes @@ -596,6 +601,12 @@ func GetSaveRestorePoint(annotations map[string]string) bool { return lookupBoolAnnotation(annotations, SaveRestorePointAnnotation, false) } +// GetSkipVRPQCreation returns true if the operator must create +// a VerticaRestorePointsQuery object after saving a restore point. +func GetSkipVRPQCreation(annotations map[string]string) bool { + return lookupBoolAnnotation(annotations, SkipVRPQCreationAnnotation, true) +} + // GetStsNameOverride returns the override for the statefulset name. If one is // not provided, an empty string is returned. func GetStsNameOverride(annotations map[string]string) string { diff --git a/tests/e2e-leg-6/save-restore-point/10-errors.yaml b/tests/e2e-leg-6/save-restore-point/10-errors.yaml new file mode 100644 index 000000000..94d9e6a08 --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/10-errors.yaml @@ -0,0 +1,15 @@ +# (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. + +apiVersion: vertica.com/v1beta1 +kind: VerticaRestorePointsQuery \ No newline at end of file diff --git a/tests/e2e-leg-6/save-restore-point/12-enable-vrpq-creation.yaml b/tests/e2e-leg-6/save-restore-point/12-enable-vrpq-creation.yaml new file mode 100644 index 000000000..a3589f631 --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/12-enable-vrpq-creation.yaml @@ -0,0 +1,20 @@ +# (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. + +apiVersion: vertica.com/v1 +kind: VerticaDB +metadata: + name: v-upgrade-vertica + annotations: + vertica.com/vcluster-ops: "true" + vertica.com/skip-restore-points-query-creation: "false" \ No newline at end of file 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..c52120af5 100644 --- a/tests/e2e-leg-6/save-restore-point/20-assert.yaml +++ b/tests/e2e-leg-6/save-restore-point/20-assert.yaml @@ -21,6 +21,16 @@ involvedObject: kind: VerticaDB name: v-restore-point --- +apiVersion: v1 +kind: Event +reason: CreateRestorePointsQuerySucceeded +source: + component: verticadb-operator +involvedObject: + apiVersion: vertica.com/v1 + kind: VerticaDB + name: v-restore-point +--- apiVersion: vertica.com/v1 kind: VerticaDB metadata: diff --git a/tests/e2e-leg-6/save-restore-point/25-wait-for-vrpq-creation.yaml b/tests/e2e-leg-6/save-restore-point/25-wait-for-vrpq-creation.yaml new file mode 100644 index 000000000..f81d4fb7c --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/25-wait-for-vrpq-creation.yaml @@ -0,0 +1,20 @@ +# (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. + +apiVersion: vertica.com/v1beta1 +kind: VerticaRestorePointsQuery +status: + restorePoints: + - archive: test + index: 2 + state: "Query successful" \ No newline at end of file From cbac10f23fd9cb7f25af13b0a60f22379cf3ce7c Mon Sep 17 00:00:00 2001 From: roypaulin Date: Wed, 2 Oct 2024 13:44:25 +0200 Subject: [PATCH 2/4] Fix unit tests --- pkg/controllers/vdb/saverestorepoint_reconciler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/controllers/vdb/saverestorepoint_reconciler.go b/pkg/controllers/vdb/saverestorepoint_reconciler.go index 198260359..d5ed87932 100644 --- a/pkg/controllers/vdb/saverestorepoint_reconciler.go +++ b/pkg/controllers/vdb/saverestorepoint_reconciler.go @@ -172,7 +172,7 @@ func (s *SaveRestorePointReconciler) createVRPQ(ctx context.Context) { return } s.VRec.Eventf(s.Vdb, corev1.EventTypeNormal, events.CreateRestorePointsQuerySucceeded, - "VerticaRestorePointsQuery %s created.", "name", rpq.Name) + "VerticaRestorePointsQuery %s created.", rpq.Name) } // runCreateArchiveVclusterAPI will do the actual execution of creating archive. From 252572c391a8cb11e8a8ad1891540cb6aa0e2cc8 Mon Sep 17 00:00:00 2001 From: roypaulin Date: Thu, 3 Oct 2024 01:58:08 +0200 Subject: [PATCH 3/4] Address coments --- api/v1/verticadb_types.go | 12 +- api/v1beta1/verticadb_types.go | 12 +- .../vdb/saverestorepoint_reconciler.go | 67 +------- .../vdb/saverestorepoint_reconciler_test.go | 2 +- .../vdb/showrestorepoint_reconciler.go | 155 ++++++++++++++++++ .../vdb/showrestorepoint_reconciler_test.go | 77 +++++++++ pkg/controllers/vdb/verticadb_controller.go | 4 +- pkg/controllers/vrpq/query_reconciler.go | 17 +- pkg/controllers/vrpq/query_reconciler_test.go | 2 +- pkg/meta/annotations.go | 11 -- pkg/vadmin/opts/showrestorepoints/opts.go | 5 +- pkg/vadmin/restore_points_query_vc_test.go | 2 +- pkg/vk8s/container.go | 13 ++ .../save-restore-point/10-assert.yaml | 13 ++ .../save-restore-point/10-errors.yaml | 15 -- .../12-enable-vrpq-creation.yaml | 20 --- .../save-restore-point/20-assert.yaml | 13 +- .../25-wait-for-vrpq-creation.yaml | 20 --- 18 files changed, 305 insertions(+), 155 deletions(-) create mode 100644 pkg/controllers/vdb/showrestorepoint_reconciler.go create mode 100644 pkg/controllers/vdb/showrestorepoint_reconciler_test.go delete mode 100644 tests/e2e-leg-6/save-restore-point/10-errors.yaml delete mode 100644 tests/e2e-leg-6/save-restore-point/12-enable-vrpq-creation.yaml delete mode 100644 tests/e2e-leg-6/save-restore-point/25-wait-for-vrpq-creation.yaml diff --git a/api/v1/verticadb_types.go b/api/v1/verticadb_types.go index 2b305d778..3966c13a3 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/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 d5ed87932..f62f5595a 100644 --- a/pkg/controllers/vdb/saverestorepoint_reconciler.go +++ b/pkg/controllers/vdb/saverestorepoint_reconciler.go @@ -18,13 +18,11 @@ package vdb import ( "context" "errors" - "fmt" "strings" "time" "github.com/go-logr/logr" vapi "github.com/vertica/vertica-kubernetes/api/v1" - "github.com/vertica/vertica-kubernetes/api/v1beta1" "github.com/vertica/vertica-kubernetes/pkg/controllers" "github.com/vertica/vertica-kubernetes/pkg/events" vmeta "github.com/vertica/vertica-kubernetes/pkg/meta" @@ -36,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, } @@ -124,57 +118,12 @@ func (s *SaveRestorePointReconciler) Reconcile(ctx context.Context, _ *ctrl.Requ } // Once save restore point, change condition // params: context, host, archive-name, sandbox, num of restore point(0 is unlimited) - err := s.runSaveRestorePointVclusterAPI(ctx, hostIP, vapi.MainCluster) - if err != nil { - return ctrl.Result{}, err - } - if !vmeta.GetSkipVRPQCreation(s.Vdb.Annotations) { - s.createVRPQ(ctx) - } - return ctrl.Result{}, nil + return ctrl.Result{}, s.runSaveRestorePointVclusterAPI(ctx, hostIP, vapi.MainCluster) } // archive name param not set correctly, return an error return ctrl.Result{}, errors.New("create archive failed, archive name not set in restorePoint spec") } -// createVRPQ creates a VerticaRestorePointsQuery to fetch the restore point info. -func (s *SaveRestorePointReconciler) createVRPQ(ctx context.Context) { - rpq := &v1beta1.VerticaRestorePointsQuery{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1beta1.GroupVersion.String(), - Kind: v1beta1.RestorePointsQueryKind, - }, - ObjectMeta: metav1.ObjectMeta{ - GenerateName: fmt.Sprintf("%s-", s.Vdb.Name), - Namespace: s.Vdb.Namespace, - OwnerReferences: []metav1.OwnerReference{s.Vdb.GenerateOwnerReference()}, - }, - Spec: v1beta1.VerticaRestorePointsQuerySpec{ - VerticaDBName: s.Vdb.Name, - FilterOptions: &v1beta1.VerticaRestorePointQueryFilterOptions{ - ArchiveName: s.Vdb.Spec.RestorePoint.Archive, - StartTimestamp: s.Vdb.Status.RestorePoint.StartTimestamp, - EndTimestamp: s.Vdb.Status.RestorePoint.EndTimestamp, - }, - }, - } - s.Log.Info("Creating a VerticaRestorePointsQuery to show the restore point info") - // We will try this only once, if the operator cannot create the object the user will - // be asked to do it manually. This is because we don't want to fail the reconciler - // just because of it and the users have a few ways to easily get the restore point info - // like creating a vrpq themselves or using vsql. - err := s.VRec.Client.Create(ctx, rpq) - if err != nil { - s.VRec.Eventf(s.Vdb, corev1.EventTypeWarning, events.CreateRestorePointsQueryFailed, - "Failed to create the VerticaRestorePointsQuery %q. Manually create one with filter options from vdb.status.restorepoint"+ - " or query archive_restore_points to get the restore point details.", - rpq.GenerateName) - return - } - s.VRec.Eventf(s.Vdb, corev1.EventTypeNormal, events.CreateRestorePointsQuerySucceeded, - "VerticaRestorePointsQuery %s created.", rpq.Name) -} - // runCreateArchiveVclusterAPI will do the actual execution of creating archive. // This handles logging of necessary events. func (s *SaveRestorePointReconciler) runCreateArchiveVclusterAPI(ctx context.Context, @@ -262,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/meta/annotations.go b/pkg/meta/annotations.go index ae6f05949..36c9947c9 100644 --- a/pkg/meta/annotations.go +++ b/pkg/meta/annotations.go @@ -300,11 +300,6 @@ const ( OnlineUpgradeArchiveBeforeReplicationAnnotation = "vertica.com/online-upgrade-archive-before-replication" SaveRestorePointAnnotation = "vertica.com/save-restore-point-on-upgrade" - // Allow users to skip the creation of a VerticaRestorePointsQuery object after saving - // a restore point. When this is false, after saving a restore point, the operator - // will create a VerticaRestorePointsQuery in order to expose the restore point info - // the user. - SkipVRPQCreationAnnotation = "vertica.com/skip-restore-points-query-creation" // This will be set in a sandbox configMap by the vdb controller to wake up the sandbox // controller for upgrading the sandboxes @@ -601,12 +596,6 @@ func GetSaveRestorePoint(annotations map[string]string) bool { return lookupBoolAnnotation(annotations, SaveRestorePointAnnotation, false) } -// GetSkipVRPQCreation returns true if the operator must create -// a VerticaRestorePointsQuery object after saving a restore point. -func GetSkipVRPQCreation(annotations map[string]string) bool { - return lookupBoolAnnotation(annotations, SkipVRPQCreationAnnotation, true) -} - // GetStsNameOverride returns the override for the statefulset name. If one is // not provided, an empty string is returned. func GetStsNameOverride(annotations map[string]string) string { 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/10-errors.yaml b/tests/e2e-leg-6/save-restore-point/10-errors.yaml deleted file mode 100644 index 94d9e6a08..000000000 --- a/tests/e2e-leg-6/save-restore-point/10-errors.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# (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. - -apiVersion: vertica.com/v1beta1 -kind: VerticaRestorePointsQuery \ No newline at end of file diff --git a/tests/e2e-leg-6/save-restore-point/12-enable-vrpq-creation.yaml b/tests/e2e-leg-6/save-restore-point/12-enable-vrpq-creation.yaml deleted file mode 100644 index a3589f631..000000000 --- a/tests/e2e-leg-6/save-restore-point/12-enable-vrpq-creation.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# (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. - -apiVersion: vertica.com/v1 -kind: VerticaDB -metadata: - name: v-upgrade-vertica - annotations: - vertica.com/vcluster-ops: "true" - vertica.com/skip-restore-points-query-creation: "false" \ No newline at end of file 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 c52120af5..9210556ec 100644 --- a/tests/e2e-leg-6/save-restore-point/20-assert.yaml +++ b/tests/e2e-leg-6/save-restore-point/20-assert.yaml @@ -21,16 +21,6 @@ involvedObject: kind: VerticaDB name: v-restore-point --- -apiVersion: v1 -kind: Event -reason: CreateRestorePointsQuerySucceeded -source: - component: verticadb-operator -involvedObject: - apiVersion: vertica.com/v1 - kind: VerticaDB - name: v-restore-point ---- apiVersion: vertica.com/v1 kind: VerticaDB metadata: @@ -38,3 +28,6 @@ metadata: status: restorePoint: archive: test + details: + archive: test + index: 2 diff --git a/tests/e2e-leg-6/save-restore-point/25-wait-for-vrpq-creation.yaml b/tests/e2e-leg-6/save-restore-point/25-wait-for-vrpq-creation.yaml deleted file mode 100644 index f81d4fb7c..000000000 --- a/tests/e2e-leg-6/save-restore-point/25-wait-for-vrpq-creation.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# (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. - -apiVersion: vertica.com/v1beta1 -kind: VerticaRestorePointsQuery -status: - restorePoints: - - archive: test - index: 2 - state: "Query successful" \ No newline at end of file From a4c3f765d81fd83c50a309095da0827c4902f948 Mon Sep 17 00:00:00 2001 From: roypaulin Date: Thu, 3 Oct 2024 02:56:11 +0200 Subject: [PATCH 4/4] Update zz_generated file --- api/v1/zz_generated.deepcopy.go | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 773103d00..d9132291c 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* Copyright [2021-2024] Open Text. @@ -22,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" @@ -110,6 +110,26 @@ func (in *LocalStorage) DeepCopy() *LocalStorage { return out } +// 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. +func (in *RestorePointInfo) DeepCopy() *RestorePointInfo { + if in == nil { + return nil + } + out := new(RestorePointInfo) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RestorePointPolicy) DeepCopyInto(out *RestorePointPolicy) { *out = *in @@ -516,6 +536,11 @@ func (in *VerticaDBStatus) DeepCopyInto(out *VerticaDBStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.RestorePoint != nil { + in, out := &in.RestorePoint, &out.RestorePoint + *out = new(RestorePointInfo) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VerticaDBStatus.