From a22d726877a05751fa6e972cea6ddfe77b234de9 Mon Sep 17 00:00:00 2001 From: andrewlecuyer Date: Fri, 13 Sep 2024 18:25:18 +0000 Subject: [PATCH 1/5] Adds the 'environment' Field to the PostgresCluster Spec An 'environment' field is now available within the PostgresCluster spec, which allows the user to specify the infrastructure and/or stage in development the PostgresCluster is associated with. Accepted values for this field are 'production' and 'development'. 'production' is the default. Additionally, a CEL validation rule has been added to the CRD that requires backups to be configured for 'production' PostgresCluster's. This change is fully backward compatible and non-breaking with existing PostgresCluster specs. Issue: PGO-1645 --- ...erator.crunchydata.com_postgresclusters.yaml | 17 +++++++++++++++++ .../v1beta1/postgrescluster_test.go | 2 ++ .../v1beta1/postgrescluster_types.go | 17 +++++++++++++++++ .../v1beta1/zz_generated.deepcopy.go | 5 +++++ 4 files changed, 41 insertions(+) diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 0550a17b94..18c15ba6ce 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -7599,6 +7599,19 @@ spec: scheduling constraints will be used in addition to any custom constraints provided. type: boolean + environment: + default: production + description: |- + Environment allows PGO to adapt its behavior according to the specific infrastructure + and/or stage of development the PostgresCluster is associated with. This includes + requiring and/or loosening the requirements for certain components and settings, while + also providing deeper insights, events and status that more closely align with + PostgresCluster's intended use. + Defaults to “production”. Acceptable values are "development" and "production". + enum: + - production + - development + type: string image: description: |- The image name to use for PostgreSQL containers. When omitted, the value @@ -16874,6 +16887,10 @@ spec: - instances - postgresVersion type: object + x-kubernetes-validations: + - message: Backups must be enabled for production PostgresCluster's. + rule: '(self.environment == ''production'') ? self.backups.pgbackrest + != null : true' status: description: PostgresClusterStatus defines the observed state of PostgresCluster properties: diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go index 83396902d0..70a1003174 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go @@ -43,6 +43,7 @@ spec: pgbackrest: repos: null config: {} + environment: production instances: null patroni: leaderLeaseDurationSeconds: 30 @@ -76,6 +77,7 @@ spec: pgbackrest: repos: null config: {} + environment: production instances: - dataVolumeClaimSpec: resources: {} diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index 5753171ed5..022f050bfd 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -13,6 +13,7 @@ import ( ) // PostgresClusterSpec defines the desired state of PostgresCluster +// +kubebuilder:validation:XValidation:rule="(self.environment == 'production') ? self.backups.pgbackrest != null : true", message="Backups must be enabled for production PostgresCluster's." type PostgresClusterSpec struct { // +optional Metadata *Metadata `json:"metadata,omitempty"` @@ -58,6 +59,17 @@ type PostgresClusterSpec struct { // +optional DisableDefaultPodScheduling *bool `json:"disableDefaultPodScheduling,omitempty"` + // Environment allows PGO to adapt its behavior according to the specific infrastructure + // and/or stage of development the PostgresCluster is associated with. This includes + // requiring and/or loosening the requirements for certain components and settings, while + // also providing deeper insights, events and status that more closely align with + // PostgresCluster's intended use. + // Defaults to “production”. Acceptable values are "development" and "production". + // +kubebuilder:validation:Enum={production,development} + // +kubebuilder:default=production + // +optional + Environment *string `json:"environment,omitempty"` + // The image name to use for PostgreSQL containers. When omitted, the value // comes from an operator environment variable. For standard PostgreSQL images, // the format is RELATED_IMAGE_POSTGRES_{postgresVersion}, @@ -305,6 +317,11 @@ func (s *PostgresClusterSpec) Default() { if s.UserInterface != nil { s.UserInterface.Default() } + + if s.Environment == nil { + s.Environment = new(string) + *s.Environment = "production" + } } // Backups defines a PostgreSQL archive configuration 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 fa32069d0f..777bbabdf3 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 @@ -1681,6 +1681,11 @@ func (in *PostgresClusterSpec) DeepCopyInto(out *PostgresClusterSpec) { *out = new(bool) **out = **in } + if in.Environment != nil { + in, out := &in.Environment, &out.Environment + *out = new(string) + **out = **in + } if in.ImagePullSecrets != nil { in, out := &in.ImagePullSecrets, &out.ImagePullSecrets *out = make([]corev1.LocalObjectReference, len(*in)) From a995cdd11e6802dbbd26ba2d1b425db4214c96b4 Mon Sep 17 00:00:00 2001 From: andrewlecuyer Date: Thu, 26 Sep 2024 17:32:49 +0000 Subject: [PATCH 2/5] Description & CEL Validation Updates for Environment Updates the description for 'PostgresCluster.spec.environment'. Also updates updates the CEL validation error message for 'environment', while also switching to has() vs. a null check for the associated validation rule. --- ...-operator.crunchydata.com_postgresclusters.yaml | 14 ++++++-------- .../v1beta1/postgrescluster_types.go | 10 ++++------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 18c15ba6ce..8911f051f5 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -7602,11 +7602,9 @@ spec: environment: default: production description: |- - Environment allows PGO to adapt its behavior according to the specific infrastructure - and/or stage of development the PostgresCluster is associated with. This includes - requiring and/or loosening the requirements for certain components and settings, while - also providing deeper insights, events and status that more closely align with - PostgresCluster's intended use. + Environment allows PGO to adapt its behavior according to the intended use of this cluster. + This includes adjusting requirements for different components, providing deeper insights, + and emitting events and status that better align with its purpose. Defaults to “production”. Acceptable values are "development" and "production". enum: - production @@ -16888,9 +16886,9 @@ spec: - postgresVersion type: object x-kubernetes-validations: - - message: Backups must be enabled for production PostgresCluster's. - rule: '(self.environment == ''production'') ? self.backups.pgbackrest - != null : true' + - message: Backups must be enabled in a production environment. + rule: '(self.environment == ''production'') ? has(self.backups.pgbackrest) + : true' status: description: PostgresClusterStatus defines the observed state of PostgresCluster properties: diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index 022f050bfd..4b23c9997e 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -13,7 +13,7 @@ import ( ) // PostgresClusterSpec defines the desired state of PostgresCluster -// +kubebuilder:validation:XValidation:rule="(self.environment == 'production') ? self.backups.pgbackrest != null : true", message="Backups must be enabled for production PostgresCluster's." +// +kubebuilder:validation:XValidation:rule="(self.environment == 'production') ? has(self.backups.pgbackrest) : true", message="Backups must be enabled in a production environment." type PostgresClusterSpec struct { // +optional Metadata *Metadata `json:"metadata,omitempty"` @@ -59,11 +59,9 @@ type PostgresClusterSpec struct { // +optional DisableDefaultPodScheduling *bool `json:"disableDefaultPodScheduling,omitempty"` - // Environment allows PGO to adapt its behavior according to the specific infrastructure - // and/or stage of development the PostgresCluster is associated with. This includes - // requiring and/or loosening the requirements for certain components and settings, while - // also providing deeper insights, events and status that more closely align with - // PostgresCluster's intended use. + // Environment allows PGO to adapt its behavior according to the intended use of this cluster. + // This includes adjusting requirements for different components, providing deeper insights, + // and emitting events and status that better align with its purpose. // Defaults to “production”. Acceptable values are "development" and "production". // +kubebuilder:validation:Enum={production,development} // +kubebuilder:default=production From ccdcaa42cb77350fae8f9bd9c3dc2c423b5ddd65 Mon Sep 17 00:00:00 2001 From: andrewlecuyer Date: Thu, 26 Sep 2024 21:44:40 +0000 Subject: [PATCH 3/5] Update Controller Gen to v0.16.3 Updates to the latest controller-gen release. CRD's and RBAC have been regenerated, and "namespace" has been removed from the markers in the Patroni and pgBackRest rbac.go files (it was no longer providing much benefit since the go code already cleanly organizes the RBAC, and changes to controller controller-gen had the potential to break RBAC generation as a result of its use). --- Makefile | 2 +- ...crunchydata.com_crunchybridgeclusters.yaml | 28 ++---- ...res-operator.crunchydata.com_pgadmins.yaml | 26 +----- ...s-operator.crunchydata.com_pgupgrades.yaml | 23 +---- ...ator.crunchydata.com_postgresclusters.yaml | 90 +++---------------- internal/patroni/rbac.go | 18 ++-- internal/pgbackrest/rbac.go | 4 +- 7 files changed, 37 insertions(+), 154 deletions(-) diff --git a/Makefile b/Makefile index b6e09d05d0..816ba20719 100644 --- a/Makefile +++ b/Makefile @@ -327,7 +327,7 @@ endef CONTROLLER ?= hack/tools/controller-gen tools: tools/controller-gen tools/controller-gen: - $(call go-get-tool,$(CONTROLLER),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.15.0) + $(call go-get-tool,$(CONTROLLER),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.16.3) ENVTEST ?= hack/tools/setup-envtest tools: tools/setup-envtest diff --git a/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml index 14b1fe1b2e..1219a36420 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_crunchybridgeclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.3 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -45,11 +45,7 @@ spec: to be managed by Crunchy Data Bridge properties: clusterName: - description: |- - The name of the cluster - --- - According to Bridge API/GUI errors, - "Field name should be between 5 and 50 characters in length, containing only unicode characters, unicode numbers, hyphens, spaces, or underscores, and starting with a character", and ending with a character or number. + description: The name of the cluster maxLength: 50 minLength: 5 pattern: ^[A-Za-z][A-Za-z0-9\-_ ]*[A-Za-z0-9]$ @@ -156,6 +152,7 @@ spec: - plan - provider - region + - secret - storage type: object status: @@ -166,16 +163,8 @@ spec: description: conditions represent the observations of postgres cluster's current state. items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: description: |- @@ -216,12 +205,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml index 4bcdce7f00..cb9652d94e 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgadmins.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.3 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -1003,14 +1003,11 @@ spec: ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. - Alpha, gated by the ClusterTrustBundleProjection feature gate. - ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. - Kubelet performs aggressive normalization of the PEM contents written into the pod filesystem. Esoteric PEM features such as inter-block comments and block headers are stripped. Certificates are deduplicated. @@ -1594,11 +1591,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -1822,16 +1817,8 @@ spec: conditions represent the observations of pgAdmin's current state. Known .status.conditions.type is: "PersistentVolumeResizing" items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: description: |- @@ -1872,12 +1859,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string diff --git a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml index c45526d179..74371e5587 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_pgupgrades.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.3 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -1028,11 +1028,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -1138,16 +1136,8 @@ spec: description: conditions represent the observations of PGUpgrade's current state. items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: description: |- @@ -1188,12 +1178,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index 8911f051f5..a007bae980 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.3 labels: app.kubernetes.io/name: pgo app.kubernetes.io/version: latest @@ -62,14 +62,11 @@ spec: ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. - Alpha, gated by the ClusterTrustBundleProjection feature gate. - ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. - Kubelet performs aggressive normalization of the PEM contents written into the pod filesystem. Esoteric PEM features such as inter-block comments and block headers are stripped. Certificates are deduplicated. @@ -1340,11 +1337,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -2428,11 +2423,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -2695,7 +2688,6 @@ spec: Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). items: type: string @@ -2735,7 +2727,6 @@ spec: Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | @@ -2753,7 +2744,6 @@ spec: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -2765,7 +2755,6 @@ spec: has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. - If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -4102,11 +4091,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -4210,11 +4197,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -4271,11 +4256,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -4347,14 +4330,11 @@ spec: ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. - Alpha, gated by the ClusterTrustBundleProjection feature gate. - ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. - Kubelet performs aggressive normalization of the PEM contents written into the pod filesystem. Esoteric PEM features such as inter-block comments and block headers are stripped. Certificates are deduplicated. @@ -5726,14 +5706,11 @@ spec: ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. - Alpha, gated by the ClusterTrustBundleProjection feature gate. - ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. - Kubelet performs aggressive normalization of the PEM contents written into the pod filesystem. Esoteric PEM features such as inter-block comments and block headers are stripped. Certificates are deduplicated. @@ -6352,11 +6329,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -7430,11 +7405,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -9062,11 +9035,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -9277,11 +9250,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -9430,11 +9403,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -9731,11 +9702,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -9950,10 +9921,8 @@ spec: RecursiveReadOnly specifies whether read-only mounts should be handled recursively. - If ReadOnly is false, this field has no meaning and must be unspecified. - If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this @@ -9961,11 +9930,9 @@ spec: supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. - If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). - If this field is not specified, it is treated as an equivalent of Disabled. type: string subPath: @@ -10255,11 +10222,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -10317,11 +10282,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -10702,7 +10665,6 @@ spec: Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). items: type: string @@ -10742,7 +10704,6 @@ spec: Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | @@ -10760,7 +10721,6 @@ spec: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -10772,7 +10732,6 @@ spec: has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. - If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -11069,14 +11028,11 @@ spec: ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. - Alpha, gated by the ClusterTrustBundleProjection feature gate. - ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. - Kubelet performs aggressive normalization of the PEM contents written into the pod filesystem. Esoteric PEM features such as inter-block comments and block headers are stripped. Certificates are deduplicated. @@ -11448,11 +11404,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -12569,14 +12523,11 @@ spec: ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. - Alpha, gated by the ClusterTrustBundleProjection feature gate. - ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. - Kubelet performs aggressive normalization of the PEM contents written into the pod filesystem. Esoteric PEM features such as inter-block comments and block headers are stripped. Certificates are deduplicated. @@ -13377,11 +13328,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -13592,11 +13543,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -13745,11 +13696,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -14047,11 +13996,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -14267,10 +14216,8 @@ spec: RecursiveReadOnly specifies whether read-only mounts should be handled recursively. - If ReadOnly is false, this field has no meaning and must be unspecified. - If ReadOnly is true, and this field is set to Disabled, the mount is not made recursively read-only. If this field is set to IfPossible, the mount is made recursively read-only, if it is supported by the container runtime. If this @@ -14278,11 +14225,9 @@ spec: supported by the container runtime, otherwise the pod will not be started and an error will be generated to indicate the reason. - If this field is set to IfPossible or Enabled, MountPropagation must be set to None (or be unspecified, which defaults to None). - If this field is not specified, it is treated as an equivalent of Disabled. type: string subPath: @@ -14430,11 +14375,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -14536,11 +14479,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -14697,7 +14638,6 @@ spec: Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). items: type: string @@ -14737,7 +14677,6 @@ spec: Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | @@ -14755,7 +14694,6 @@ spec: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -14767,7 +14705,6 @@ spec: has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. - If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -15911,14 +15848,11 @@ spec: ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. - Alpha, gated by the ClusterTrustBundleProjection feature gate. - ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. - Kubelet performs aggressive normalization of the PEM contents written into the pod filesystem. Esoteric PEM features such as inter-block comments and block headers are stripped. Certificates are deduplicated. @@ -16492,11 +16426,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -16693,7 +16625,6 @@ spec: Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). items: type: string @@ -16733,7 +16664,6 @@ spec: Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | @@ -16751,7 +16681,6 @@ spec: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -16763,7 +16692,6 @@ spec: has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. - If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -17215,6 +17143,10 @@ spec: type: description: The pgBackRest backup type for this Job type: string + required: + - cronJobName + - repo + - type type: object type: array type: object diff --git a/internal/patroni/rbac.go b/internal/patroni/rbac.go index f1e55b1137..dcf3f18cea 100644 --- a/internal/patroni/rbac.go +++ b/internal/patroni/rbac.go @@ -12,25 +12,25 @@ import ( ) // "list", "patch", and "watch" are required. Include "get" for good measure. -// +kubebuilder:rbac:namespace=patroni,groups="",resources="pods",verbs={get} -// +kubebuilder:rbac:namespace=patroni,groups="",resources="pods",verbs={list,watch} -// +kubebuilder:rbac:namespace=patroni,groups="",resources="pods",verbs={patch} +// +kubebuilder:rbac:groups="",resources="pods",verbs={get} +// +kubebuilder:rbac:groups="",resources="pods",verbs={list,watch} +// +kubebuilder:rbac:groups="",resources="pods",verbs={patch} // TODO(cbandy): Separate these so that one can choose ConfigMap over Endpoints. // When using Endpoints for DCS, "create", "list", "patch", and "watch" are // required. Include "get" for good measure. The `patronictl scaffold` and // `patronictl remove` commands require "deletecollection". -// +kubebuilder:rbac:namespace=patroni,groups="",resources="endpoints",verbs={get} -// +kubebuilder:rbac:namespace=patroni,groups="",resources="endpoints",verbs={create,deletecollection} -// +kubebuilder:rbac:namespace=patroni,groups="",resources="endpoints",verbs={list,watch} -// +kubebuilder:rbac:namespace=patroni,groups="",resources="endpoints",verbs={patch} -// +kubebuilder:rbac:namespace=patroni,groups="",resources="services",verbs={create} +// +kubebuilder:rbac:groups="",resources="endpoints",verbs={get} +// +kubebuilder:rbac:groups="",resources="endpoints",verbs={create,deletecollection} +// +kubebuilder:rbac:groups="",resources="endpoints",verbs={list,watch} +// +kubebuilder:rbac:groups="",resources="endpoints",verbs={patch} +// +kubebuilder:rbac:groups="",resources="services",verbs={create} // The OpenShift RestrictedEndpointsAdmission plugin requires special // authorization to create Endpoints that contain Pod IPs. // - https://github.com/openshift/origin/pull/9383 -// +kubebuilder:rbac:namespace=patroni,groups="",resources="endpoints/restricted",verbs={create} +// +kubebuilder:rbac:groups="",resources="endpoints/restricted",verbs={create} // Permissions returns the RBAC rules Patroni needs for cluster. func Permissions(cluster *v1beta1.PostgresCluster) []rbacv1.PolicyRule { diff --git a/internal/pgbackrest/rbac.go b/internal/pgbackrest/rbac.go index 56e8d27986..e525d9741c 100644 --- a/internal/pgbackrest/rbac.go +++ b/internal/pgbackrest/rbac.go @@ -11,8 +11,8 @@ import ( "github.com/crunchydata/postgres-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1" ) -// +kubebuilder:rbac:namespace=pgbackrest,groups="",resources="pods",verbs={list} -// +kubebuilder:rbac:namespace=pgbackrest,groups="",resources="pods/exec",verbs={create} +// +kubebuilder:groups="",resources="pods",verbs={list} +// +kubebuilder:groups="",resources="pods/exec",verbs={create} // Permissions returns the RBAC rules pgBackRest needs for a cluster. func Permissions(cluster *v1beta1.PostgresCluster) []rbacv1.PolicyRule { From e0fb9bdbd645b522154b931fa415cc54eb743276 Mon Sep 17 00:00:00 2001 From: andrewlecuyer Date: Thu, 26 Sep 2024 22:07:11 +0000 Subject: [PATCH 4/5] Cleanup environment Validation Rule and Add fieldPath & reason Updates the validation rule for environment to make the error message consistent across missing and empty 'backup' sections. Additionally, adds "fieldPath" and "reason" to the CEL validation marker. --- ...ostgres-operator.crunchydata.com_postgresclusters.yaml | 8 +++++--- .../v1beta1/postgrescluster_types.go | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index a007bae980..e339306cb5 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -16814,9 +16814,11 @@ spec: - postgresVersion type: object x-kubernetes-validations: - - message: Backups must be enabled in a production environment. - rule: '(self.environment == ''production'') ? has(self.backups.pgbackrest) - : true' + - fieldPath: .backups + message: Backups must be enabled in a production environment. + reason: FieldValueRequired + rule: '(self.environment == ''production'') ? (has(self.backups) && + has(self.backups.pgbackrest)) : true' status: description: PostgresClusterStatus defines the observed state of PostgresCluster properties: diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index 4b23c9997e..3773e97b7a 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -13,7 +13,7 @@ import ( ) // PostgresClusterSpec defines the desired state of PostgresCluster -// +kubebuilder:validation:XValidation:rule="(self.environment == 'production') ? has(self.backups.pgbackrest) : true", message="Backups must be enabled in a production environment." +// +kubebuilder:validation:XValidation:rule="(self.environment == 'production') ? (has(self.backups) && has(self.backups.pgbackrest)) : true", message="Backups must be enabled in a production environment.",fieldPath=".backups",reason="FieldValueRequired" type PostgresClusterSpec struct { // +optional Metadata *Metadata `json:"metadata,omitempty"` From 049007c9399c76e90ec63bb009055e4ab0e35295 Mon Sep 17 00:00:00 2001 From: andrewlecuyer Date: Fri, 27 Sep 2024 20:01:27 +0000 Subject: [PATCH 5/5] Update Validation for 'environment' and 'backups' 'pgbackrest' is now required when 'spec.backups' is provided. Additionally, the CEL validation rule to make backups required in production environments no longer checks for 'pgbackrest'. Although there is no functional difference with this change, it better aligns backup API behavior/validation with the backups portion of the spec. Additionally, 'fieldPath' and 'reason' have been removed from CEL validation since they are only supported in Kubernetes v1.28+. --- ...stgres-operator.crunchydata.com_postgresclusters.yaml | 9 ++++----- .../v1beta1/postgrescluster_types.go | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml index e339306cb5..2f8ff2a2e0 100644 --- a/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml +++ b/config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml @@ -4317,6 +4317,8 @@ spec: required: - volumeSnapshotClassName type: object + required: + - pgbackrest type: object config: properties: @@ -16814,11 +16816,8 @@ spec: - postgresVersion type: object x-kubernetes-validations: - - fieldPath: .backups - message: Backups must be enabled in a production environment. - reason: FieldValueRequired - rule: '(self.environment == ''production'') ? (has(self.backups) && - has(self.backups.pgbackrest)) : true' + - message: Backups must be enabled in a production environment. + rule: '(self.environment == ''production'') ? has(self.backups) : true' status: description: PostgresClusterStatus defines the observed state of PostgresCluster properties: diff --git a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go index 3773e97b7a..e306b6210b 100644 --- a/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go +++ b/pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go @@ -13,7 +13,7 @@ import ( ) // PostgresClusterSpec defines the desired state of PostgresCluster -// +kubebuilder:validation:XValidation:rule="(self.environment == 'production') ? (has(self.backups) && has(self.backups.pgbackrest)) : true", message="Backups must be enabled in a production environment.",fieldPath=".backups",reason="FieldValueRequired" +// +kubebuilder:validation:XValidation:rule="(self.environment == 'production') ? has(self.backups) : true", message="Backups must be enabled in a production environment." type PostgresClusterSpec struct { // +optional Metadata *Metadata `json:"metadata,omitempty"` @@ -326,7 +326,6 @@ func (s *PostgresClusterSpec) Default() { type Backups struct { // pgBackRest archive configuration - // +optional PGBackRest PGBackRestArchive `json:"pgbackrest"` // VolumeSnapshot configuration