Allow feature flags to be passed from install CLI (#2503)
* allow feature flags to be passed from install CLI Signed-off-by: Ashish Amarnath <ashisham@vmware.com>pull/2512/head
parent
577e87d1b8
commit
911a607cf8
|
@ -0,0 +1 @@
|
||||||
|
allow feature flags to be passed from install CLI
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 the Velero contributors.
|
Copyright 2019,2020 the Velero contributors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -69,6 +69,7 @@ type InstallOptions struct {
|
||||||
NoDefaultBackupLocation bool
|
NoDefaultBackupLocation bool
|
||||||
CRDsOnly bool
|
CRDsOnly bool
|
||||||
CACertFile string
|
CACertFile string
|
||||||
|
Features string
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindFlags adds command line values to the options struct.
|
// BindFlags adds command line values to the options struct.
|
||||||
|
@ -95,12 +96,13 @@ func (o *InstallOptions) BindFlags(flags *pflag.FlagSet) {
|
||||||
flags.BoolVar(&o.UseVolumeSnapshots, "use-volume-snapshots", o.UseVolumeSnapshots, "whether or not to create snapshot location automatically. Set to false if you do not plan to create volume snapshots via a storage provider.")
|
flags.BoolVar(&o.UseVolumeSnapshots, "use-volume-snapshots", o.UseVolumeSnapshots, "whether or not to create snapshot location automatically. Set to false if you do not plan to create volume snapshots via a storage provider.")
|
||||||
flags.BoolVar(&o.RestoreOnly, "restore-only", o.RestoreOnly, "run the server in restore-only mode. Optional.")
|
flags.BoolVar(&o.RestoreOnly, "restore-only", o.RestoreOnly, "run the server in restore-only mode. Optional.")
|
||||||
flags.BoolVar(&o.DryRun, "dry-run", o.DryRun, "generate resources, but don't send them to the cluster. Use with -o. Optional.")
|
flags.BoolVar(&o.DryRun, "dry-run", o.DryRun, "generate resources, but don't send them to the cluster. Use with -o. Optional.")
|
||||||
flags.BoolVar(&o.UseRestic, "use-restic", o.UseRestic, "create restic deployment. Optional.")
|
flags.BoolVar(&o.UseRestic, "use-restic", o.UseRestic, "create restic daemonset. Optional.")
|
||||||
flags.BoolVar(&o.Wait, "wait", o.Wait, "wait for Velero deployment to be ready. Optional.")
|
flags.BoolVar(&o.Wait, "wait", o.Wait, "wait for Velero deployment to be ready. Optional.")
|
||||||
flags.DurationVar(&o.DefaultResticMaintenanceFrequency, "default-restic-prune-frequency", o.DefaultResticMaintenanceFrequency, "how often 'restic prune' is run for restic repositories by default. Optional.")
|
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.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.BoolVar(&o.CRDsOnly, "crds-only", o.CRDsOnly, "only generate CustomResourceDefinition resources. Useful for updating CRDs for an existing Velero install.")
|
||||||
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.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")
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInstallOptions instantiates a new, default InstallOptions struct.
|
// NewInstallOptions instantiates a new, default InstallOptions struct.
|
||||||
|
@ -180,6 +182,7 @@ func (o *InstallOptions) AsVeleroOptions() (*install.VeleroOptions, error) {
|
||||||
Plugins: o.Plugins,
|
Plugins: o.Plugins,
|
||||||
NoDefaultBackupLocation: o.NoDefaultBackupLocation,
|
NoDefaultBackupLocation: o.NoDefaultBackupLocation,
|
||||||
CACertData: caCertData,
|
CACertData: caCertData,
|
||||||
|
Features: strings.Split(o.Features, ","),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2018, 2019 the Velero contributors.
|
Copyright 2018, 2019, 2020 the Velero contributors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||||
package install
|
package install
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
@ -40,6 +41,14 @@ func DaemonSet(namespace string, opts ...podTemplateOption) *appsv1.DaemonSet {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resticArgs := []string{
|
||||||
|
"restic",
|
||||||
|
"server",
|
||||||
|
}
|
||||||
|
if len(c.features) > 0 {
|
||||||
|
resticArgs = append(resticArgs, fmt.Sprintf("--features=%s", strings.Join(c.features, ",")))
|
||||||
|
}
|
||||||
|
|
||||||
userID := int64(0)
|
userID := int64(0)
|
||||||
mountPropagationMode := corev1.MountPropagationHostToContainer
|
mountPropagationMode := corev1.MountPropagationHostToContainer
|
||||||
|
|
||||||
|
@ -92,10 +101,7 @@ func DaemonSet(namespace string, opts ...podTemplateOption) *appsv1.DaemonSet {
|
||||||
Command: []string{
|
Command: []string{
|
||||||
"/velero",
|
"/velero",
|
||||||
},
|
},
|
||||||
Args: []string{
|
Args: resticArgs,
|
||||||
"restic",
|
|
||||||
"server",
|
|
||||||
},
|
|
||||||
|
|
||||||
VolumeMounts: []corev1.VolumeMount{
|
VolumeMounts: []corev1.VolumeMount{
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 the Velero contributors.
|
Copyright 2019, 2020 the Velero contributors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -36,4 +36,8 @@ func TestDaemonSet(t *testing.T) {
|
||||||
ds = DaemonSet("velero", WithSecret(true))
|
ds = DaemonSet("velero", WithSecret(true))
|
||||||
assert.Equal(t, 7, len(ds.Spec.Template.Spec.Containers[0].Env))
|
assert.Equal(t, 7, len(ds.Spec.Template.Spec.Containers[0].Env))
|
||||||
assert.Equal(t, 3, len(ds.Spec.Template.Spec.Volumes))
|
assert.Equal(t, 3, len(ds.Spec.Template.Spec.Volumes))
|
||||||
|
|
||||||
|
ds = DaemonSet("velero", WithFeatures([]string{"foo,bar,baz"}))
|
||||||
|
assert.Len(t, ds.Spec.Template.Spec.Containers[0].Args, 3)
|
||||||
|
assert.Equal(t, "--features=foo,bar,baz", ds.Spec.Template.Spec.Containers[0].Args[2])
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2018, 2019 the Velero contributors.
|
Copyright 2018, 2019, 2020 the Velero contributors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -39,6 +39,7 @@ type podTemplateConfig struct {
|
||||||
withSecret bool
|
withSecret bool
|
||||||
defaultResticMaintenanceFrequency time.Duration
|
defaultResticMaintenanceFrequency time.Duration
|
||||||
plugins []string
|
plugins []string
|
||||||
|
features []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithImage(image string) podTemplateOption {
|
func WithImage(image string) podTemplateOption {
|
||||||
|
@ -100,6 +101,12 @@ func WithPlugins(plugins []string) podTemplateOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithFeatures(features []string) podTemplateOption {
|
||||||
|
return func(c *podTemplateConfig) {
|
||||||
|
c.features = features
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Deployment(namespace string, opts ...podTemplateOption) *appsv1.Deployment {
|
func Deployment(namespace string, opts ...podTemplateOption) *appsv1.Deployment {
|
||||||
// TODO: Add support for server args
|
// TODO: Add support for server args
|
||||||
c := &podTemplateConfig{
|
c := &podTemplateConfig{
|
||||||
|
@ -117,6 +124,11 @@ func Deployment(namespace string, opts ...podTemplateOption) *appsv1.Deployment
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
args := []string{"server"}
|
||||||
|
if len(c.features) > 0 {
|
||||||
|
args = append(args, fmt.Sprintf("--features=%s", strings.Join(c.features, ",")))
|
||||||
|
}
|
||||||
|
|
||||||
containerLabels := labels()
|
containerLabels := labels()
|
||||||
containerLabels["deploy"] = "velero"
|
containerLabels["deploy"] = "velero"
|
||||||
|
|
||||||
|
@ -145,9 +157,7 @@ func Deployment(namespace string, opts ...podTemplateOption) *appsv1.Deployment
|
||||||
Command: []string{
|
Command: []string{
|
||||||
"/velero",
|
"/velero",
|
||||||
},
|
},
|
||||||
Args: []string{
|
Args: args,
|
||||||
"server",
|
|
||||||
},
|
|
||||||
VolumeMounts: []corev1.VolumeMount{
|
VolumeMounts: []corev1.VolumeMount{
|
||||||
{
|
{
|
||||||
Name: "plugins",
|
Name: "plugins",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 the Velero contributors.
|
Copyright 2019, 2020 the Velero contributors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -49,4 +49,8 @@ func TestDeployment(t *testing.T) {
|
||||||
deploy = Deployment("velero", WithDefaultResticMaintenanceFrequency(24*time.Hour))
|
deploy = Deployment("velero", WithDefaultResticMaintenanceFrequency(24*time.Hour))
|
||||||
assert.Len(t, deploy.Spec.Template.Spec.Containers[0].Args, 2)
|
assert.Len(t, deploy.Spec.Template.Spec.Containers[0].Args, 2)
|
||||||
assert.Equal(t, "--default-restic-prune-frequency=24h0m0s", deploy.Spec.Template.Spec.Containers[0].Args[1])
|
assert.Equal(t, "--default-restic-prune-frequency=24h0m0s", deploy.Spec.Template.Spec.Containers[0].Args[1])
|
||||||
|
|
||||||
|
deploy = Deployment("velero", WithFeatures([]string{"EnableCSI", "foo", "bar", "baz"}))
|
||||||
|
assert.Len(t, deploy.Spec.Template.Spec.Containers[0].Args, 2)
|
||||||
|
assert.Equal(t, "--features=EnableCSI,foo,bar,baz", deploy.Spec.Template.Spec.Containers[0].Args[1])
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2018, 2019 the Velero contributors.
|
Copyright 2018, 2019, 2020 the Velero contributors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -219,6 +219,7 @@ type VeleroOptions struct {
|
||||||
Plugins []string
|
Plugins []string
|
||||||
NoDefaultBackupLocation bool
|
NoDefaultBackupLocation bool
|
||||||
CACertData []byte
|
CACertData []byte
|
||||||
|
Features []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func AllCRDs() *unstructured.UnstructuredList {
|
func AllCRDs() *unstructured.UnstructuredList {
|
||||||
|
@ -274,6 +275,10 @@ func AllResources(o *VeleroOptions) (*unstructured.UnstructuredList, error) {
|
||||||
WithDefaultResticMaintenanceFrequency(o.DefaultResticMaintenanceFrequency),
|
WithDefaultResticMaintenanceFrequency(o.DefaultResticMaintenanceFrequency),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(o.Features) > 0 {
|
||||||
|
deployOpts = append(deployOpts, WithFeatures(o.Features))
|
||||||
|
}
|
||||||
|
|
||||||
if o.RestoreOnly {
|
if o.RestoreOnly {
|
||||||
deployOpts = append(deployOpts, WithRestoreOnly())
|
deployOpts = append(deployOpts, WithRestoreOnly())
|
||||||
}
|
}
|
||||||
|
@ -287,12 +292,16 @@ func AllResources(o *VeleroOptions) (*unstructured.UnstructuredList, error) {
|
||||||
appendUnstructured(resources, deploy)
|
appendUnstructured(resources, deploy)
|
||||||
|
|
||||||
if o.UseRestic {
|
if o.UseRestic {
|
||||||
ds := DaemonSet(o.Namespace,
|
dsOpts := []podTemplateOption{
|
||||||
WithAnnotations(o.PodAnnotations),
|
WithAnnotations(o.PodAnnotations),
|
||||||
WithImage(o.Image),
|
WithImage(o.Image),
|
||||||
WithResources(o.ResticPodResources),
|
WithResources(o.ResticPodResources),
|
||||||
WithSecret(secretPresent),
|
WithSecret(secretPresent),
|
||||||
)
|
}
|
||||||
|
if len(o.Features) > 0 {
|
||||||
|
dsOpts = append(dsOpts, WithFeatures(o.Features))
|
||||||
|
}
|
||||||
|
ds := DaemonSet(o.Namespace, dsOpts...)
|
||||||
appendUnstructured(resources, ds)
|
appendUnstructured(resources, ds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue