diff --git a/cmd/backup/config.go b/cmd/backup/config.go index 398a96a..88ebba1 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"` + AzureStoragePath string `split_words:"true"` AzureStorageEndpoint string `split_words:"true" default:"https://{{ .AccountName }}.blob.core.windows.net/"` } diff --git a/cmd/backup/script.go b/cmd/backup/script.go index 379df28..c4d34ac 100644 --- a/cmd/backup/script.go +++ b/cmd/backup/script.go @@ -197,6 +197,7 @@ func newScript() (*script, error) { AccountName: s.c.AzureStorageAccountName, PrimaryAccountKey: s.c.AzureStoragePrimaryAccountKey, Endpoint: s.c.AzureStorageEndpoint, + RemotePath: s.c.AzureStoragePath, } azureBackend, err := azure.NewStorageBackend(azureConfig, logFunc) if err != nil { diff --git a/internal/storage/azure/azure.go b/internal/storage/azure/azure.go index dd850bb..8f306b3 100644 --- a/internal/storage/azure/azure.go +++ b/internal/storage/azure/azure.go @@ -8,7 +8,7 @@ import ( "context" "fmt" "os" - "path" + "path/filepath" "sync" "text/template" "time" @@ -31,6 +31,7 @@ type Config struct { ContainerName string PrimaryAccountKey string Endpoint string + RemotePath string } // NewStorageBackend creates and initializes a new Azure Blob Storage backend. @@ -57,7 +58,8 @@ func NewStorageBackend(opts Config, logFunc storage.Log) (storage.Backend, error client: client, containerName: opts.ContainerName, StorageBackend: &storage.StorageBackend{ - Log: logFunc, + DestinationPath: opts.RemotePath, + Log: logFunc, }, } return &storage, nil @@ -74,11 +76,10 @@ func (b *azureBlobStorage) Copy(file string) error { if err != nil { return fmt.Errorf("(*azureBlobStorage).Copy: error opening file %s: %w", file, err) } - _, err = b.client.UploadStream( context.Background(), b.containerName, - path.Base(file), + filepath.Join(b.DestinationPath, filepath.Base(file)), fileReader, nil, ) @@ -91,8 +92,9 @@ func (b *azureBlobStorage) Copy(file string) error { // Prune rotates away backups according to the configuration and provided // deadline for the Azure Blob storage backend. func (b *azureBlobStorage) Prune(deadline time.Time, pruningPrefix string) (*storage.PruneStats, error) { + lookupPrefix := filepath.Join(b.DestinationPath, pruningPrefix) pager := b.client.NewListBlobsFlatPager(b.containerName, &container.ListBlobsFlatOptions{ - Prefix: &pruningPrefix, + Prefix: &lookupPrefix, }) var matches []string var totalCount uint diff --git a/test/azure/docker-compose.yml b/test/azure/docker-compose.yml index a1146c3..d2bceb8 100644 --- a/test/azure/docker-compose.yml +++ b/test/azure/docker-compose.yml @@ -35,6 +35,7 @@ services: AZURE_STORAGE_PRIMARY_ACCOUNT_KEY: Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw== AZURE_STORAGE_CONTAINER_NAME: test-container AZURE_STORAGE_ENDPOINT: http://storage:10000/{{ .AccountName }}/ + AZURE_STORAGE_PATH: 'path/to/backup' BACKUP_FILENAME: test.tar.gz BACKUP_CRON_EXPRESSION: 0 0 5 31 2 ? BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-7} diff --git a/test/azure/run.sh b/test/azure/run.sh index f380ab9..0077706 100644 --- a/test/azure/run.sh +++ b/test/azure/run.sh @@ -18,7 +18,7 @@ sleep 5 expect_running_containers "3" docker-compose run --rm az_cli \ - az storage blob download -f /dump/test.tar.gz -c test-container -n test.tar.gz + az storage blob download -f /dump/test.tar.gz -c test-container -n path/to/backup/test.tar.gz tar -xvf ./local/test.tar.gz -C /tmp && test -f /tmp/backup/app_data/offen.db pass "Found relevant files in untared remote backups." @@ -32,7 +32,7 @@ sleep 5 docker-compose exec backup backup docker-compose run --rm az_cli \ - az storage blob download -f /dump/test.tar.gz -c test-container -n test.tar.gz + az storage blob download -f /dump/test.tar.gz -c test-container -n path/to/backup/test.tar.gz test -f ./local/test.tar.gz pass "Remote backups have not been deleted."