diff --git a/changelogs/unreleased/4686-reasonerjt b/changelogs/unreleased/4686-reasonerjt new file mode 100644 index 000000000..ed64de8f6 --- /dev/null +++ b/changelogs/unreleased/4686-reasonerjt @@ -0,0 +1 @@ +Bypass the remap CRD version plugin when v1beta1 CRD is not supported diff --git a/pkg/backup/remap_crd_version_action.go b/pkg/backup/remap_crd_version_action.go index b282e876e..d54f018ca 100644 --- a/pkg/backup/remap_crd_version_action.go +++ b/pkg/backup/remap_crd_version_action.go @@ -30,6 +30,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + velerodiscovery "github.com/vmware-tanzu/velero/pkg/discovery" + v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "github.com/vmware-tanzu/velero/pkg/plugin/velero" ) @@ -37,13 +39,14 @@ import ( // RemapCRDVersionAction inspects CustomResourceDefinition and decides if it is a v1 // CRD that needs to be backed up as v1beta1. type RemapCRDVersionAction struct { - logger logrus.FieldLogger - betaCRDClient apiextv1beta1client.CustomResourceDefinitionInterface + logger logrus.FieldLogger + betaCRDClient apiextv1beta1client.CustomResourceDefinitionInterface + discoveryHelper velerodiscovery.Helper } // NewRemapCRDVersionAction instantiates a new RemapCRDVersionAction plugin. -func NewRemapCRDVersionAction(logger logrus.FieldLogger, betaCRDClient apiextv1beta1client.CustomResourceDefinitionInterface) *RemapCRDVersionAction { - return &RemapCRDVersionAction{logger: logger, betaCRDClient: betaCRDClient} +func NewRemapCRDVersionAction(logger logrus.FieldLogger, betaCRDClient apiextv1beta1client.CustomResourceDefinitionInterface, discoveryHelper velerodiscovery.Helper) *RemapCRDVersionAction { + return &RemapCRDVersionAction{logger: logger, betaCRDClient: betaCRDClient, discoveryHelper: discoveryHelper} } // AppliesTo selects the resources the plugin should run against. In this case, CustomResourceDefinitions. @@ -68,7 +71,26 @@ func (a *RemapCRDVersionAction) Execute(item runtime.Unstructured, backup *v1.Ba return item, nil, nil } - // We've got a v1 CRD, so proceed. + // This plugin will exit if the CRD was installed via v1beta1 but the cluster does not support v1beta1 CRD + supportv1b1 := false +CheckVersion: + for _, g := range a.discoveryHelper.APIGroups() { + if g.Name == apiextv1.GroupName { + for _, v := range g.Versions { + if v.Version == apiextv1beta1.SchemeGroupVersion.Version { + supportv1b1 = true + break CheckVersion + } + } + + } + } + if !supportv1b1 { + a.logger.Info("Exiting RemapCRDVersionAction, the cluster does not support v1beta1 CRD") + return item, nil, nil + } + + // We've got a v1 CRD and the cluster supports v1beta1 CRD, so proceed. var crd apiextv1.CustomResourceDefinition // Do not use runtime.DefaultUnstructuredConverter.FromUnstructured here because it has a bug when converting integers/whole diff --git a/pkg/backup/remap_crd_version_action_test.go b/pkg/backup/remap_crd_version_action_test.go index 9308ea049..ea679ef0e 100644 --- a/pkg/backup/remap_crd_version_action_test.go +++ b/pkg/backup/remap_crd_version_action_test.go @@ -32,6 +32,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + velerodiscovery "github.com/vmware-tanzu/velero/pkg/discovery" + v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" "github.com/vmware-tanzu/velero/pkg/builder" velerotest "github.com/vmware-tanzu/velero/pkg/test" @@ -48,8 +50,7 @@ func TestRemapCRDVersionAction(t *testing.T) { c := b.Result() _, err := betaClient.Create(context.TODO(), c, metav1.CreateOptions{}) require.NoError(t, err) - - a := NewRemapCRDVersionAction(velerotest.NewLogger(), betaClient) + a := NewRemapCRDVersionAction(velerotest.NewLogger(), betaClient, fakeDiscoveryHelper()) t.Run("Test a v1 CRD without any Schema information", func(t *testing.T) { b := builder.ForV1CustomResourceDefinition("test.velero.io") @@ -109,6 +110,33 @@ func TestRemapCRDVersionAction(t *testing.T) { require.NoError(t, err) assert.Equal(t, "apiextensions.k8s.io/v1beta1", item.UnstructuredContent()["apiVersion"]) }) + + t.Run("When the cluster only supports v1 CRD, v1 CRD will be returned even the input has Spec.PreserveUnknownFields set to true (issue 4080)", func(t *testing.T) { + a.discoveryHelper = &velerotest.FakeDiscoveryHelper{ + APIGroupsList: []metav1.APIGroup{ + { + Name: apiextv1.GroupName, + Versions: []metav1.GroupVersionForDiscovery{ + { + Version: apiextv1.SchemeGroupVersion.Version, + }, + }, + }, + }, + } + b := builder.ForV1CustomResourceDefinition("test.velero.io") + b.PreserveUnknownFields(true) + c := b.Result() + obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&c) + require.NoError(t, err) + + item, _, err := a.Execute(&unstructured.Unstructured{Object: obj}, backup) + require.NoError(t, err) + assert.Equal(t, "apiextensions.k8s.io/v1", item.UnstructuredContent()["apiVersion"]) + // set it back to the default one + a.discoveryHelper = fakeDiscoveryHelper() + }) + } // TestRemapCRDVersionActionData tests the RemapCRDVersionAction plugin against actual CRD to confirm that the v1beta1 version is returned when the v1 version is passed in to the plugin. @@ -116,8 +144,7 @@ func TestRemapCRDVersionActionData(t *testing.T) { backup := &v1.Backup{} clientset := apiextfakes.NewSimpleClientset() betaClient := clientset.ApiextensionsV1beta1().CustomResourceDefinitions() - - a := NewRemapCRDVersionAction(velerotest.NewLogger(), betaClient) + a := NewRemapCRDVersionAction(velerotest.NewLogger(), betaClient, fakeDiscoveryHelper()) tests := []struct { crd string @@ -192,3 +219,21 @@ func TestRemapCRDVersionActionData(t *testing.T) { } } + +func fakeDiscoveryHelper() velerodiscovery.Helper { + return &velerotest.FakeDiscoveryHelper{ + APIGroupsList: []metav1.APIGroup{ + { + Name: apiextv1.GroupName, + Versions: []metav1.GroupVersionForDiscovery{ + { + Version: apiextv1beta1.SchemeGroupVersion.Version, + }, + { + Version: apiextv1.SchemeGroupVersion.Version, + }, + }, + }, + }, + } +} diff --git a/pkg/cmd/server/plugin/plugin.go b/pkg/cmd/server/plugin/plugin.go index 507200266..5c833d76a 100644 --- a/pkg/cmd/server/plugin/plugin.go +++ b/pkg/cmd/server/plugin/plugin.go @@ -110,7 +110,16 @@ func newRemapCRDVersionAction(f client.Factory) veleroplugin.HandlerInitializer return nil, err } - return backup.NewRemapCRDVersionAction(logger, client.ApiextensionsV1beta1().CustomResourceDefinitions()), nil + clientset, err := f.KubeClient() + if err != nil { + return nil, err + } + discoveryHelper, err := velerodiscovery.NewHelper(clientset.Discovery(), logger) + if err != nil { + return nil, err + } + + return backup.NewRemapCRDVersionAction(logger, client.ApiextensionsV1beta1().CustomResourceDefinitions(), discoveryHelper), nil } }