From 7aa2166aeea4252b808c6ef1d9e0f55ab132a998 Mon Sep 17 00:00:00 2001 From: Frederik Ring Date: Fri, 23 Dec 2022 10:14:37 +0100 Subject: [PATCH] Implement copy for Azure Blob Storage --- cmd/backup/config.go | 1 + internal/storage/azure/azure.go | 37 ++++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/cmd/backup/config.go b/cmd/backup/config.go index d2fea13..f293bdc 100644 --- a/cmd/backup/config.go +++ b/cmd/backup/config.go @@ -66,6 +66,7 @@ type Config struct { AzureStorageAccountName string `split_words:"true"` AzureStoragePrimaryAccountKey string `split_words:"true"` AzureStorageContainerName string `split_words:"true"` + AzureStorageEndpoint string `split_words:"true" default:""https://%s.blob.core.windows.net/""` } func (c *Config) resolveSecret(envVar string, secretPath string) (string, error) { diff --git a/internal/storage/azure/azure.go b/internal/storage/azure/azure.go index 726979f..1034076 100644 --- a/internal/storage/azure/azure.go +++ b/internal/storage/azure/azure.go @@ -4,13 +4,19 @@ package azure import ( + "context" + "fmt" + "os" "time" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" "github.com/offen/docker-volume-backup/internal/storage" ) type azureBlobStorage struct { *storage.StorageBackend + client *azblob.Client + containerName string } // Config contains values that define the configuration of an Azure Blob Storage. @@ -18,21 +24,46 @@ type Config struct { AccountName string ContainerName string PrimaryAccountKey string + Endpoint string } -// NewStorageBackend creates and initializes a new S3/Minio storage backend. +// NewStorageBackend creates and initializes a new Azure Blob Storage backend. func NewStorageBackend(opts Config, logFunc storage.Log) (storage.Backend, error) { - storage := azureBlobStorage{} + cred, err := azblob.NewSharedKeyCredential(opts.AccountName, opts.PrimaryAccountKey) + if err != nil { + return nil, fmt.Errorf("NewStorageBackend: error creating shared Azure credential: %w", err) + } + client, err := azblob.NewClientWithSharedKeyCredential(fmt.Sprintf(opts.Endpoint, opts.AccountName), cred, nil) + if err != nil { + return nil, fmt.Errorf("NewStorageBackend: error creating Azure client: %w", err) + } + storage := azureBlobStorage{ + client: client, + containerName: opts.ContainerName, + } return &storage, nil } // Name returns the name of the storage backend -func (v *azureBlobStorage) Name() string { +func (b *azureBlobStorage) Name() string { return "Azure" } // Copy copies the given file to the storage backend. func (b *azureBlobStorage) Copy(file string) error { + fileReader, err := os.Open(file) + if err != nil { + return fmt.Errorf("(*azureBlobStorage).Copy: error opening file %s: %w", file, err) + } + _, err = b.client.UploadStream(context.TODO(), + b.containerName, + file, + fileReader, + nil, + ) + if err != nil { + return fmt.Errorf("(*azureBlobStorage).Copy: error uploading file %s: %w", file, err) + } return nil }