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
Ashish Amarnath 2020-05-06 10:52:44 -07:00 committed by GitHub
parent 577e87d1b8
commit 911a607cf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 53 additions and 16 deletions

View File

@ -0,0 +1 @@
allow feature flags to be passed from install CLI

View File

@ -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");
you may not use this file except in compliance with the License.
@ -69,6 +69,7 @@ type InstallOptions struct {
NoDefaultBackupLocation bool
CRDsOnly bool
CACertFile string
Features string
}
// 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.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.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.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.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.
@ -180,6 +182,7 @@ func (o *InstallOptions) AsVeleroOptions() (*install.VeleroOptions, error) {
Plugins: o.Plugins,
NoDefaultBackupLocation: o.NoDefaultBackupLocation,
CACertData: caCertData,
Features: strings.Split(o.Features, ","),
}, nil
}

View File

@ -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");
you may not use this file except in compliance with the License.
@ -17,6 +17,7 @@ limitations under the License.
package install
import (
"fmt"
"strings"
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)
mountPropagationMode := corev1.MountPropagationHostToContainer
@ -92,10 +101,7 @@ func DaemonSet(namespace string, opts ...podTemplateOption) *appsv1.DaemonSet {
Command: []string{
"/velero",
},
Args: []string{
"restic",
"server",
},
Args: resticArgs,
VolumeMounts: []corev1.VolumeMount{
{

View File

@ -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");
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))
assert.Equal(t, 7, len(ds.Spec.Template.Spec.Containers[0].Env))
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])
}

View File

@ -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");
you may not use this file except in compliance with the License.
@ -39,6 +39,7 @@ type podTemplateConfig struct {
withSecret bool
defaultResticMaintenanceFrequency time.Duration
plugins []string
features []string
}
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 {
// TODO: Add support for server args
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["deploy"] = "velero"
@ -145,9 +157,7 @@ func Deployment(namespace string, opts ...podTemplateOption) *appsv1.Deployment
Command: []string{
"/velero",
},
Args: []string{
"server",
},
Args: args,
VolumeMounts: []corev1.VolumeMount{
{
Name: "plugins",

View File

@ -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");
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))
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])
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])
}

View File

@ -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");
you may not use this file except in compliance with the License.
@ -219,6 +219,7 @@ type VeleroOptions struct {
Plugins []string
NoDefaultBackupLocation bool
CACertData []byte
Features []string
}
func AllCRDs() *unstructured.UnstructuredList {
@ -274,6 +275,10 @@ func AllResources(o *VeleroOptions) (*unstructured.UnstructuredList, error) {
WithDefaultResticMaintenanceFrequency(o.DefaultResticMaintenanceFrequency),
}
if len(o.Features) > 0 {
deployOpts = append(deployOpts, WithFeatures(o.Features))
}
if o.RestoreOnly {
deployOpts = append(deployOpts, WithRestoreOnly())
}
@ -287,12 +292,16 @@ func AllResources(o *VeleroOptions) (*unstructured.UnstructuredList, error) {
appendUnstructured(resources, deploy)
if o.UseRestic {
ds := DaemonSet(o.Namespace,
dsOpts := []podTemplateOption{
WithAnnotations(o.PodAnnotations),
WithImage(o.Image),
WithResources(o.ResticPodResources),
WithSecret(secretPresent),
)
}
if len(o.Features) > 0 {
dsOpts = append(dsOpts, WithFeatures(o.Features))
}
ds := DaemonSet(o.Namespace, dsOpts...)
appendUnstructured(resources, ds)
}