From af2d0f7d920c7acbf42f96ce046246e590091149 Mon Sep 17 00:00:00 2001
From: Felix Kunde <felix-kunde@gmx.de>
Date: Wed, 3 Jul 2024 17:27:00 +0200
Subject: [PATCH] block automatic major version upgrade with annotation for
 single cluster

---
 charts/postgres-operator/crds/operatorconfigurations.yaml | 2 ++
 charts/postgres-operator/values.yaml                      | 3 +++
 docs/reference/operator_parameters.md                     | 8 ++++++++
 manifests/configmap.yaml                                  | 1 +
 manifests/operatorconfiguration.crd.yaml                  | 2 ++
 manifests/postgresql-operator-default-configuration.yaml  | 1 +
 pkg/apis/acid.zalan.do/v1/crds.go                         | 3 +++
 pkg/apis/acid.zalan.do/v1/operator_configuration_type.go  | 1 +
 pkg/cluster/majorversionupgrade.go                        | 7 +++++++
 pkg/controller/operator_config.go                         | 1 +
 pkg/util/config/config.go                                 | 1 +
 11 files changed, 30 insertions(+)

diff --git a/charts/postgres-operator/crds/operatorconfigurations.yaml b/charts/postgres-operator/crds/operatorconfigurations.yaml
index bf4ae34b..0c6c1517 100644
--- a/charts/postgres-operator/crds/operatorconfigurations.yaml
+++ b/charts/postgres-operator/crds/operatorconfigurations.yaml
@@ -158,6 +158,8 @@ spec:
               major_version_upgrade:
                 type: object
                 properties:
+                  ignore_auto_version_upgrade_key:
+                    type: string
                   major_version_upgrade_mode:
                     type: string
                     default: "off"
diff --git a/charts/postgres-operator/values.yaml b/charts/postgres-operator/values.yaml
index 5700ff78..0bc669e1 100644
--- a/charts/postgres-operator/values.yaml
+++ b/charts/postgres-operator/values.yaml
@@ -82,6 +82,9 @@ configUsers:
   super_username: postgres
 
 configMajorVersionUpgrade:
+  # key name for annotation to ignore globally enabled major version upgrades
+  # ignore_auto_version_upgrade_key: ""
+
   # "off": no upgrade, "manual": manifest triggers action, "full": minimal version violation triggers too
   major_version_upgrade_mode: "off"
   # upgrades will only be carried out for clusters of listed teams when mode is "off"
diff --git a/docs/reference/operator_parameters.md b/docs/reference/operator_parameters.md
index 1474c5bb..d365e0c8 100644
--- a/docs/reference/operator_parameters.md
+++ b/docs/reference/operator_parameters.md
@@ -257,6 +257,14 @@ CRD-configuration, they are grouped under the `major_version_upgrade` key.
   which violate the configured allowed `minimal_major_version` when
   `major_version_upgrade_mode` is set to `"full"`. The default is `"16"`.
 
+* **ignore_auto_version_upgrade_key**
+  Even if automatic major version upgrades are generally desired for most
+  clusters there might be exceptions where you want to be under full control
+  of the starting time to execute the upgrade script in Spilo manually.
+  With this option you can define an annotation key that can be used as a
+  toggle in cluster manifests to ignore globally enabled (or allowed per team)
+  automatic major version upgrade. The default is empty.
+
 ## Kubernetes resources
 
 Parameters to configure cluster-related Kubernetes objects created by the
diff --git a/manifests/configmap.yaml b/manifests/configmap.yaml
index 7f76d0b3..e7070f55 100644
--- a/manifests/configmap.yaml
+++ b/manifests/configmap.yaml
@@ -72,6 +72,7 @@ data:
   # ignored_annotations: ""
   # infrastructure_roles_secret_name: "postgresql-infrastructure-roles"
   # infrastructure_roles_secrets: "secretname:monitoring-roles,userkey:user,passwordkey:password,rolekey:inrole"
+  # ignore_auto_version_upgrade_key: ""
   # ignore_instance_limits_annotation_key: ""
   # inherited_annotations: owned-by
   # inherited_labels: application,environment
diff --git a/manifests/operatorconfiguration.crd.yaml b/manifests/operatorconfiguration.crd.yaml
index 88757794..3dbb4a64 100644
--- a/manifests/operatorconfiguration.crd.yaml
+++ b/manifests/operatorconfiguration.crd.yaml
@@ -156,6 +156,8 @@ spec:
               major_version_upgrade:
                 type: object
                 properties:
+                  ignore_auto_version_upgrade_key:
+                    type: string
                   major_version_upgrade_mode:
                     type: string
                     default: "off"
diff --git a/manifests/postgresql-operator-default-configuration.yaml b/manifests/postgresql-operator-default-configuration.yaml
index ee3123e3..c213dd04 100644
--- a/manifests/postgresql-operator-default-configuration.yaml
+++ b/manifests/postgresql-operator-default-configuration.yaml
@@ -36,6 +36,7 @@ configuration:
     replication_username: standby
     super_username: postgres
   major_version_upgrade:
+    # ignore_auto_version_upgrade_key: ""
     major_version_upgrade_mode: "off"
     # major_version_upgrade_team_allow_list:
     # - acid
diff --git a/pkg/apis/acid.zalan.do/v1/crds.go b/pkg/apis/acid.zalan.do/v1/crds.go
index 9e65869e..71b35907 100644
--- a/pkg/apis/acid.zalan.do/v1/crds.go
+++ b/pkg/apis/acid.zalan.do/v1/crds.go
@@ -1254,6 +1254,9 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{
 					"major_version_upgrade": {
 						Type: "object",
 						Properties: map[string]apiextv1.JSONSchemaProps{
+							"ignore_auto_version_upgrade_key": {
+								Type: "string",
+							},
 							"major_version_upgrade_mode": {
 								Type: "string",
 							},
diff --git a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go
index 48fd0a13..d53c6b94 100644
--- a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go
+++ b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go
@@ -47,6 +47,7 @@ type PostgresUsersConfiguration struct {
 
 // MajorVersionUpgradeConfiguration defines how to execute major version upgrades of Postgres.
 type MajorVersionUpgradeConfiguration struct {
+	IgnoreAutoVersionUpgradeKey      string   `json:"ignore_auto_version_upgrade_key,omitempty"`
 	MajorVersionUpgradeMode          string   `json:"major_version_upgrade_mode" default:"off"` // off - no actions, manual - manifest triggers action, full - manifest and minimal version violation trigger upgrade
 	MajorVersionUpgradeTeamAllowList []string `json:"major_version_upgrade_team_allow_list,omitempty"`
 	MinimalMajorVersion              string   `json:"minimal_major_version" default:"12"`
diff --git a/pkg/cluster/majorversionupgrade.go b/pkg/cluster/majorversionupgrade.go
index 5a1599cd..32707992 100644
--- a/pkg/cluster/majorversionupgrade.go
+++ b/pkg/cluster/majorversionupgrade.go
@@ -67,6 +67,13 @@ func (c *Cluster) majorVersionUpgrade() error {
 		return nil
 	}
 
+	ignoreAutoVersionUpgradeKey := c.OpConfig.IgnoreAutoVersionUpgradeKey
+	if ignoreAutoVersionUpgradeKey != "" {
+		if value, exists := c.ObjectMeta.Annotations[ignoreAutoVersionUpgradeKey]; exists && value == "true" {
+			return nil
+		}
+	}
+
 	desiredVersion := c.GetDesiredMajorVersionAsInt()
 
 	if c.currentMajorVersion >= desiredVersion {
diff --git a/pkg/controller/operator_config.go b/pkg/controller/operator_config.go
index 88f1d73c..40bb23c2 100644
--- a/pkg/controller/operator_config.go
+++ b/pkg/controller/operator_config.go
@@ -60,6 +60,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
 	result.PasswordRotationUserRetention = util.CoalesceUInt32(fromCRD.PostgresUsersConfiguration.DeepCopy().PasswordRotationUserRetention, 180)
 
 	// major version upgrade config
+	result.IgnoreAutoVersionUpgradeKey = fromCRD.MajorVersionUpgrade.IgnoreAutoVersionUpgradeKey
 	result.MajorVersionUpgradeMode = util.Coalesce(fromCRD.MajorVersionUpgrade.MajorVersionUpgradeMode, "off")
 	result.MajorVersionUpgradeTeamAllowList = fromCRD.MajorVersionUpgrade.MajorVersionUpgradeTeamAllowList
 	result.MinimalMajorVersion = util.Coalesce(fromCRD.MajorVersionUpgrade.MinimalMajorVersion, "12")
diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go
index 829c1d19..e802a476 100644
--- a/pkg/util/config/config.go
+++ b/pkg/util/config/config.go
@@ -243,6 +243,7 @@ type Config struct {
 	EnablePgVersionEnvVar                    bool              `name:"enable_pgversion_env_var" default:"true"`
 	EnableSpiloWalPathCompat                 bool              `name:"enable_spilo_wal_path_compat" default:"false"`
 	EnableTeamIdClusternamePrefix            bool              `name:"enable_team_id_clustername_prefix" default:"false"`
+	IgnoreAutoVersionUpgradeKey              string            `name:"ignore_auto_version_upgrade_key"`
 	MajorVersionUpgradeMode                  string            `name:"major_version_upgrade_mode" default:"off"`
 	MajorVersionUpgradeTeamAllowList         []string          `name:"major_version_upgrade_team_allow_list" default:""`
 	MinimalMajorVersion                      string            `name:"minimal_major_version" default:"12"`
-- 
GitLab