diff --git a/Makefile b/Makefile index 0bdf6e8d78..3fce3e9242 100644 --- a/Makefile +++ b/Makefile @@ -359,5 +359,9 @@ gen-docs: test-e2e: local $(MAKE) -e VERSION=$(VERSION) -C test/e2e run +.PHONY: test-perf +test-perf: local + $(MAKE) -e VERSION=$(VERSION) -C test/perf run + go-generate: go generate ./pkg/... \ No newline at end of file diff --git a/changelogs/unreleased/6569-qiuming-best b/changelogs/unreleased/6569-qiuming-best new file mode 100644 index 0000000000..510959833d --- /dev/null +++ b/changelogs/unreleased/6569-qiuming-best @@ -0,0 +1 @@ +Add performance E2E test diff --git a/go.mod b/go.mod index 0c754f8547..5f49f570bd 100644 --- a/go.mod +++ b/go.mod @@ -51,6 +51,7 @@ require ( k8s.io/client-go v0.25.6 k8s.io/klog/v2 v2.70.1 k8s.io/kube-aggregator v0.19.12 + k8s.io/metrics v0.25.6 k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed sigs.k8s.io/controller-runtime v0.12.2 sigs.k8s.io/yaml v1.3.0 diff --git a/go.sum b/go.sum index 7eb1e5c06b..bdc7d0922a 100644 --- a/go.sum +++ b/go.sum @@ -1360,6 +1360,8 @@ k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2R k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= +k8s.io/metrics v0.25.6 h1:EezfQTfTsSW/Cs9oHJXAftRlbL0fnHfDh02ObTOs/34= +k8s.io/metrics v0.25.6/go.mod h1:LGcsjMsQQvt/4vrvQzqOIHv9/sIVov1ZE7HtQxc8d9w= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= diff --git a/golangci.yaml b/golangci.yaml index fd25dea90e..bdd7b5d068 100644 --- a/golangci.yaml +++ b/golangci.yaml @@ -19,7 +19,7 @@ run: # "/" will be replaced by current OS file path separator to properly work # on Windows. skip-dirs: - - test/e2e/* + - test/* - pkg/plugin/generated/* # - autogenerated_by_my_lib diff --git a/test/e2e/backup/backup.go b/test/e2e/backup/backup.go index 9ad7b94ebc..267b92cd4e 100644 --- a/test/e2e/backup/backup.go +++ b/test/e2e/backup/backup.go @@ -25,10 +25,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/kibishii" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/kibishii" + . "github.com/vmware-tanzu/velero/test/util/velero" ) func BackupRestoreWithSnapshots() { diff --git a/test/e2e/backups/deletion.go b/test/e2e/backups/deletion.go index b51d937008..4e32d3ba38 100644 --- a/test/e2e/backups/deletion.go +++ b/test/e2e/backups/deletion.go @@ -26,11 +26,11 @@ import ( . "github.com/onsi/gomega" "github.com/pkg/errors" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/kibishii" - . "github.com/vmware-tanzu/velero/test/e2e/util/providers" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/kibishii" + . "github.com/vmware-tanzu/velero/test/util/providers" + . "github.com/vmware-tanzu/velero/test/util/velero" ) const deletionTest = "deletion-workload" diff --git a/test/e2e/backups/sync_backups.go b/test/e2e/backups/sync_backups.go index 62f724e14a..d7b3f96405 100644 --- a/test/e2e/backups/sync_backups.go +++ b/test/e2e/backups/sync_backups.go @@ -30,10 +30,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/providers" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/providers" + . "github.com/vmware-tanzu/velero/test/util/velero" ) type SyncBackups struct { diff --git a/test/e2e/backups/ttl.go b/test/e2e/backups/ttl.go index 4cc2d59204..93eb7a4052 100644 --- a/test/e2e/backups/ttl.go +++ b/test/e2e/backups/ttl.go @@ -30,12 +30,12 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/kibishii" - . "github.com/vmware-tanzu/velero/test/e2e/util/providers" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test/util/kibishii" + . "github.com/vmware-tanzu/velero/test/util/providers" + . "github.com/vmware-tanzu/velero/test/util/velero" ) type TTL struct { diff --git a/test/e2e/basic/api-group/enable_api_group_extentions.go b/test/e2e/basic/api-group/enable_api_group_extentions.go index 40bd64000e..cf33251f39 100644 --- a/test/e2e/basic/api-group/enable_api_group_extentions.go +++ b/test/e2e/basic/api-group/enable_api_group_extentions.go @@ -24,9 +24,9 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) func APIExtensionsVersionsTest() { diff --git a/test/e2e/basic/api-group/enable_api_group_versions.go b/test/e2e/basic/api-group/enable_api_group_versions.go index 776c8966e2..b0e4b3d729 100644 --- a/test/e2e/basic/api-group/enable_api_group_versions.go +++ b/test/e2e/basic/api-group/enable_api_group_versions.go @@ -36,9 +36,9 @@ import ( "github.com/vmware-tanzu/velero/pkg/builder" veleroexec "github.com/vmware-tanzu/velero/pkg/util/exec" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) var veleroCfg VeleroConfig @@ -121,12 +121,12 @@ func runEnableAPIGroupVersionsTests(ctx context.Context, client TestClient, grou tests := []apiGropuVersionsTest{ { name: "Target and source cluster preferred versions match; Preferred version v1 is restored (Priority 1, Case A).", - srcCrdYaml: "testdata/enable_api_group_versions/case-a-source.yaml", + srcCrdYaml: "../testdata/enable_api_group_versions/case-a-source.yaml", srcCRs: map[string]string{ - "v1": "testdata/enable_api_group_versions/music_v1_rockband.yaml", - "v1alpha1": "testdata/enable_api_group_versions/music_v1alpha1_rockband.yaml", + "v1": "../testdata/enable_api_group_versions/music_v1_rockband.yaml", + "v1alpha1": "../testdata/enable_api_group_versions/music_v1alpha1_rockband.yaml", }, - tgtCrdYaml: "testdata/enable_api_group_versions/case-a-target.yaml", + tgtCrdYaml: "../testdata/enable_api_group_versions/case-a-target.yaml", tgtVer: "v1", cm: nil, want: map[string]map[string]string{ @@ -140,13 +140,13 @@ func runEnableAPIGroupVersionsTests(ctx context.Context, client TestClient, grou }, { name: "Latest common non-preferred supported version v2beta2 is restored (Priority 3, Case D).", - srcCrdYaml: "testdata/enable_api_group_versions/case-b-source-manually-added-mutations.yaml", + srcCrdYaml: "../testdata/enable_api_group_versions/case-b-source-manually-added-mutations.yaml", srcCRs: map[string]string{ - "v2beta2": "testdata/enable_api_group_versions/music_v2beta2_rockband.yaml", - "v2beta1": "testdata/enable_api_group_versions/music_v2beta1_rockband.yaml", - "v1": "testdata/enable_api_group_versions/music_v1_rockband.yaml", + "v2beta2": "../testdata/enable_api_group_versions/music_v2beta2_rockband.yaml", + "v2beta1": "../testdata/enable_api_group_versions/music_v2beta1_rockband.yaml", + "v1": "../testdata/enable_api_group_versions/music_v1_rockband.yaml", }, - tgtCrdYaml: "testdata/enable_api_group_versions/case-d-target-manually-added-mutations.yaml", + tgtCrdYaml: "../testdata/enable_api_group_versions/case-d-target-manually-added-mutations.yaml", tgtVer: "v2beta2", cm: nil, want: map[string]map[string]string{ @@ -160,25 +160,25 @@ func runEnableAPIGroupVersionsTests(ctx context.Context, client TestClient, grou }, { name: "No common supported versions means no rockbands custom resource is restored.", - srcCrdYaml: "testdata/enable_api_group_versions/case-a-source.yaml", + srcCrdYaml: "../testdata/enable_api_group_versions/case-a-source.yaml", srcCRs: map[string]string{ - "v1": "testdata/enable_api_group_versions/music_v1_rockband.yaml", - "v1alpha1": "testdata/enable_api_group_versions/music_v1alpha1_rockband.yaml", + "v1": "../testdata/enable_api_group_versions/music_v1_rockband.yaml", + "v1alpha1": "../testdata/enable_api_group_versions/music_v1alpha1_rockband.yaml", }, - tgtCrdYaml: "testdata/enable_api_group_versions/case-b-target-manually-added-mutations.yaml", + tgtCrdYaml: "../testdata/enable_api_group_versions/case-b-target-manually-added-mutations.yaml", tgtVer: "", cm: nil, want: nil, }, { name: "User config map overrides Priority 3, Case D and restores v2beta1", - srcCrdYaml: "testdata/enable_api_group_versions/case-b-source-manually-added-mutations.yaml", + srcCrdYaml: "../testdata/enable_api_group_versions/case-b-source-manually-added-mutations.yaml", srcCRs: map[string]string{ - "v2beta2": "testdata/enable_api_group_versions/music_v2beta2_rockband.yaml", - "v2beta1": "testdata/enable_api_group_versions/music_v2beta1_rockband.yaml", - "v1": "testdata/enable_api_group_versions/music_v1_rockband.yaml", + "v2beta2": "../testdata/enable_api_group_versions/music_v2beta2_rockband.yaml", + "v2beta1": "../testdata/enable_api_group_versions/music_v2beta1_rockband.yaml", + "v1": "../testdata/enable_api_group_versions/music_v1_rockband.yaml", }, - tgtCrdYaml: "testdata/enable_api_group_versions/case-d-target-manually-added-mutations.yaml", + tgtCrdYaml: "../testdata/enable_api_group_versions/case-d-target-manually-added-mutations.yaml", tgtVer: "v2beta1", cm: builder.ForConfigMap(veleroCfg.VeleroNamespace, "enableapigroupversions").Data( "restoreResourcesVersionPriority", @@ -195,9 +195,9 @@ func runEnableAPIGroupVersionsTests(ctx context.Context, client TestClient, grou }, { name: "Restore successful when CRD doesn't (yet) exist in target", - srcCrdYaml: "testdata/enable_api_group_versions/case-a-source.yaml", + srcCrdYaml: "../testdata/enable_api_group_versions/case-a-source.yaml", srcCRs: map[string]string{ - "v1": "testdata/enable_api_group_versions/music_v1_rockband.yaml", + "v1": "../testdata/enable_api_group_versions/music_v1_rockband.yaml", }, tgtCrdYaml: "", tgtVer: "v1", diff --git a/test/e2e/basic/namespace-mapping.go b/test/e2e/basic/namespace-mapping.go index ae9c0509e1..ea2a8f53a7 100644 --- a/test/e2e/basic/namespace-mapping.go +++ b/test/e2e/basic/namespace-mapping.go @@ -9,10 +9,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/kibishii" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/kibishii" ) type NamespaceMapping struct { diff --git a/test/e2e/basic/nodeport.go b/test/e2e/basic/nodeport.go index 440aab27de..7bb9d5f108 100644 --- a/test/e2e/basic/nodeport.go +++ b/test/e2e/basic/nodeport.go @@ -13,10 +13,10 @@ import ( velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) type NodePort struct { diff --git a/test/e2e/basic/pvc-selected-node-changing.go b/test/e2e/basic/pvc-selected-node-changing.go index 94db1c52cf..d26350f2bc 100644 --- a/test/e2e/basic/pvc-selected-node-changing.go +++ b/test/e2e/basic/pvc-selected-node-changing.go @@ -10,10 +10,10 @@ import ( velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) type PVCSelectedNodeChanging struct { diff --git a/test/e2e/basic/resources-check/namespaces.go b/test/e2e/basic/resources-check/namespaces.go index 5b9d1460f6..78386fb9b9 100644 --- a/test/e2e/basic/resources-check/namespaces.go +++ b/test/e2e/basic/resources-check/namespaces.go @@ -25,9 +25,9 @@ import ( "github.com/pkg/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) type MultiNSBackup struct { diff --git a/test/e2e/basic/resources-check/namespaces_annotation.go b/test/e2e/basic/resources-check/namespaces_annotation.go index fada2b28c9..3f81c456d7 100644 --- a/test/e2e/basic/resources-check/namespaces_annotation.go +++ b/test/e2e/basic/resources-check/namespaces_annotation.go @@ -24,9 +24,9 @@ import ( "github.com/pkg/errors" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) type NSAnnotationCase struct { diff --git a/test/e2e/basic/resources-check/rbac.go b/test/e2e/basic/resources-check/rbac.go index deb3203a57..6df97cc57c 100644 --- a/test/e2e/basic/resources-check/rbac.go +++ b/test/e2e/basic/resources-check/rbac.go @@ -40,9 +40,9 @@ import ( "github.com/pkg/errors" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) type RBACCase struct { diff --git a/test/e2e/basic/storage-class-changing.go b/test/e2e/basic/storage-class-changing.go index 05eb7e855f..6255f8e65a 100644 --- a/test/e2e/basic/storage-class-changing.go +++ b/test/e2e/basic/storage-class-changing.go @@ -10,10 +10,10 @@ import ( velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) type StorageClasssChanging struct { @@ -70,7 +70,7 @@ func (s *StorageClasssChanging) Init() error { func (s *StorageClasssChanging) CreateResources() error { s.Ctx, s.CtxCancel = context.WithTimeout(context.Background(), 10*time.Minute) By(fmt.Sprintf("Create a storage class %s", s.desStorageClass), func() { - Expect(InstallStorageClass(s.Ctx, fmt.Sprintf("testdata/storage-class/%s.yaml", + Expect(InstallStorageClass(s.Ctx, fmt.Sprintf("../testdata/storage-class/%s.yaml", s.VeleroCfg.CloudProvider))).To(Succeed()) }) By(fmt.Sprintf("Create namespace %s", s.namespace), func() { diff --git a/test/e2e/bsl-mgmt/deletion.go b/test/e2e/bsl-mgmt/deletion.go index 834ab5ca5b..f7576ff4b0 100644 --- a/test/e2e/bsl-mgmt/deletion.go +++ b/test/e2e/bsl-mgmt/deletion.go @@ -27,12 +27,12 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/kibishii" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/kibishii" - . "github.com/vmware-tanzu/velero/test/e2e/util/providers" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test/util/providers" + . "github.com/vmware-tanzu/velero/test/util/velero" ) const ( diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index c62d9e87fa..d050b37dd2 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -28,7 +28,7 @@ import ( "github.com/onsi/ginkgo/reporters" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/backup" . "github.com/vmware-tanzu/velero/test/e2e/backups" . "github.com/vmware-tanzu/velero/test/e2e/basic" @@ -43,8 +43,8 @@ import ( . "github.com/vmware-tanzu/velero/test/e2e/scale" . "github.com/vmware-tanzu/velero/test/e2e/schedule" . "github.com/vmware-tanzu/velero/test/e2e/upgrade" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) func init() { diff --git a/test/e2e/migration/migration.go b/test/e2e/migration/migration.go index c62d7f27f2..1cb1398ddc 100644 --- a/test/e2e/migration/migration.go +++ b/test/e2e/migration/migration.go @@ -26,11 +26,11 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/kibishii" - . "github.com/vmware-tanzu/velero/test/e2e/util/providers" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/kibishii" + . "github.com/vmware-tanzu/velero/test/util/providers" + . "github.com/vmware-tanzu/velero/test/util/velero" ) var migrationNamespace string @@ -295,7 +295,7 @@ func MigrationTest(useVolumeSnapshots bool, veleroCLI2Version VeleroCLI2Version) By(fmt.Sprintf("Restore %s", migrationNamespace), func() { if OriginVeleroCfg.SnapshotMoveData { By(fmt.Sprintf("Create a storage class %s for restore PV provisioned by storage class %s on different cloud provider", StorageClassName, KibishiiStorageClassName), func() { - Expect(InstallStorageClass(context.Background(), fmt.Sprintf("testdata/storage-class/%s.yaml", veleroCfg.StandbyClusterCloudProvider))).To(Succeed()) + Expect(InstallStorageClass(context.Background(), fmt.Sprintf("../testdata/storage-class/%s.yaml", veleroCfg.StandbyClusterCloudProvider))).To(Succeed()) }) configmaptName := "datamover-storage-class-config" labels := map[string]string{"velero.io/change-storage-class": "RestoreItemAction", diff --git a/test/e2e/privilegesmgmt/ssr.go b/test/e2e/privilegesmgmt/ssr.go index 1f840db684..2ce784afdd 100644 --- a/test/e2e/privilegesmgmt/ssr.go +++ b/test/e2e/privilegesmgmt/ssr.go @@ -29,9 +29,9 @@ import ( kbclient "sigs.k8s.io/controller-runtime/pkg/client" v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) func SSRTest() { diff --git a/test/e2e/pv-backup/pv-backup-filter.go b/test/e2e/pv-backup/pv-backup-filter.go index 503afd1c43..d8de42dd2e 100644 --- a/test/e2e/pv-backup/pv-backup-filter.go +++ b/test/e2e/pv-backup/pv-backup-filter.go @@ -10,9 +10,9 @@ import ( . "github.com/onsi/gomega" "github.com/pkg/errors" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) type PVBackupFiltering struct { @@ -67,7 +67,7 @@ func (p *PVBackupFiltering) Init() error { func (p *PVBackupFiltering) CreateResources() error { p.Ctx, p.CtxCancel = context.WithTimeout(context.Background(), 30*time.Minute) - err := InstallStorageClass(p.Ctx, fmt.Sprintf("testdata/storage-class/%s.yaml", VeleroCfg.CloudProvider)) + err := InstallStorageClass(p.Ctx, fmt.Sprintf("../testdata/storage-class/%s.yaml", VeleroCfg.CloudProvider)) if err != nil { return errors.Wrapf(err, "failed to install storage class for pv backup filtering test") } diff --git a/test/e2e/resource-filtering/base.go b/test/e2e/resource-filtering/base.go index 256bf5167c..9d45adba21 100644 --- a/test/e2e/resource-filtering/base.go +++ b/test/e2e/resource-filtering/base.go @@ -24,9 +24,9 @@ import ( "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) type FilteringCase struct { diff --git a/test/e2e/resource-filtering/exclude_label.go b/test/e2e/resource-filtering/exclude_label.go index 24db8288e3..50167ddd71 100644 --- a/test/e2e/resource-filtering/exclude_label.go +++ b/test/e2e/resource-filtering/exclude_label.go @@ -27,9 +27,9 @@ import ( "github.com/pkg/errors" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) /* diff --git a/test/e2e/resource-filtering/exclude_namespaces.go b/test/e2e/resource-filtering/exclude_namespaces.go index a1cd29b692..a31dfa625b 100644 --- a/test/e2e/resource-filtering/exclude_namespaces.go +++ b/test/e2e/resource-filtering/exclude_namespaces.go @@ -25,9 +25,9 @@ import ( "github.com/pkg/errors" apierrors "k8s.io/apimachinery/pkg/api/errors" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) /* diff --git a/test/e2e/resource-filtering/exclude_resources.go b/test/e2e/resource-filtering/exclude_resources.go index d405742983..033fe95ffe 100644 --- a/test/e2e/resource-filtering/exclude_resources.go +++ b/test/e2e/resource-filtering/exclude_resources.go @@ -24,9 +24,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) /* diff --git a/test/e2e/resource-filtering/include_namespaces.go b/test/e2e/resource-filtering/include_namespaces.go index 789d9d787a..6d3b32b72b 100644 --- a/test/e2e/resource-filtering/include_namespaces.go +++ b/test/e2e/resource-filtering/include_namespaces.go @@ -25,9 +25,9 @@ import ( "github.com/pkg/errors" apierrors "k8s.io/apimachinery/pkg/api/errors" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) /* diff --git a/test/e2e/resource-filtering/include_resources.go b/test/e2e/resource-filtering/include_resources.go index 28b166f0fc..4b6ac7126d 100644 --- a/test/e2e/resource-filtering/include_resources.go +++ b/test/e2e/resource-filtering/include_resources.go @@ -24,9 +24,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) /* diff --git a/test/e2e/resource-filtering/label_selector.go b/test/e2e/resource-filtering/label_selector.go index 81dbffc8e9..56712a3d7b 100644 --- a/test/e2e/resource-filtering/label_selector.go +++ b/test/e2e/resource-filtering/label_selector.go @@ -26,9 +26,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) /* diff --git a/test/e2e/resourcepolicies/resource_policies.go b/test/e2e/resourcepolicies/resource_policies.go index 1fa2d49467..9defd19c00 100644 --- a/test/e2e/resourcepolicies/resource_policies.go +++ b/test/e2e/resourcepolicies/resource_policies.go @@ -30,9 +30,9 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) const FileName = "test-data.txt" @@ -110,7 +110,7 @@ func (r *ResourcePoliciesCase) CreateResources() error { r.Ctx, r.CtxCancel = context.WithTimeout(context.Background(), 10*time.Minute) By(("Installing storage class..."), func() { - Expect(r.installTestStorageClasses(fmt.Sprintf("testdata/storage-class/%s.yaml", VeleroCfg.CloudProvider))).To(Succeed(), "Failed to install storage class") + Expect(r.installTestStorageClasses(fmt.Sprintf("../testdata/storage-class/%s.yaml", VeleroCfg.CloudProvider))).To(Succeed(), "Failed to install storage class") }) By(fmt.Sprintf("Create configmap %s in namespaces %s for workload\n", r.cmName, r.VeleroCfg.VeleroNamespace), func() { diff --git a/test/e2e/schedule/ordered_resources.go b/test/e2e/schedule/ordered_resources.go index ce9eb97c0c..a9cbe3399b 100644 --- a/test/e2e/schedule/ordered_resources.go +++ b/test/e2e/schedule/ordered_resources.go @@ -30,10 +30,10 @@ import ( kbclient "sigs.k8s.io/controller-runtime/pkg/client" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) var ScheduleOrderedResources func() = TestFunc(&OrderedResources{}) diff --git a/test/e2e/schedule/schedule-backup-creation.go b/test/e2e/schedule/schedule-backup-creation.go index 57fbab1361..c9a7a79172 100644 --- a/test/e2e/schedule/schedule-backup-creation.go +++ b/test/e2e/schedule/schedule-backup-creation.go @@ -10,10 +10,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) type ScheduleBackupCreation struct { diff --git a/test/e2e/schedule/schedule.go b/test/e2e/schedule/schedule.go index 7b7f2682fa..3c18c2dd3f 100644 --- a/test/e2e/schedule/schedule.go +++ b/test/e2e/schedule/schedule.go @@ -10,10 +10,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" . "github.com/vmware-tanzu/velero/test/e2e/test" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) type ScheduleBackup struct { diff --git a/test/e2e/test/test.go b/test/e2e/test/test.go index d37b9138cd..9b04c28e30 100644 --- a/test/e2e/test/test.go +++ b/test/e2e/test/test.go @@ -30,10 +30,9 @@ import ( "github.com/pkg/errors" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" ) /* @@ -84,7 +83,7 @@ func TestFunc(test VeleroBackupRestoreTest) func() { BeforeEach(func() { flag.Parse() // Using the global velero config which covered the installation for most common cases - veleroCfg := e2e.VeleroCfg + veleroCfg := VeleroCfg // TODO: Skip nodeport test until issue https://github.com/kubernetes/kubernetes/issues/114384 fixed // TODO: Although this issue is closed, but it's not fixed. // TODO: After bump up k8s version in AWS pipeline, this issue also apply for AWS pipeline. @@ -103,7 +102,7 @@ func TestFunc(test VeleroBackupRestoreTest) func() { func TestFuncWithMultiIt(tests []VeleroBackupRestoreTest) func() { return func() { - veleroCfg := e2e.VeleroCfg + veleroCfg := VeleroCfg for k := range tests { Expect(tests[k].Init()).To(Succeed(), fmt.Sprintf("Failed to instantiate test %s case", tests[k].GetTestMsg().Desc)) defer tests[k].GetTestCase().CtxCancel() @@ -212,7 +211,9 @@ func RunTestCase(test VeleroBackupRestoreTest) error { if test == nil { return errors.New("No case should be tested") } + defer test.Clean() + fmt.Printf("CreateResources %s\n", time.Now().Format("2006-01-02 15:04:05")) err := test.CreateResources() if err != nil { diff --git a/test/e2e/upgrade/upgrade.go b/test/e2e/upgrade/upgrade.go index 077823526d..6bc23c070b 100644 --- a/test/e2e/upgrade/upgrade.go +++ b/test/e2e/upgrade/upgrade.go @@ -26,12 +26,12 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/kibishii" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/kibishii" - . "github.com/vmware-tanzu/velero/test/e2e/util/providers" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test/util/providers" + . "github.com/vmware-tanzu/velero/test/util/velero" ) const ( diff --git a/test/perf/Makefile b/test/perf/Makefile new file mode 100644 index 0000000000..f30ee5b995 --- /dev/null +++ b/test/perf/Makefile @@ -0,0 +1,117 @@ +# Copyright 2020 The Kubernetes Authors. +# +# 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. + +# If you update this file, please follow: +# https://suva.sh/posts/well-documented-makefiles/ + +# Use GOPROXY environment variable if set + +.DEFAULT_GOAL:=help + +ARCH ?= $(shell go env GOOS)-$(shell go env GOARCH) +platform_temp = $(subst -, ,$(ARCH)) +GOOS = $(word 1, $(platform_temp)) +GOARCH = $(word 2, $(platform_temp)) + +GOPROXY := $(shell go env GOPROXY) +ifeq ($(GOPROXY),) +GOPROXY := https://proxy.golang.org +endif +export GOPROXY + +REPO_ROOT := $(shell git rev-parse --show-toplevel) + +help: ## Display this help + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-25s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +## -------------------------------------- +## Binaries +## -------------------------------------- + +TOOLS_DIR := $(REPO_ROOT)/hack/tools +BIN_DIR := bin +TOOLS_BIN_DIR := $(TOOLS_DIR)/$(BIN_DIR) +GINKGO := $(GOPATH)/bin/ginkgo +KUSTOMIZE := $(TOOLS_BIN_DIR)/kustomize +OUTPUT_DIR := _output/$(GOOS)/$(GOARCH)/bin +GINKGO_FOCUS ?= +GINKGO_SKIP ?= +SKIP_STR := $(foreach var, $(subst ., ,$(GINKGO_SKIP)),-skip "$(var)") +FOCUS_STR := $(foreach var, $(subst ., ,$(GINKGO_FOCUS)),-focus "$(var)") +VELERO_CLI ?=$$(pwd)/../../_output/bin/$(GOOS)/$(GOARCH)/velero +VELERO_IMAGE ?= velero/velero:main +VELERO_VERSION ?= $(VERSION) +PLUGINS ?= +RESTORE_HELPER_IMAGE ?= + +VELERO_NAMESPACE ?= velero +CREDS_FILE ?= +BSL_BUCKET ?= +BSL_PREFIX ?= +BSL_CONFIG ?= +VSL_CONFIG ?= +CLOUD_PROVIDER ?= +OBJECT_STORE_PROVIDER ?= +INSTALL_VELERO ?= true +REGISTRY_CREDENTIAL_FILE ?= + +FEATURES ?= +DEBUG_E2E_TEST ?= false +VELERO_SERVER_DEBUG_MODE ?= false +NFS_SERVER_PATH ?= +# Parameters to run migration tests along with all other E2E tests, and both of them should +# be provided or left them all empty to skip migration tests with no influence to other +# E2E tests. +UPLOADER_TYPE ?= +TEST_CASE_DESCRIBE ?= 'velero performance test' +BACKUP_FOR_RESTORE ?= + +.PHONY:ginkgo +ginkgo: # Make sure ginkgo is in $GOPATH/bin + go install github.com/onsi/ginkgo/ginkgo@v1.16.5 + +.PHONY: run +run: ginkgo + @[ "${CREDS_FILE}" ] && echo "Using credentials from ${CREDS_FILE}" || \ + ( echo "A credentials file is required to run E2E tests, please re-run the make target with CREDS_FILE="; exit 1 ) + @[ "${BSL_BUCKET}" ] && echo "Using bucket ${BSL_BUCKET} to store backups from E2E tests" || \ + (echo "Bucket to store the backups from E2E tests is required, please re-run with BSL_BUCKET="; exit 1 ) + @[ "${CLOUD_PROVIDER}" ] && echo "Using cloud provider ${CLOUD_PROVIDER}" || \ + (echo "Cloud provider for target cloud/plugin provider is required, please rerun with CLOUD_PROVIDER="; exit 1) + @$(GINKGO) -v $(FOCUS_STR) $(SKIP_STR) . -- -velerocli=$(VELERO_CLI) \ + -velero-image=$(VELERO_IMAGE) \ + -plugins=$(PLUGINS) \ + -velero-version=$(VELERO_VERSION) \ + -restore-helper-image=$(RESTORE_HELPER_IMAGE) \ + -velero-namespace=$(VELERO_NAMESPACE) \ + -credentials-file=$(CREDS_FILE) \ + -bucket=$(BSL_BUCKET) \ + -prefix=$(BSL_PREFIX) \ + -bsl-config=$(BSL_CONFIG) \ + -vsl-config=$(VSL_CONFIG) \ + -cloud-provider=$(CLOUD_PROVIDER) \ + -object-store-provider="$(OBJECT_STORE_PROVIDER)" \ + -features=$(FEATURES) \ + -install-velero=$(INSTALL_VELERO) \ + -registry-credential-file=$(REGISTRY_CREDENTIAL_FILE) \ + -debug-e2e-test=$(DEBUG_E2E_TEST) \ + -velero-server-debug-mode=$(VELERO_SERVER_DEBUG_MODE) \ + -uploader-type=$(UPLOADER_TYPE) \ + -nfs-server-path=$(NFS_SERVER_PATH) \ + -test-case-describe=$(TEST_CASE_DESCRIBE) \ + -backup-for-restore=$(BACKUP_FOR_RESTORE) + +build: ginkgo + mkdir -p $(OUTPUT_DIR) + $(GINKGO) build . diff --git a/test/perf/README.md b/test/perf/README.md new file mode 100644 index 0000000000..a3dd295baf --- /dev/null +++ b/test/perf/README.md @@ -0,0 +1,5 @@ +# End-to-end tests + +Document for running Velero end-to-end performance test suite. + +And the data generate tool for performance test could be found in [here](https://github.com/vmware-tanzu/velero-performance-test) \ No newline at end of file diff --git a/test/perf/backup/backup.go b/test/perf/backup/backup.go new file mode 100644 index 0000000000..7f9f35de08 --- /dev/null +++ b/test/perf/backup/backup.go @@ -0,0 +1,54 @@ +/* +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 backup + +import ( + "context" + "fmt" + "strings" + "time" + + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/perf/test" +) + +type BackupTest struct { + TestCase +} + +func (b *BackupTest) Init() error { + b.TestCase.Init() + b.Ctx, b.CtxCancel = context.WithTimeout(context.Background(), 1*time.Hour) + b.CaseBaseName = "backup" + b.BackupName = "backup-" + b.CaseBaseName + "-" + b.UUIDgen + + b.NSExcluded = &[]string{"kube-system", "velero", "default", "kube-public", "kube-node-lease"} + + b.BackupArgs = []string{ + "create", "--namespace", VeleroCfg.VeleroNamespace, "backup", b.BackupName, + "--exclude-namespaces", strings.Join(*b.NSExcluded, ","), + "--default-volumes-to-fs-backup", + "--snapshot-volumes=false", "--wait", + } + + b.TestMsg = &TestMSG{ + Desc: "Do backup resources for performance test", + FailedMSG: "Failed to backup resources", + Text: fmt.Sprintf("Should backup resources success"), + } + return nil +} diff --git a/test/perf/basic/basic.go b/test/perf/basic/basic.go new file mode 100644 index 0000000000..80c6b02185 --- /dev/null +++ b/test/perf/basic/basic.go @@ -0,0 +1,58 @@ +/* +Copyright 2021 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 basic + +import ( + "context" + "fmt" + "strings" + "time" + + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/perf/test" +) + +type BasicTest struct { + TestCase +} + +func (b *BasicTest) Init() error { + b.TestCase.Init() + b.Ctx, b.CtxCancel = context.WithTimeout(context.Background(), 1*time.Hour) + b.CaseBaseName = "backuprestore" + b.BackupName = "backup-" + b.CaseBaseName + "-" + b.UUIDgen + b.RestoreName = "restore-" + b.CaseBaseName + "-" + b.UUIDgen + + b.BackupArgs = []string{ + "create", "--namespace", VeleroCfg.VeleroNamespace, "backup", b.BackupName, + "--exclude-namespaces", strings.Join(*b.NSExcluded, ","), + "--default-volumes-to-fs-backup", + "--snapshot-volumes=false", "--wait", + } + + b.RestoreArgs = []string{ + "create", "--namespace", VeleroCfg.VeleroNamespace, "restore", b.RestoreName, + "--from-backup", b.BackupName, "--wait", + } + + b.TestMsg = &TestMSG{ + Desc: "Do backup and restore resources for performance test", + FailedMSG: "Failed to backup and restore resources", + Text: fmt.Sprintf("Should backup and restore resources success"), + } + return nil +} diff --git a/test/perf/e2e_suite_test.go b/test/perf/e2e_suite_test.go new file mode 100644 index 0000000000..4d3275dec1 --- /dev/null +++ b/test/perf/e2e_suite_test.go @@ -0,0 +1,121 @@ +/* +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 perf_test + +import ( + "context" + "flag" + "fmt" + "testing" + + . "github.com/onsi/ginkgo" + "github.com/onsi/ginkgo/reporters" + . "github.com/onsi/gomega" + "github.com/pkg/errors" + + . "github.com/vmware-tanzu/velero/test" + + "github.com/vmware-tanzu/velero/test/perf/backup" + "github.com/vmware-tanzu/velero/test/perf/basic" + "github.com/vmware-tanzu/velero/test/perf/restore" + "github.com/vmware-tanzu/velero/test/perf/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + "github.com/vmware-tanzu/velero/test/util/report" + . "github.com/vmware-tanzu/velero/test/util/velero" +) + +func init() { + flag.StringVar(&VeleroCfg.CloudProvider, "cloud-provider", "", "cloud that Velero will be installed into. Required.") + flag.StringVar(&VeleroCfg.ObjectStoreProvider, "object-store-provider", "", "provider of object store plugin. Required if cloud-provider is kind, otherwise ignored.") + flag.StringVar(&VeleroCfg.BSLBucket, "bucket", "", "name of the object storage bucket where backups from e2e tests should be stored. Required.") + flag.StringVar(&VeleroCfg.CloudCredentialsFile, "credentials-file", "", "file containing credentials for backup and volume provider. Required.") + flag.StringVar(&VeleroCfg.VeleroCLI, "velerocli", "velero", "path to the velero application to use.") + flag.StringVar(&VeleroCfg.VeleroImage, "velero-image", "velero/velero:main", "image for the velero server to be tested.") + flag.StringVar(&VeleroCfg.Plugins, "plugins", "", "provider plugins to be tested.") + flag.StringVar(&VeleroCfg.AddBSLPlugins, "additional-bsl-plugins", "", "additional plugins to be tested.") + flag.StringVar(&VeleroCfg.VeleroVersion, "velero-version", "main", "image version for the velero server to be tested with.") + flag.StringVar(&VeleroCfg.RestoreHelperImage, "restore-helper-image", "", "image for the velero restore helper to be tested.") + flag.StringVar(&VeleroCfg.BSLConfig, "bsl-config", "", "configuration to use for the backup storage location. Format is key1=value1,key2=value2") + flag.StringVar(&VeleroCfg.BSLPrefix, "prefix", "", "prefix under which all Velero data should be stored within the bucket. Optional.") + flag.StringVar(&VeleroCfg.VSLConfig, "vsl-config", "", "configuration to use for the volume snapshot location. Format is key1=value1,key2=value2") + flag.StringVar(&VeleroCfg.VeleroNamespace, "velero-namespace", "velero", "namespace to install Velero into") + flag.BoolVar(&VeleroCfg.InstallVelero, "install-velero", true, "install/uninstall velero during the test. Optional.") + flag.BoolVar(&VeleroCfg.UseNodeAgent, "use-node-agent", true, "whether deploy node agent daemonset velero during the test. Optional.") + flag.StringVar(&VeleroCfg.RegistryCredentialFile, "registry-credential-file", "", "file containing credential for the image registry, follows the same format rules as the ~/.docker/config.json file. Optional.") + //vmware-tanzu-experiments + flag.StringVar(&VeleroCfg.Features, "features", "", "Comma-separated list of features to enable for this Velero process.") + flag.StringVar(&VeleroCfg.DefaultCluster, "default-cluster-context", "", "Default cluster context for migration test.") + flag.BoolVar(&VeleroCfg.Debug, "debug-e2e-test", true, "Switch to control namespace cleaning.") + flag.StringVar(&VeleroCfg.UploaderType, "uploader-type", "kopia", "Identify persistent volume backup uploader.") + flag.BoolVar(&VeleroCfg.VeleroServerDebugMode, "velero-server-debug-mode", false, "Identify persistent volume backup uploader.") + flag.StringVar(&VeleroCfg.NFSServerPath, "nfs-server-path", "", "the path of nfs server") + flag.StringVar(&VeleroCfg.TestCaseDescribe, "test-case-describe", "velero performance test", "the description for the current test") + flag.StringVar(&VeleroCfg.BackupForRestore, "backup-for-restore", "", "the name of backup for restore") +} + +func initConfig() error { + cli, err := NewTestClient("") + if err != nil { + return errors.WithStack(err) + } + VeleroCfg.DefaultClient = &cli + + ReportData = &Report{ + TestDescription: VeleroCfg.TestCaseDescribe, + OtherFields: make(map[string]interface{}), + } + + return nil +} + +var _ = Describe("[PerformanceTest][BackupAndRestore] Velero test on both backup and restore resources", test.TestFunc(&basic.BasicTest{})) + +var _ = Describe("[PerformanceTest][Backup] Velero test on only backup resources", test.TestFunc(&backup.BackupTest{})) + +var _ = Describe("[PerformanceTest][Restore] Velero test on only restore resources", test.TestFunc(&restore.RestoreTest{})) + +func TestE2e(t *testing.T) { + flag.Parse() + By("Install test resources before testing TestE2e") + // Skip running E2E tests when running only "short" tests because: + // 1. E2E tests are long running tests involving installation of Velero and performing backup and restore operations. + // 2. E2E tests require a Kubernetes cluster to install and run velero which further requires more configuration. See above referenced command line flags. + + if err := initConfig(); err != nil { + fmt.Println(err) + t.FailNow() + } + + RegisterFailHandler(Fail) + junitReporter := reporters.NewJUnitReporter("report.xml") + RunSpecsWithDefaultAndCustomReporters(t, "E2e Suite", []Reporter{junitReporter}) +} + +var _ = BeforeSuite(func() { + if VeleroCfg.InstallVelero { + By("Install test resources before testing BeforeSuite") + Expect(PrepareVelero(context.Background(), "install resource before testing")).To(Succeed()) + } +}) + +var _ = AfterSuite(func() { + Expect(report.GenerateYamlReport()).To(Succeed()) + if VeleroCfg.InstallVelero && !VeleroCfg.Debug { + By("release test resources after testing") + Expect(VeleroUninstall(context.Background(), VeleroCfg.VeleroCLI, VeleroCfg.VeleroNamespace)).To(Succeed()) + } +}) diff --git a/test/perf/metrics/minio.go b/test/perf/metrics/minio.go new file mode 100644 index 0000000000..8ea7ae4c33 --- /dev/null +++ b/test/perf/metrics/minio.go @@ -0,0 +1,51 @@ +/* +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 metrics + +import ( + "github.com/pkg/errors" + + "github.com/vmware-tanzu/velero/test/util/metrics" +) + +const MinioDesc = "Minio disk usage" + +type MinioMetrics struct { + Metrics map[string]string + CloudCredentialsFile string + BslBucket string + BslPrefix string + BslConfig string +} + +func (m *MinioMetrics) Update() error { + if bucketSize, err := metrics.GetMinioDiskUsage(m.CloudCredentialsFile, + m.BslBucket, m.BslPrefix, m.BslConfig); err != nil { + return errors.WithStack(err) + } else { + m.Metrics["minio"] = formatMemoryDiskValue(bucketSize) + } + return nil +} + +func (m *MinioMetrics) GetMetrics() map[string]string { + return m.Metrics +} + +func (m *MinioMetrics) GetMetricsName() string { + return MinioDesc +} diff --git a/test/perf/metrics/monitor.go b/test/perf/metrics/monitor.go new file mode 100644 index 0000000000..f9032b38c7 --- /dev/null +++ b/test/perf/metrics/monitor.go @@ -0,0 +1,132 @@ +/* +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 metrics + +import ( + "fmt" + "strings" + "sync" + "time" +) + +// Metric is an interface for metrics that test needs. +type Metric interface { + Update() error + GetMetricsName() string + GetMetrics() map[string]string +} + +// MetricsCollector is a singleton struct for collecting metrics. +type MetricsCollector struct { + Metrics []Metric // metrics need update periodically + OneTimeMetrics []Metric // OneTimeMetrics just update one time + Mu sync.Mutex // mutex for protecting shared resources +} + +// GetMetricsCollector returns the singleton instance of MetricsCollector +func GetMetricsCollector() *MetricsCollector { + return &MetricsCollector{ + Metrics: []Metric{}, + OneTimeMetrics: []Metric{}, + } +} + +// RegisterMetric adds a metric to the MetricsCollector +func (m *MetricsCollector) RegisterMetric(metric Metric) { + m.Metrics = append(m.Metrics, metric) +} + +// RegisterOneTimeMetric adds a one-time metric to the MetricsCollector +func (m *MetricsCollector) RegisterOneTimeMetric(metric Metric) { + m.OneTimeMetrics = append(m.OneTimeMetrics, metric) +} + +// UpdateMetrics periodically updates the metrics for all metrics +func (m *MetricsCollector) UpdateMetrics() { + for { + m.Mu.Lock() // Acquire the lock before accessing shared resources + for _, metric := range m.Metrics { + if err := metric.Update(); err != nil { + fmt.Printf("Failed to update metrics: %v\n", err) + continue + } + } + m.Mu.Unlock() // Release the lock after accessing shared resources + time.Sleep(15 * time.Second) // Adjust the interval as per your requirement. + } +} + +// UpdateMetrics periodically updates the one-time metrics for all metrics +func (m *MetricsCollector) UpdateOneTimeMetrics() { + // NotifyOneTimeMonitors notifies the one-time metrics about the metric + for _, metric := range m.OneTimeMetrics { + if err := metric.Update(); err != nil { + fmt.Printf("Failed to update one-time metrics: %v\n", err) + continue + } + } +} + +// GetMetrics returns the metrics from all metrics +func (m *MetricsCollector) GetMetrics() map[string]interface{} { + m.Mu.Lock() // Acquire the lock before accessing shared resources + defer m.Mu.Unlock() // Release the lock after the function returns + + dataMap := make(map[string]interface{}) + resData := make(map[string]([]map[string]map[string]string)) + for _, metric := range m.Metrics { + monitorMetrics := metric.GetMetrics() + res := getResourceConsumption(monitorMetrics) + if _, ok := resData[metric.GetMetricsName()]; !ok { + resData[metric.GetMetricsName()] = make([]map[string]map[string]string, 0) + } + resData[metric.GetMetricsName()] = append(resData[metric.GetMetricsName()], res) + } + + for metricsName, metrics := range resData { + dataMap[metricsName] = metrics + } + + for _, metric := range m.OneTimeMetrics { + oneTimeMetricsMap := make(map[string]interface{}) + monitorMetrics := metric.GetMetrics() + for key, value := range monitorMetrics { + oneTimeMetricsMap[key] = value + } + dataMap[metric.GetMetricsName()] = oneTimeMetricsMap + } + return dataMap +} + +// Helper function to process Resource Consumption data +func getResourceConsumption(resourceMap map[string]string) map[string]map[string]string { + result := map[string]map[string]string{} + resourcePrefix := map[string]string{"MaxCPU": "Max CPU", "MaxMemory": "MaxMemory", "AverageCPU": "Average CPU", "AverageMemory": "Average Memory"} + + for key, value := range resourceMap { + parts := strings.Split(key, ":") + resourceName := parts[0] + resourceType := parts[1] + if _, ok := resourcePrefix[resourceType]; ok { + if result[resourceName] == nil { + result[resourceName] = map[string]string{} + } + result[resourceName][resourcePrefix[resourceType]] = value + } + } + return result +} diff --git a/test/perf/metrics/nfs.go b/test/perf/metrics/nfs.go new file mode 100644 index 0000000000..043a4f976d --- /dev/null +++ b/test/perf/metrics/nfs.go @@ -0,0 +1,51 @@ +/* +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 metrics + +import ( + "context" + + "github.com/pkg/errors" + + "github.com/vmware-tanzu/velero/test/util/metrics" +) + +const NFSDesc = "NFS disk usage" + +type NFSMetrics struct { + Metrics map[string]string + NFSServerPath string + Ctx context.Context +} + +func (n *NFSMetrics) Update() error { + if usedSpace, err := metrics.GetNFSPathDiskUsage(n.Ctx, n.NFSServerPath); err != nil { + return errors.WithStack(err) + } else { + n.Metrics["nfs"] = usedSpace + } + + return nil +} + +func (n *NFSMetrics) GetMetrics() map[string]string { + return n.Metrics +} + +func (n *NFSMetrics) GetMetricsName() string { + return NFSDesc +} diff --git a/test/perf/metrics/pod.go b/test/perf/metrics/pod.go new file mode 100644 index 0000000000..f341fe918a --- /dev/null +++ b/test/perf/metrics/pod.go @@ -0,0 +1,109 @@ +/* +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 metrics + +import ( + "context" + "fmt" + "strings" + + "github.com/pkg/errors" + + metricsclientset "k8s.io/metrics/pkg/client/clientset/versioned" + + "github.com/vmware-tanzu/velero/test/util/metrics" +) + +const PodResourceDesc = "Resource consumption" + +type PodMetrics struct { + Client *metricsclientset.Clientset + Metrics map[string]int64 + count int64 + PodName, Namespace string + Ctx context.Context +} + +func (p *PodMetrics) Update() error { + cpu, mem, err := metrics.GetPodUsageMetrics(p.Ctx, p.Client, p.PodName, p.Namespace) + if err != nil { + return errors.WithStack(err) + } else { + keyMaxCPU := p.PodName + ":MaxCPU" + curCPU := cpu.MilliValue() + if curCPU > p.Metrics[keyMaxCPU] { + p.Metrics[keyMaxCPU] = curCPU + } + + keyMaxMem := p.PodName + ":MaxMemory" + curMem := mem.MilliValue() + if curMem > p.Metrics[keyMaxMem] { + p.Metrics[keyMaxMem] = curMem + } + + keyAvgCPU := p.PodName + ":AverageCPU" + preAvgCPU := p.Metrics[keyAvgCPU] + p.Metrics[keyAvgCPU] = (preAvgCPU*p.count + curCPU) / (p.count + 1) + + keyAvgMem := p.PodName + ":AverageMemory" + preAvgMem := p.Metrics[keyAvgMem] + p.Metrics[keyAvgMem] = (preAvgMem*p.count + curMem) / (p.count + 1) + p.count++ + } + return nil +} + +func (p *PodMetrics) GetMetrics() map[string]string { + tmpMetrics := make(map[string]string) + for k := range p.Metrics { + if strings.Contains(k, "CPU") { + tmpMetrics[k] = formatCPUValue(p.Metrics[k]) + } else if strings.Contains(k, "Memory") { + tmpMetrics[k] = formatMemoryDiskValue(p.Metrics[k] / 1024) + } + } + return tmpMetrics +} + +func (p *PodMetrics) GetMetricsName() string { + return PodResourceDesc +} + +func formatCPUValue(milliValue int64) string { + if milliValue < 1000 { + return fmt.Sprintf("%d mili core", milliValue) + } + coreValue := float64(milliValue) / 1000.0 + return fmt.Sprintf("%.2f core", coreValue) +} + +func formatMemoryDiskValue(memoryValue int64) string { + units := []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"} + + if memoryValue == 0 { + return "0 B" + } + + base := int64(1024) + exp := int64(0) + for memoryValue >= base && exp < int64(len(units)-1) { + memoryValue /= base + exp++ + } + + return fmt.Sprintf("%d %s", memoryValue, units[exp]) +} diff --git a/test/perf/metrics/time.go b/test/perf/metrics/time.go new file mode 100644 index 0000000000..3334cbb297 --- /dev/null +++ b/test/perf/metrics/time.go @@ -0,0 +1,58 @@ +/* +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 metrics + +import "time" + +const TimeCaseDesc = "Time cost" + +type TimeMetrics struct { + Name string + TimeInfo map[string]time.Time // metric name : start timestamp + Metrics map[string]float64 // metric name : time duration +} + +func (t *TimeMetrics) GetMetrics() map[string]string { + tmpMetrics := make(map[string]string) + for k, v := range t.Metrics { + duration := time.Duration(v) * time.Second + tmpMetrics[k] = duration.String() + } + return tmpMetrics +} + +func (t *TimeMetrics) Start(name string) { + t.TimeInfo[name] = time.Now() +} + +func (t *TimeMetrics) End(name string) { + t.Metrics[name] = time.Now().Sub(t.TimeInfo[name]).Seconds() + if t.Metrics[name] < 1 { + // For those too shoter time difference we should ignored + // as it may not really execute the logic + delete(t.Metrics, name) + } +} + +func (t *TimeMetrics) Update() error { + t.Metrics[t.Name] = time.Now().Sub(t.TimeInfo[t.Name]).Seconds() + return nil +} + +func (t *TimeMetrics) GetMetricsName() string { + return TimeCaseDesc +} diff --git a/test/perf/restore/restore.go b/test/perf/restore/restore.go new file mode 100644 index 0000000000..025ef49865 --- /dev/null +++ b/test/perf/restore/restore.go @@ -0,0 +1,78 @@ +/* +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 restore + +import ( + "context" + "fmt" + "time" + + "github.com/pkg/errors" + + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/perf/test" + . "github.com/vmware-tanzu/velero/test/util/velero" +) + +type RestoreTest struct { + TestCase +} + +func (r *RestoreTest) Init() error { + r.TestCase.Init() + r.Ctx, r.CtxCancel = context.WithTimeout(context.Background(), 1*time.Hour) + r.CaseBaseName = "restore" + r.RestoreName = "restore-" + r.CaseBaseName + "-" + r.UUIDgen + + r.TestMsg = &TestMSG{ + Desc: "Do restore resources for performance test", + FailedMSG: "Failed to restore resources", + Text: fmt.Sprintf("Should restore resources success"), + } + return r.clearUpResourcesBeforRestore() +} + +func (r *RestoreTest) clearUpResourcesBeforRestore() error { + // we need to clear up all resources before do the restore test + return r.TestCase.Destroy() +} + +func (r *RestoreTest) Restore() error { + var backupName string + if VeleroCfg.BackupForRestore != "" { + backupName = VeleroCfg.BackupForRestore + } else { + // put partial parameters initialization here because we could not get latest backups in init periods for + // velero may not ready + var err error + backupName, err = GetLatestSuccessBackupsFromBSL(r.Ctx, VeleroCfg.VeleroCLI, "default") + if err != nil { + return errors.Wrapf(err, "failed to get backup to do the restore test") + } + } + + r.BackupName = backupName + r.RestoreArgs = []string{ + "create", "--namespace", VeleroCfg.VeleroNamespace, "restore", r.RestoreName, + "--from-backup", r.BackupName, "--wait", + } + + return r.TestCase.Restore() +} +func (r *RestoreTest) Destroy() error { + return nil +} diff --git a/test/perf/test/test.go b/test/perf/test/test.go new file mode 100644 index 0000000000..9aed01bb27 --- /dev/null +++ b/test/perf/test/test.go @@ -0,0 +1,292 @@ +/* +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 test + +import ( + "context" + "fmt" + "math/rand" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/pkg/errors" + + "github.com/vmware-tanzu/velero/test/util/report" + "github.com/vmware-tanzu/velero/test/util/velero" + + velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + . "github.com/vmware-tanzu/velero/test" + "github.com/vmware-tanzu/velero/test/perf/metrics" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/velero" +) + +/* +The VeleroBackupRestoreTest interface is just could be suit for the cases that follow the test flow of +create resources, backup, delete test resource, restore and verify. +And the cases have similar execute function and similar data. it's both fine for you to use it or not which +depends on your test patterns. +*/ +type VeleroBackupRestoreTest interface { + Init() error + CreateResources() error + Backup() error + Destroy() error + Restore() error + Verify() error + Clean() error + GetTestMsg() *TestMSG + GetTestCase() *TestCase +} + +type TestMSG struct { + Desc string + Text string + FailedMSG string +} + +type TestCase struct { + BackupName string + RestoreName string + CaseBaseName string + BackupArgs []string + RestoreArgs []string + NamespacesTotal int + TestMsg *TestMSG + Client TestClient + NSIncluded *[]string + NSExcluded *[]string + UseVolumeSnapshots bool + RestorePhaseExpect velerov1api.RestorePhase + Ctx context.Context + CtxCancel context.CancelFunc + UUIDgen string + timer *metrics.TimeMetrics +} + +func TestFunc(test VeleroBackupRestoreTest) func() { + return func() { + Expect(test.Init()).To(Succeed(), "Failed to instantiate test cases") + By(fmt.Sprintf("Run test %s ...... \n", test.GetTestCase().CaseBaseName)) + BeforeEach(func() { + // Using the global velero config which covered the installation for most common cases + if VeleroCfg.InstallVelero { + Expect(PrepareVelero(context.Background(), test.GetTestCase().CaseBaseName)).To(Succeed()) + } + }) + It(test.GetTestMsg().Text, func() { + Expect(RunTestCase(test)).To(Succeed(), test.GetTestMsg().FailedMSG) + }) + } +} + +func (t *TestCase) Init() error { + t.Ctx, t.CtxCancel = context.WithTimeout(context.Background(), 1*time.Hour) + t.NSExcluded = &[]string{"kube-system", "velero", "default", "kube-public", "kube-node-lease"} + t.UUIDgen = t.GenerateUUID() + t.Client = *VeleroCfg.DefaultClient + t.timer = &metrics.TimeMetrics{ + Name: "Total time cost", + TimeInfo: map[string]time.Time{"Total time cost": time.Now()}, + Metrics: make(map[string]float64), + } + return nil +} + +func (t *TestCase) GenerateUUID() string { + rand.Seed(time.Now().UnixNano()) + return fmt.Sprintf("%08d", rand.Intn(100000000)) +} + +func (t *TestCase) CreateResources() error { + return nil +} + +func (t *TestCase) Backup() error { + if len(t.BackupArgs) == 0 { + return nil + } + + if err := VeleroBackupExec(t.Ctx, VeleroCfg.VeleroCLI, VeleroCfg.VeleroNamespace, t.BackupName, t.BackupArgs); err != nil { + RunDebug(context.Background(), VeleroCfg.VeleroCLI, VeleroCfg.VeleroNamespace, t.BackupName, "") + return errors.Wrap(err, "Failed to backup resources") + } + return nil +} + +func (t *TestCase) Destroy() error { + By(fmt.Sprintf("Start to destroy namespace %s......", t.CaseBaseName), func() { + Expect(CleanupNamespacesFiterdByExcludes(t.GetTestCase().Ctx, t.Client, *t.NSExcluded)).To(Succeed(), "Could cleanup retrieve namespaces") + Expect(ClearClaimRefForFailedPVs(t.Ctx, t.Client)).To(Succeed(), "Failed to make PV status become to available") + }) + return nil +} + +func (t *TestCase) Restore() error { + if len(t.RestoreArgs) == 0 { + return nil + } + + By("Start to restore ......", func() { + if t.RestorePhaseExpect == "" { + t.RestorePhaseExpect = velerov1api.RestorePhaseCompleted + } + Expect(VeleroRestoreExec(t.Ctx, VeleroCfg.VeleroCLI, VeleroCfg.VeleroNamespace, t.RestoreName, t.RestoreArgs, t.RestorePhaseExpect)).To(Succeed(), func() string { + RunDebug(context.Background(), VeleroCfg.VeleroCLI, VeleroCfg.VeleroNamespace, "", t.RestoreName) + return "Fail to restore workload" + }) + }) + return nil +} + +func (t *TestCase) Verify() error { + return nil +} + +func (t *TestCase) Clean() error { + if !VeleroCfg.Debug { + By("Clean backups and restore after test", func() { + if len(t.BackupArgs) != 0 { + if err := VeleroBackupDelete(t.Ctx, VeleroCfg.VeleroCLI, VeleroCfg.VeleroNamespace, t.BackupName); err != nil { + fmt.Printf("Failed to delete backup %s with err %v\n", t.BackupName, err) + } + } + + if len(t.RestoreArgs) != 0 { + if err := VeleroRestoreDelete(t.Ctx, VeleroCfg.VeleroCLI, VeleroCfg.VeleroNamespace, t.RestoreName); err != nil { + fmt.Printf("Failed to delete restore %s with err %v\n", t.RestoreName, err) + } + } + }) + Expect(ClearClaimRefForFailedPVs(t.Ctx, t.Client)).To(Succeed(), "Failed to make PV status become to available") + } + return nil +} + +func (t *TestCase) GetTestMsg() *TestMSG { + return t.TestMsg +} + +func (t *TestCase) GetTestCase() *TestCase { + return t +} + +func RunTestCase(test VeleroBackupRestoreTest) error { + collectors := new(metrics.MetricsCollector) + test.GetTestCase().MonitorMetircs(test.GetTestCase().Ctx, collectors) + + timer := test.GetTestCase().timer + collectors.RegisterOneTimeMetric(timer) + + go collectors.UpdateMetrics() + By(fmt.Sprintf("Running test case %s %s\n", test.GetTestMsg().Desc, time.Now().Format("2006-01-02 15:04:05"))) + if test == nil { + return errors.New("No case should be tested") + } + + defer func() { + collectors.UpdateOneTimeMetrics() + metrics := collectors.GetMetrics() + report.AddTestSuitData(metrics, test.GetTestMsg().Desc) + test.Clean() + fmt.Printf("OutPut metrics %v for case %s", metrics, test.GetTestCase().CaseBaseName) + }() + + fmt.Printf("CreateResources %s\n", time.Now().Format("2006-01-02 15:04:05")) + timer.Start("Create Resources Time Cost") + err := test.CreateResources() + if err != nil { + return err + } + timer.End("Create Resources Time Cost") + + timer.Start("Backup Time Cost") + fmt.Printf("Backup %s\n", time.Now().Format("2006-01-02 15:04:05")) + err = test.Backup() + if err != nil { + return err + } + timer.End("Backup Time Cost") + + fmt.Printf("Destroy %s\n", time.Now().Format("2006-01-02 15:04:05")) + timer.Start("Destroy Resources Time Cost") + err = test.Destroy() + if err != nil { + return err + } + timer.End("Destroy Resources Time Cost") + + fmt.Printf("Restore %s\n", time.Now().Format("2006-01-02 15:04:05")) + timer.Start("Restore Time Cost") + err = test.Restore() + if err != nil { + return err + } + timer.End("Restore Time Cost") + + fmt.Printf("Verify %s\n", time.Now().Format("2006-01-02 15:04:05")) + timer.Start("Verify Resource Time Cost") + err = test.Verify() + if err != nil { + return err + } + timer.End("Verify Resource Time Cost") + fmt.Printf("Finish run test %s\n", time.Now().Format("2006-01-02 15:04:05")) + return nil +} + +func (t *TestCase) MonitorMetircs(ctx context.Context, collectors *metrics.MetricsCollector) { + if VeleroCfg.NFSServerPath == "" { + fmt.Println("couldn't monitor nfs server disk usage for nfs server path is not configured") + } else { + nfsMetrics := &metrics.NFSMetrics{NFSServerPath: VeleroCfg.NFSServerPath, Metrics: make(map[string]string), Ctx: ctx} + collectors.RegisterOneTimeMetric(nfsMetrics) + } + + minioMetrics := &metrics.MinioMetrics{ + CloudCredentialsFile: VeleroCfg.CloudCredentialsFile, + BslPrefix: VeleroCfg.BSLPrefix, + BslConfig: VeleroCfg.BSLConfig, + Metrics: make(map[string]string), + BslBucket: VeleroCfg.BSLBucket} + collectors.RegisterOneTimeMetric(minioMetrics) + + timeMetrics := &metrics.TimeMetrics{ + Name: t.CaseBaseName, + TimeInfo: make(map[string]time.Time), + Metrics: make(map[string]float64), + } + collectors.RegisterOneTimeMetric(timeMetrics) + + veleroPodList, err := velero.ListVeleroPods(ctx, VeleroCfg.VeleroNamespace) + if err != nil { + fmt.Printf("couldn't monitor velero pod metrics for failed to get velero pod with err %v\n", err) + } else { + for _, pod := range veleroPodList { + podMetrics := &metrics.PodMetrics{ + Ctx: ctx, + Client: VeleroCfg.DefaultClient.MetricsClient, + Metrics: make(map[string]int64), + PodName: pod, + Namespace: VeleroCfg.VeleroNamespace, + } + collectors.RegisterMetric(podMetrics) + } + } +} diff --git a/test/e2e/pkg/client/auth_providers.go b/test/pkg/client/auth_providers.go similarity index 100% rename from test/e2e/pkg/client/auth_providers.go rename to test/pkg/client/auth_providers.go diff --git a/test/e2e/pkg/client/client.go b/test/pkg/client/client.go similarity index 100% rename from test/e2e/pkg/client/client.go rename to test/pkg/client/client.go diff --git a/test/e2e/pkg/client/client_test.go b/test/pkg/client/client_test.go similarity index 100% rename from test/e2e/pkg/client/client_test.go rename to test/pkg/client/client_test.go diff --git a/test/e2e/pkg/client/config.go b/test/pkg/client/config.go similarity index 100% rename from test/e2e/pkg/client/config.go rename to test/pkg/client/config.go diff --git a/test/e2e/pkg/client/config_test.go b/test/pkg/client/config_test.go similarity index 100% rename from test/e2e/pkg/client/config_test.go rename to test/pkg/client/config_test.go diff --git a/test/e2e/pkg/client/dynamic.go b/test/pkg/client/dynamic.go similarity index 100% rename from test/e2e/pkg/client/dynamic.go rename to test/pkg/client/dynamic.go diff --git a/test/e2e/pkg/client/factory.go b/test/pkg/client/factory.go similarity index 93% rename from test/e2e/pkg/client/factory.go rename to test/pkg/client/factory.go index 75bffae82d..3c09111776 100644 --- a/test/e2e/pkg/client/factory.go +++ b/test/pkg/client/factory.go @@ -30,6 +30,7 @@ import ( "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + metricsclientset "k8s.io/metrics/pkg/client/clientset/versioned" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1" @@ -53,6 +54,9 @@ type Factory interface { // types to its scheme. It uses the following priority to specify the cluster // configuration: --kubeconfig flag, KUBECONFIG environment variable, in-cluster configuration. KubebuilderClient() (kbclient.Client, error) + + MetricsClient() (*metricsclientset.Clientset, error) + // SetBasename changes the basename for an already-constructed client. // This is useful for generating clients that require a different user-agent string below the root `velero` // command, such as the server subcommand. @@ -170,6 +174,19 @@ func (f *factory) KubebuilderClient() (kbclient.Client, error) { return kubebuilderClient, nil } +func (f *factory) MetricsClient() (*metricsclientset.Clientset, error) { + clientConfig, err := f.ClientConfig() + if err != nil { + return nil, err + } + + metricsClient, err := metricsclientset.NewForConfig(clientConfig) + if err != nil { + return nil, errors.WithStack(err) + } + return metricsClient, nil +} + func (f *factory) SetBasename(name string) { f.baseName = name } diff --git a/test/e2e/pkg/client/factory_test.go b/test/pkg/client/factory_test.go similarity index 100% rename from test/e2e/pkg/client/factory_test.go rename to test/pkg/client/factory_test.go diff --git a/test/e2e/testdata/enable_api_group_versions/README.md b/test/testdata/enable_api_group_versions/README.md similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/README.md rename to test/testdata/enable_api_group_versions/README.md diff --git a/test/e2e/testdata/enable_api_group_versions/case-a-source-v1beta1.yaml b/test/testdata/enable_api_group_versions/case-a-source-v1beta1.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/case-a-source-v1beta1.yaml rename to test/testdata/enable_api_group_versions/case-a-source-v1beta1.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/case-a-source.yaml b/test/testdata/enable_api_group_versions/case-a-source.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/case-a-source.yaml rename to test/testdata/enable_api_group_versions/case-a-source.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/case-a-target.yaml b/test/testdata/enable_api_group_versions/case-a-target.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/case-a-target.yaml rename to test/testdata/enable_api_group_versions/case-a-target.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/case-b-source-manually-added-mutations.yaml b/test/testdata/enable_api_group_versions/case-b-source-manually-added-mutations.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/case-b-source-manually-added-mutations.yaml rename to test/testdata/enable_api_group_versions/case-b-source-manually-added-mutations.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/case-b-target-manually-added-mutations.yaml b/test/testdata/enable_api_group_versions/case-b-target-manually-added-mutations.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/case-b-target-manually-added-mutations.yaml rename to test/testdata/enable_api_group_versions/case-b-target-manually-added-mutations.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/case-c-target-manually-added-mutations.yaml b/test/testdata/enable_api_group_versions/case-c-target-manually-added-mutations.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/case-c-target-manually-added-mutations.yaml rename to test/testdata/enable_api_group_versions/case-c-target-manually-added-mutations.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/case-d-target-manually-added-mutations.yaml b/test/testdata/enable_api_group_versions/case-d-target-manually-added-mutations.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/case-d-target-manually-added-mutations.yaml rename to test/testdata/enable_api_group_versions/case-d-target-manually-added-mutations.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/music_v1_rockband.yaml b/test/testdata/enable_api_group_versions/music_v1_rockband.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/music_v1_rockband.yaml rename to test/testdata/enable_api_group_versions/music_v1_rockband.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/music_v1alpha1_rockband.yaml b/test/testdata/enable_api_group_versions/music_v1alpha1_rockband.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/music_v1alpha1_rockband.yaml rename to test/testdata/enable_api_group_versions/music_v1alpha1_rockband.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/music_v2_rockband.yaml b/test/testdata/enable_api_group_versions/music_v2_rockband.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/music_v2_rockband.yaml rename to test/testdata/enable_api_group_versions/music_v2_rockband.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/music_v2beta1_rockband.yaml b/test/testdata/enable_api_group_versions/music_v2beta1_rockband.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/music_v2beta1_rockband.yaml rename to test/testdata/enable_api_group_versions/music_v2beta1_rockband.yaml diff --git a/test/e2e/testdata/enable_api_group_versions/music_v2beta2_rockband.yaml b/test/testdata/enable_api_group_versions/music_v2beta2_rockband.yaml similarity index 100% rename from test/e2e/testdata/enable_api_group_versions/music_v2beta2_rockband.yaml rename to test/testdata/enable_api_group_versions/music_v2beta2_rockband.yaml diff --git a/test/e2e/testdata/storage-class/aws.yaml b/test/testdata/storage-class/aws.yaml similarity index 100% rename from test/e2e/testdata/storage-class/aws.yaml rename to test/testdata/storage-class/aws.yaml diff --git a/test/e2e/testdata/storage-class/azure.yaml b/test/testdata/storage-class/azure.yaml similarity index 100% rename from test/e2e/testdata/storage-class/azure.yaml rename to test/testdata/storage-class/azure.yaml diff --git a/test/e2e/testdata/storage-class/gcp.yaml b/test/testdata/storage-class/gcp.yaml similarity index 100% rename from test/e2e/testdata/storage-class/gcp.yaml rename to test/testdata/storage-class/gcp.yaml diff --git a/test/e2e/testdata/storage-class/vsphere.yaml b/test/testdata/storage-class/vsphere.yaml similarity index 100% rename from test/e2e/testdata/storage-class/vsphere.yaml rename to test/testdata/storage-class/vsphere.yaml diff --git a/test/e2e/types.go b/test/types.go similarity index 89% rename from test/e2e/types.go rename to test/types.go index 4e3dcd1cd5..f0c00d9cfd 100644 --- a/test/e2e/types.go +++ b/test/types.go @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package e2e +package test import ( "time" "github.com/google/uuid" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) const StorageClassName = "e2e-storage-class" @@ -30,7 +30,15 @@ var UUIDgen uuid.UUID var VeleroCfg VeleroConfig +type Report struct { + TestDescription string `yaml:"Test Description"` + OtherFields map[string]interface{} `yaml:",inline"` +} + +var ReportData *Report + type VeleroConfig struct { + VeleroCfgInPerf VeleroCLI string VeleroImage string VeleroVersion string @@ -77,6 +85,12 @@ type VeleroConfig struct { StandbyClusterCloudProvider string } +type VeleroCfgInPerf struct { + NFSServerPath string + TestCaseDescribe string + BackupForRestore string +} + type SnapshotCheckPoint struct { NamespaceBackedUp string // SnapshotIDList is for Azure CSI Verification diff --git a/test/e2e/util/common/common.go b/test/util/common/common.go similarity index 100% rename from test/e2e/util/common/common.go rename to test/util/common/common.go diff --git a/test/e2e/util/csi/AzureVolumeSnapshotClass.yaml b/test/util/csi/AzureVolumeSnapshotClass.yaml similarity index 100% rename from test/e2e/util/csi/AzureVolumeSnapshotClass.yaml rename to test/util/csi/AzureVolumeSnapshotClass.yaml diff --git a/test/e2e/util/csi/common.go b/test/util/csi/common.go similarity index 99% rename from test/e2e/util/csi/common.go rename to test/util/csi/common.go index 56af1ef58f..9c2a2d5b52 100644 --- a/test/e2e/util/csi/common.go +++ b/test/util/csi/common.go @@ -29,7 +29,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) func GetClients() (*kubernetes.Clientset, *snapshotterClientSet.Clientset, error) { diff --git a/test/e2e/util/k8s/client.go b/test/util/k8s/client.go similarity index 87% rename from test/e2e/util/k8s/client.go rename to test/util/k8s/client.go index 0db9d3aaa5..1018e3bdf1 100644 --- a/test/e2e/util/k8s/client.go +++ b/test/util/k8s/client.go @@ -18,9 +18,10 @@ package k8s import ( "k8s.io/client-go/kubernetes" + metricsclientset "k8s.io/metrics/pkg/client/clientset/versioned" kbclient "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/vmware-tanzu/velero/test/e2e/pkg/client" + "github.com/vmware-tanzu/velero/test/pkg/client" ) // TestClient contains different API clients that are in use throughout @@ -43,6 +44,8 @@ type TestClient struct { // controller runtime framework by v2.0, it is the intent to remove all // client-go API clients. Please use the controller runtime to make API calls for tests. dynamicFactory client.DynamicFactory + + MetricsClient *metricsclientset.Clientset } var ( @@ -80,9 +83,16 @@ func InitTestClient(kubecontext string) (TestClient, error) { factory := client.NewDynamicFactory(dynamicClient) - return TestClient{ + metricsClient, err := f.MetricsClient() + if err != nil { + return TestClient{}, err + } + testClient := TestClient{ Kubebuilder: kb, ClientGo: clientGo, dynamicFactory: factory, - }, nil + MetricsClient: metricsClient, + } + + return testClient, nil } diff --git a/test/e2e/util/k8s/common.go b/test/util/k8s/common.go similarity index 99% rename from test/e2e/util/k8s/common.go rename to test/util/k8s/common.go index 7a48b52d66..7efb56add5 100644 --- a/test/e2e/util/k8s/common.go +++ b/test/util/k8s/common.go @@ -30,7 +30,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/builder" veleroexec "github.com/vmware-tanzu/velero/pkg/util/exec" - "github.com/vmware-tanzu/velero/test/e2e/util/common" + "github.com/vmware-tanzu/velero/test/util/common" ) // ensureClusterExists returns whether or not a Kubernetes cluster exists for tests to be run on. diff --git a/test/e2e/util/k8s/configmap.go b/test/util/k8s/configmap.go similarity index 100% rename from test/e2e/util/k8s/configmap.go rename to test/util/k8s/configmap.go diff --git a/test/e2e/util/k8s/crd.go b/test/util/k8s/crd.go similarity index 100% rename from test/e2e/util/k8s/crd.go rename to test/util/k8s/crd.go diff --git a/test/e2e/util/k8s/deployment.go b/test/util/k8s/deployment.go similarity index 100% rename from test/e2e/util/k8s/deployment.go rename to test/util/k8s/deployment.go diff --git a/test/e2e/util/k8s/namespace.go b/test/util/k8s/namespace.go similarity index 89% rename from test/e2e/util/k8s/namespace.go rename to test/util/k8s/namespace.go index 1978f06b6b..e056dc9905 100644 --- a/test/e2e/util/k8s/namespace.go +++ b/test/util/k8s/namespace.go @@ -126,6 +126,30 @@ func CleanupNamespacesWithPoll(ctx context.Context, client TestClient, CaseBaseN return nil } +func CleanupNamespacesFiterdByExcludes(ctx context.Context, client TestClient, excludeNS []string) error { + namespaces, err := client.ClientGo.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) + + if err != nil { + return errors.Wrap(err, "Could not retrieve namespaces") + } + for _, checkNamespace := range namespaces.Items { + isExclude := false + for k := range excludeNS { + if checkNamespace.Name == excludeNS[k] { + isExclude = true + } + } + if !isExclude { + err := DeleteNamespace(ctx, client, checkNamespace.Name, true) + if err != nil { + return errors.Wrapf(err, "Could not delete namespace %s", checkNamespace.Name) + } + fmt.Printf("Namespace %s was deleted\n", checkNamespace.Name) + } + } + return nil +} + func CleanupNamespaces(ctx context.Context, client TestClient, CaseBaseName string) error { namespaces, err := client.ClientGo.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) if err != nil { diff --git a/test/e2e/util/k8s/node.go b/test/util/k8s/node.go similarity index 93% rename from test/e2e/util/k8s/node.go rename to test/util/k8s/node.go index 223bc0416d..9e402850c5 100644 --- a/test/e2e/util/k8s/node.go +++ b/test/util/k8s/node.go @@ -8,7 +8,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - common "github.com/vmware-tanzu/velero/test/e2e/util/common" + common "github.com/vmware-tanzu/velero/test/util/common" ) func GetWorkerNodes(ctx context.Context) ([]string, error) { diff --git a/test/e2e/util/k8s/persistentvolumes.go b/test/util/k8s/persistentvolumes.go similarity index 70% rename from test/e2e/util/k8s/persistentvolumes.go rename to test/util/k8s/persistentvolumes.go index 44ee5fff10..f4c8005945 100644 --- a/test/e2e/util/k8s/persistentvolumes.go +++ b/test/util/k8s/persistentvolumes.go @@ -22,6 +22,7 @@ import ( "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/util/retry" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -64,3 +65,31 @@ func AddAnnotationToPersistentVolume(ctx context.Context, client TestClient, nam return client.ClientGo.CoreV1().PersistentVolumes().Update(ctx, newPV, metav1.UpdateOptions{}) } + +func ClearClaimRefForFailedPVs(ctx context.Context, client TestClient) error { + pvList, err := client.ClientGo.CoreV1().PersistentVolumes().List(ctx, metav1.ListOptions{}) + if err != nil { + return fmt.Errorf("failed to list PVs: %v", err) + } + + for _, pv := range pvList.Items { + pvName := pv.Name + + if pv.Status.Phase != corev1.VolumeAvailable { + retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { + pv, getErr := client.ClientGo.CoreV1().PersistentVolumes().Get(ctx, pvName, metav1.GetOptions{}) + if getErr != nil { + return fmt.Errorf("failed to get PV %s: %v", pvName, getErr) + } + pv.Spec.ClaimRef = nil + _, updateErr := client.ClientGo.CoreV1().PersistentVolumes().Update(ctx, pv, metav1.UpdateOptions{}) + return updateErr + }) + if retryErr != nil { + return fmt.Errorf("failed to clear claimRef for PV %s: %v", pvName, retryErr) + } + } + } + + return nil +} diff --git a/test/e2e/util/k8s/pod.go b/test/util/k8s/pod.go similarity index 100% rename from test/e2e/util/k8s/pod.go rename to test/util/k8s/pod.go diff --git a/test/e2e/util/k8s/pvc.go b/test/util/k8s/pvc.go similarity index 100% rename from test/e2e/util/k8s/pvc.go rename to test/util/k8s/pvc.go diff --git a/test/e2e/util/k8s/rbac.go b/test/util/k8s/rbac.go similarity index 100% rename from test/e2e/util/k8s/rbac.go rename to test/util/k8s/rbac.go diff --git a/test/e2e/util/k8s/sc.go b/test/util/k8s/sc.go similarity index 100% rename from test/e2e/util/k8s/sc.go rename to test/util/k8s/sc.go diff --git a/test/e2e/util/k8s/secret.go b/test/util/k8s/secret.go similarity index 100% rename from test/e2e/util/k8s/secret.go rename to test/util/k8s/secret.go diff --git a/test/e2e/util/k8s/service.go b/test/util/k8s/service.go similarity index 100% rename from test/e2e/util/k8s/service.go rename to test/util/k8s/service.go diff --git a/test/e2e/util/k8s/serviceaccount.go b/test/util/k8s/serviceaccount.go similarity index 100% rename from test/e2e/util/k8s/serviceaccount.go rename to test/util/k8s/serviceaccount.go diff --git a/test/e2e/util/k8s/statefulset.go b/test/util/k8s/statefulset.go similarity index 100% rename from test/e2e/util/k8s/statefulset.go rename to test/util/k8s/statefulset.go diff --git a/test/e2e/util/kibishii/kibishii_utils.go b/test/util/kibishii/kibishii_utils.go similarity index 98% rename from test/e2e/util/kibishii/kibishii_utils.go rename to test/util/kibishii/kibishii_utils.go index 2d641bdecf..0b2251112b 100644 --- a/test/e2e/util/kibishii/kibishii_utils.go +++ b/test/util/kibishii/kibishii_utils.go @@ -28,10 +28,10 @@ import ( "k8s.io/apimachinery/pkg/util/wait" veleroexec "github.com/vmware-tanzu/velero/pkg/util/exec" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" - . "github.com/vmware-tanzu/velero/test/e2e/util/providers" - . "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" + . "github.com/vmware-tanzu/velero/test/util/providers" + . "github.com/vmware-tanzu/velero/test/util/velero" ) const ( diff --git a/test/util/metrics/minio.go b/test/util/metrics/minio.go new file mode 100644 index 0000000000..163212713c --- /dev/null +++ b/test/util/metrics/minio.go @@ -0,0 +1,33 @@ +/* +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 metrics + +import ( + "github.com/pkg/errors" + + "github.com/vmware-tanzu/velero/test/util/providers" +) + +func GetMinioDiskUsage(cloudCredentialsFile string, bslBucket string, bslPrefix string, bslConfig string) (int64, error) { + var aws providers.AWSStorage + toatalSize, err := aws.GetMinioBucketSize(cloudCredentialsFile, bslBucket, bslPrefix, bslConfig) + if err != nil { + return 0, errors.Errorf("a Failed to get minio bucket size with err %v", err) + } else { + return toatalSize, nil + } +} diff --git a/test/util/metrics/nfs.go b/test/util/metrics/nfs.go new file mode 100644 index 0000000000..2ea6b2f1e3 --- /dev/null +++ b/test/util/metrics/nfs.go @@ -0,0 +1,48 @@ +/* +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 metrics + +import ( + "context" + "os/exec" + "strings" + + "github.com/pkg/errors" +) + +func GetNFSPathDiskUsage(ctx context.Context, nfsServerPath string) (string, error) { + cmd := exec.CommandContext(ctx, "df", "-h", nfsServerPath) + output, err := cmd.Output() + if err != nil { + return "0B", errors.WithStack(err) + } + + strOutput := string(output) + // parse command output + lines := strings.Split(strOutput, "\n") + if len(lines) < 2 { + return "0B", errors.Errorf("Failed to get disk usage for nfs server path %s with command output %s", nfsServerPath, strOutput) + } + + fields := strings.Fields(lines[1]) + if len(fields) < 5 { + return "0B", errors.Errorf("Failed to parse disk usage for nfs server path %s with command output %s", nfsServerPath, strOutput) + } + + usedSpaceStr := fields[2] + return usedSpaceStr, nil +} diff --git a/test/util/metrics/pod.go b/test/util/metrics/pod.go new file mode 100644 index 0000000000..331211bb0e --- /dev/null +++ b/test/util/metrics/pod.go @@ -0,0 +1,45 @@ +/* +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 metrics + +import ( + "context" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/metrics/pkg/apis/metrics/v1beta1" + metricsclientset "k8s.io/metrics/pkg/client/clientset/versioned" +) + +func GetPodUsageMetrics(ctx context.Context, metricsClient *metricsclientset.Clientset, podName, namespace string) (cpuUsage, memoryUsage resource.Quantity, err error) { + var podMetrics *v1beta1.PodMetrics + podMetrics, err = metricsClient.MetricsV1beta1().PodMetricses(namespace).Get(ctx, podName, metav1.GetOptions{}) + if err != nil { + return + } + + // Variables to store the max and sum of CPU and memory usage + // For velero pod we only return the main container + for _, container := range podMetrics.Containers { + cpuUsage = container.Usage[corev1.ResourceCPU] + memoryUsage = container.Usage[corev1.ResourceMemory] + return + } + + return +} diff --git a/test/e2e/util/providers/aws_utils.go b/test/util/providers/aws_utils.go similarity index 79% rename from test/e2e/util/providers/aws_utils.go rename to test/util/providers/aws_utils.go index e84c4fd637..e30913d71a 100644 --- a/test/e2e/util/providers/aws_utils.go +++ b/test/util/providers/aws_utils.go @@ -29,7 +29,7 @@ import ( "github.com/pkg/errors" "github.com/vmware-tanzu/velero/pkg/cmd/util/flag" - e2e "github.com/vmware-tanzu/velero/test/e2e" + "github.com/vmware-tanzu/velero/test" ) type AWSStorage string @@ -145,7 +145,7 @@ func (s AWSStorage) DeleteObjectsInBucket(cloudCredentialsFile, bslBucket, bslPr return nil } -func (s AWSStorage) IsSnapshotExisted(cloudCredentialsFile, bslConfig, backupObject string, snapshotCheck e2e.SnapshotCheckPoint) error { +func (s AWSStorage) IsSnapshotExisted(cloudCredentialsFile, bslConfig, backupObject string, snapshotCheck test.SnapshotCheckPoint) error { config := flag.NewMap() config.Set(bslConfig) @@ -197,3 +197,57 @@ func (s AWSStorage) IsSnapshotExisted(cloudCredentialsFile, bslConfig, backupObj return nil } } + +func (s AWSStorage) GetMinioBucketSize(cloudCredentialsFile, bslBucket, bslPrefix, bslConfig string) (int64, error) { + config := flag.NewMap() + config.Set(bslConfig) + region := config.Data()["region"] + s3url := config.Data()["s3Url"] + s3Config := &aws.Config{ + Credentials: credentials.NewSharedCredentials(cloudCredentialsFile, ""), + Endpoint: aws.String(s3url), + Region: aws.String(region), + DisableSSL: aws.Bool(true), + S3ForcePathStyle: aws.Bool(true), + } + if region != "minio" { + return 0, errors.New("it only supported by minio") + } + sess, err := session.NewSession(s3Config) + if err != nil { + return 0, errors.Wrapf(err, "Error create config session") + } + + svc := s3.New(sess) + var totalSize int64 + var continuationToken *string + // Paginate through objects in the bucket + objectsInput := &s3.ListObjectsV2Input{ + Bucket: aws.String(bslBucket), + ContinuationToken: continuationToken, + } + if bslPrefix != "" { + objectsInput.Prefix = aws.String(bslPrefix) + } + + for { + resp, err := svc.ListObjectsV2(objectsInput) + if err != nil { + return 0, errors.Wrapf(err, "Error list objects") + } + + // Process objects in the current response + for _, obj := range resp.Contents { + totalSize += *obj.Size + } + + // Check if there are more objects to retrieve + if !*resp.IsTruncated { + break + } + + // Set the continuation token for the next page + continuationToken = resp.NextContinuationToken + } + return totalSize, nil +} diff --git a/test/e2e/util/providers/azure_utils.go b/test/util/providers/azure_utils.go similarity index 99% rename from test/e2e/util/providers/azure_utils.go rename to test/util/providers/azure_utils.go index d97b7e9aee..af7339905f 100644 --- a/test/e2e/util/providers/azure_utils.go +++ b/test/util/providers/azure_utils.go @@ -37,7 +37,7 @@ import ( "golang.org/x/net/context" "github.com/vmware-tanzu/velero/pkg/cmd/util/flag" - . "github.com/vmware-tanzu/velero/test/e2e" + . "github.com/vmware-tanzu/velero/test" ) type AzureStorage string diff --git a/test/e2e/util/providers/common.go b/test/util/providers/common.go similarity index 98% rename from test/e2e/util/providers/common.go rename to test/util/providers/common.go index eaeb5c3c13..6502fbe201 100644 --- a/test/e2e/util/providers/common.go +++ b/test/util/providers/common.go @@ -24,8 +24,8 @@ import ( "github.com/pkg/errors" - . "github.com/vmware-tanzu/velero/test/e2e" - velero "github.com/vmware-tanzu/velero/test/e2e/util/velero" + . "github.com/vmware-tanzu/velero/test" + velero "github.com/vmware-tanzu/velero/test/util/velero" ) type ObjectsInStorage interface { diff --git a/test/e2e/util/providers/gcloud_utils.go b/test/util/providers/gcloud_utils.go similarity index 97% rename from test/e2e/util/providers/gcloud_utils.go rename to test/util/providers/gcloud_utils.go index 47008a0a97..6702f37ba4 100644 --- a/test/e2e/util/providers/gcloud_utils.go +++ b/test/util/providers/gcloud_utils.go @@ -30,7 +30,7 @@ import ( "google.golang.org/api/iterator" "google.golang.org/api/option" - "github.com/vmware-tanzu/velero/test/e2e" + "github.com/vmware-tanzu/velero/test" ) type GCSStorage string @@ -101,7 +101,7 @@ func (s GCSStorage) DeleteObjectsInBucket(cloudCredentialsFile, bslBucket, bslPr } } -func (s GCSStorage) IsSnapshotExisted(cloudCredentialsFile, bslConfig, backupObject string, snapshotCheck e2e.SnapshotCheckPoint) error { +func (s GCSStorage) IsSnapshotExisted(cloudCredentialsFile, bslConfig, backupObject string, snapshotCheck test.SnapshotCheckPoint) error { ctx := context.Background() data, err := os.ReadFile(cloudCredentialsFile) if err != nil { diff --git a/test/util/report/report.go b/test/util/report/report.go new file mode 100644 index 0000000000..91ec876b17 --- /dev/null +++ b/test/util/report/report.go @@ -0,0 +1,52 @@ +/* +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 report + +import ( + "os" + + "github.com/pkg/errors" + "gopkg.in/yaml.v3" + + "github.com/vmware-tanzu/velero/test" +) + +func GenerateYamlReport() error { + yamlData, err := yaml.Marshal(test.ReportData) + if err != nil { + return errors.Wrap(err, "error marshal data into yaml") + } + + // Open the file in append mode. If the file does not exist, it will be created. + filePath := "perf-report.yaml" + file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return errors.Wrap(err, "error opening file") + } + defer file.Close() + + // Write the YAML data to the file + _, err = file.Write(yamlData) + if err != nil { + return errors.Wrap(err, "Error writing YAML to file:") + } + return nil +} + +func AddTestSuitData(dataMap map[string]interface{}, testSuitDesc string) { + test.ReportData.OtherFields[testSuitDesc] = dataMap +} diff --git a/test/e2e/util/velero/install.go b/test/util/velero/install.go similarity index 99% rename from test/e2e/util/velero/install.go rename to test/util/velero/install.go index 7d9ce3546b..fcf2a2090d 100644 --- a/test/e2e/util/velero/install.go +++ b/test/util/velero/install.go @@ -38,8 +38,8 @@ import ( velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "github.com/vmware-tanzu/velero/pkg/cmd/cli/install" velerexec "github.com/vmware-tanzu/velero/pkg/util/exec" - . "github.com/vmware-tanzu/velero/test/e2e" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) const ( diff --git a/test/e2e/util/velero/velero_utils.go b/test/util/velero/velero_utils.go similarity index 95% rename from test/e2e/util/velero/velero_utils.go rename to test/util/velero/velero_utils.go index 5fb4c59907..1720de008f 100644 --- a/test/e2e/util/velero/velero_utils.go +++ b/test/util/velero/velero_utils.go @@ -45,10 +45,10 @@ import ( cliinstall "github.com/vmware-tanzu/velero/pkg/cmd/cli/install" "github.com/vmware-tanzu/velero/pkg/cmd/util/flag" veleroexec "github.com/vmware-tanzu/velero/pkg/util/exec" - . "github.com/vmware-tanzu/velero/test/e2e" - common "github.com/vmware-tanzu/velero/test/e2e/util/common" - util "github.com/vmware-tanzu/velero/test/e2e/util/csi" - . "github.com/vmware-tanzu/velero/test/e2e/util/k8s" + . "github.com/vmware-tanzu/velero/test" + common "github.com/vmware-tanzu/velero/test/util/common" + util "github.com/vmware-tanzu/velero/test/util/csi" + . "github.com/vmware-tanzu/velero/test/util/k8s" ) const BackupObjectsPrefix = "backups" @@ -1013,6 +1013,46 @@ func GetBackupsFromBsl(ctx context.Context, veleroCLI, bslName string) ([]string return common.GetListByCmdPipes(ctx, cmds) } +func GetLatestSuccessBackupsFromBSL(ctx context.Context, veleroCLI, bslName string) (string, error) { + args1 := []string{"get", "backups"} + if strings.TrimSpace(bslName) != "" { + args1 = append(args1, "-l", "velero.io/storage-location="+bslName) + } + cmds := []*common.OsCommandLine{} + + cmd := &common.OsCommandLine{ + Cmd: veleroCLI, + Args: args1, + } + cmds = append(cmds, cmd) + + cmd = &common.OsCommandLine{ + Cmd: "grep", + Args: []string{"Completed"}, + } + cmds = append(cmds, cmd) + + cmd = &common.OsCommandLine{ + Cmd: "awk", + Args: []string{"{print $1}"}, + } + cmds = append(cmds, cmd) + + cmd = &common.OsCommandLine{ + Cmd: "head", + Args: []string{"-n", "1"}, + } + cmds = append(cmds, cmd) + + backups, err := common.GetListByCmdPipes(ctx, cmds) + if err != nil { + return "", errors.WithStack(err) + } else if len(backups) != 1 { + return "", errors.Errorf("failed to get latest success backup from bsl %s with result %v", bslName, backups) + } + return backups[0], nil +} + func GetScheduledBackupsCreationTime(ctx context.Context, veleroCLI, bslName, scheduleName string) ([]string, error) { var creationTimes []string backups, err := GetBackupsCreationTime(ctx, veleroCLI, bslName) @@ -1208,6 +1248,20 @@ func DeleteBackups(ctx context.Context, client TestClient) error { return nil } +func DeleteRestores(ctx context.Context, client TestClient) error { + restoreList := new(velerov1api.RestoreList) + if err := client.Kubebuilder.List(ctx, restoreList, &kbclient.ListOptions{Namespace: VeleroCfg.VeleroNamespace}); err != nil { + return fmt.Errorf("failed to list restore object in %s namespace with err %v", VeleroCfg.VeleroNamespace, err) + } + for _, restore := range restoreList.Items { + fmt.Printf("Restore %s is going to be deleted...\n", restore.Name) + if err := VeleroRestoreDelete(ctx, VeleroCfg.VeleroCLI, VeleroCfg.VeleroNamespace, restore.Name); err != nil { + return err + } + } + return nil +} + func GetSchedule(ctx context.Context, veleroNamespace, scheduleName string) (string, error) { checkSnapshotCmd := exec.CommandContext(ctx, "kubectl", "get", "schedule", "-n", veleroNamespace, scheduleName, "-o=jsonpath='{.metadata.creationTimestamp}'") @@ -1355,6 +1409,23 @@ func UpdateNodeAgent(ctx context.Context, veleroCfg VeleroConfig, dsjson string) return common.GetListByCmdPipes(ctx, cmds) } +func ListVeleroPods(ctx context.Context, veleroNamespace string) ([]string, error) { + cmds := []*common.OsCommandLine{} + cmd := &common.OsCommandLine{ + Cmd: "kubectl", + Args: []string{"get", "pod", "-n", veleroNamespace, "--no-headers"}, + } + cmds = append(cmds, cmd) + + cmd = &common.OsCommandLine{ + Cmd: "awk", + Args: []string{"{print $1}"}, + } + cmds = append(cmds, cmd) + + return common.GetListByCmdPipes(ctx, cmds) +} + func GetVeleroResource(ctx context.Context, veleroNamespace, namespace, resourceName string) ([]string, error) { cmds := []*common.OsCommandLine{} cmd := &common.OsCommandLine{