mirror of
https://github.com/zalando/postgres-operator.git
synced 2026-09-30 13:16:25 +02:00
Support for GCS WAL-E backups (#620)
* Support for WAL_GS_BUCKET and GOOGLE_APPLICATION_CREDENTIALS environtment variables * Fixed merge issue but also removed all changes to support macos. * Updated test to new format * Missed macos specific changes * Added documentation and addressed comments * Update docs/administrator.md * Update docs/administrator.md * Update e2e/run.sh Co-authored-by: Felix Kunde <felix-kunde@gmx.de>
This commit is contained in:
@@ -111,6 +111,8 @@ type LoadBalancerConfiguration struct {
|
||||
type AWSGCPConfiguration struct {
|
||||
WALES3Bucket string `json:"wal_s3_bucket,omitempty"`
|
||||
AWSRegion string `json:"aws_region,omitempty"`
|
||||
WALGSBucket string `json:"wal_gs_bucket,omitempty"`
|
||||
GCPCredentials string `json:"gcp_credentials,omitempty"`
|
||||
LogS3Bucket string `json:"log_s3_bucket,omitempty"`
|
||||
KubeIAMRole string `json:"kube_iam_role,omitempty"`
|
||||
AdditionalSecretMount string `json:"additional_secret_mount,omitempty"`
|
||||
|
||||
@@ -714,12 +714,23 @@ func (c *Cluster) generateSpiloPodEnvVars(uid types.UID, spiloConfiguration stri
|
||||
if spiloConfiguration != "" {
|
||||
envVars = append(envVars, v1.EnvVar{Name: "SPILO_CONFIGURATION", Value: spiloConfiguration})
|
||||
}
|
||||
|
||||
if c.OpConfig.WALES3Bucket != "" {
|
||||
envVars = append(envVars, v1.EnvVar{Name: "WAL_S3_BUCKET", Value: c.OpConfig.WALES3Bucket})
|
||||
envVars = append(envVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))})
|
||||
envVars = append(envVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_PREFIX", Value: ""})
|
||||
}
|
||||
|
||||
if c.OpConfig.WALGSBucket != "" {
|
||||
envVars = append(envVars, v1.EnvVar{Name: "WAL_GS_BUCKET", Value: c.OpConfig.WALGSBucket})
|
||||
envVars = append(envVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))})
|
||||
envVars = append(envVars, v1.EnvVar{Name: "WAL_BUCKET_SCOPE_PREFIX", Value: ""})
|
||||
}
|
||||
|
||||
if c.OpConfig.GCPCredentials != "" {
|
||||
envVars = append(envVars, v1.EnvVar{Name: "GOOGLE_APPLICATION_CREDENTIALS", Value: c.OpConfig.GCPCredentials})
|
||||
}
|
||||
|
||||
if c.OpConfig.LogS3Bucket != "" {
|
||||
envVars = append(envVars, v1.EnvVar{Name: "LOG_S3_BUCKET", Value: c.OpConfig.LogS3Bucket})
|
||||
envVars = append(envVars, v1.EnvVar{Name: "LOG_BUCKET_SCOPE_SUFFIX", Value: getBucketScopeSuffix(string(uid))})
|
||||
|
||||
@@ -20,9 +20,17 @@ import (
|
||||
policyv1beta1 "k8s.io/api/policy/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
// For testing purposes
|
||||
type ExpectedValue struct {
|
||||
envIndex int
|
||||
envVarConstant string
|
||||
envVarValue string
|
||||
}
|
||||
|
||||
func toIntStr(val int) *intstr.IntOrString {
|
||||
b := intstr.FromInt(val)
|
||||
return &b
|
||||
@@ -93,6 +101,119 @@ func TestGenerateSpiloJSONConfiguration(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateSpiloPodEnvVars(t *testing.T) {
|
||||
var cluster = New(
|
||||
Config{
|
||||
OpConfig: config.Config{
|
||||
WALGSBucket: "wale-gs-bucket",
|
||||
ProtectedRoles: []string{"admin"},
|
||||
Auth: config.Auth{
|
||||
SuperUsername: superUserName,
|
||||
ReplicationUsername: replicationUserName,
|
||||
},
|
||||
},
|
||||
}, k8sutil.KubernetesClient{}, acidv1.Postgresql{}, logger, eventRecorder)
|
||||
|
||||
expectedValuesGSBucket := []ExpectedValue{
|
||||
ExpectedValue{
|
||||
envIndex: 14,
|
||||
envVarConstant: "WAL_GS_BUCKET",
|
||||
envVarValue: "wale-gs-bucket",
|
||||
},
|
||||
ExpectedValue{
|
||||
envIndex: 15,
|
||||
envVarConstant: "WAL_BUCKET_SCOPE_SUFFIX",
|
||||
envVarValue: "/SomeUUID",
|
||||
},
|
||||
ExpectedValue{
|
||||
envIndex: 16,
|
||||
envVarConstant: "WAL_BUCKET_SCOPE_PREFIX",
|
||||
envVarValue: "",
|
||||
},
|
||||
}
|
||||
|
||||
expectedValuesGCPCreds := []ExpectedValue{
|
||||
ExpectedValue{
|
||||
envIndex: 14,
|
||||
envVarConstant: "WAL_GS_BUCKET",
|
||||
envVarValue: "wale-gs-bucket",
|
||||
},
|
||||
ExpectedValue{
|
||||
envIndex: 15,
|
||||
envVarConstant: "WAL_BUCKET_SCOPE_SUFFIX",
|
||||
envVarValue: "/SomeUUID",
|
||||
},
|
||||
ExpectedValue{
|
||||
envIndex: 16,
|
||||
envVarConstant: "WAL_BUCKET_SCOPE_PREFIX",
|
||||
envVarValue: "",
|
||||
},
|
||||
ExpectedValue{
|
||||
envIndex: 17,
|
||||
envVarConstant: "GOOGLE_APPLICATION_CREDENTIALS",
|
||||
envVarValue: "some_path_to_credentials",
|
||||
},
|
||||
}
|
||||
|
||||
testName := "TestGenerateSpiloPodEnvVars"
|
||||
tests := []struct {
|
||||
subTest string
|
||||
opConfig config.Config
|
||||
uid types.UID
|
||||
spiloConfig string
|
||||
cloneDescription *acidv1.CloneDescription
|
||||
standbyDescription *acidv1.StandbyDescription
|
||||
customEnvList []v1.EnvVar
|
||||
expectedValues []ExpectedValue
|
||||
}{
|
||||
{
|
||||
subTest: "Will set WAL_GS_BUCKET env",
|
||||
opConfig: config.Config{
|
||||
WALGSBucket: "wale-gs-bucket",
|
||||
},
|
||||
uid: "SomeUUID",
|
||||
spiloConfig: "someConfig",
|
||||
cloneDescription: &acidv1.CloneDescription{},
|
||||
standbyDescription: &acidv1.StandbyDescription{},
|
||||
customEnvList: []v1.EnvVar{},
|
||||
expectedValues: expectedValuesGSBucket,
|
||||
},
|
||||
{
|
||||
subTest: "Will set GOOGLE_APPLICATION_CREDENTIALS env",
|
||||
opConfig: config.Config{
|
||||
WALGSBucket: "wale-gs-bucket",
|
||||
GCPCredentials: "some_path_to_credentials",
|
||||
},
|
||||
uid: "SomeUUID",
|
||||
spiloConfig: "someConfig",
|
||||
cloneDescription: &acidv1.CloneDescription{},
|
||||
standbyDescription: &acidv1.StandbyDescription{},
|
||||
customEnvList: []v1.EnvVar{},
|
||||
expectedValues: expectedValuesGCPCreds,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
cluster.OpConfig = tt.opConfig
|
||||
|
||||
actualEnvs := cluster.generateSpiloPodEnvVars(tt.uid, tt.spiloConfig, tt.cloneDescription, tt.standbyDescription, tt.customEnvList)
|
||||
|
||||
for _, ev := range tt.expectedValues {
|
||||
env := actualEnvs[ev.envIndex]
|
||||
|
||||
if env.Name != ev.envVarConstant {
|
||||
t.Errorf("%s %s: Expected env name %s, have %s instead",
|
||||
testName, tt.subTest, ev.envVarConstant, env.Name)
|
||||
}
|
||||
|
||||
if env.Value != ev.envVarValue {
|
||||
t.Errorf("%s %s: Expected env value %s, have %s instead",
|
||||
testName, tt.subTest, ev.envVarValue, env.Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateLoadBalancerLogic(t *testing.T) {
|
||||
var cluster = New(
|
||||
Config{
|
||||
|
||||
@@ -111,6 +111,8 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
||||
result.AWSRegion = fromCRD.AWSGCP.AWSRegion
|
||||
result.LogS3Bucket = fromCRD.AWSGCP.LogS3Bucket
|
||||
result.KubeIAMRole = fromCRD.AWSGCP.KubeIAMRole
|
||||
result.WALGSBucket = fromCRD.AWSGCP.WALGSBucket
|
||||
result.GCPCredentials = fromCRD.AWSGCP.GCPCredentials
|
||||
result.AdditionalSecretMount = fromCRD.AWSGCP.AdditionalSecretMount
|
||||
result.AdditionalSecretMountPath = fromCRD.AWSGCP.AdditionalSecretMountPath
|
||||
|
||||
|
||||
@@ -126,6 +126,8 @@ type Config struct {
|
||||
WALES3Bucket string `name:"wal_s3_bucket"`
|
||||
LogS3Bucket string `name:"log_s3_bucket"`
|
||||
KubeIAMRole string `name:"kube_iam_role"`
|
||||
WALGSBucket string `name:"wal_gs_bucket"`
|
||||
GCPCredentials string `name:"gcp_credentials"`
|
||||
AdditionalSecretMount string `name:"additional_secret_mount"`
|
||||
AdditionalSecretMountPath string `name:"additional_secret_mount_path" default:"/meta/credentials"`
|
||||
DebugLogging bool `name:"debug_logging" default:"true"`
|
||||
|
||||
Reference in New Issue
Block a user