mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-01-09 06:33:22 +00:00
* Restore API group version by priority Signed-off-by: F. Gold <fgold@vmware.com> * Add changelog Signed-off-by: F. Gold <fgold@vmware.com> * Correct spelling Signed-off-by: F. Gold <fgold@vmware.com> * Refactor userResourceGroupVersionPriorities(...) to accept config map, adjust unit test Signed-off-by: F. Gold <fgold@vmware.com> * Move some unit tests into e2e Signed-off-by: F. Gold <fgold@vmware.com> * Add three e2e tests using Testify Suites Summary of changes Makefile - add testify e2e test target go.sum - changed with go mod tidy pkg/install/install.go - increased polling timeout test/e2e/restore_priority_group_test.go - deleted test/e2e/restore_test.go - deleted test/e2e/velero_utils.go - made restic optional in velero install test/e2e_testify/Makefile - makefile for testify e2e tests test/e2e_testify/README.md - example command for running tests test/e2e_testify/common_test.go - helper functions test/e2e_testify/e2e_suite_test.go - prepare for tests and run test/e2e_testify/restore_priority_apigv_test.go - test cases Signed-off-by: F. Gold <fgold@vmware.com> * Make changes per @nrb code review Signed-off-by: F. Gold <fgold@vmware.com> * Wait for pods in e2e tests Signed-off-by: F. Gold <fgold@vmware.com> * Remove testify suites e2e scaffolding moved to PR #3354 Signed-off-by: F. Gold <fgold@vmware.com> * Make changes per @brito-rafa and Velero maintainers code reviews - Made changes suggested by @brito-rafa in GitHub. - We had a code review meeting with @carlisia, @dsu-igeek, @zubron, and @nrb - and changes were made based on their suggetions: - pull in logic from 'meetsAPIGVResotreReqs()' to restore.go. - add TODO to remove APIGroupVersionFeatureFlag check - have feature flag and backup version format checks in separate `if` statements. - rename variables to be sourceGVs, targetGVs, and userGVs. Signed-off-by: F. Gold <fgold@vmware.com> * Convert Testify Suites e2e tests to existing Ginkgo framework Signed-off-by: F. Gold <fgold@vmware.com> * Made changes per @zubron PR review Signed-off-by: F. Gold <fgold@vmware.com> * Run go mod tidy after resolving go.sum merge conflict Signed-off-by: F. Gold <fgold@vmware.com> * Add feature documentation to velero.io site Signed-off-by: F. Gold <fgold@vmware.com> * Add config map e2e test; rename e2e test file and name Signed-off-by: F. Gold <fgold@vmware.com> * Update go.{mod,sum} files Signed-off-by: F. Gold <fgold@vmware.com> * Move CRDs and CRs to testdata folder Signed-off-by: F. Gold <fgold@vmware.com> * Fix typos in cert-manager to pass codespell CICD check Signed-off-by: F. Gold <fgold@vmware.com> * Make changes per @nrb code review round 2 - make checkAndReadDir function private - add info level messages when priorties 1-3 API group versions can not be used Signed-off-by: F. Gold <fgold@vmware.com> * Make user config map rules less strict Signed-off-by: F. Gold <fgold@vmware.com> * Update e2e test image version in example Signed-off-by: F. Gold <fgold@vmware.com> * Update case A music-system controller code Signed-off-by: F. Gold <fgold@vmware.com> * Documentation updates Signed-off-by: F. Gold <fgold@vmware.com> * Update migration case documentation Signed-off-by: F. Gold <fgold@vmware.com>
272 lines
7.8 KiB
Go
272 lines
7.8 KiB
Go
/*
|
|
Copyright The Velero Contributors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package archive
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
"github.com/vmware-tanzu/velero/pkg/test"
|
|
)
|
|
|
|
func TestParse(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
files []string
|
|
dir string
|
|
wantErrMsg string
|
|
want map[string]*ResourceItems
|
|
}{
|
|
{
|
|
name: "when there is no top-level resources directory, an error is returned",
|
|
dir: "root-dir",
|
|
wantErrMsg: "directory \"resources\" does not exist",
|
|
},
|
|
{
|
|
name: "when there are no directories under the resources directory, an empty map is returned",
|
|
dir: "root-dir",
|
|
files: []string{"root-dir/resources/"},
|
|
want: map[string]*ResourceItems{},
|
|
},
|
|
{
|
|
name: "a mix of cluster-scoped and namespaced items across multiple resources are correctly returned",
|
|
dir: "root-dir",
|
|
files: []string{
|
|
"root-dir/resources/widgets.foo/cluster/item-1.json",
|
|
"root-dir/resources/widgets.foo/cluster/item-2.json",
|
|
"root-dir/resources/widgets.foo/namespaces/ns-1/item-1.json",
|
|
"root-dir/resources/widgets.foo/namespaces/ns-1/item-2.json",
|
|
"root-dir/resources/widgets.foo/namespaces/ns-2/item-1.json",
|
|
"root-dir/resources/widgets.foo/namespaces/ns-2/item-2.json",
|
|
|
|
"root-dir/resources/dongles.foo/cluster/item-3.json",
|
|
"root-dir/resources/dongles.foo/cluster/item-4.json",
|
|
|
|
"root-dir/resources/dongles.bar/namespaces/ns-3/item-3.json",
|
|
"root-dir/resources/dongles.bar/namespaces/ns-3/item-4.json",
|
|
"root-dir/resources/dongles.bar/namespaces/ns-4/item-5.json",
|
|
"root-dir/resources/dongles.bar/namespaces/ns-4/item-6.json",
|
|
},
|
|
want: map[string]*ResourceItems{
|
|
"widgets.foo": {
|
|
GroupResource: "widgets.foo",
|
|
ItemsByNamespace: map[string][]string{
|
|
"": {"item-1", "item-2"},
|
|
"ns-1": {"item-1", "item-2"},
|
|
"ns-2": {"item-1", "item-2"},
|
|
},
|
|
},
|
|
"dongles.foo": {
|
|
GroupResource: "dongles.foo",
|
|
ItemsByNamespace: map[string][]string{
|
|
"": {"item-3", "item-4"},
|
|
},
|
|
},
|
|
"dongles.bar": {
|
|
GroupResource: "dongles.bar",
|
|
ItemsByNamespace: map[string][]string{
|
|
"ns-3": {"item-3", "item-4"},
|
|
"ns-4": {"item-5", "item-6"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
p := &Parser{
|
|
log: test.NewLogger(),
|
|
fs: test.NewFakeFileSystem(),
|
|
}
|
|
|
|
for _, file := range tc.files {
|
|
require.NoError(t, p.fs.MkdirAll(file, 0755))
|
|
|
|
if !strings.HasSuffix(file, "/") {
|
|
res, err := p.fs.Create(file)
|
|
require.NoError(t, err)
|
|
require.NoError(t, res.Close())
|
|
}
|
|
}
|
|
|
|
res, err := p.Parse(tc.dir)
|
|
if tc.wantErrMsg != "" {
|
|
assert.EqualError(t, err, tc.wantErrMsg)
|
|
} else {
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, tc.want, res)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseGroupVersions(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
files []string
|
|
backupDir string
|
|
wantErrMsg string
|
|
want map[string]metav1.APIGroup
|
|
}{
|
|
{
|
|
name: "when there is no top-level resources directory, an error is returned",
|
|
backupDir: "/var/folders",
|
|
wantErrMsg: "\"/var/folders/resources\" not found",
|
|
},
|
|
{
|
|
name: "when there are no directories under the resources directory, an empty map is returned",
|
|
backupDir: "/var/folders",
|
|
files: []string{"/var/folders/resources/"},
|
|
want: map[string]metav1.APIGroup{},
|
|
},
|
|
{
|
|
name: "when there is a mix of cluster-scoped and namespaced items for resources with preferred or multiple API groups, all group versions are correctly returned",
|
|
backupDir: "/var/folders",
|
|
files: []string{
|
|
"/var/folders/resources/clusterroles.rbac.authorization.k8s.io/v1-preferredversion/cluster/system/controller/attachdetach-controller.json",
|
|
"/var/folders/resources/clusterroles.rbac.authorization.k8s.io/cluster/system/controller/attachdetach-controller.json",
|
|
|
|
"/var/folders/resources/horizontalpodautoscalers.autoscaling/namespaces/myexample/php-apache-autoscaler.json",
|
|
"/var/folders/resources/horizontalpodautoscalers.autoscaling/v1-preferredversion/namespaces/myexample/php-apache-autoscaler.json",
|
|
"/var/folders/resources/horizontalpodautoscalers.autoscaling/v2beta1/namespaces/myexample/php-apache-autoscaler.json",
|
|
"/var/folders/resources/horizontalpodautoscalers.autoscaling/v2beta2/namespaces/myexample/php-apache-autoscaler.json",
|
|
|
|
"/var/folders/resources/pods/namespaces/nginx-example/nginx-deployment-57d5dcb68-wrqsc.json",
|
|
"/var/folders/resources/pods/v1-preferredversion/namespaces/nginx-example/nginx-deployment-57d5dcb68-wrqsc.json",
|
|
},
|
|
want: map[string]metav1.APIGroup{
|
|
"clusterroles.rbac.authorization.k8s.io": {
|
|
Name: "rbac.authorization.k8s.io",
|
|
Versions: []metav1.GroupVersionForDiscovery{
|
|
{
|
|
GroupVersion: "rbac.authorization.k8s.io/v1",
|
|
Version: "v1",
|
|
},
|
|
},
|
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
|
GroupVersion: "rbac.authorization.k8s.io/v1",
|
|
Version: "v1",
|
|
},
|
|
},
|
|
"horizontalpodautoscalers.autoscaling": {
|
|
Name: "autoscaling",
|
|
Versions: []metav1.GroupVersionForDiscovery{
|
|
{
|
|
GroupVersion: "autoscaling/v1",
|
|
Version: "v1",
|
|
},
|
|
{
|
|
GroupVersion: "autoscaling/v2beta1",
|
|
Version: "v2beta1",
|
|
},
|
|
{
|
|
GroupVersion: "autoscaling/v2beta2",
|
|
Version: "v2beta2",
|
|
},
|
|
},
|
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
|
GroupVersion: "autoscaling/v1",
|
|
Version: "v1",
|
|
},
|
|
},
|
|
"pods": {
|
|
Name: "",
|
|
Versions: []metav1.GroupVersionForDiscovery{
|
|
{
|
|
GroupVersion: "v1",
|
|
Version: "v1",
|
|
},
|
|
},
|
|
PreferredVersion: metav1.GroupVersionForDiscovery{
|
|
GroupVersion: "v1",
|
|
Version: "v1",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
p := &Parser{
|
|
log: test.NewLogger(),
|
|
fs: test.NewFakeFileSystem(),
|
|
}
|
|
|
|
for _, file := range tc.files {
|
|
require.NoError(t, p.fs.MkdirAll(file, 0755))
|
|
|
|
if !strings.HasSuffix(file, "/") {
|
|
res, err := p.fs.Create(file)
|
|
require.NoError(t, err)
|
|
require.NoError(t, res.Close())
|
|
}
|
|
}
|
|
|
|
res, err := p.ParseGroupVersions(tc.backupDir)
|
|
if tc.wantErrMsg != "" {
|
|
assert.EqualError(t, err, tc.wantErrMsg)
|
|
} else {
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, tc.want, res)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExtractGroupName(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
rgDir string
|
|
want string
|
|
}{
|
|
{
|
|
name: "Directory has no dots (only a group name)",
|
|
rgDir: "pods",
|
|
want: "",
|
|
},
|
|
{
|
|
name: "Directory has one concatenation dot (has both resource and group name which have 0 dots",
|
|
rgDir: "cronjobs.batch",
|
|
want: "batch",
|
|
},
|
|
{
|
|
name: "Directory has 3 dots in name (group has 2 dot)",
|
|
rgDir: "leases.coordination.k8s.io",
|
|
want: "coordination.k8s.io",
|
|
},
|
|
{
|
|
name: "Directory has 4 dots in name (group has 3 dots)",
|
|
rgDir: "roles.rbac.authorization.k8s.io",
|
|
want: "rbac.authorization.k8s.io",
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
grp := extractGroupName(tc.rgDir)
|
|
|
|
assert.Equal(t, tc.want, grp)
|
|
})
|
|
}
|
|
}
|