From fca2b5c417ed87facb08038273d6af5ccd46b524 Mon Sep 17 00:00:00 2001 From: JenTing Hsiao Date: Fri, 9 Jul 2021 13:26:57 +0800 Subject: [PATCH] Add new flag --crds-version of default CRD version to generated If the Velero CLI can't discover the Kubernetes preferred CRD API version, use the flag --crds-version to determine the CRDs version. Signed-off-by: JenTing Hsiao --- pkg/cmd/cli/install/install.go | 35 +++++++++++++++++++++++++++++++++- pkg/install/resources.go | 25 ++++++++++++++++-------- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/pkg/cmd/cli/install/install.go b/pkg/cmd/cli/install/install.go index 037fca2f7c..0e1af55441 100644 --- a/pkg/cmd/cli/install/install.go +++ b/pkg/cmd/cli/install/install.go @@ -25,9 +25,11 @@ import ( "time" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/spf13/pflag" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" "github.com/vmware-tanzu/velero/internal/velero" velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" @@ -35,6 +37,7 @@ import ( "github.com/vmware-tanzu/velero/pkg/cmd" "github.com/vmware-tanzu/velero/pkg/cmd/util/flag" "github.com/vmware-tanzu/velero/pkg/cmd/util/output" + velerodiscovery "github.com/vmware-tanzu/velero/pkg/discovery" "github.com/vmware-tanzu/velero/pkg/install" kubeutil "github.com/vmware-tanzu/velero/pkg/util/kube" ) @@ -69,6 +72,7 @@ type InstallOptions struct { Plugins flag.StringArray NoDefaultBackupLocation bool CRDsOnly bool + CRDsVersion string CACertFile string Features string DefaultVolumesToRestic bool @@ -103,6 +107,7 @@ func (o *InstallOptions) BindFlags(flags *pflag.FlagSet) { flags.DurationVar(&o.DefaultResticMaintenanceFrequency, "default-restic-prune-frequency", o.DefaultResticMaintenanceFrequency, "How often 'restic prune' is run for restic repositories by default. Optional.") flags.Var(&o.Plugins, "plugins", "Plugin container images to install into the Velero Deployment") flags.BoolVar(&o.CRDsOnly, "crds-only", o.CRDsOnly, "Only generate CustomResourceDefinition resources. Useful for updating CRDs for an existing Velero install.") + flags.StringVar(&o.CRDsVersion, "crds-version", o.CRDsVersion, "The version to generate CustomResourceDefinition resources if Velero can't discover the Kubernetes preferred CRD API version. Optional.") flags.StringVar(&o.CACertFile, "cacert", o.CACertFile, "File containing a certificate bundle to use when verifying TLS connections to the object store. Optional.") flags.StringVar(&o.Features, "features", o.Features, "Comma separated list of Velero feature flags to be set on the Velero deployment and the restic daemonset, if restic is enabled") flags.BoolVar(&o.DefaultVolumesToRestic, "default-volumes-to-restic", o.DefaultVolumesToRestic, "Bool flag to configure Velero server to use restic by default to backup all pod volumes on all backups. Optional.") @@ -129,6 +134,7 @@ func NewInstallOptions() *InstallOptions { UseVolumeSnapshots: true, NoDefaultBackupLocation: false, CRDsOnly: false, + CRDsVersion: "v1beta1", DefaultVolumesToRestic: false, } } @@ -187,6 +193,7 @@ func (o *InstallOptions) AsVeleroOptions() (*install.VeleroOptions, error) { NoDefaultBackupLocation: o.NoDefaultBackupLocation, CACertData: caCertData, Features: strings.Split(o.Features, ","), + CRDsVersion: o.CRDsVersion, DefaultVolumesToRestic: o.DefaultVolumesToRestic, }, nil } @@ -247,9 +254,30 @@ This is useful as a starting point for more customized installations. // Run executes a command in the context of the provided arguments. func (o *InstallOptions) Run(c *cobra.Command, f client.Factory) error { + // Find the kube-apiserver group apiextensions.k8s.io preferred API version + clientset, err := f.KubeClient() + if err == nil { + // kubeconfig available + discoveryHelper, err := velerodiscovery.NewHelper(clientset.Discovery(), &logrus.Logger{}) + if err == nil { + // kubernetes apiserver available + gvr, _, err := discoveryHelper.ResourceFor( + schema.GroupVersionResource{ + Group: "apiextensions.k8s.io", + Resource: "customresourcedefinitions", + }) + if err != nil { + return err + } + + // Update the group apiextensions.k8s.io preferred API version + o.CRDsVersion = gvr.Version + } + } + var resources *unstructured.UnstructuredList if o.CRDsOnly { - resources = install.AllCRDs() + resources = install.AllCRDs(o.CRDsVersion) } else { vo, err := o.AsVeleroOptions() if err != nil { @@ -316,6 +344,11 @@ func (o *InstallOptions) Validate(c *cobra.Command, args []string, f client.Fact return err } + // Check the CRD version is valid. + if o.CRDsVersion != "v1beta1" && o.CRDsVersion != "v1" { + return errors.Errorf("CRD version must be v1beta1 or v1") + } + // If we're only installing CRDs, we can skip the rest of the validation. if o.CRDsOnly { return nil diff --git a/pkg/install/resources.go b/pkg/install/resources.go index 16d89e01f8..dbe19fba90 100644 --- a/pkg/install/resources.go +++ b/pkg/install/resources.go @@ -19,8 +19,6 @@ package install import ( "time" - velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" - corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -28,7 +26,9 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "github.com/vmware-tanzu/velero/config/crd/crds" + v1crds "github.com/vmware-tanzu/velero/config/crd/v1/crds" + v1beta1crds "github.com/vmware-tanzu/velero/config/crd/v1beta1/crds" + velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" ) var ( @@ -216,17 +216,26 @@ type VeleroOptions struct { NoDefaultBackupLocation bool CACertData []byte Features []string + CRDsVersion string DefaultVolumesToRestic bool } -func AllCRDs() *unstructured.UnstructuredList { +func AllCRDs(perferredAPIVersion string) *unstructured.UnstructuredList { resources := new(unstructured.UnstructuredList) // Set the GVK so that the serialization framework outputs the list properly resources.SetGroupVersionKind(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "List"}) - for _, crd := range crds.CRDs { - crd.SetLabels(Labels()) - appendUnstructured(resources, crd) + switch perferredAPIVersion { + case "v1beta1": + for _, crd := range v1beta1crds.CRDs { + crd.SetLabels(Labels()) + appendUnstructured(resources, crd) + } + case "v1": + for _, crd := range v1crds.CRDs { + crd.SetLabels(Labels()) + appendUnstructured(resources, crd) + } } return resources @@ -235,7 +244,7 @@ func AllCRDs() *unstructured.UnstructuredList { // AllResources returns a list of all resources necessary to install Velero, in the appropriate order, into a Kubernetes cluster. // Items are unstructured, since there are different data types returned. func AllResources(o *VeleroOptions) *unstructured.UnstructuredList { - resources := AllCRDs() + resources := AllCRDs(o.CRDsVersion) ns := Namespace(o.Namespace) appendUnstructured(resources, ns)