mirror of
https://github.com/vmware-tanzu/velero.git
synced 2025-12-23 06:15:21 +00:00
Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Set `GOBIN` so Makefile don't modify $PATH on `go install` Fix realPath resolving when cloud credentials is prefixed by `~` for home dir Use `~/.docker/config.json` if REGISTRY_CREDENTIAL_FILE not defined and skip step if does not exists since it is optional Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Add kind testdata storageclass Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Add kind testdata storageclass Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> log `Start to install Azure VolumeSnapshotClass ...` only on azure when csi is enabled Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Add BSL_CONFIG example and notes Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Makefile: Set `GOBIN` for `_output/...` Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> README spacing Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> StandbyClusterObjectStoreProvider typo Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Specify velero namespace during get/delete command Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Use object stores rather than cloudProvider for bucket queries Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Remove debug print Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> simplify NS get changes, add velero NS to `DeleteBackupResource` Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Skip file system backups on kind which uses hostPath volumes Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Add StorageClass change test to PR kind e2e Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Add more tests to pr Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Add NS mapping to PR e2e Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Add `SKIP_KIND` to some jobs containing volumes Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Remove kind from kibishii tests Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Label volume resource policies as restic, skip restic/snapshot tests, add more tests Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> TTLTest is a snapshot test Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Remove non working tests Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Resolve https://github.com/vmware-tanzu/velero/pull/7353#issuecomment-1925660077 Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> address https://github.com/vmware-tanzu/velero/pull/7353/files#r1477218762 Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com> Address https://github.com/vmware-tanzu/velero/pull/7353#issuecomment-1923414840 Signed-off-by: Tiger Kaovilai <tkaovila@redhat.com>
192 lines
8.3 KiB
Go
192 lines
8.3 KiB
Go
/*
|
|
Copyright the Velero contributors.
|
|
|
|
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 providers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
. "github.com/vmware-tanzu/velero/test"
|
|
velero "github.com/vmware-tanzu/velero/test/util/velero"
|
|
)
|
|
|
|
type ObjectsInStorage interface {
|
|
IsObjectsInBucket(cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, backupObject string) (bool, error)
|
|
DeleteObjectsInBucket(cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, backupObject string) error
|
|
IsSnapshotExisted(cloudCredentialsFile, bslConfig, backupName string, snapshotCheck SnapshotCheckPoint) error
|
|
}
|
|
|
|
func ObjectsShouldBeInBucket(objectStoreProvider, cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, backupName, subPrefix string) error {
|
|
fmt.Printf("|| VERIFICATION || - %s should exist in storage [%s %s]\n", backupName, bslPrefix, subPrefix)
|
|
exist, err := IsObjectsInBucket(objectStoreProvider, cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, backupName, subPrefix)
|
|
if !exist {
|
|
return errors.Wrap(err, fmt.Sprintf("|| UNEXPECTED ||Backup object %s is not exist in object store after backup as expected\n", backupName))
|
|
}
|
|
fmt.Printf("|| EXPECTED || - Backup %s exist in object storage bucket %s\n", backupName, bslBucket)
|
|
return nil
|
|
}
|
|
func ObjectsShouldNotBeInBucket(objectStoreProvider, cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, backupName, subPrefix string, retryTimes int) error {
|
|
var err error
|
|
var exist bool
|
|
fmt.Printf("|| VERIFICATION || - %s %s should not exist in object store %s\n", subPrefix, backupName, bslPrefix)
|
|
if cloudCredentialsFile == "" {
|
|
return errors.New(fmt.Sprintf("|| ERROR || - Please provide credential file of cloud %s \n", objectStoreProvider))
|
|
}
|
|
for i := 0; i < retryTimes; i++ {
|
|
exist, err = IsObjectsInBucket(objectStoreProvider, cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, backupName, subPrefix)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "|| UNEXPECTED || - Failed to get backup %s in object store\n", backupName)
|
|
}
|
|
if !exist {
|
|
fmt.Printf("|| EXPECTED || - Backup %s is not in object store\n", backupName)
|
|
return nil
|
|
}
|
|
time.Sleep(1 * time.Minute)
|
|
}
|
|
return errors.New(fmt.Sprintf("|| UNEXPECTED ||Backup object %s still exist in object store after backup deletion\n", backupName))
|
|
}
|
|
|
|
// This function returns a storage interface based on the cloud provider for querying objects and snapshots
|
|
// When cloudProvider is kind, pass in object storage provider instead. For example, "aws".
|
|
// Snapshots are not supported on kind.
|
|
func getProvider(cloudProvider string) (ObjectsInStorage, error) {
|
|
var s ObjectsInStorage
|
|
switch cloudProvider {
|
|
case "aws", "vsphere":
|
|
aws := AWSStorage("")
|
|
s = &aws
|
|
case "gcp":
|
|
gcs := GCSStorage("")
|
|
s = &gcs
|
|
case "azure":
|
|
az := AzureStorage("")
|
|
s = &az
|
|
default:
|
|
return nil, errors.New(fmt.Sprintf("Cloud provider %s is not valid", cloudProvider))
|
|
}
|
|
return s, nil
|
|
}
|
|
func getFullPrefix(bslPrefix, subPrefix string) string {
|
|
if bslPrefix == "" {
|
|
bslPrefix = subPrefix + "/"
|
|
} else {
|
|
//subPrefix must have surfix "/", so that objects under it can be listed
|
|
bslPrefix = strings.Trim(bslPrefix, "/") + "/" + strings.Trim(subPrefix, "/") + "/"
|
|
}
|
|
return bslPrefix
|
|
}
|
|
func IsObjectsInBucket(objectStoreProvider, cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, backupName, subPrefix string) (bool, error) {
|
|
bslPrefix = getFullPrefix(bslPrefix, subPrefix)
|
|
s, err := getProvider(objectStoreProvider)
|
|
if err != nil {
|
|
return false, errors.Wrapf(err, fmt.Sprintf("Object store provider %s is not valid", objectStoreProvider))
|
|
}
|
|
return s.IsObjectsInBucket(cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, backupName)
|
|
}
|
|
|
|
func DeleteObjectsInBucket(objectStoreProvider, cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, backupName, subPrefix string) error {
|
|
bslPrefix = getFullPrefix(bslPrefix, subPrefix)
|
|
fmt.Printf("|| VERIFICATION || - Delete backup %s in storage %s\n", backupName, bslPrefix)
|
|
if cloudCredentialsFile == "" {
|
|
return errors.New(fmt.Sprintf("|| ERROR || - Please provide credential file of cloud %s \n", objectStoreProvider))
|
|
}
|
|
s, err := getProvider(objectStoreProvider)
|
|
if err != nil {
|
|
return errors.Wrapf(err, fmt.Sprintf("Object store provider %s is not valid", objectStoreProvider))
|
|
}
|
|
err = s.DeleteObjectsInBucket(cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, backupName)
|
|
if err != nil {
|
|
return errors.Wrapf(err, fmt.Sprintf("Fail to delete %s", bslPrefix))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func SnapshotsShouldNotExistInCloud(cloudProvider, cloudCredentialsFile, bslBucket, bslConfig, backupName string, snapshotCheckPoint SnapshotCheckPoint) error {
|
|
fmt.Printf("|| VERIFICATION || - Snapshots should not exist in cloud, backup %s\n", backupName)
|
|
if cloudCredentialsFile == "" {
|
|
return errors.New(fmt.Sprintf("|| ERROR || - Please provide credential file of cloud %s \n", cloudProvider))
|
|
}
|
|
snapshotCheckPoint.ExpectCount = 0
|
|
err := IsSnapshotExisted(cloudProvider, cloudCredentialsFile, bslBucket, bslConfig, backupName, snapshotCheckPoint)
|
|
if err != nil {
|
|
return errors.Wrapf(err, fmt.Sprintf("|| UNEXPECTED ||Snapshots %s exist in cloud after backup as expected", backupName))
|
|
}
|
|
fmt.Printf("|| EXPECTED || - Snapshots do not exist in cloud, backup %s\n", backupName)
|
|
return nil
|
|
}
|
|
|
|
func SnapshotsShouldBeCreatedInCloud(cloudProvider, cloudCredentialsFile, bslBucket, bslConfig, backupName string, snapshotCheckPoint SnapshotCheckPoint) error {
|
|
fmt.Printf("|| VERIFICATION || - Snapshots should exist in cloud, backup %s\n", backupName)
|
|
if cloudCredentialsFile == "" {
|
|
return errors.New(fmt.Sprintf("|| ERROR || - Please provide credential file of cloud %s \n", cloudProvider))
|
|
}
|
|
err := IsSnapshotExisted(cloudProvider, cloudCredentialsFile, bslBucket, bslConfig, backupName, snapshotCheckPoint)
|
|
if err != nil {
|
|
return errors.Wrapf(err, fmt.Sprintf("|| UNEXPECTED ||Snapshots %s do not exist in cloud after backup as expected", backupName))
|
|
}
|
|
fmt.Printf("|| EXPECTED || - Snapshots exist in cloud, backup %s\n", backupName)
|
|
return nil
|
|
}
|
|
|
|
func IsSnapshotExisted(cloudProvider, cloudCredentialsFile, bslBucket, bslConfig, backupName string, snapshotCheck SnapshotCheckPoint) error {
|
|
|
|
s, err := getProvider(cloudProvider)
|
|
if err != nil {
|
|
return errors.Wrapf(err, fmt.Sprintf("Cloud provider %s is not valid", cloudProvider))
|
|
}
|
|
if cloudProvider == "vsphere" {
|
|
var retSnapshotIDs []string
|
|
ctx, ctxCancel := context.WithTimeout(context.Background(), time.Minute*2)
|
|
defer ctxCancel()
|
|
retSnapshotIDs, err = velero.GetVsphereSnapshotIDs(ctx, time.Hour, snapshotCheck.NamespaceBackedUp, snapshotCheck.PodName)
|
|
if err != nil {
|
|
return errors.Wrapf(err, fmt.Sprintf("Fail to get snapshot CRs of backup%s", backupName))
|
|
}
|
|
|
|
bslPrefix := "plugins"
|
|
subPrefix := "vsphere-astrolabe-repo/ivd/data"
|
|
if snapshotCheck.ExpectCount == 0 {
|
|
for _, snapshotID := range retSnapshotIDs {
|
|
err := ObjectsShouldNotBeInBucket(cloudProvider, cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, snapshotID, subPrefix, 5)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "|| UNEXPECTED || - Snapshot %s of backup %s exist in object store", snapshotID, backupName)
|
|
}
|
|
}
|
|
} else {
|
|
if snapshotCheck.ExpectCount != len(retSnapshotIDs) {
|
|
return errors.New(fmt.Sprintf("Snapshot CRs count %d is not equal to expected %d", len(retSnapshotIDs), snapshotCheck.ExpectCount))
|
|
}
|
|
for _, snapshotID := range retSnapshotIDs {
|
|
err := ObjectsShouldBeInBucket(cloudProvider, cloudCredentialsFile, bslBucket, bslPrefix, bslConfig, snapshotID, subPrefix)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "|| UNEXPECTED || - Snapshot %s of backup %s does not exist in object store", snapshotID, backupName)
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
err = s.IsSnapshotExisted(cloudCredentialsFile, bslConfig, backupName, snapshotCheck)
|
|
if err != nil {
|
|
return errors.Wrapf(err, fmt.Sprintf("Fail to get snapshot of backup %s", backupName))
|
|
}
|
|
}
|
|
return nil
|
|
}
|