Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
20 changes: 20 additions & 0 deletions pkg/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,20 @@ type GoogleCredentials struct {
GKEEnvironment bool `json:"gkeEnvironment,omitempty"`
}

// S3AddressingStyle controls how Barman Cloud addresses S3 buckets.
type S3AddressingStyle string

const (
// S3AddressingStyleAuto lets Barman Cloud choose the addressing style.
S3AddressingStyleAuto S3AddressingStyle = "auto"

// S3AddressingStyleVirtual addresses buckets as subdomains of the endpoint.
S3AddressingStyleVirtual S3AddressingStyle = "virtual"

// S3AddressingStylePath addresses buckets as a path below the endpoint.
S3AddressingStylePath S3AddressingStyle = "path"
)

// BarmanObjectStoreConfiguration contains the backup configuration
// using Barman against an S3-compatible object storage
type BarmanObjectStoreConfiguration struct {
Expand All @@ -176,6 +190,12 @@ type BarmanObjectStoreConfiguration struct {
// +optional
EndpointURL string `json:"endpointURL,omitempty"`

// S3AddressingStyle controls how Barman Cloud addresses S3 buckets. It is
// applied to every Barman Cloud command that uses this object store.
// +kubebuilder:validation:Enum=auto;virtual;path
// +optional
S3AddressingStyle S3AddressingStyle `json:"s3AddressingStyle,omitempty"`

// EndpointCA store the CA bundle of the barman endpoint.
// Useful when using self-signed certificates to avoid
// errors with certificate issuer and barman-cloud-wal-archive
Expand Down
19 changes: 19 additions & 0 deletions pkg/backup/backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,23 @@ var _ = Describe("GetBarmanCloudBackupOptions", func() {
"s3://bucket-name/ test-cluster",
))
})

It("should apply the configured S3 addressing style over additional arguments", func(ctx SpecContext) {
backupCommand.configuration.BarmanCredentials = barmanApi.BarmanCredentials{
AWS: &barmanApi.S3Credentials{InheritFromIAMRole: true},
}
backupCommand.configuration.S3AddressingStyle = barmanApi.S3AddressingStyleVirtual
backupCommand.configuration.Data.AdditionalCommandArgs = []string{
"--addressing-style", "path",
}

options, err := backupCommand.GetBarmanCloudBackupOptions(ctx, "test-backup", "test-cluster")
Expect(err).ToNot(HaveOccurred())
Expect(strings.Join(options, " ")).To(Equal(
"--user postgres --name test-backup " +
"--gzip --encryption aes256 --immediate-checkpoint --jobs 4 " +
"--cloud-provider aws-s3 --addressing-style virtual " +
"s3://bucket-name/ test-cluster",
))
})
})
46 changes: 45 additions & 1 deletion pkg/command/commandbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ package command

import (
"context"
"fmt"
"strings"

barmanApi "github.com/cloudnative-pg/barman-cloud/pkg/api"
)
Expand Down Expand Up @@ -62,7 +64,27 @@ func AppendCloudProviderOptionsFromConfiguration(
options []string,
barmanConfiguration *barmanApi.BarmanObjectStoreConfiguration,
) ([]string, error) {
return appendCloudProviderOptions(ctx, options, barmanConfiguration.BarmanCredentials)
if barmanConfiguration.S3AddressingStyle != "" {
if barmanConfiguration.AWS == nil {
return nil, fmt.Errorf("s3AddressingStyle requires s3Credentials")
}

options = withoutOption(options, "--addressing-style")
}

options, err := appendCloudProviderOptions(ctx, options, barmanConfiguration.BarmanCredentials)
if err != nil {
return nil, err
}

if barmanConfiguration.S3AddressingStyle != "" {
options = append(options,
"--addressing-style",
string(barmanConfiguration.S3AddressingStyle),
)
}

return options, nil
}

// AppendCloudProviderOptionsFromBackup takes an options array and adds the cloud provider specified
Expand Down Expand Up @@ -127,6 +149,28 @@ func appendCloudProviderOptions(
return options, nil
}

// withoutOption removes a command-line option and its value from options.
// The configured ObjectStore value must take precedence over a command-specific
// additional argument so every Barman command uses the same addressing style.
func withoutOption(options []string, option string) []string {
result := make([]string, 0, len(options))
for index := 0; index < len(options); index++ {
current := options[index]
switch {
case current == option:
if index+1 < len(options) {
index++
}
case strings.HasPrefix(current, option+"="):
continue
default:
result = append(result, current)
}
}

return result
}

type contextKey string

// contextKeyUseDefaultAzureCredentials contains a bool indicating if the default azure credentials should be used
Expand Down
45 changes: 45 additions & 0 deletions pkg/command/commandbuilder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,21 @@ var _ = Describe("barmanCloudWalRestoreOptions", func() {
"s3://bucket-name/ test-cluster --read-timeout=60 -vv",
))
})

It("should apply the configured S3 addressing style", func(ctx SpecContext) {
storageConf.BarmanCredentials = barmanApi.BarmanCredentials{
AWS: &barmanApi.S3Credentials{InheritFromIAMRole: true},
}
storageConf.S3AddressingStyle = barmanApi.S3AddressingStyleVirtual

options, err := CloudWalRestoreOptions(ctx, storageConf, "test-cluster")
Expect(err).ToNot(HaveOccurred())
Expect(options).To(Equal([]string{
"--cloud-provider", "aws-s3",
"--addressing-style", "virtual",
"s3://bucket-name/", "test-cluster",
}))
})
})

var _ = Describe("useDefaultAzureCredentials", func() {
Expand Down Expand Up @@ -172,3 +187,33 @@ var _ = Describe("AppendCloudProviderOptions with Azure credentials", func() {
))
})
})

var _ = Describe("AppendCloudProviderOptionsFromConfiguration with S3 addressing", func() {
It("should replace an addressing style from command-specific arguments", func(ctx SpecContext) {
configuration := &barmanApi.BarmanObjectStoreConfiguration{
BarmanCredentials: barmanApi.BarmanCredentials{
AWS: &barmanApi.S3Credentials{InheritFromIAMRole: true},
},
S3AddressingStyle: barmanApi.S3AddressingStyleVirtual,
}

options, err := AppendCloudProviderOptionsFromConfiguration(ctx, []string{
"--addressing-style", "path", "--read-timeout=60",
}, configuration)
Expect(err).ToNot(HaveOccurred())
Expect(options).To(Equal([]string{
"--read-timeout=60",
"--cloud-provider", "aws-s3",
"--addressing-style", "virtual",
}))
})

It("should reject an addressing style without S3 credentials", func(ctx SpecContext) {
configuration := &barmanApi.BarmanObjectStoreConfiguration{
S3AddressingStyle: barmanApi.S3AddressingStyleVirtual,
}

_, err := AppendCloudProviderOptionsFromConfiguration(ctx, nil, configuration)
Expect(err).To(MatchError("s3AddressingStyle requires s3Credentials"))
})
})