mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-08-15 11:46:06 +00:00
Use LabelSelector in Action ResourceSelector
Instead of converting the unstructured item to check for the presence of the `kube-aggregator.kubernetes.io/automanaged` label, use this label in the `AppliesTo` to enable the restore logic to select the item. This means that any item that matches the selector will have restore skipped. Also add a new test case to the restore action test to check that label selectors are applied correctly. Signed-off-by: Bridget McErlean <bmcerlean@vmware.com>
This commit is contained in:
@@ -17,10 +17,7 @@ limitations under the License.
|
||||
package restore
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
"k8s.io/kube-aggregator/pkg/controllers/autoregister"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
@@ -41,20 +38,14 @@ func NewAPIServiceAction(logger logrus.FieldLogger) *APIServiceAction {
|
||||
func (a *APIServiceAction) AppliesTo() (velero.ResourceSelector, error) {
|
||||
return velero.ResourceSelector{
|
||||
IncludedResources: []string{"apiservices"},
|
||||
LabelSelector: autoregister.AutoRegisterManagedLabel,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *APIServiceAction) Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error) {
|
||||
apiService := new(apiregistrationv1.APIService)
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(input.Item.UnstructuredContent(), apiService); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
a.logger.Info("Executing APIServiceAction")
|
||||
defer a.logger.Info("Done executing APIServiceAction")
|
||||
|
||||
output := velero.NewRestoreItemActionExecuteOutput(input.Item)
|
||||
|
||||
if _, ok := apiService.Labels[autoregister.AutoRegisterManagedLabel]; ok {
|
||||
output = output.WithoutRestore()
|
||||
}
|
||||
|
||||
return output, nil
|
||||
a.logger.Infof("Skipping restore of APIService as it is managed by Kubernetes")
|
||||
return velero.NewRestoreItemActionExecuteOutput(input.Item).WithoutRestore(), nil
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2017 the Velero contributors.
|
||||
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.
|
||||
@@ -19,129 +19,35 @@ package restore
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||
"k8s.io/kube-aggregator/pkg/controllers/autoregister"
|
||||
|
||||
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
|
||||
velerotest "github.com/vmware-tanzu/velero/pkg/test"
|
||||
)
|
||||
|
||||
func TestAPIServiceActionExecute(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
obj apiregistrationv1.APIService
|
||||
skipRestore bool
|
||||
}{
|
||||
{
|
||||
name: "APIService with no labels should be restored without modification",
|
||||
obj: apiregistrationv1.APIService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "v1.foo.velero.io",
|
||||
},
|
||||
},
|
||||
skipRestore: false,
|
||||
},
|
||||
{
|
||||
name: "Non-Local APIService without Kubernetes managed label should be restored without modification",
|
||||
obj: apiregistrationv1.APIService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "v1.foo.velero.io",
|
||||
Labels: map[string]string{
|
||||
"component": "velero",
|
||||
},
|
||||
},
|
||||
Spec: apiregistrationv1.APIServiceSpec{
|
||||
Group: "velero.io",
|
||||
Version: "v1",
|
||||
Service: &apiregistrationv1.ServiceReference{
|
||||
Namespace: "velero",
|
||||
Name: "velero-aggregated-api-server",
|
||||
},
|
||||
},
|
||||
},
|
||||
skipRestore: false,
|
||||
},
|
||||
{
|
||||
name: "APIService with Kubernetes managed label with 'true' value should not be restored",
|
||||
obj: apiregistrationv1.APIService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "v1.foo.velero.io",
|
||||
Labels: map[string]string{
|
||||
autoregister.AutoRegisterManagedLabel: "true",
|
||||
},
|
||||
},
|
||||
},
|
||||
skipRestore: true,
|
||||
},
|
||||
{
|
||||
name: "APIService with Kubernetes managed label with 'onstart' value should not be restored",
|
||||
obj: apiregistrationv1.APIService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "v1.foo.velero.io",
|
||||
Labels: map[string]string{
|
||||
autoregister.AutoRegisterManagedLabel: "onstart",
|
||||
},
|
||||
},
|
||||
},
|
||||
skipRestore: true,
|
||||
},
|
||||
{
|
||||
name: "APIService with Kubernetes managed label with any value should not be restored",
|
||||
obj: apiregistrationv1.APIService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "v1.foo.velero.io",
|
||||
Labels: map[string]string{
|
||||
autoregister.AutoRegisterManagedLabel: "randomvalue",
|
||||
},
|
||||
},
|
||||
},
|
||||
skipRestore: true,
|
||||
},
|
||||
{
|
||||
name: "Non-Local APIService with Kubernetes managed label should not be restored",
|
||||
obj: apiregistrationv1.APIService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "v1.foo.velero.io",
|
||||
Labels: map[string]string{
|
||||
autoregister.AutoRegisterManagedLabel: "onstart",
|
||||
},
|
||||
},
|
||||
Spec: apiregistrationv1.APIServiceSpec{
|
||||
Group: "velero.io",
|
||||
Version: "v1",
|
||||
Service: &apiregistrationv1.ServiceReference{
|
||||
Namespace: "velero",
|
||||
Name: "velero-aggregated-api-server",
|
||||
},
|
||||
},
|
||||
},
|
||||
skipRestore: true,
|
||||
func TestAPIServiceActionExecuteSkipsRestore(t *testing.T) {
|
||||
obj := apiregistrationv1.APIService{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "v1.test.velero.io",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
action := NewAPIServiceAction(velerotest.NewLogger())
|
||||
unstructuredAPIService, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&obj)
|
||||
require.NoError(t, err)
|
||||
|
||||
unstructuredAPIService, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&test.obj)
|
||||
require.NoError(t, err)
|
||||
action := NewAPIServiceAction(velerotest.NewLogger())
|
||||
res, err := action.Execute(&velero.RestoreItemActionExecuteInput{
|
||||
Item: &unstructured.Unstructured{Object: unstructuredAPIService},
|
||||
ItemFromBackup: &unstructured.Unstructured{Object: unstructuredAPIService},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
res, err := action.Execute(&velero.RestoreItemActionExecuteInput{
|
||||
Item: &unstructured.Unstructured{Object: unstructuredAPIService},
|
||||
ItemFromBackup: &unstructured.Unstructured{Object: unstructuredAPIService},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
var apiService apiregistrationv1.APIService
|
||||
require.NoError(t, runtime.DefaultUnstructuredConverter.FromUnstructured(res.UpdatedItem.UnstructuredContent(), &apiService))
|
||||
assert.Equal(t, test.obj, apiService)
|
||||
assert.Equal(t, test.skipRestore, res.SkipRestore)
|
||||
})
|
||||
}
|
||||
var apiService apiregistrationv1.APIService
|
||||
require.NoError(t, runtime.DefaultUnstructuredConverter.FromUnstructured(res.UpdatedItem.UnstructuredContent(), &apiService))
|
||||
require.Equal(t, obj, apiService)
|
||||
require.Equal(t, true, res.SkipRestore)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 the Velero contributors.
|
||||
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.
|
||||
@@ -1139,6 +1139,22 @@ func TestRestoreActionsRunForCorrectItems(t *testing.T) {
|
||||
new(recordResourcesAction).ForNamespace("ns-1").ForResource("pods"): {"ns-1/pod-1"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "single action with a resource and label selector runs only for resources matching that label",
|
||||
restore: defaultRestore().Result(),
|
||||
backup: defaultBackup().Result(),
|
||||
tarball: test.NewTarWriter(t).
|
||||
AddItems("pods",
|
||||
builder.ForPod("ns-1", "pod-1").ObjectMeta(builder.WithLabels("restore-resource", "true")).Result(),
|
||||
builder.ForPod("ns-1", "pod-2").ObjectMeta(builder.WithLabels("do-not-restore-resource", "true")).Result(),
|
||||
builder.ForPod("ns-2", "pod-1").Result(),
|
||||
builder.ForPod("ns-2", "pod-2").ObjectMeta(builder.WithLabels("restore-resource")).Result(),
|
||||
).Done(),
|
||||
apiResources: []*test.APIResource{test.Pods()},
|
||||
actions: map[*recordResourcesAction][]string{
|
||||
new(recordResourcesAction).ForResource("pods").ForLabelSelector("restore-resource"): {"ns-1/pod-1", "ns-2/pod-2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple actions, each with a different resource selector using short name, run for matching resources",
|
||||
restore: defaultRestore().Result(),
|
||||
|
||||
Reference in New Issue
Block a user