diff --git a/.gitignore b/.gitignore index 2fa618677..dcfd7074a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .DS_Store /vendor/ /testing/kuttl/e2e-generated*/ +gke_gcloud_auth_plugin_cache diff --git a/internal/controller/postgrescluster/pgbackrest.go b/internal/controller/postgrescluster/pgbackrest.go index a417730ac..a3589b168 100644 --- a/internal/controller/postgrescluster/pgbackrest.go +++ b/internal/controller/postgrescluster/pgbackrest.go @@ -2640,7 +2640,7 @@ func (r *Reconciler) reconcileStanzaCreate(ctx context.Context, // Always attempt to create pgBackRest stanza first configHashMismatch, err := pgbackrest.Executor(exec).StanzaCreateOrUpgrade(ctx, configHash, - false) + false, postgresCluster) if err != nil { // record and log any errors resulting from running the stanza-create command r.Recorder.Event(postgresCluster, corev1.EventTypeWarning, EventUnableToCreateStanzas, diff --git a/internal/pgbackrest/pgbackrest.go b/internal/pgbackrest/pgbackrest.go index a62f098a1..9f8bbebf2 100644 --- a/internal/pgbackrest/pgbackrest.go +++ b/internal/pgbackrest/pgbackrest.go @@ -22,6 +22,7 @@ import ( "io" "strings" + "github.com/crunchydata/postgres-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" "github.com/pkg/errors" ) @@ -51,7 +52,7 @@ type Executor func( // from running (with a config mismatch indicating that the pgBackRest configuration as stored in // the cluster's pgBackRest ConfigMap has not yet propagated to the Pod). func (exec Executor) StanzaCreateOrUpgrade(ctx context.Context, configHash string, - upgrade bool) (bool, error) { + upgrade bool, postgresCluster *v1beta1.PostgresCluster) (bool, error) { var stdout, stderr bytes.Buffer @@ -60,22 +61,44 @@ func (exec Executor) StanzaCreateOrUpgrade(ctx context.Context, configHash strin stanzaCmd = "upgrade" } + var reposWithVolumes []v1beta1.PGBackRestRepo + for _, repo := range postgresCluster.Spec.Backups.PGBackRest.Repos { + if repo.Volume != nil { + reposWithVolumes = append(reposWithVolumes, repo) + } + } + + grep := "grep %s-path /etc/pgbackrest/conf.d/pgbackrest_instance.conf" + + var checkRepoCmd string + if len(reposWithVolumes) > 0 { + repo := reposWithVolumes[0] + checkRepoCmd = checkRepoCmd + fmt.Sprintf(grep, repo.Name) + + reposWithVolumes = reposWithVolumes[1:] + for _, repo := range reposWithVolumes { + checkRepoCmd = checkRepoCmd + fmt.Sprintf(" && "+grep, repo.Name) + } + } + // this is the script that is run to create a stanza. First it checks the // "config-hash" file to ensure all configuration changes (e.g. from ConfigMaps) have // propagated to the container, and if not, it prints an error and returns with exit code 1). // Otherwise, it runs the pgbackrest command, which will either be "stanza-create" or // "stanza-upgrade", depending on the value of the boolean "upgrade" parameter. const script = ` -declare -r hash="$1" stanza="$2" message="$3" cmd="$4" +declare -r hash="$1" stanza="$2" message="$3" cmd="$4" check_repo_cmd="$5" if [[ "$(< /etc/pgbackrest/conf.d/config-hash)" != "${hash}" ]]; then printf >&2 "%s" "${message}"; exit 1; +elif ! bash -c "${check_repo_cmd}"; then + printf >&2 "%s" "${message}"; exit 1; else pgbackrest "${cmd}" --stanza="${stanza}" fi ` if err := exec(ctx, nil, &stdout, &stderr, "bash", "-ceu", "--", script, "-", configHash, DefaultStanzaName, errMsgConfigHashMismatch, - fmt.Sprintf("stanza-%s", stanzaCmd)); err != nil { + fmt.Sprintf("stanza-%s", stanzaCmd), checkRepoCmd); err != nil { errReturn := stderr.String() @@ -89,7 +112,7 @@ fi // if the err returned from pgbackrest command is about a version mismatch // then we should run upgrade rather than create if strings.Contains(errReturn, errMsgBackupDbMismatch) { - return exec.StanzaCreateOrUpgrade(ctx, configHash, true) + return exec.StanzaCreateOrUpgrade(ctx, configHash, true, postgresCluster) } // if none of the above errors, return the err diff --git a/internal/pgbackrest/pgbackrest_test.go b/internal/pgbackrest/pgbackrest_test.go index 0af8b2aab..bb285c290 100644 --- a/internal/pgbackrest/pgbackrest_test.go +++ b/internal/pgbackrest/pgbackrest_test.go @@ -24,8 +24,11 @@ import ( "testing" "gotest.tools/v3/assert" + "k8s.io/apimachinery/pkg/api/resource" "github.com/crunchydata/postgres-operator/internal/testing/require" + "github.com/crunchydata/postgres-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" + corev1 "k8s.io/api/core/v1" ) func TestStanzaCreateOrUpgrade(t *testing.T) { @@ -34,15 +37,19 @@ func TestStanzaCreateOrUpgrade(t *testing.T) { ctx := context.Background() configHash := "7f5d4d5bdc" expectedCommand := []string{"bash", "-ceu", "--", ` -declare -r hash="$1" stanza="$2" message="$3" cmd="$4" +declare -r hash="$1" stanza="$2" message="$3" cmd="$4" check_repo_cmd="$5" if [[ "$(< /etc/pgbackrest/conf.d/config-hash)" != "${hash}" ]]; then printf >&2 "%s" "${message}"; exit 1; +elif ! bash -c "${check_repo_cmd}"; then + printf >&2 "%s" "${message}"; exit 1; else pgbackrest "${cmd}" --stanza="${stanza}" fi `, "-", "7f5d4d5bdc", "db", "postgres operator error: pgBackRest config hash mismatch", - "stanza-create"} + "stanza-create", + "grep repo1-path /etc/pgbackrest/conf.d/pgbackrest_instance.conf", + } var shellCheckScript string stanzaExec := func(ctx context.Context, stdin io.Reader, stdout, stderr io.Writer, @@ -56,8 +63,36 @@ fi return nil } + postgresCluster := &v1beta1.PostgresCluster{ + Spec: v1beta1.PostgresClusterSpec{ + Backups: v1beta1.Backups{ + PGBackRest: v1beta1.PGBackRestArchive{ + Repos: []v1beta1.PGBackRestRepo{{ + Name: "repo1", + Volume: &v1beta1.RepoPVC{ + VolumeClaimSpec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteMany}, + Resources: corev1.VolumeResourceRequirements{ + Requests: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, { + Name: "repo2", + S3: &v1beta1.RepoS3{ + Bucket: "bucket", + Endpoint: "endpoint", + Region: "region", + }, + }}, + }, + }, + }, + } - configHashMismatch, err := Executor(stanzaExec).StanzaCreateOrUpgrade(ctx, configHash, false) + configHashMismatch, err := Executor(stanzaExec).StanzaCreateOrUpgrade(ctx, configHash, false, postgresCluster) assert.NilError(t, err) assert.Assert(t, !configHashMismatch) diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go index 2a4702d15..271eb37d4 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go @@ -21,7 +21,7 @@ package v1beta1 import ( corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" )