mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-01-03 03:35:22 +00:00
316 lines
9.5 KiB
Go
316 lines
9.5 KiB
Go
/*
|
|
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.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package provider
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"github.com/vmware-tanzu/velero/internal/credentials"
|
|
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
|
repoconfig "github.com/vmware-tanzu/velero/pkg/repository/config"
|
|
repokey "github.com/vmware-tanzu/velero/pkg/repository/keys"
|
|
"github.com/vmware-tanzu/velero/pkg/repository/udmrepo"
|
|
"github.com/vmware-tanzu/velero/pkg/util/ownership"
|
|
)
|
|
|
|
type unifiedRepoProvider struct {
|
|
credentialGetter credentials.CredentialGetter
|
|
workPath string
|
|
repoService udmrepo.BackupRepoService
|
|
log logrus.FieldLogger
|
|
}
|
|
|
|
// this func is assigned to a package-level variable so it can be
|
|
// replaced when unit-testing
|
|
var getAzureCredentials = repoconfig.GetAzureCredentials
|
|
var getS3Credentials = repoconfig.GetS3Credentials
|
|
var getGCPCredentials = repoconfig.GetGCPCredentials
|
|
var getS3BucketRegion = repoconfig.GetAWSBucketRegion
|
|
var getAzureStorageDomain = repoconfig.GetAzureStorageDomain
|
|
|
|
type localFuncTable struct {
|
|
getRepoPassword func(credentials.SecretStore, RepoParam) (string, error)
|
|
getStorageVariables func(*velerov1api.BackupStorageLocation, string) (map[string]string, error)
|
|
getStorageCredentials func(*velerov1api.BackupStorageLocation, credentials.FileStore) (map[string]string, error)
|
|
}
|
|
|
|
var funcTable = localFuncTable{
|
|
getRepoPassword: getRepoPassword,
|
|
getStorageVariables: getStorageVariables,
|
|
getStorageCredentials: getStorageCredentials,
|
|
}
|
|
|
|
// NewUnifiedRepoProvider creates the service provider for Unified Repo
|
|
// workPath is the path for Unified Repo to store some local information
|
|
// workPath could be empty, if so, the default path will be used
|
|
func NewUnifiedRepoProvider(
|
|
credentialGetter credentials.CredentialGetter,
|
|
workPath string,
|
|
log logrus.FieldLogger,
|
|
) (Provider, error) {
|
|
repo := unifiedRepoProvider{
|
|
credentialGetter: credentialGetter,
|
|
workPath: workPath,
|
|
log: log,
|
|
}
|
|
|
|
repo.repoService = createRepoService(log)
|
|
|
|
log.Debug("Finished create unified repo service")
|
|
|
|
return &repo, nil
|
|
}
|
|
|
|
func (urp *unifiedRepoProvider) InitRepo(ctx context.Context, param RepoParam) error {
|
|
log := urp.log.WithFields(logrus.Fields{
|
|
"BSL name": param.BackupLocation.Name,
|
|
"BSL UID": param.BackupLocation.UID,
|
|
})
|
|
|
|
log.Debug("Start to init repo")
|
|
|
|
repoOption, err := urp.getRepoOption(param)
|
|
if err != nil {
|
|
return errors.Wrap(err, "error to get repo options")
|
|
}
|
|
|
|
err = urp.repoService.Init(ctx, repoOption, true)
|
|
if err != nil {
|
|
return errors.Wrap(err, "error to init backup repo")
|
|
}
|
|
|
|
log.Debug("Init repo complete")
|
|
|
|
return nil
|
|
}
|
|
|
|
func (urp *unifiedRepoProvider) ConnectToRepo(ctx context.Context, param RepoParam) error {
|
|
///TODO
|
|
return nil
|
|
}
|
|
|
|
func (urp *unifiedRepoProvider) PrepareRepo(ctx context.Context, param RepoParam) error {
|
|
///TODO
|
|
return nil
|
|
}
|
|
|
|
func (urp *unifiedRepoProvider) PruneRepo(ctx context.Context, param RepoParam) error {
|
|
///TODO
|
|
return nil
|
|
}
|
|
|
|
func (urp *unifiedRepoProvider) PruneRepoQuick(ctx context.Context, param RepoParam) error {
|
|
///TODO
|
|
return nil
|
|
}
|
|
|
|
func (urp *unifiedRepoProvider) EnsureUnlockRepo(ctx context.Context, param RepoParam) error {
|
|
return nil
|
|
}
|
|
|
|
func (urp *unifiedRepoProvider) Forget(ctx context.Context, snapshotID string, param RepoParam) error {
|
|
///TODO
|
|
return nil
|
|
}
|
|
|
|
func getRepoPassword(secretStore credentials.SecretStore, param RepoParam) (string, error) {
|
|
if secretStore == nil {
|
|
return "", errors.New("invalid credentials interface")
|
|
}
|
|
|
|
buf, err := secretStore.Get(repokey.RepoKeySelector())
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "error to get password buffer")
|
|
}
|
|
|
|
return strings.TrimSpace(string(buf)), nil
|
|
}
|
|
|
|
func (urp *unifiedRepoProvider) getRepoOption(param RepoParam) (udmrepo.RepoOptions, error) {
|
|
repoPassword, err := funcTable.getRepoPassword(urp.credentialGetter.FromSecret, param)
|
|
if err != nil {
|
|
return udmrepo.RepoOptions{}, errors.Wrap(err, "error to get repo password")
|
|
}
|
|
|
|
storeVar, err := funcTable.getStorageVariables(param.BackupLocation, param.SubDir)
|
|
if err != nil {
|
|
return udmrepo.RepoOptions{}, errors.Wrap(err, "error to get storage variables")
|
|
}
|
|
|
|
storeCred, err := funcTable.getStorageCredentials(param.BackupLocation, urp.credentialGetter.FromFile)
|
|
if err != nil {
|
|
return udmrepo.RepoOptions{}, errors.Wrap(err, "error to get repo credentials")
|
|
}
|
|
|
|
repoOption := udmrepo.RepoOptions{
|
|
StorageType: getStorageType(param.BackupLocation),
|
|
RepoPassword: repoPassword,
|
|
ConfigFilePath: getRepoConfigFile(urp.workPath, string(param.BackupLocation.UID)),
|
|
Ownership: udmrepo.OwnershipOptions{
|
|
Username: ownership.GetRepositoryOwner().Username,
|
|
DomainName: ownership.GetRepositoryOwner().DomainName,
|
|
},
|
|
StorageOptions: make(map[string]string),
|
|
GeneralOptions: make(map[string]string),
|
|
}
|
|
|
|
for k, v := range storeVar {
|
|
repoOption.StorageOptions[k] = v
|
|
}
|
|
|
|
for k, v := range storeCred {
|
|
repoOption.StorageOptions[k] = v
|
|
}
|
|
|
|
return repoOption, nil
|
|
}
|
|
|
|
func getStorageType(backupLocation *velerov1api.BackupStorageLocation) string {
|
|
backendType := repoconfig.GetBackendType(backupLocation.Spec.Provider)
|
|
|
|
switch backendType {
|
|
case repoconfig.AWSBackend:
|
|
return udmrepo.StorageTypeS3
|
|
case repoconfig.AzureBackend:
|
|
return udmrepo.StorageTypeAzure
|
|
case repoconfig.GCPBackend:
|
|
return udmrepo.StorageTypeGcs
|
|
case repoconfig.FSBackend:
|
|
return udmrepo.StorageTypeFs
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func getStorageCredentials(backupLocation *velerov1api.BackupStorageLocation, credentialsFileStore credentials.FileStore) (map[string]string, error) {
|
|
result := make(map[string]string)
|
|
var err error
|
|
|
|
if credentialsFileStore == nil {
|
|
return map[string]string{}, errors.New("invalid credentials interface")
|
|
}
|
|
|
|
backendType := repoconfig.GetBackendType(backupLocation.Spec.Provider)
|
|
if !repoconfig.IsBackendTypeValid(backendType) {
|
|
return map[string]string{}, errors.New("invalid storage provider")
|
|
}
|
|
|
|
config := backupLocation.Spec.Config
|
|
if config == nil {
|
|
config = map[string]string{}
|
|
}
|
|
|
|
if backupLocation.Spec.Credential != nil {
|
|
config[repoconfig.CredentialsFileKey], err = credentialsFileStore.Path(backupLocation.Spec.Credential)
|
|
if err != nil {
|
|
return map[string]string{}, errors.Wrap(err, "error get credential file in bsl")
|
|
}
|
|
}
|
|
|
|
switch backendType {
|
|
case repoconfig.AWSBackend:
|
|
credValue, err := getS3Credentials(config)
|
|
if err != nil {
|
|
return map[string]string{}, errors.Wrap(err, "error get s3 credentials")
|
|
}
|
|
result[udmrepo.StoreOptionS3KeyId] = credValue.AccessKeyID
|
|
result[udmrepo.StoreOptionS3Provider] = credValue.ProviderName
|
|
result[udmrepo.StoreOptionS3SecretKey] = credValue.SecretAccessKey
|
|
result[udmrepo.StoreOptionS3Token] = credValue.SessionToken
|
|
|
|
case repoconfig.AzureBackend:
|
|
storageAccount, accountKey, err := getAzureCredentials(config)
|
|
if err != nil {
|
|
return map[string]string{}, errors.Wrap(err, "error get azure credentials")
|
|
}
|
|
result[udmrepo.StoreOptionAzureStorageAccount] = storageAccount
|
|
result[udmrepo.StoreOptionAzureKey] = accountKey
|
|
|
|
case repoconfig.GCPBackend:
|
|
result[udmrepo.StoreOptionCredentialFile] = getGCPCredentials(config)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func getStorageVariables(backupLocation *velerov1api.BackupStorageLocation, repoName string) (map[string]string, error) {
|
|
result := make(map[string]string)
|
|
|
|
backendType := repoconfig.GetBackendType(backupLocation.Spec.Provider)
|
|
if !repoconfig.IsBackendTypeValid(backendType) {
|
|
return map[string]string{}, errors.New("invalid storage provider")
|
|
}
|
|
|
|
config := backupLocation.Spec.Config
|
|
if config == nil {
|
|
config = map[string]string{}
|
|
}
|
|
|
|
bucket := strings.Trim(config["bucket"], "/")
|
|
prefix := strings.Trim(config["prefix"], "/")
|
|
if backupLocation.Spec.ObjectStorage != nil {
|
|
bucket = strings.Trim(backupLocation.Spec.ObjectStorage.Bucket, "/")
|
|
prefix = strings.Trim(backupLocation.Spec.ObjectStorage.Prefix, "/")
|
|
}
|
|
|
|
prefix = path.Join(prefix, udmrepo.StoreOptionPrefixName, repoName) + "/"
|
|
|
|
region := config["region"]
|
|
|
|
if backendType == repoconfig.AWSBackend {
|
|
s3Url := config["s3Url"]
|
|
|
|
var err error
|
|
if s3Url == "" {
|
|
region, err = getS3BucketRegion(bucket)
|
|
if err != nil {
|
|
return map[string]string{}, errors.Wrap(err, "error get s3 bucket region")
|
|
}
|
|
|
|
s3Url = fmt.Sprintf("s3-%s.amazonaws.com", region)
|
|
}
|
|
|
|
result[udmrepo.StoreOptionS3Endpoint] = strings.Trim(s3Url, "/")
|
|
result[udmrepo.StoreOptionS3DisableTlsVerify] = config["insecureSkipTLSVerify"]
|
|
} else if backendType == repoconfig.AzureBackend {
|
|
result[udmrepo.StoreOptionAzureDomain] = getAzureStorageDomain(config)
|
|
}
|
|
|
|
result[udmrepo.StoreOptionOssBucket] = bucket
|
|
result[udmrepo.StoreOptionPrefix] = prefix
|
|
result[udmrepo.StoreOptionOssRegion] = strings.Trim(region, "/")
|
|
result[udmrepo.StoreOptionFsPath] = config["fspath"]
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func getRepoConfigFile(workPath string, repoID string) string {
|
|
///TODO: call udmrepo to get config file
|
|
return ""
|
|
}
|
|
|
|
func createRepoService(log logrus.FieldLogger) udmrepo.BackupRepoService {
|
|
///TODO: call udmrepo create repo service
|
|
return nil
|
|
}
|