use the default backup storage location for restic
Signed-off-by: Steve Kriss <steve@heptio.com>pull/799/head
parent
833a6307a9
commit
20f89fbcef
|
@ -271,6 +271,11 @@ func (s *server) run() error {
|
|||
|
||||
s.watchConfig(originalConfig)
|
||||
|
||||
backupStorageLocation, err := s.arkClient.ArkV1().BackupStorageLocations(s.namespace).Get(s.defaultBackupLocation, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
objectStore, err := getObjectStore(config.BackupStorageProvider.CloudProviderConfig, s.pluginManager)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -288,13 +293,13 @@ func (s *server) run() error {
|
|||
s.blockStore = blockStore
|
||||
}
|
||||
|
||||
if config.BackupStorageProvider.ResticLocation != "" {
|
||||
if err := s.initRestic(config.BackupStorageProvider); err != nil {
|
||||
if backupStorageLocation.Spec.Config[restic.ResticLocationConfigKey] != "" {
|
||||
if err := s.initRestic(backupStorageLocation.Spec.Provider); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := s.runControllers(config); err != nil {
|
||||
if err := s.runControllers(config, backupStorageLocation); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -525,7 +530,7 @@ func durationMin(a, b time.Duration) time.Duration {
|
|||
return b
|
||||
}
|
||||
|
||||
func (s *server) initRestic(config api.ObjectStorageProviderConfig) error {
|
||||
func (s *server) initRestic(providerName string) error {
|
||||
// warn if restic daemonset does not exist
|
||||
if _, err := s.kubeClient.AppsV1().DaemonSets(s.namespace).Get(restic.DaemonSet, metav1.GetOptions{}); apierrors.IsNotFound(err) {
|
||||
s.logger.Warn("Ark restic daemonset not found; restic backups/restores will not work until it's created")
|
||||
|
@ -539,7 +544,7 @@ func (s *server) initRestic(config api.ObjectStorageProviderConfig) error {
|
|||
}
|
||||
|
||||
// set the env vars that restic uses for creds purposes
|
||||
if config.Name == string(restic.AzureBackend) {
|
||||
if providerName == string(restic.AzureBackend) {
|
||||
os.Setenv("AZURE_ACCOUNT_NAME", os.Getenv("AZURE_STORAGE_ACCOUNT_ID"))
|
||||
os.Setenv("AZURE_ACCOUNT_KEY", os.Getenv("AZURE_STORAGE_KEY"))
|
||||
}
|
||||
|
@ -578,7 +583,7 @@ func (s *server) initRestic(config api.ObjectStorageProviderConfig) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *server) runControllers(config *api.Config) error {
|
||||
func (s *server) runControllers(config *api.Config, defaultBackupLocation *api.BackupStorageLocation) error {
|
||||
s.logger.Info("Starting controllers")
|
||||
|
||||
ctx := s.ctx
|
||||
|
@ -755,7 +760,7 @@ func (s *server) runControllers(config *api.Config) error {
|
|||
s.logger,
|
||||
s.sharedInformerFactory.Ark().V1().ResticRepositories(),
|
||||
s.arkClient.ArkV1(),
|
||||
config.BackupStorageProvider,
|
||||
defaultBackupLocation,
|
||||
s.resticManager,
|
||||
)
|
||||
wg.Add(1)
|
||||
|
|
|
@ -44,7 +44,7 @@ type resticRepositoryController struct {
|
|||
|
||||
resticRepositoryClient arkv1client.ResticRepositoriesGetter
|
||||
resticRepositoryLister listers.ResticRepositoryLister
|
||||
objectStorageConfig arkv1api.ObjectStorageProviderConfig
|
||||
storageLocation *arkv1api.BackupStorageLocation
|
||||
repositoryManager restic.RepositoryManager
|
||||
|
||||
clock clock.Clock
|
||||
|
@ -55,14 +55,14 @@ func NewResticRepositoryController(
|
|||
logger logrus.FieldLogger,
|
||||
resticRepositoryInformer informers.ResticRepositoryInformer,
|
||||
resticRepositoryClient arkv1client.ResticRepositoriesGetter,
|
||||
objectStorageConfig arkv1api.ObjectStorageProviderConfig,
|
||||
storageLocation *arkv1api.BackupStorageLocation,
|
||||
repositoryManager restic.RepositoryManager,
|
||||
) Interface {
|
||||
c := &resticRepositoryController{
|
||||
genericController: newGenericController("restic-repository", logger),
|
||||
resticRepositoryClient: resticRepositoryClient,
|
||||
resticRepositoryLister: resticRepositoryInformer.Lister(),
|
||||
objectStorageConfig: objectStorageConfig,
|
||||
storageLocation: storageLocation,
|
||||
repositoryManager: repositoryManager,
|
||||
clock: &clock.RealClock{},
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ func (c *resticRepositoryController) initializeRepo(req *v1.ResticRepository, lo
|
|||
|
||||
// defaulting - if the patch fails, return an error so the item is returned to the queue
|
||||
if err := c.patchResticRepository(req, func(r *v1.ResticRepository) {
|
||||
r.Spec.ResticIdentifier = restic.GetRepoIdentifier(c.objectStorageConfig, r.Name)
|
||||
r.Spec.ResticIdentifier = restic.GetRepoIdentifier(c.storageLocation, r.Name)
|
||||
|
||||
if r.Spec.MaintenanceFrequency.Duration <= 0 {
|
||||
r.Spec.MaintenanceFrequency = metav1.Duration{Duration: restic.DefaultMaintenanceFrequency}
|
||||
|
|
|
@ -36,6 +36,7 @@ const (
|
|||
DaemonSet = "restic"
|
||||
InitContainer = "restic-wait"
|
||||
DefaultMaintenanceFrequency = 24 * time.Hour
|
||||
ResticLocationConfigKey = "restic-location"
|
||||
|
||||
podAnnotationPrefix = "snapshot.ark.heptio.com/"
|
||||
volumesToBackupAnnotation = "backup.ark.heptio.com/backup-volumes"
|
||||
|
|
|
@ -38,9 +38,10 @@ var getAWSBucketRegion = aws.GetBucketRegion
|
|||
|
||||
// getRepoPrefix returns the prefix of the value of the --repo flag for
|
||||
// restic commands, i.e. everything except the "/<repo-name>".
|
||||
func getRepoPrefix(config arkv1api.ObjectStorageProviderConfig) string {
|
||||
func getRepoPrefix(location *arkv1api.BackupStorageLocation) string {
|
||||
var (
|
||||
parts = strings.SplitN(config.ResticLocation, "/", 2)
|
||||
resticLocation = location.Spec.Config[ResticLocationConfigKey]
|
||||
parts = strings.SplitN(resticLocation, "/", 2)
|
||||
bucket, path, prefix string
|
||||
)
|
||||
|
||||
|
@ -51,13 +52,13 @@ func getRepoPrefix(config arkv1api.ObjectStorageProviderConfig) string {
|
|||
path = parts[1]
|
||||
}
|
||||
|
||||
switch BackendType(config.Name) {
|
||||
switch BackendType(location.Spec.Provider) {
|
||||
case AWSBackend:
|
||||
var url string
|
||||
switch {
|
||||
// non-AWS, S3-compatible object store
|
||||
case config.Config["s3Url"] != "":
|
||||
url = config.Config["s3Url"]
|
||||
case location.Spec.Config["s3Url"] != "":
|
||||
url = location.Spec.Config["s3Url"]
|
||||
default:
|
||||
region, err := getAWSBucketRegion(bucket)
|
||||
if err != nil {
|
||||
|
@ -68,7 +69,7 @@ func getRepoPrefix(config arkv1api.ObjectStorageProviderConfig) string {
|
|||
url = fmt.Sprintf("s3-%s.amazonaws.com", region)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("s3:%s/%s", url, config.ResticLocation)
|
||||
return fmt.Sprintf("s3:%s/%s", url, resticLocation)
|
||||
case AzureBackend:
|
||||
prefix = "azure"
|
||||
case GCPBackend:
|
||||
|
@ -80,8 +81,8 @@ func getRepoPrefix(config arkv1api.ObjectStorageProviderConfig) string {
|
|||
|
||||
// GetRepoIdentifier returns the string to be used as the value of the --repo flag in
|
||||
// restic commands for the given repository.
|
||||
func GetRepoIdentifier(config arkv1api.ObjectStorageProviderConfig, name string) string {
|
||||
prefix := getRepoPrefix(config)
|
||||
func GetRepoIdentifier(location *arkv1api.BackupStorageLocation, name string) string {
|
||||
prefix := getRepoPrefix(location)
|
||||
|
||||
return fmt.Sprintf("%s/%s", strings.TrimSuffix(prefix, "/"), name)
|
||||
}
|
||||
|
|
|
@ -30,47 +30,60 @@ func TestGetRepoIdentifier(t *testing.T) {
|
|||
getAWSBucketRegion = func(string) (string, error) {
|
||||
return "", errors.New("no region found")
|
||||
}
|
||||
config := arkv1api.ObjectStorageProviderConfig{
|
||||
CloudProviderConfig: arkv1api.CloudProviderConfig{Name: "aws"},
|
||||
ResticLocation: "bucket/prefix",
|
||||
|
||||
backupLocation := &arkv1api.BackupStorageLocation{
|
||||
Spec: arkv1api.BackupStorageLocationSpec{
|
||||
Provider: "aws",
|
||||
Config: map[string]string{ResticLocationConfigKey: "bucket/prefix"},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, "s3:s3.amazonaws.com/bucket/prefix/repo-1", GetRepoIdentifier(config, "repo-1"))
|
||||
assert.Equal(t, "s3:s3.amazonaws.com/bucket/prefix/repo-1", GetRepoIdentifier(backupLocation, "repo-1"))
|
||||
|
||||
// stub implementation of getAWSBucketRegion
|
||||
getAWSBucketRegion = func(string) (string, error) {
|
||||
return "us-west-2", nil
|
||||
}
|
||||
|
||||
config = arkv1api.ObjectStorageProviderConfig{
|
||||
CloudProviderConfig: arkv1api.CloudProviderConfig{Name: "aws"},
|
||||
ResticLocation: "bucket",
|
||||
}
|
||||
assert.Equal(t, "s3:s3-us-west-2.amazonaws.com/bucket/repo-1", GetRepoIdentifier(config, "repo-1"))
|
||||
|
||||
config = arkv1api.ObjectStorageProviderConfig{
|
||||
CloudProviderConfig: arkv1api.CloudProviderConfig{Name: "aws"},
|
||||
ResticLocation: "bucket/prefix",
|
||||
}
|
||||
assert.Equal(t, "s3:s3-us-west-2.amazonaws.com/bucket/prefix/repo-1", GetRepoIdentifier(config, "repo-1"))
|
||||
|
||||
config = arkv1api.ObjectStorageProviderConfig{
|
||||
CloudProviderConfig: arkv1api.CloudProviderConfig{
|
||||
Name: "aws",
|
||||
Config: map[string]string{"s3Url": "alternate-url"},
|
||||
backupLocation = &arkv1api.BackupStorageLocation{
|
||||
Spec: arkv1api.BackupStorageLocationSpec{
|
||||
Provider: "aws",
|
||||
Config: map[string]string{ResticLocationConfigKey: "bucket"},
|
||||
},
|
||||
ResticLocation: "bucket/prefix",
|
||||
}
|
||||
assert.Equal(t, "s3:alternate-url/bucket/prefix/repo-1", GetRepoIdentifier(config, "repo-1"))
|
||||
assert.Equal(t, "s3:s3-us-west-2.amazonaws.com/bucket/repo-1", GetRepoIdentifier(backupLocation, "repo-1"))
|
||||
|
||||
config = arkv1api.ObjectStorageProviderConfig{
|
||||
CloudProviderConfig: arkv1api.CloudProviderConfig{Name: "azure"},
|
||||
ResticLocation: "bucket/prefix",
|
||||
backupLocation = &arkv1api.BackupStorageLocation{
|
||||
Spec: arkv1api.BackupStorageLocationSpec{
|
||||
Provider: "aws",
|
||||
Config: map[string]string{ResticLocationConfigKey: "bucket/prefix"},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, "azure:bucket:/prefix/repo-1", GetRepoIdentifier(config, "repo-1"))
|
||||
assert.Equal(t, "s3:s3-us-west-2.amazonaws.com/bucket/prefix/repo-1", GetRepoIdentifier(backupLocation, "repo-1"))
|
||||
|
||||
config = arkv1api.ObjectStorageProviderConfig{
|
||||
CloudProviderConfig: arkv1api.CloudProviderConfig{Name: "gcp"},
|
||||
ResticLocation: "bucket-2/prefix-2",
|
||||
backupLocation = &arkv1api.BackupStorageLocation{
|
||||
Spec: arkv1api.BackupStorageLocationSpec{
|
||||
Provider: "aws",
|
||||
Config: map[string]string{
|
||||
ResticLocationConfigKey: "bucket/prefix",
|
||||
"s3Url": "alternate-url",
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, "gs:bucket-2:/prefix-2/repo-2", GetRepoIdentifier(config, "repo-2"))
|
||||
assert.Equal(t, "s3:alternate-url/bucket/prefix/repo-1", GetRepoIdentifier(backupLocation, "repo-1"))
|
||||
|
||||
backupLocation = &arkv1api.BackupStorageLocation{
|
||||
Spec: arkv1api.BackupStorageLocationSpec{
|
||||
Provider: "azure",
|
||||
Config: map[string]string{ResticLocationConfigKey: "bucket/prefix"},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, "azure:bucket:/prefix/repo-1", GetRepoIdentifier(backupLocation, "repo-1"))
|
||||
|
||||
backupLocation = &arkv1api.BackupStorageLocation{
|
||||
Spec: arkv1api.BackupStorageLocationSpec{
|
||||
Provider: "gcp",
|
||||
Config: map[string]string{ResticLocationConfigKey: "bucket-2/prefix-2"},
|
||||
},
|
||||
}
|
||||
assert.Equal(t, "gs:bucket-2:/prefix-2/repo-2", GetRepoIdentifier(backupLocation, "repo-2"))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue