diff --git a/Makefile b/Makefile index f224c0274..ae1fafe11 100644 --- a/Makefile +++ b/Makefile @@ -389,7 +389,6 @@ docker-build-operator: manifests generate fmt vet ## Build operator docker image --build-arg GO_VERSION=${GO_VERSION} \ -f docker-operator/Dockerfile . - .PHONY: docker-build-vlogger docker-build-vlogger: ## Build vertica logger docker image docker pull ${VLOGGER_BASE_IMG}:${VLOGGER_ALPINE_VERSION} # Ensure we have the latest alpine version diff --git a/api/v1/helpers.go b/api/v1/helpers.go index cbdcd5cd8..4fc75022c 100644 --- a/api/v1/helpers.go +++ b/api/v1/helpers.go @@ -868,12 +868,24 @@ func (r *RestorePointPolicy) IsValidRestorePointPolicy() bool { return r != nil && r.Archive != "" && ((r.Index > 0) != (r.ID != "")) } +// IsValidForSaveRestorePoint returns true id archive name to be used +// for creating a restore point is set. +func (r *RestorePointPolicy) IsValidForSaveRestorePoint() bool { + return r != nil && r.Archive != "" +} + // IsRestoreEnabled will return whether the vdb is configured to initialize by reviving from // a restore point in an archive func (v *VerticaDB) IsRestoreEnabled() bool { return v.Spec.InitPolicy == CommunalInitPolicyRevive && v.Spec.RestorePoint != nil } +// IsSaveRestorepointEnabled returns true if the status condition that +// control restore point is set to true. +func (v *VerticaDB) IsSaveRestorepointEnabled() bool { + return v.IsStatusConditionTrue(SaveRestorePointsNeeded) +} + // IsHTTPSTLSConfGenerationEnabled return true if the httpstls.json file should // be generated by the installer. func (v *VerticaDB) IsHTTPSTLSConfGenerationEnabled() (bool, error) { diff --git a/api/v1/version.go b/api/v1/version.go index 38338465b..69cc336e7 100644 --- a/api/v1/version.go +++ b/api/v1/version.go @@ -83,6 +83,8 @@ const ( SandboxSupportedMinVersion = "v24.3.0" // Starting in v24.3.0, we call vclusterops API to get node details instead of executing vsql within the pod FetchNodeDetailsWithVclusterOpsMinVersion = "v24.3.0" + // Starting in v24.4.0, nma server will support create restore point to an existing archive + SaveRestorePointNMAOpsMinVersion = "v24.4.0" ) // GetVerticaVersionStr returns the vertica version, in string form, that is stored diff --git a/api/v1/verticadb_types.go b/api/v1/verticadb_types.go index 3a06d0718..5d437c710 100644 --- a/api/v1/verticadb_types.go +++ b/api/v1/verticadb_types.go @@ -843,6 +843,21 @@ type VerticaDBStatus struct { // +optional // The sandbox statuses Sandboxes []SandboxStatus `json:"sandboxes,omitempty"` + + // +operator-sdk:csv:customresourcedefinitions:type=status + // +optional + // The details about the last created restore point + RestorePoint *RestorePointInfo `json:"restorePoint"` +} + +type RestorePointInfo struct { + // +operator-sdk:csv:customresourcedefinitions:type=status + // Name of the archive that this restore point was created in. + Archive string `json:"archive"` + // +operator-sdk:csv:customresourcedefinitions:type=status + StartTimestamp string `json:"startTimestamp"` + // +operator-sdk:csv:customresourcedefinitions:type=status + EndTimestamp string `json:"endTimestamp"` } type SandboxUpgradeState struct { @@ -890,6 +905,10 @@ const ( // VerticaRestartNeeded is a condition that when set to true will force the // operator to stop/start the vertica pods. VerticaRestartNeeded = "VerticaRestartNeeded" + // SaveRestorePointsNeeded is a condition that when set to true will, + // the operator will create the archive, using the spec.restorePoint.archive + // as the archive name to save to. + SaveRestorePointsNeeded = "SaveRestorePointsNeeded" ) const ( diff --git a/api/v1/verticadb_webhook.go b/api/v1/verticadb_webhook.go index 1ff0ac9f0..86c7b9f15 100644 --- a/api/v1/verticadb_webhook.go +++ b/api/v1/verticadb_webhook.go @@ -193,6 +193,7 @@ func (v *VerticaDB) validateVerticaDBSpec() field.ErrorList { allErrs = v.hasValidSubclusterTypes(allErrs) allErrs = v.hasValidInitPolicy(allErrs) allErrs = v.hasValidRestorePolicy(allErrs) + allErrs = v.hasValidSaveRestorePointConfig(allErrs) allErrs = v.hasValidDBName(allErrs) allErrs = v.hasPrimarySubcluster(allErrs) allErrs = v.validateKsafety(allErrs) @@ -304,6 +305,17 @@ func (v *VerticaDB) hasValidRestorePolicy(allErrs field.ErrorList) field.ErrorLi return allErrs } +func (v *VerticaDB) hasValidSaveRestorePointConfig(allErrs field.ErrorList) field.ErrorList { + if v.IsSaveRestorepointEnabled() && !v.Spec.RestorePoint.IsValidForSaveRestorePoint() { + err := field.Invalid(field.NewPath("spec").Child("restorePoint"), + v.Spec.RestorePoint, + "restorePoint is invalid. When save restore point is enabled, "+ + "archive must be specified.") + allErrs = append(allErrs, err) + } + return allErrs +} + func (v *VerticaDB) validateCommunalPath(allErrs field.ErrorList) field.ErrorList { if v.Spec.InitPolicy == CommunalInitPolicyScheduleOnly { return allErrs diff --git a/api/v1beta1/verticadb_conversion.go b/api/v1beta1/verticadb_conversion.go index aa7b26931..a8b5a1b6f 100644 --- a/api/v1beta1/verticadb_conversion.go +++ b/api/v1beta1/verticadb_conversion.go @@ -261,6 +261,7 @@ func convertToStatus(src *VerticaDBStatus) v1.VerticaDBStatus { Conditions: make([]metav1.Condition, 0), UpgradeStatus: src.UpgradeStatus, Sandboxes: make([]v1.SandboxStatus, len(src.Sandboxes)), + RestorePoint: (*v1.RestorePointInfo)(src.RestorePoint), } for i := range src.Subclusters { dst.Subclusters[i] = convertToSubclusterStatus(src.Subclusters[i]) @@ -285,6 +286,7 @@ func convertFromStatus(src *v1.VerticaDBStatus) VerticaDBStatus { Conditions: make([]VerticaDBCondition, len(src.Conditions)), UpgradeStatus: src.UpgradeStatus, Sandboxes: make([]SandboxStatus, len(src.Sandboxes)), + RestorePoint: (*RestorePointInfo)(src.RestorePoint), } for i := range src.Subclusters { dst.Subclusters[i] = convertFromSubclusterStatus(src.Subclusters[i]) diff --git a/api/v1beta1/verticadb_types.go b/api/v1beta1/verticadb_types.go index 4372b655a..199c6588f 100644 --- a/api/v1beta1/verticadb_types.go +++ b/api/v1beta1/verticadb_types.go @@ -924,6 +924,21 @@ type VerticaDBStatus struct { // +optional // The sandbox statuses Sandboxes []SandboxStatus `json:"sandboxes,omitempty"` + + // +operator-sdk:csv:customresourcedefinitions:type=status + // +optional + // The details about the last created restore point + RestorePoint *RestorePointInfo `json:"restorePoint"` +} + +type RestorePointInfo struct { + // +operator-sdk:csv:customresourcedefinitions:type=status + // Name of the archive that this restore point was created in. + Archive string `json:"archive"` + // +operator-sdk:csv:customresourcedefinitions:type=status + StartTimestamp string `json:"startTimestamp"` + // +operator-sdk:csv:customresourcedefinitions:type=status + EndTimestamp string `json:"endTimestamp"` } type SandboxUpgradeState struct { @@ -974,6 +989,10 @@ const ( // VerticaRestartNeeded is a condition that when set to true will force the // operator to stop/start the vertica pods. VerticaRestartNeeded VerticaDBConditionType = "VerticaRestartNeeded" + // SaveRestorePointsNeeded is a condition that when set to true will, + // the operator will create the archive, using the spec.restorePoint.archive + // as the archive name to save to. + SaveRestorePointsNeeded VerticaDBConditionType = "SaveRestorePointsNeeded" ) // VerticaDBCondition defines condition for VerticaDB diff --git a/go.mod b/go.mod index a77a27eda..b098589cb 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/onsi/gomega v1.24.2 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.14.0 - github.com/vertica/vcluster v1.2.1-0.20240824015949-397ced8a6708 + github.com/vertica/vcluster v1.2.1-0.20240916125930-0654788be326 github.com/vertica/vertica-sql-go v1.1.1 go.uber.org/zap v1.25.0 golang.org/x/text v0.14.0 diff --git a/go.sum b/go.sum index af6315dc9..bce7c6ffc 100644 --- a/go.sum +++ b/go.sum @@ -330,8 +330,8 @@ github.com/theckman/yacspin v0.13.12 h1:CdZ57+n0U6JMuh2xqjnjRq5Haj6v1ner2djtLQRz github.com/theckman/yacspin v0.13.12/go.mod h1:Rd2+oG2LmQi5f3zC3yeZAOl245z8QOvrH4OPOJNZxLg= github.com/tonglil/buflogr v1.0.1 h1:WXFZLKxLfqcVSmckwiMCF8jJwjIgmStJmg63YKRF1p0= github.com/tonglil/buflogr v1.0.1/go.mod h1:yYWwvSpn/3uAaqjf6mJg/XMiAciaR0QcRJH2gJGDxNE= -github.com/vertica/vcluster v1.2.1-0.20240824015949-397ced8a6708 h1:wjYVhJxvlymSIlBYfRMJuBngPzm/qavKhH/vLcKxzf0= -github.com/vertica/vcluster v1.2.1-0.20240824015949-397ced8a6708/go.mod h1:yZ3lnvlwuXWgyCZ9Z6bMYisVjP6Ecffl+Lk5wGX/lPQ= +github.com/vertica/vcluster v1.2.1-0.20240916125930-0654788be326 h1:ZLUnWRhcMQDMDePS+qKZAmQkx/qn/mt6gcrL3y4iaaI= +github.com/vertica/vcluster v1.2.1-0.20240916125930-0654788be326/go.mod h1:yZ3lnvlwuXWgyCZ9Z6bMYisVjP6Ecffl+Lk5wGX/lPQ= github.com/vertica/vertica-sql-go v1.1.1 h1:sZYijzBbvdAbJcl4cYlKjR+Eh/X1hGKzukWuhh8PjvI= github.com/vertica/vertica-sql-go v1.1.1/go.mod h1:fGr44VWdEvL+f+Qt5LkKLOT7GoxaWdoUCnPBU9h6t04= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/pkg/controllers/vdb/offlineupgrade_reconciler.go b/pkg/controllers/vdb/offlineupgrade_reconciler.go index 2b4961178..3eea771bb 100644 --- a/pkg/controllers/vdb/offlineupgrade_reconciler.go +++ b/pkg/controllers/vdb/offlineupgrade_reconciler.go @@ -107,6 +107,8 @@ func (o *OfflineUpgradeReconciler) Reconcile(ctx context.Context, _ *ctrl.Reques // Functions to perform when the image changes. Order matters. funcs := []func(context.Context) (ctrl.Result, error){ + // Save restore point before start upgrade + o.saveRestorePoint, // Initiate an upgrade by setting condition and event recording o.startUpgrade, o.logEventIfThisUpgradeWasNotChosen, @@ -151,6 +153,15 @@ func (o *OfflineUpgradeReconciler) Reconcile(ctx context.Context, _ *ctrl.Reques return ctrl.Result{}, o.Manager.logUpgradeSucceeded(sandbox) } +func (o *OfflineUpgradeReconciler) saveRestorePoint(ctx context.Context) (ctrl.Result, error) { + actor := MakeSaveRestorePointReconciler(o.Rec, o.Vdb, o.Log, o.PFacts, o.Dispatcher, o.Rec.GetClient()) + saveRestoreRec := actor.(*SaveRestorePoint) + + hostIP, ok := pfacts.FindFirstUpPodIP(true, "") + saveRestoreRec.runSaveRestorePointVclusterAPI(ctx, hostIP, archive, pf.sandbox) + return o.Manager.startUpgrade(ctx, o.PFacts.GetSandboxName()) +} + func (o *OfflineUpgradeReconciler) startUpgrade(ctx context.Context) (ctrl.Result, error) { return o.Manager.startUpgrade(ctx, o.PFacts.GetSandboxName()) } diff --git a/pkg/controllers/vdb/saverestorepoint_reconciler.go b/pkg/controllers/vdb/saverestorepoint_reconciler.go new file mode 100644 index 000000000..99446ad7a --- /dev/null +++ b/pkg/controllers/vdb/saverestorepoint_reconciler.go @@ -0,0 +1,225 @@ +/* + (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" + "strings" + "time" + + "github.com/go-logr/logr" + vapi "github.com/vertica/vertica-kubernetes/api/v1" + "github.com/vertica/vertica-kubernetes/pkg/controllers" + "github.com/vertica/vertica-kubernetes/pkg/events" + vmeta "github.com/vertica/vertica-kubernetes/pkg/meta" + "github.com/vertica/vertica-kubernetes/pkg/vadmin" + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/createarchive" + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/saverestorepoint" + "github.com/vertica/vertica-kubernetes/pkg/vdbstatus" + corev1 "k8s.io/api/core/v1" + "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" +) + +// SaveRestorePoint will create archive and save restore point if triggered +type SaveRestorePoint struct { + VRec *VerticaDBReconciler + Vdb *vapi.VerticaDB + Log logr.Logger + client.Client + Dispatcher vadmin.Dispatcher + PFacts *PodFacts + OriginalPFacts *PodFacts + InitiatorIP string // The IP of the pod that we run vclusterOps from +} + +func MakeSaveRestorePointReconciler(r *VerticaDBReconciler, vdb *vapi.VerticaDB, log logr.Logger, + pfacts *PodFacts, dispatcher vadmin.Dispatcher, cli client.Client) controllers.ReconcileActor { + pfactsForMainCluster := pfacts.Copy(vapi.MainCluster) + return &SaveRestorePoint{ + VRec: r, + Log: log.WithName("SaveRestorePoint"), + Vdb: vdb, + Client: cli, + Dispatcher: dispatcher, + PFacts: &pfactsForMainCluster, + OriginalPFacts: pfacts, + } +} + +// Reconcile will create an archive if the status condition indicates true +// And will save restore point to the created archive if restorePoint.archive value +// is provided in the CRD spec +func (s *SaveRestorePoint) Reconcile(ctx context.Context, _ *ctrl.Request) (ctrl.Result, error) { + // Only proceed if the SaveRestorePointsNeeded status condition is set to true. + if !s.Vdb.IsStatusConditionTrue(vapi.SaveRestorePointsNeeded) { + return ctrl.Result{}, nil + } + // Check if deployment is using vclusterops + if !vmeta.UseVClusterOps(s.Vdb.Annotations) { + s.VRec.Event(s.Vdb, corev1.EventTypeWarning, events.InDBSaveRestorePointNotSupported, + "SaveRestorePoint is not supported for admintools deployments") + err := vdbstatus.UpdateCondition(ctx, s.VRec.Client, s.Vdb, + vapi.MakeCondition(vapi.SaveRestorePointsNeeded, + metav1.ConditionFalse, "AdmintoolsNotSupported"), + ) + if err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, nil + } + + // Ensure vertica version supports in-database SaveRestorePoint vcluster API + vinf, err := s.Vdb.MakeVersionInfoCheck() + if err != nil { + return ctrl.Result{}, err + } + if !vinf.IsEqualOrNewer(vapi.SaveRestorePointNMAOpsMinVersion) { + s.VRec.Eventf(s.Vdb, corev1.EventTypeWarning, events.UnsupportedVerticaVersion, + "The Vertica version %q doesn't support create restore points. The minimum version supported is %s.", + vinf.VdbVer, vapi.SaveRestorePointNMAOpsMinVersion) + err = vdbstatus.UpdateCondition(ctx, s.VRec.Client, s.Vdb, + vapi.MakeCondition(vapi.SaveRestorePointsNeeded, + metav1.ConditionFalse, "IncompatibleDB"), + ) + if err != nil { + return ctrl.Result{}, err + } + return ctrl.Result{}, nil + } + + err = s.PFacts.Collect(ctx, s.Vdb) + if err != nil { + return ctrl.Result{}, err + } + + hostIP, ok := s.PFacts.FindFirstUpPodIP(false, "") + if !ok { + s.Log.Info("No running pod for create restore point. Requeuing.") + return ctrl.Result{Requeue: true}, nil + } + + // Check if required attribute is set in spec: restorePoint.archive + if s.Vdb.Spec.RestorePoint != nil && s.Vdb.Spec.RestorePoint.Archive != "" { + // Always tried to create archive + // params: context, host, archive-name, sandbox, num of restore point(0 is unlimited) + err = s.runCreateArchiveVclusterAPI(ctx, hostIP, s.Vdb.Spec.RestorePoint.Archive, "", 0) + if err != nil { + return ctrl.Result{}, err + } + // Once save restore point, change condition + // params: context, host, archive-name, sandbox, num of restore point(0 is unlimited) + err = s.runSaveRestorePointVclusterAPI(ctx, hostIP, s.Vdb.Spec.RestorePoint.Archive, "") + if err != nil { + return ctrl.Result{}, err + } + } + // archive name param not set correctly, Log warning + s.Log.Info("create archive failed, archive name not set in restorePoint spec.") + return ctrl.Result{Requeue: true}, nil +} + +// runCreateArchiveVclusterAPI will do the actual execution of creating archive. +// This handles logging of necessary events. +func (s *SaveRestorePoint) runCreateArchiveVclusterAPI(ctx context.Context, + host string, archiveName string, sandbox string, numRestorePoint int) error { + opts := s.genCreateArchiveOpts(host, archiveName, numRestorePoint, sandbox) + s.VRec.Event(s.Vdb, corev1.EventTypeNormal, events.CreateArchiveStart, "Starting create archive") + start := time.Now() + + // Always try to create + err := s.Dispatcher.CreateArchive(ctx, opts...) + if err != nil { + // If already exist, ignore error, log warning + if strings.Contains(err.Error(), "Duplicate object on host") { + s.VRec.Eventf(s.Vdb, corev1.EventTypeNormal, events.ArchiveExists, + "archive: %s already exist", archiveName) + return nil + } + // For all other errors, return error + s.VRec.Eventf(s.Vdb, corev1.EventTypeWarning, events.CreateArchiveFailed, + "Failed to create archive %q", archiveName) + return err + } + + s.VRec.Eventf(s.Vdb, corev1.EventTypeNormal, events.CreateArchiveSucceeded, + "Successfully create archive. It took %s", time.Since(start).Truncate(time.Second)) + return nil +} + +// runSaveRestorePointVclusterAPI will do the actual execution of saving restore point to +// an existing archive. +// This handles logging of necessary events. +func (s *SaveRestorePoint) runSaveRestorePointVclusterAPI(ctx context.Context, + host string, archiveName string, sandbox string) error { + opts := s.genSaveRestorePointOpts(host, archiveName, sandbox) + s.VRec.Event(s.Vdb, corev1.EventTypeNormal, + events.SaveRestorePointStart, "Starting save restore point") + start := time.Now() + + err := s.Dispatcher.SaveRestorePoint(ctx, opts...) + if err != nil { + s.VRec.Eventf(s.Vdb, corev1.EventTypeWarning, events.SaveRestorePointFailed, + "Failed to save restore point to archive: %s", archiveName) + return err + } + end := time.Now() + s.VRec.Eventf(s.Vdb, corev1.EventTypeNormal, events.SaveRestorePointSucceeded, + "Successfully save restore point to archive: %s. It took %s", + archiveName, time.Since(start).Truncate(time.Second)) + refreshStatusInPlace := func(vdb *vapi.VerticaDB) error { + meta.SetStatusCondition(&vdb.Status.Conditions, *vapi.MakeCondition(vapi.SaveRestorePointsNeeded, + metav1.ConditionFalse, "Completed")) + if vdb.Status.RestorePoint == nil { + vdb.Status.RestorePoint = new(vapi.RestorePointInfo) + } + vdb.Status.RestorePoint.Archive = archiveName + 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") + return nil + } + // Clear the condition and add a status after restore point creation. + err = vdbstatus.Update(ctx, s.VRec.Client, s.Vdb, refreshStatusInPlace) + if err != nil { + return err + } + return nil +} + +// genCreateArchiveOpts will return the options to use with the create archive command +func (s *SaveRestorePoint) genCreateArchiveOpts(initiatorIP string, archiveName string, + numRestorePoint int, sandbox string) []createarchive.Option { + opts := []createarchive.Option{ + createarchive.WithInitiator(initiatorIP), + createarchive.WithArchiveName(archiveName), + createarchive.WithNumRestorePoints(numRestorePoint), + createarchive.WithSandbox(sandbox), + } + return opts +} + +// genSaveRestorePointOpts will return the options to use with the create archive command +func (s *SaveRestorePoint) genSaveRestorePointOpts(initiatorIP string, archiveName string, + sandbox string) []saverestorepoint.Option { + opts := []saverestorepoint.Option{ + saverestorepoint.WithInitiator(initiatorIP), + saverestorepoint.WithArchiveName(archiveName), + saverestorepoint.WithSandbox(sandbox), + } + return opts +} diff --git a/pkg/controllers/vdb/saverestorepoint_reconciler_test.go b/pkg/controllers/vdb/saverestorepoint_reconciler_test.go new file mode 100644 index 000000000..a64e05840 --- /dev/null +++ b/pkg/controllers/vdb/saverestorepoint_reconciler_test.go @@ -0,0 +1,52 @@ +/* + (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" + vapi "github.com/vertica/vertica-kubernetes/api/v1" + "github.com/vertica/vertica-kubernetes/pkg/cmds" + "github.com/vertica/vertica-kubernetes/pkg/test" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ctrl "sigs.k8s.io/controller-runtime" +) + +var _ = Describe("saverestorepoint_reconciler", func() { + ctx := context.Background() + + It("should update status if vclusterops is disabled", func() { + vdb := vapi.MakeVDB() + test.CreateVDB(ctx, k8sClient, vdb) + defer test.DeleteVDB(ctx, k8sClient, vdb) + + meta.SetStatusCondition(&vdb.Status.Conditions, + *vapi.MakeCondition(vapi.SaveRestorePointsNeeded, metav1.ConditionTrue, "Done")) + 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) + res, err := r.Reconcile(ctx, &ctrl.Request{}) + Expect(err).Should(Succeed()) + Expect(res.Requeue).Should(BeFalse()) + fetchedVdb := &vapi.VerticaDB{} + Expect(k8sClient.Get(ctx, vdb.ExtractNamespacedName(), fetchedVdb)).Should(Succeed()) + Expect(fetchedVdb.IsStatusConditionFalse(vapi.SaveRestorePointsNeeded)).Should(BeTrue()) + }) +}) diff --git a/pkg/controllers/vdb/upgrade.go b/pkg/controllers/vdb/upgrade.go index 74f895f68..94053b566 100644 --- a/pkg/controllers/vdb/upgrade.go +++ b/pkg/controllers/vdb/upgrade.go @@ -192,6 +192,15 @@ func (i *UpgradeManager) finishUpgrade(ctx context.Context, sbName string) (ctrl return ctrl.Result{}, nil } +// saveRestorePoint handles condition status and event recording for start of an upgrade +func (i *UpgradeManager) saveRestorePoint(ctx context.Context) (ctrl.Result, error) { + if i.Vdb.Annotations[vmeta.SaveRestorePointsTriggerID] == vmeta.SaveRestorePointsTrue { + i.Rec.Eventf(i.Vdb, corev1.EventTypeNormal, events.SaveRestorePointStart, + "save a restore point before initiating the upgrade") + } + return ctrl.Result{}, nil +} + // logUpgradeSucceeded logs an event msg when upgrade is successful func (i *UpgradeManager) logUpgradeSucceeded(sandbox string) error { targetImage, err := i.getTargetImage(sandbox) diff --git a/pkg/controllers/vdb/verticadb_controller.go b/pkg/controllers/vdb/verticadb_controller.go index 8fd83476a..e196ce352 100644 --- a/pkg/controllers/vdb/verticadb_controller.go +++ b/pkg/controllers/vdb/verticadb_controller.go @@ -265,6 +265,8 @@ func (r *VerticaDBReconciler) constructActors(log logr.Logger, vdb *vapi.Vertica MakeSandboxUpgradeReconciler(r, log, vdb), // 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), // 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/events/event.go b/pkg/events/event.go index cdf81e3b9..5fb605e17 100644 --- a/pkg/events/event.go +++ b/pkg/events/event.go @@ -18,93 +18,101 @@ 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" - 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" - PauseConnectionsRetry = "PauseConnectionsRetry" - 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" + 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" ) // Constants for VerticaAutoscaler reconciler diff --git a/pkg/meta/annotations.go b/pkg/meta/annotations.go index a0c03553e..1fa228347 100644 --- a/pkg/meta/annotations.go +++ b/pkg/meta/annotations.go @@ -303,6 +303,11 @@ const ( // omitted, then the name of the subclusters' statefulset will be // `-' StsNameOverrideAnnotation = "vertica.com/statefulset-name-override" + + // This will be used to force an upgrade to create a restore point before starting. + SaveRestorePointsTriggerID = "vertica.com/save-restore-point-on-upgrade" + SaveRestorePointsTrue = "true" + SaveRestorePointsFalse = "false" ) // IsPauseAnnotationSet will check the annotations for a special value that will diff --git a/pkg/mockvops/mockvops.go b/pkg/mockvops/mockvops.go index 9a90c8d34..316ec3e28 100644 --- a/pkg/mockvops/mockvops.go +++ b/pkg/mockvops/mockvops.go @@ -72,8 +72,8 @@ func (*MockVClusterOps) VStopDatabase(_ *vclusterops.VStopDatabaseOptions) error func (*MockVClusterOps) VInstallPackages(_ *vclusterops.VInstallPackagesOptions) (*vclusterops.InstallPackageStatus, error) { return nil, nil } -func (*MockVClusterOps) VReplicateDatabase(_ *vclusterops.VReplicationDatabaseOptions) error { - return nil +func (*MockVClusterOps) VReplicateDatabase(_ *vclusterops.VReplicationDatabaseOptions) (int64, error) { + return 0, nil } func (*MockVClusterOps) VFetchNodesDetails(_ *vclusterops.VFetchNodesDetailsOptions) (vclusterops.NodesDetails, error) { return nil, nil @@ -84,6 +84,12 @@ func (*MockVClusterOps) VSandbox(_ *vclusterops.VSandboxOptions) error { func (*MockVClusterOps) VUnsandbox(_ *vclusterops.VUnsandboxOptions) error { return nil } +func (*MockVClusterOps) VCreateArchive(_ *vclusterops.VCreateArchiveOptions) error { + return nil +} +func (*MockVClusterOps) VSaveRestorePoint(_ *vclusterops.VSaveRestorePointOptions) error { + return nil +} func (*MockVClusterOps) VPromoteSandboxToMain(_ *vclusterops.VPromoteSandboxToMainOptions) error { return nil } diff --git a/pkg/vadmin/create_archive_at.go b/pkg/vadmin/create_archive_at.go new file mode 100644 index 000000000..f461b196a --- /dev/null +++ b/pkg/vadmin/create_archive_at.go @@ -0,0 +1,27 @@ +/* + (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 vadmin + +import ( + "context" + "errors" + + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/createarchive" +) + +func (a *Admintools) CreateArchive(_ context.Context, opts ...createarchive.Option) error { + return errors.New("CreateArchive is not supported for admintools deployments") +} diff --git a/pkg/vadmin/create_archive_vc.go b/pkg/vadmin/create_archive_vc.go new file mode 100644 index 000000000..5c2a4eab2 --- /dev/null +++ b/pkg/vadmin/create_archive_vc.go @@ -0,0 +1,74 @@ +/* + (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 vadmin + +import ( + "context" + + vops "github.com/vertica/vcluster/vclusterops" + "github.com/vertica/vertica-kubernetes/pkg/net" + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/createarchive" +) + +// CreateArchive will create an archive point in the database +func (v *VClusterOps) CreateArchive(ctx context.Context, opts ...createarchive.Option) error { + v.setupForAPICall("CreateArchive") + defer v.tearDownForAPICall() + v.Log.Info("Starting vcluster CreateArchive") + + // get the certs + certs, err := v.retrieveNMACerts(ctx) + if err != nil { + return err + } + + s := createarchive.Params{} + s.Make(opts...) + + // call vclusterOps library to sandbox a subcluster + vopts := v.genCreateArchiveOptions(&s, certs) + err = v.VCreateArchive(&vopts) + if err != nil { + v.Log.Error(err, "failed to create an archive", "archive name", + vopts.ArchiveName, "sandbox", vopts.Sandbox, "num restore point", vopts.NumRestorePoint) + return err + } + + v.Log.Info("Successfully create an archive", "archive name", + vopts.ArchiveName, "sandbox", vopts.Sandbox, "num restore point", vopts.NumRestorePoint) + return nil +} + +func (v *VClusterOps) genCreateArchiveOptions(s *createarchive.Params, certs *HTTPSCerts) vops.VCreateArchiveOptions { + opts := vops.VCreateArchiveFactory() + + opts.DBName = v.VDB.Spec.DBName + opts.IsEon = v.VDB.IsEON() + opts.RawHosts = append(opts.RawHosts, s.InitiatorIP) + opts.IPv6 = net.IsIPv6(s.InitiatorIP) + opts.ArchiveName = s.ArchiveName + opts.Sandbox = s.Sandbox + opts.NumRestorePoint = s.NumRestorePoints + + // auth options + opts.UserName = v.VDB.GetVerticaUser() + opts.Password = &v.Password + opts.Key = certs.Key + opts.Cert = certs.Cert + opts.CaCert = certs.CaCert + + return opts +} diff --git a/pkg/vadmin/create_archive_vc_test.go b/pkg/vadmin/create_archive_vc_test.go new file mode 100644 index 000000000..6e7e6654d --- /dev/null +++ b/pkg/vadmin/create_archive_vc_test.go @@ -0,0 +1,51 @@ +/* + (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 vadmin + +import ( + "context" + "fmt" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + vops "github.com/vertica/vcluster/vclusterops" + "github.com/vertica/vertica-kubernetes/pkg/test" + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/createarchive" +) + +// mock version of VCreateArchive() that is invoked inside VClusterOps.CreateArchive() +func (m *MockVClusterOps) VCreateArchive(options *vops.VCreateArchiveOptions) error { + // verify basic options + if options.ArchiveName != TestArchiveName { + return fmt.Errorf("failed to retrieve subcluster name") + } + return m.VerifyDBOptions(&options.DatabaseOptions) +} + +var _ = Describe("create_archive_vc", func() { + ctx := context.Background() + + It("should call vclusterOps library with create_archive task", func() { + dispatcher := mockVClusterOpsDispatcher() + dispatcher.VDB.Spec.DBName = TestDBName + dispatcher.VDB.Spec.NMATLSSecret = "create-archive" + test.CreateFakeTLSSecret(ctx, dispatcher.VDB, dispatcher.Client, dispatcher.VDB.Spec.NMATLSSecret) + defer test.DeleteSecret(ctx, dispatcher.Client, dispatcher.VDB.Spec.NMATLSSecret) + Ω(dispatcher.CreateArchive(ctx, + createarchive.WithInitiator(TestInitiatorIP), + createarchive.WithArchiveName(TestArchiveName))).Should(Succeed()) + }) +}) diff --git a/pkg/vadmin/interface.go b/pkg/vadmin/interface.go index 420695409..431c755d4 100644 --- a/pkg/vadmin/interface.go +++ b/pkg/vadmin/interface.go @@ -27,6 +27,7 @@ import ( "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/addnode" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/addsc" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/altersc" + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/createarchive" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/createdb" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/describedb" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/fetchnodedetails" @@ -44,11 +45,13 @@ import ( "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/restartnode" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/revivedb" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/sandboxsc" + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/saverestorepoint" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/setconfigparameter" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/showrestorepoints" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/startdb" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/stopdb" "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/unsandboxsc" + ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -120,6 +123,12 @@ type Dispatcher interface { // UnsandboxSubcluster will move a subcluster from a sandbox to main cluster UnsandboxSubcluster(ctx context.Context, opts ...unsandboxsc.Option) error + // CreateArchive will create an archive in database + CreateArchive(ctx context.Context, opts ...createarchive.Option) error + + // SaveRestorePoint will create a restore point to an existing archive + SaveRestorePoint(ctx context.Context, opts ...saverestorepoint.Option) error + AlterSubclusterType(ctx context.Context, opts ...altersc.Option) error // SetConfigurationParameter will set a config parameter to a certain value at a certain level in a given cluster @@ -258,11 +267,13 @@ type VClusterProvider interface { VStartNodes(options *vops.VStartNodesOptions) error VShowRestorePoints(options *vops.VShowRestorePointsOptions) ([]vops.RestorePoint, error) VInstallPackages(options *vops.VInstallPackagesOptions) (*vops.InstallPackageStatus, error) - VReplicateDatabase(options *vops.VReplicationDatabaseOptions) error + VReplicateDatabase(options *vops.VReplicationDatabaseOptions) (int64, error) VFetchNodesDetails(options *vops.VFetchNodesDetailsOptions) (vops.NodesDetails, error) VPromoteSandboxToMain(options *vops.VPromoteSandboxToMainOptions) error VSandbox(options *vops.VSandboxOptions) error VUnsandbox(options *vops.VUnsandboxOptions) error + VCreateArchive(options *vops.VCreateArchiveOptions) error + VSaveRestorePoint(options *vops.VSaveRestorePointOptions) error VAlterSubclusterType(options *vops.VAlterSubclusterTypeOptions) error VSetConfigurationParameters(options *vops.VSetConfigurationParameterOptions) error VGetConfigurationParameters(options *vops.VGetConfigurationParameterOptions) (string, error) diff --git a/pkg/vadmin/opts/createarchive/opts.go b/pkg/vadmin/opts/createarchive/opts.go new file mode 100644 index 000000000..ddd3d7ae5 --- /dev/null +++ b/pkg/vadmin/opts/createarchive/opts.go @@ -0,0 +1,59 @@ +/* + (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 createarchive + +// Params holds all of the option for an create archive invocation. +type Params struct { + InitiatorIP string + // Required arguments + ArchiveName string + // Optional arguments + NumRestorePoints int + Sandbox string +} + +type Option func(*Params) + +// Make will fill in the Params based on the options chosen +func (s *Params) Make(opts ...Option) { + for _, opt := range opts { + opt(s) + } +} + +func WithInitiator(initiatorIP string) Option { + return func(s *Params) { + s.InitiatorIP = initiatorIP + } +} + +func WithArchiveName(archiveName string) Option { + return func(s *Params) { + s.ArchiveName = archiveName + } +} + +func WithNumRestorePoints(numRestorePoints int) Option { + return func(s *Params) { + s.NumRestorePoints = numRestorePoints + } +} + +func WithSandbox(sandbox string) Option { + return func(s *Params) { + s.Sandbox = sandbox + } +} diff --git a/pkg/vadmin/opts/saverestorepoint/opts.go b/pkg/vadmin/opts/saverestorepoint/opts.go new file mode 100644 index 000000000..81fb293df --- /dev/null +++ b/pkg/vadmin/opts/saverestorepoint/opts.go @@ -0,0 +1,52 @@ +/* + (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 saverestorepoint + +// Params holds all of the option for an create archive invocation. +type Params struct { + InitiatorIP string + // Required arguments + ArchiveName string + // Optional arguments + Sandbox string +} + +type Option func(*Params) + +// Make will fill in the Params based on the options chosen +func (s *Params) Make(opts ...Option) { + for _, opt := range opts { + opt(s) + } +} + +func WithInitiator(initiatorIP string) Option { + return func(s *Params) { + s.InitiatorIP = initiatorIP + } +} + +func WithArchiveName(archiveName string) Option { + return func(s *Params) { + s.ArchiveName = archiveName + } +} + +func WithSandbox(sandbox string) Option { + return func(s *Params) { + s.Sandbox = sandbox + } +} diff --git a/pkg/vadmin/replication_start_vc.go b/pkg/vadmin/replication_start_vc.go index 2fa756941..412cfde30 100644 --- a/pkg/vadmin/replication_start_vc.go +++ b/pkg/vadmin/replication_start_vc.go @@ -43,7 +43,7 @@ func (v *VClusterOps) ReplicateDB(ctx context.Context, opts ...replicationstart. // call vcluster-ops library to replicate db vopts := v.genReplicateDBOptions(&r, certs) - err = v.VReplicateDatabase(vopts) + _, err = v.VReplicateDatabase(vopts) if err != nil { v.Log.Error(err, "failed to replicate a database") return ctrl.Result{}, err diff --git a/pkg/vadmin/replication_start_vc_test.go b/pkg/vadmin/replication_start_vc_test.go index c33e9c067..005892b43 100644 --- a/pkg/vadmin/replication_start_vc_test.go +++ b/pkg/vadmin/replication_start_vc_test.go @@ -27,43 +27,43 @@ import ( ) // mock version of VReplicateDatabase() that is invoked inside VClusterOps.ReplicateDB() -func (m *MockVClusterOps) VReplicateDatabase(options *vops.VReplicationDatabaseOptions) (err error) { +func (m *MockVClusterOps) VReplicateDatabase(options *vops.VReplicationDatabaseOptions) (a int64, err error) { // verify source db name, source username and source password err = m.VerifyCommonOptions(&options.DatabaseOptions) if err != nil { - return err + return a, err } // verify target db name, target username and target password err = m.VerifyTargetDBNameUserNamePassword(options) if err != nil { - return err + return a, err } // verify auth options err = m.VerifyCerts(&options.DatabaseOptions) if err != nil { - return err + return a, err } // verify source IP and target IP err = m.VerifySourceAndTargetIPs(options) if err != nil { - return err + return a, err } // verify source TLS config err = m.VerifySourceTLSConfig(options) if err != nil { - return err + return a, err } // verify eon mode err = m.VerifyEonMode(&options.DatabaseOptions) if err != nil { - return err + return a, err } - return nil + return a, nil } var _ = Describe("replication_start_vc", func() { diff --git a/pkg/vadmin/sandbox_sc_vc.go b/pkg/vadmin/sandbox_sc_vc.go index a240bf827..88be407c1 100644 --- a/pkg/vadmin/sandbox_sc_vc.go +++ b/pkg/vadmin/sandbox_sc_vc.go @@ -24,6 +24,8 @@ import ( ) // SandboxSubcluster will add a subcluster in a sandbox of the database +// +//nolint:dupl func (v *VClusterOps) SandboxSubcluster(ctx context.Context, opts ...sandboxsc.Option) error { v.setupForAPICall("SandboxSubcluster") defer v.tearDownForAPICall() diff --git a/pkg/vadmin/save_restore_point_at.go b/pkg/vadmin/save_restore_point_at.go new file mode 100644 index 000000000..674a46aff --- /dev/null +++ b/pkg/vadmin/save_restore_point_at.go @@ -0,0 +1,27 @@ +/* + (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 vadmin + +import ( + "context" + "errors" + + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/saverestorepoint" +) + +func (a *Admintools) SaveRestorePoint(_ context.Context, opts ...saverestorepoint.Option) error { + return errors.New("SaveRestorePoint is not supported for admintools deployments") +} diff --git a/pkg/vadmin/save_restore_point_vc.go b/pkg/vadmin/save_restore_point_vc.go new file mode 100644 index 000000000..81392d424 --- /dev/null +++ b/pkg/vadmin/save_restore_point_vc.go @@ -0,0 +1,75 @@ +/* + (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 vadmin + +import ( + "context" + + vops "github.com/vertica/vcluster/vclusterops" + "github.com/vertica/vertica-kubernetes/pkg/net" + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/saverestorepoint" +) + +// SaveRestorePoint will create an archive point in the database +// +//nolint:dupl +func (v *VClusterOps) SaveRestorePoint(ctx context.Context, opts ...saverestorepoint.Option) error { + v.setupForAPICall("SaveRestorePoint") + defer v.tearDownForAPICall() + v.Log.Info("Starting vcluster SaveRestorePoint") + + // get the certs + certs, err := v.retrieveNMACerts(ctx) + if err != nil { + return err + } + + s := saverestorepoint.Params{} + s.Make(opts...) + + // call vclusterOps library to sandbox a subcluster + vopts := v.genSaveRestorePointOptions(&s, certs) + err = v.VSaveRestorePoint(&vopts) + if err != nil { + v.Log.Error(err, "failed to create a restore point to archive", "archive name", + vopts.ArchiveName, "sandbox", vopts.Sandbox) + return err + } + + v.Log.Info("Successfully create a restore point to archive", "archive name", + vopts.ArchiveName, "sandbox", vopts.Sandbox) + return nil +} + +func (v *VClusterOps) genSaveRestorePointOptions(s *saverestorepoint.Params, certs *HTTPSCerts) vops.VSaveRestorePointOptions { + opts := vops.VSaveRestorePointFactory() + + opts.DBName = v.VDB.Spec.DBName + opts.IsEon = v.VDB.IsEON() + opts.RawHosts = append(opts.RawHosts, s.InitiatorIP) + opts.ArchiveName = s.ArchiveName + opts.Sandbox = s.Sandbox + opts.IPv6 = net.IsIPv6(s.InitiatorIP) + + // auth options + opts.UserName = v.VDB.GetVerticaUser() + opts.Password = &v.Password + opts.Key = certs.Key + opts.Cert = certs.Cert + opts.CaCert = certs.CaCert + + return opts +} diff --git a/pkg/vadmin/save_restore_point_vc_test.go b/pkg/vadmin/save_restore_point_vc_test.go new file mode 100644 index 000000000..2ea0562be --- /dev/null +++ b/pkg/vadmin/save_restore_point_vc_test.go @@ -0,0 +1,74 @@ +/* + (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 vadmin + +import ( + "context" + "fmt" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + vops "github.com/vertica/vcluster/vclusterops" + "github.com/vertica/vertica-kubernetes/pkg/test" + "github.com/vertica/vertica-kubernetes/pkg/vadmin/opts/saverestorepoint" +) + +const ( + sb = "sand" +) + +// mock version of VSaveRestorePoint() that is invoked inside VClusterOps.VSaveRestorePoint() +func (m *MockVClusterOps) VSaveRestorePoint(options *vops.VSaveRestorePointOptions) error { + // verify common options + err := m.VerifyCommonOptions(&options.DatabaseOptions) + if err != nil { + return err + } + + // verify hosts and eon mode + err = m.VerifyInitiatorIPAndEonMode(&options.DatabaseOptions) + if err != nil { + return err + } + + // verify basic options + if options.ArchiveName != TestArchiveName { + return fmt.Errorf("failed to retrieve archive name") + } + + if options.Sandbox != sb { + return fmt.Errorf("failed to retrieve sandbox") + } + + // verify auth options + return m.VerifyCerts(&options.DatabaseOptions) +} + +var _ = Describe("create_save_restore_point_vc", func() { + ctx := context.Background() + + It("should call vclusterOps library with create_save_restore_point task", func() { + dispatcher := mockVClusterOpsDispatcher() + dispatcher.VDB.Spec.DBName = TestDBName + dispatcher.VDB.Spec.NMATLSSecret = "save-restore-point" + test.CreateFakeTLSSecret(ctx, dispatcher.VDB, dispatcher.Client, dispatcher.VDB.Spec.NMATLSSecret) + defer test.DeleteSecret(ctx, dispatcher.Client, dispatcher.VDB.Spec.NMATLSSecret) + Ω(dispatcher.SaveRestorePoint(ctx, + saverestorepoint.WithInitiator(TestInitiatorIP), + saverestorepoint.WithSandbox(sb), + saverestorepoint.WithArchiveName(TestArchiveName))).Should(Succeed()) + }) +}) diff --git a/pkg/vadmin/suite_test.go b/pkg/vadmin/suite_test.go index b0cecdddd..5e093fddb 100644 --- a/pkg/vadmin/suite_test.go +++ b/pkg/vadmin/suite_test.go @@ -286,6 +286,23 @@ func (m *MockVClusterOps) VerifyCerts(options *vops.DatabaseOptions) error { return nil } +func (m *MockVClusterOps) VerifyDBOptions(options *vops.DatabaseOptions) error { + // verify common options + err := m.VerifyCommonOptions(options) + if err != nil { + return err + } + + // verify hosts and eon mode + err = m.VerifyInitiatorIPAndEonMode(options) + if err != nil { + return err + } + + // verify auth options + return m.VerifyCerts(options) +} + // VerifySourceAndTargetIPs is used in vcluster-ops unit test for verifying source and target hosts // (both a single IP) in a replication func (m *MockVClusterOps) VerifySourceAndTargetIPs(options *vops.VReplicationDatabaseOptions) error { diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/05-create-communal-creds.yaml b/tests/e2e-leg-6/save-restore-point/00-create-communal-creds.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/05-create-communal-creds.yaml rename to tests/e2e-leg-6/save-restore-point/00-create-communal-creds.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/15-assert.yaml b/tests/e2e-leg-6/save-restore-point/01-assert.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/15-assert.yaml rename to tests/e2e-leg-6/save-restore-point/01-assert.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/15-deploy-operator.yaml b/tests/e2e-leg-6/save-restore-point/01-deploy-operator.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/15-deploy-operator.yaml rename to tests/e2e-leg-6/save-restore-point/01-deploy-operator.yaml diff --git a/tests/e2e-leg-6/save-restore-point/02-assert.yaml b/tests/e2e-leg-6/save-restore-point/02-assert.yaml new file mode 100644 index 000000000..0bd1a36d6 --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/02-assert.yaml @@ -0,0 +1,22 @@ +# (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: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: integration-test-role +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: integration-test-rb diff --git a/tests/e2e-leg-6/save-restore-point/02-rbac.yaml b/tests/e2e-leg-6/save-restore-point/02-rbac.yaml new file mode 100644 index 000000000..c6c5d01da --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/02-rbac.yaml @@ -0,0 +1,18 @@ +# (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: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: kubectl apply --namespace $NAMESPACE -f ../../manifests/rbac/base/rbac.yaml + ignoreFailure: true diff --git a/tests/e2e-leg-6/save-restore-point/03-assert.yaml b/tests/e2e-leg-6/save-restore-point/03-assert.yaml new file mode 100644 index 000000000..f40bec57a --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/03-assert.yaml @@ -0,0 +1,29 @@ +# (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: apps/v1 +kind: StatefulSet +metadata: + name: v-restore-point-sc1 +status: + replicas: 1 + readyReplicas: 1 +--- +apiVersion: vertica.com/v1 +kind: VerticaDB +metadata: + name: v-restore-point +status: + subclusters: + - addedToDBCount: 1 + upNodeCount: 1 diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/25-setup-v12-vdb.yaml b/tests/e2e-leg-6/save-restore-point/03-create-db.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/25-setup-v12-vdb.yaml rename to tests/e2e-leg-6/save-restore-point/03-create-db.yaml diff --git a/tests/e2e-leg-6/save-restore-point/05-assert.yaml b/tests/e2e-leg-6/save-restore-point/05-assert.yaml new file mode 100644 index 000000000..ed42cfdd3 --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/05-assert.yaml @@ -0,0 +1,22 @@ +# (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: v1 +kind: Event +reason: CreateArchiveStart +source: + component: verticadb-operator +involvedObject: + apiVersion: vertica.com/v1 + kind: VerticaDB + name: v-restore-point \ No newline at end of file diff --git a/tests/e2e-leg-6/save-restore-point/05-create-restore-point.yaml b/tests/e2e-leg-6/save-restore-point/05-create-restore-point.yaml new file mode 100644 index 000000000..91735d536 --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/05-create-restore-point.yaml @@ -0,0 +1,25 @@ +# (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: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: > + kubectl patch vdb v-restore-point --type='json' -p='[{ + "op": "add", + "path": "/status/conditions/-", + "value": {"type": "SaveRestorePointsNeeded", "status": "True", "message": "test", "reason": "test", "lastTransitionTime": "2024-09-16T21:38:27Z"} + }]' --subresource='status' + namespaced: true + - command: kubectl wait --for=condition=SaveRestorePointsNeeded=True vdb/v-restore-point --timeout=600s + namespaced: true \ No newline at end of file diff --git a/tests/e2e-leg-6/save-restore-point/10-assert.yaml b/tests/e2e-leg-6/save-restore-point/10-assert.yaml new file mode 100644 index 000000000..7f0a00555 --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/10-assert.yaml @@ -0,0 +1,40 @@ +# (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: v1 +kind: Event +reason: CreateArchiveStart +source: + component: verticadb-operator +involvedObject: + apiVersion: vertica.com/v1 + kind: VerticaDB + name: v-restore-point +--- +apiVersion: v1 +kind: Event +reason: SaveRestorePointSucceeded +source: + component: verticadb-operator +involvedObject: + apiVersion: vertica.com/v1 + kind: VerticaDB + name: v-restore-point +--- +apiVersion: vertica.com/v1 +kind: VerticaDB +metadata: + name: v-restore-point +status: + restorePoint: + archive: test diff --git a/tests/e2e-leg-6/save-restore-point/10-wait-for-restore-point.yaml b/tests/e2e-leg-6/save-restore-point/10-wait-for-restore-point.yaml new file mode 100644 index 000000000..a478f6301 --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/10-wait-for-restore-point.yaml @@ -0,0 +1,18 @@ +# (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: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: kubectl wait --for=condition=SaveRestorePointsNeeded=False vdb/v-restore-point --timeout=600s + namespaced: true diff --git a/tests/e2e-leg-6/save-restore-point/95-delete-cr.yaml b/tests/e2e-leg-6/save-restore-point/95-delete-cr.yaml new file mode 100644 index 000000000..96d43c1de --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/95-delete-cr.yaml @@ -0,0 +1,18 @@ +# (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: kuttl.dev/v1beta1 +kind: TestStep +delete: + - apiVersion: vertica.com/v1 + kind: VerticaDB diff --git a/tests/e2e-leg-6/save-restore-point/95-errors.yaml b/tests/e2e-leg-6/save-restore-point/95-errors.yaml new file mode 100644 index 000000000..0794a6b38 --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/95-errors.yaml @@ -0,0 +1,21 @@ +# (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: apps/v1 +kind: StatefulSet +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/managed-by: verticadb-operator diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/98-assert.yaml b/tests/e2e-leg-6/save-restore-point/96-assert.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/98-assert.yaml rename to tests/e2e-leg-6/save-restore-point/96-assert.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/98-cleanup-storage.yaml b/tests/e2e-leg-6/save-restore-point/96-cleanup-storage.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/98-cleanup-storage.yaml rename to tests/e2e-leg-6/save-restore-point/96-cleanup-storage.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/98-errors.yaml b/tests/e2e-leg-6/save-restore-point/96-errors.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/98-errors.yaml rename to tests/e2e-leg-6/save-restore-point/96-errors.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/99-delete-ns.yaml b/tests/e2e-leg-6/save-restore-point/99-delete-ns.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/99-delete-ns.yaml rename to tests/e2e-leg-6/save-restore-point/99-delete-ns.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/setup-vdb/base/kustomization.yaml b/tests/e2e-leg-6/save-restore-point/setup-vdb/base/kustomization.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/setup-vdb/base/kustomization.yaml rename to tests/e2e-leg-6/save-restore-point/setup-vdb/base/kustomization.yaml diff --git a/tests/e2e-leg-6/save-restore-point/setup-vdb/base/setup-vdb.yaml b/tests/e2e-leg-6/save-restore-point/setup-vdb/base/setup-vdb.yaml new file mode 100644 index 000000000..a4f873a93 --- /dev/null +++ b/tests/e2e-leg-6/save-restore-point/setup-vdb/base/setup-vdb.yaml @@ -0,0 +1,40 @@ +# (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-restore-point + annotations: + vertica.com/include-uid-in-path: "true" + vertica.com/k-safety: "0" + vertica.com/requeue-time: "5" +spec: + image: kustomize-vertica-image + communal: + path: "s3://nimbusdb/db" + endpoint: "http://minio" + credentialSecret: s3-auth + local: + requestSize: 100Mi + initPolicy: CreateSkipPackageInstall + dbName: vertdb + restorePoint: + archive: test + subclusters: + - name: sc1 + size: 1 + certSecrets: [] + imagePullSecrets: [] + volumes: [] + volumeMounts: [] diff --git a/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/05-create-communal-creds.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/05-create-communal-creds.yaml new file mode 100644 index 000000000..626bea17d --- /dev/null +++ b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/05-create-communal-creds.yaml @@ -0,0 +1,18 @@ +# (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: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: kustomize build ../../manifests/communal-creds/overlay | kubectl apply -f - --namespace $NAMESPACE + - script: kustomize build ../../manifests/priv-container-creds/overlay | kubectl apply -f - --namespace $NAMESPACE diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/10-assert.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/10-assert.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/10-assert.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/10-assert.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/10-password-secret.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/10-password-secret.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/10-password-secret.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/10-password-secret.yaml diff --git a/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/15-assert.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/15-assert.yaml new file mode 100644 index 000000000..9faca75c9 --- /dev/null +++ b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/15-assert.yaml @@ -0,0 +1,21 @@ +# (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: v1 +kind: Pod +metadata: + namespace: verticadb-operator + labels: + control-plane: verticadb-operator +status: + phase: Running diff --git a/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/15-deploy-operator.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/15-deploy-operator.yaml new file mode 100644 index 000000000..0cd372046 --- /dev/null +++ b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/15-deploy-operator.yaml @@ -0,0 +1,12 @@ +# (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. diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/20-assert.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/20-assert.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/20-assert.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/20-assert.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/20-pull-images.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/20-pull-images.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/20-pull-images.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/20-pull-images.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/25-assert.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/25-assert.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/25-assert.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/25-assert.yaml diff --git a/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/25-setup-v12-vdb.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/25-setup-v12-vdb.yaml new file mode 100644 index 000000000..c9ed69089 --- /dev/null +++ b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/25-setup-v12-vdb.yaml @@ -0,0 +1,17 @@ +# (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: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: bash -c "kustomize build setup-vdb/overlay | kubectl -n $NAMESPACE apply -f - " diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/30-assert.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/30-assert.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/30-assert.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/30-assert.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/30-wait-for-createdb.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/30-wait-for-createdb.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/30-wait-for-createdb.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/30-wait-for-createdb.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/40-assert.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/40-assert.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/40-assert.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/40-assert.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/40-upgrade-to-23-4.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/40-upgrade-to-23-4.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/40-upgrade-to-23-4.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/40-upgrade-to-23-4.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/41-wait-for-upgrade.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/41-wait-for-upgrade.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/41-wait-for-upgrade.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/41-wait-for-upgrade.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/45-assert.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/45-assert.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/45-assert.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/45-assert.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/45-upgrade-to-24-1.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/45-upgrade-to-24-1.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/45-upgrade-to-24-1.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/45-upgrade-to-24-1.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/46-wait-for-upgrade.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/46-wait-for-upgrade.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/46-wait-for-upgrade.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/46-wait-for-upgrade.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/50-assert.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/50-assert.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/50-assert.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/50-assert.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/50-upgrade-to-latest.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/50-upgrade-to-latest.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/50-upgrade-to-latest.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/50-upgrade-to-latest.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/51-wait-for-upgrade.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/51-wait-for-upgrade.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/51-wait-for-upgrade.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/51-wait-for-upgrade.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/97-delete-cr.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/97-delete-cr.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/97-delete-cr.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/97-delete-cr.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/97-errors.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/97-errors.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/97-errors.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/97-errors.yaml diff --git a/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/98-assert.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/98-assert.yaml new file mode 100644 index 000000000..861c7dc8f --- /dev/null +++ b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/98-assert.yaml @@ -0,0 +1,19 @@ +# (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: v1 +kind: Pod +metadata: + name: clean-communal +status: + phase: Succeeded diff --git a/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/98-cleanup-storage.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/98-cleanup-storage.yaml new file mode 100644 index 000000000..dcc6306f3 --- /dev/null +++ b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/98-cleanup-storage.yaml @@ -0,0 +1,17 @@ +# (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: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: bash -c "kustomize build clean-communal/overlay | kubectl -n $NAMESPACE apply -f - " diff --git a/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/98-errors.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/98-errors.yaml new file mode 100644 index 000000000..671be36cf --- /dev/null +++ b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/98-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: v1 +kind: PersistentVolumeClaim diff --git a/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/99-delete-ns.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/99-delete-ns.yaml new file mode 100644 index 000000000..1674b3e8f --- /dev/null +++ b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/99-delete-ns.yaml @@ -0,0 +1,17 @@ +# (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: kuttl.dev/v1beta1 +kind: TestStep +commands: + - command: kubectl delete ns $NAMESPACE diff --git a/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/setup-vdb/base/kustomization.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/setup-vdb/base/kustomization.yaml new file mode 100644 index 000000000..681396735 --- /dev/null +++ b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/setup-vdb/base/kustomization.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. + +resources: + - setup-vdb.yaml diff --git a/tests/e2e-leg-8-online/online-upgrade-through-vclusterops/setup-vdb/base/setup-vdb.yaml b/tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/setup-vdb/base/setup-vdb.yaml similarity index 100% rename from tests/e2e-leg-8-online/online-upgrade-through-vclusterops/setup-vdb/base/setup-vdb.yaml rename to tests/e2e-leg-8-online/readonly-online-upgrade-through-vclusterops/setup-vdb/base/setup-vdb.yaml