Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support AWS_PROFILE for restic backups/restore operations #2096

Merged
merged 3 commits into from
Dec 9, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/controller/pod_volume_backup_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ func (c *podVolumeBackupController) processBackup(req *velerov1api.PodVolumeBack
return c.fail(req, errors.Wrap(err, "error setting restic cmd env").Error(), log)
}
resticCmd.Env = env
} else if strings.HasPrefix(req.Spec.RepoIdentifier, "s3") {
skriss marked this conversation as resolved.
Show resolved Hide resolved
if env, err = restic.S3CmdEnv(c.backupLocationLister, req.Namespace, req.Spec.BackupStorageLocation); err != nil {
return c.fail(req, errors.Wrap(err, "error setting restic cmd env").Error(), log)
}
resticCmd.Env = env
}

// If this is a PVC, look for the most recent completed pod volume backup for it and get
Expand Down
6 changes: 6 additions & 0 deletions pkg/controller/pod_volume_restore_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,12 @@ func (c *podVolumeRestoreController) restorePodVolume(req *velerov1api.PodVolume
return c.failRestore(req, errors.Wrap(err, "error setting restic cmd env").Error(), log)
}
resticCmd.Env = env
} else if strings.HasPrefix(req.Spec.RepoIdentifier, "s3") {
skriss marked this conversation as resolved.
Show resolved Hide resolved
env, err := restic.S3CmdEnv(c.backupLocationLister, req.Namespace, req.Spec.BackupStorageLocation)
if err != nil {
return c.failRestore(req, errors.Wrap(err, "error setting restic cmd env").Error(), log)
}
resticCmd.Env = env
}

var stdout, stderr string
Expand Down
36 changes: 36 additions & 0 deletions pkg/restic/aws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Copyright 2017, 2019 the Velero contributors.
skriss marked this conversation as resolved.
Show resolved Hide resolved

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.
See the License for the specific language governing permissions and
limitations under the License.
*/

package restic

const (
// AWS specific environment variable
awsProfileEnvVar = "AWS_PROFILE"
awsProfileKey = "profile"
)

// getS3ResticEnvVars gets the environment variables that restic
// relies on (AWS_PROFILE) based on info in the provided object
// storage location config map.
func getS3ResticEnvVars(config map[string]string) (map[string]string, error) {
result := make(map[string]string)

if profile, ok := config[awsProfileKey]; ok {
result[awsProfileEnvVar] = profile
}

return result, nil
}
4 changes: 2 additions & 2 deletions pkg/restic/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ func mapLookup(data map[string]string) func(string) string {
}
}

// getResticEnvVars gets the environment variables that restic
// getAzureResticEnvVars gets the environment variables that restic
// relies on (AZURE_ACCOUNT_NAME and AZURE_ACCOUNT_KEY) based
// on info in the provided object storage location config map.
func getResticEnvVars(config map[string]string) (map[string]string, error) {
func getAzureResticEnvVars(config map[string]string) (map[string]string, error) {
storageAccountKey, _, err := getStorageAccountKey(config)
if err != nil {
return nil, err
Expand Down
25 changes: 24 additions & 1 deletion pkg/restic/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func AzureCmdEnv(backupLocationLister velerov1listers.BackupStorageLocationListe
return nil, errors.Wrap(err, "error getting backup storage location")
}

azureVars, err := getResticEnvVars(loc.Spec.Config)
azureVars, err := getAzureResticEnvVars(loc.Spec.Config)
if err != nil {
return nil, errors.Wrap(err, "error getting azure restic env vars")
}
Expand All @@ -240,3 +240,26 @@ func AzureCmdEnv(backupLocationLister velerov1listers.BackupStorageLocationListe

return env, nil
}

// S3CmdEnv returns a list of environment variables (in the format var=val) that
// should be used when running a restic command for an Azure backend. This list is
skriss marked this conversation as resolved.
Show resolved Hide resolved
// the current environment, plus the AWS-specific variables restic needs, namely
// a credential profile.
func S3CmdEnv(backupLocationLister velerov1listers.BackupStorageLocationLister, namespace, backupLocation string) ([]string, error) {
loc, err := backupLocationLister.BackupStorageLocations(namespace).Get(backupLocation)
if err != nil {
return nil, errors.Wrap(err, "error getting backup storage location")
}

awsVars, err := getS3ResticEnvVars(loc.Spec.Config)
if err != nil {
return nil, errors.Wrap(err, "error getting aws restic env vars")
}

env := os.Environ()
for k, v := range awsVars {
env = append(env, fmt.Sprintf("%s=%s", k, v))
}

return env, nil
}
10 changes: 10 additions & 0 deletions pkg/restic/repository_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,16 @@ func (rm *repositoryManager) exec(cmd *Command, backupLocation string) error {
return err
}
cmd.Env = env
} else if strings.HasPrefix(cmd.RepoIdentifier, "s3") {
if !cache.WaitForCacheSync(rm.ctx.Done(), rm.backupLocationInformerSynced) {
return errors.New("timed out waiting for cache to sync")
}

env, err := S3CmdEnv(rm.backupLocationLister, rm.namespace, backupLocation)
if err != nil {
return err
}
cmd.Env = env
}

stdout, stderr, err := veleroexec.RunCommand(cmd.Cmd())
Expand Down