Skip to content

Commit

Permalink
Add parameter "uploader-type" to velero server (vmware-tanzu#5212)
Browse files Browse the repository at this point in the history
This commit adds the parameter "uploader-type" to velero server, add exposes the
setting via "velero install" in CLI.

fixes vmware-tanzu#5062

Signed-off-by: Daniel Jiang <[email protected]>

Signed-off-by: Daniel Jiang <[email protected]>
  • Loading branch information
reasonerjt authored and danfengliu committed Sep 13, 2022
1 parent 03d9a19 commit 8fa1cfb
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 4 deletions.
1 change: 1 addition & 0 deletions changelogs/unreleased/5212-reasonerjt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add parameter "uploader-type" to velero server
10 changes: 10 additions & 0 deletions pkg/cmd/cli/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (
"strings"
"time"

"github.com/vmware-tanzu/velero/pkg/uploader"

"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -74,6 +76,7 @@ type InstallOptions struct {
CACertFile string
Features string
DefaultVolumesToRestic bool
UploaderType string
}

// BindFlags adds command line values to the options struct.
Expand Down Expand Up @@ -110,6 +113,7 @@ func (o *InstallOptions) BindFlags(flags *pflag.FlagSet) {
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.")
flags.StringVar(&o.UploaderType, "uploader-type", o.UploaderType, fmt.Sprintf("The type of uploader to transfer the data of pod volumes, the supported values are '%s', '%s'", uploader.ResticType, uploader.KopiaType))
}

// NewInstallOptions instantiates a new, default InstallOptions struct.
Expand All @@ -135,6 +139,7 @@ func NewInstallOptions() *InstallOptions {
NoDefaultBackupLocation: false,
CRDsOnly: false,
DefaultVolumesToRestic: false,
UploaderType: uploader.ResticType,
}
}

Expand Down Expand Up @@ -195,6 +200,7 @@ func (o *InstallOptions) AsVeleroOptions() (*install.VeleroOptions, error) {
CACertData: caCertData,
Features: strings.Split(o.Features, ","),
DefaultVolumesToRestic: o.DefaultVolumesToRestic,
UploaderType: o.UploaderType,
}, nil
}

Expand Down Expand Up @@ -327,6 +333,10 @@ func (o *InstallOptions) Validate(c *cobra.Command, args []string, f client.Fact
return err
}

if err := uploader.ValidateUploaderType(o.UploaderType); err != nil {
return err
}

// If we're only installing CRDs, we can skip the rest of the validation.
if o.CRDsOnly {
return nil
Expand Down
9 changes: 9 additions & 0 deletions pkg/cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
"strings"
"time"

"github.com/vmware-tanzu/velero/pkg/uploader"

"github.com/bombsimon/logrusr"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus/promhttp"
Expand Down Expand Up @@ -127,6 +129,7 @@ type serverConfig struct {
defaultResticMaintenanceFrequency time.Duration
garbageCollectionFrequency time.Duration
defaultVolumesToRestic bool
uploaderType string
}

type controllerRunInfo struct {
Expand Down Expand Up @@ -157,6 +160,7 @@ func NewCommand(f client.Factory) *cobra.Command {
formatFlag: logging.NewFormatFlag(),
defaultResticMaintenanceFrequency: restic.DefaultMaintenanceFrequency,
defaultVolumesToRestic: restic.DefaultVolumesToRestic,
uploaderType: uploader.ResticType,
}
)

Expand Down Expand Up @@ -222,6 +226,7 @@ func NewCommand(f client.Factory) *cobra.Command {
command.Flags().DurationVar(&config.defaultResticMaintenanceFrequency, "default-restic-prune-frequency", config.defaultResticMaintenanceFrequency, "How often 'restic prune' is run for restic repositories by default.")
command.Flags().DurationVar(&config.garbageCollectionFrequency, "garbage-collection-frequency", config.garbageCollectionFrequency, "How often garbage collection is run for expired backups.")
command.Flags().BoolVar(&config.defaultVolumesToRestic, "default-volumes-to-restic", config.defaultVolumesToRestic, "Backup all volumes with restic by default.")
command.Flags().StringVar(&config.uploaderType, "uploader-type", config.uploaderType, "Type of uploader to handle the transfer of data of pod volumes")

return command
}
Expand Down Expand Up @@ -251,6 +256,10 @@ type server struct {
}

func newServer(f client.Factory, config serverConfig, logger *logrus.Logger) (*server, error) {
if err := uploader.ValidateUploaderType(config.uploaderType); err != nil {
return nil, err
}

if config.clientQPS < 0.0 {
return nil, errors.New("client-qps must be positive")
}
Expand Down
12 changes: 11 additions & 1 deletion pkg/install/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type podTemplateConfig struct {
plugins []string
features []string
defaultVolumesToRestic bool
uploaderType string
}

func WithImage(image string) podTemplateOption {
Expand Down Expand Up @@ -83,7 +84,6 @@ func WithEnvFromSecretKey(varName, secret, key string) podTemplateOption {
func WithSecret(secretPresent bool) podTemplateOption {
return func(c *podTemplateConfig) {
c.withSecret = secretPresent

}
}

Expand Down Expand Up @@ -123,6 +123,12 @@ func WithFeatures(features []string) podTemplateOption {
}
}

func WithUploaderType(t string) podTemplateOption {
return func(c *podTemplateConfig) {
c.uploaderType = t
}
}

func WithDefaultVolumesToRestic() podTemplateOption {
return func(c *podTemplateConfig) {
c.defaultVolumesToRestic = true
Expand Down Expand Up @@ -155,6 +161,10 @@ func Deployment(namespace string, opts ...podTemplateOption) *appsv1.Deployment
args = append(args, "--default-volumes-to-restic=true")
}

if len(c.uploaderType) > 0 {
args = append(args, fmt.Sprintf("--uploader-type=%s", c.uploaderType))
}

deployment := &appsv1.Deployment{
ObjectMeta: objectMeta(namespace, "velero"),
TypeMeta: metav1.TypeMeta{
Expand Down
4 changes: 4 additions & 0 deletions pkg/install/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,8 @@ func TestDeployment(t *testing.T) {
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])

deploy = Deployment("velero", WithUploaderType("kopia"))
assert.Len(t, deploy.Spec.Template.Spec.Containers[0].Args, 2)
assert.Equal(t, "--uploader-type=kopia", deploy.Spec.Template.Spec.Containers[0].Args[1])
}
2 changes: 2 additions & 0 deletions pkg/install/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ type VeleroOptions struct {
CACertData []byte
Features []string
DefaultVolumesToRestic bool
UploaderType string
}

func AllCRDs() *unstructured.UnstructuredList {
Expand Down Expand Up @@ -287,6 +288,7 @@ func AllResources(o *VeleroOptions) *unstructured.UnstructuredList {
WithSecret(secretPresent),
WithDefaultResticMaintenanceFrequency(o.DefaultResticMaintenanceFrequency),
WithGarbageCollectionFrequency(o.GarbageCollectionFrequency),
WithUploaderType(o.UploaderType),
}

if len(o.Features) > 0 {
Expand Down
26 changes: 23 additions & 3 deletions pkg/uploader/types.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
/*
Copyright 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -13,11 +16,28 @@ limitations under the License.

package uploader

import (
"fmt"
"strings"
)

const (
VeleroBackup string = "backup"
VeleroRestore string = "restore"
ResticType = "restic"
KopiaType = "kopia"
VeleroBackup = "backup"
VeleroRestore = "restore"
)

// ValidateUploaderType validates if the input param is a valid uploader type.
// It will return an error if it's invalid.
func ValidateUploaderType(t string) error {
t = strings.TrimSpace(t)
if t != ResticType && t != KopiaType {
return fmt.Errorf("invalid uploader type '%s', valid upload types are: '%s', '%s'", t, ResticType, KopiaType)
}
return nil
}

type SnapshotInfo struct {
ID string `json:"id"`
Size int64 `json:"Size"`
Expand Down
34 changes: 34 additions & 0 deletions pkg/uploader/types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package uploader

import "testing"

func TestValidateUploaderType(t *testing.T) {
tests := []struct {
name string
input string
wantErr bool
}{
{
"'restic' is a valid type",
"restic",
false,
},
{
"' kopia ' is a valid type (space will be trimmed)",
" kopia ",
false,
},
{
"'anything_else' is invalid",
"anything_else",
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := ValidateUploaderType(tt.input); (err != nil) != tt.wantErr {
t.Errorf("ValidateUploaderType(), input = '%s' error = %v, wantErr %v", tt.input, err, tt.wantErr)
}
})
}
}

0 comments on commit 8fa1cfb

Please sign in to comment.