Merge branch 'master' into add-topologySpreadConstraints
This commit is contained in:
		
						commit
						3a8fc1b259
					
				|  | @ -195,12 +195,14 @@ from numerous escape characters in the latter log entry, view it in CLI with | ||||||
| used internally in K8s. | used internally in K8s. | ||||||
| 
 | 
 | ||||||
| The StatefulSet is replaced if the following properties change: | The StatefulSet is replaced if the following properties change: | ||||||
|  | 
 | ||||||
| - annotations | - annotations | ||||||
| - volumeClaimTemplates | - volumeClaimTemplates | ||||||
| - template volumes | - template volumes | ||||||
| 
 | 
 | ||||||
| The StatefulSet is replaced and a rolling updates is triggered if the following | The StatefulSet is replaced and a rolling updates is triggered if the following | ||||||
| properties differ between the old and new state: | properties differ between the old and new state: | ||||||
|  | 
 | ||||||
| - container name, ports, image, resources, env, envFrom, securityContext and volumeMounts | - container name, ports, image, resources, env, envFrom, securityContext and volumeMounts | ||||||
| - template labels, annotations, service account, securityContext, affinity, priority class and termination grace period | - template labels, annotations, service account, securityContext, affinity, priority class and termination grace period | ||||||
| 
 | 
 | ||||||
|  | @ -898,6 +900,7 @@ services: | ||||||
| There are multiple options to specify service annotations that will be merged | There are multiple options to specify service annotations that will be merged | ||||||
| with each other and override in the following order (where latter take | with each other and override in the following order (where latter take | ||||||
| precedence): | precedence): | ||||||
|  | 
 | ||||||
| 1. Default annotations if LoadBalancer is enabled | 1. Default annotations if LoadBalancer is enabled | ||||||
| 2. Globally configured `custom_service_annotations` | 2. Globally configured `custom_service_annotations` | ||||||
| 3. `serviceAnnotations` specified in the cluster manifest | 3. `serviceAnnotations` specified in the cluster manifest | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ under the ~/go/src sub directories. | ||||||
| 
 | 
 | ||||||
| Given the schema above, the Postgres Operator source code located at | Given the schema above, the Postgres Operator source code located at | ||||||
| `github.com/zalando/postgres-operator` should be put at | `github.com/zalando/postgres-operator` should be put at | ||||||
| -`~/go/src/github.com/zalando/postgres-operator`. | `~/go/src/github.com/zalando/postgres-operator`. | ||||||
| 
 | 
 | ||||||
| ```bash | ```bash | ||||||
| export GOPATH=~/go | export GOPATH=~/go | ||||||
|  | @ -105,6 +105,7 @@ and K8s-like APIs for its custom resource definitions, namely the | ||||||
| Postgres CRD and the operator CRD. The usage of the code generation follows | Postgres CRD and the operator CRD. The usage of the code generation follows | ||||||
| conventions from the K8s community. Relevant scripts live in the `hack` | conventions from the K8s community. Relevant scripts live in the `hack` | ||||||
| directory: | directory: | ||||||
|  | 
 | ||||||
| * `update-codegen.sh` triggers code generation for the APIs defined in `pkg/apis/acid.zalan.do/`, | * `update-codegen.sh` triggers code generation for the APIs defined in `pkg/apis/acid.zalan.do/`, | ||||||
| * `verify-codegen.sh` checks if the generated code is up-to-date (to be used within CI). | * `verify-codegen.sh` checks if the generated code is up-to-date (to be used within CI). | ||||||
| 
 | 
 | ||||||
|  | @ -112,6 +113,7 @@ The `/pkg/generated/` contains the resultant code. To make these scripts work, | ||||||
| you may need to `export GOPATH=$(go env GOPATH)` | you may need to `export GOPATH=$(go env GOPATH)` | ||||||
| 
 | 
 | ||||||
| References for code generation are: | References for code generation are: | ||||||
|  | 
 | ||||||
| * [Relevant pull request](https://github.com/zalando/postgres-operator/pull/369) | * [Relevant pull request](https://github.com/zalando/postgres-operator/pull/369) | ||||||
| See comments there for minor issues that can sometimes broke the generation process. | See comments there for minor issues that can sometimes broke the generation process. | ||||||
| * [Code generator source code](https://github.com/kubernetes/code-generator) | * [Code generator source code](https://github.com/kubernetes/code-generator) | ||||||
|  | @ -315,6 +317,7 @@ precedence. | ||||||
| 
 | 
 | ||||||
| Update the following Go files that obtain the configuration parameter from the | Update the following Go files that obtain the configuration parameter from the | ||||||
| manifest files: | manifest files: | ||||||
|  | 
 | ||||||
| * [operator_configuration_type.go](https://github.com/zalando/postgres-operator/blob/master/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go) | * [operator_configuration_type.go](https://github.com/zalando/postgres-operator/blob/master/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go) | ||||||
| * [operator_config.go](https://github.com/zalando/postgres-operator/blob/master/pkg/controller/operator_config.go) | * [operator_config.go](https://github.com/zalando/postgres-operator/blob/master/pkg/controller/operator_config.go) | ||||||
| * [config.go](https://github.com/zalando/postgres-operator/blob/master/pkg/util/config/config.go) | * [config.go](https://github.com/zalando/postgres-operator/blob/master/pkg/util/config/config.go) | ||||||
|  | @ -323,6 +326,7 @@ Postgres manifest parameters are defined in the [api package](https://github.com | ||||||
| The operator behavior has to be implemented at least in [k8sres.go](https://github.com/zalando/postgres-operator/blob/master/pkg/cluster/k8sres.go). | The operator behavior has to be implemented at least in [k8sres.go](https://github.com/zalando/postgres-operator/blob/master/pkg/cluster/k8sres.go). | ||||||
| Validation of CRD parameters is controlled in [crds.go](https://github.com/zalando/postgres-operator/blob/master/pkg/apis/acid.zalan.do/v1/crds.go). | Validation of CRD parameters is controlled in [crds.go](https://github.com/zalando/postgres-operator/blob/master/pkg/apis/acid.zalan.do/v1/crds.go). | ||||||
| Please, reflect your changes in tests, for example in: | Please, reflect your changes in tests, for example in: | ||||||
|  | 
 | ||||||
| * [config_test.go](https://github.com/zalando/postgres-operator/blob/master/pkg/util/config/config_test.go) | * [config_test.go](https://github.com/zalando/postgres-operator/blob/master/pkg/util/config/config_test.go) | ||||||
| * [k8sres_test.go](https://github.com/zalando/postgres-operator/blob/master/pkg/cluster/k8sres_test.go) | * [k8sres_test.go](https://github.com/zalando/postgres-operator/blob/master/pkg/cluster/k8sres_test.go) | ||||||
| * [util_test.go](https://github.com/zalando/postgres-operator/blob/master/pkg/apis/acid.zalan.do/v1/util_test.go) | * [util_test.go](https://github.com/zalando/postgres-operator/blob/master/pkg/apis/acid.zalan.do/v1/util_test.go) | ||||||
|  | @ -330,6 +334,7 @@ Please, reflect your changes in tests, for example in: | ||||||
| ### Updating manifest files | ### Updating manifest files | ||||||
| 
 | 
 | ||||||
| For the CRD-based configuration, please update the following files: | For the CRD-based configuration, please update the following files: | ||||||
|  | 
 | ||||||
| * the default [OperatorConfiguration](https://github.com/zalando/postgres-operator/blob/master/manifests/postgresql-operator-default-configuration.yaml) | * the default [OperatorConfiguration](https://github.com/zalando/postgres-operator/blob/master/manifests/postgresql-operator-default-configuration.yaml) | ||||||
| * the CRD's [validation](https://github.com/zalando/postgres-operator/blob/master/manifests/operatorconfiguration.crd.yaml) | * the CRD's [validation](https://github.com/zalando/postgres-operator/blob/master/manifests/operatorconfiguration.crd.yaml) | ||||||
| * the CRD's validation in the [Helm chart](https://github.com/zalando/postgres-operator/blob/master/charts/postgres-operator/crds/operatorconfigurations.yaml) | * the CRD's validation in the [Helm chart](https://github.com/zalando/postgres-operator/blob/master/charts/postgres-operator/crds/operatorconfigurations.yaml) | ||||||
|  | @ -342,6 +347,7 @@ Last but no least, update the [ConfigMap](https://github.com/zalando/postgres-op | ||||||
| 
 | 
 | ||||||
| Finally, add a section for each new configuration option and/or cluster manifest | Finally, add a section for each new configuration option and/or cluster manifest | ||||||
| parameter in the reference documents: | parameter in the reference documents: | ||||||
|  | 
 | ||||||
| * [config reference](reference/operator_parameters.md) | * [config reference](reference/operator_parameters.md) | ||||||
| * [manifest reference](reference/cluster_manifest.md) | * [manifest reference](reference/cluster_manifest.md) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ hence set it up first. For local tests we recommend to use one of the following | ||||||
| solutions: | solutions: | ||||||
| 
 | 
 | ||||||
| * [minikube](https://github.com/kubernetes/minikube/releases), which creates a | * [minikube](https://github.com/kubernetes/minikube/releases), which creates a | ||||||
|   single-node K8s cluster inside a VM (requires KVM or VirtualBox), |   K8s cluster inside a container or VM (requires Docker, KVM, Hyper-V, HyperKit, VirtualBox, or similar), | ||||||
| * [kind](https://kind.sigs.k8s.io/) and [k3d](https://k3d.io), which allows creating multi-nodes K8s | * [kind](https://kind.sigs.k8s.io/) and [k3d](https://k3d.io), which allows creating multi-nodes K8s | ||||||
|   clusters running on Docker (requires Docker) |   clusters running on Docker (requires Docker) | ||||||
| 
 | 
 | ||||||
|  | @ -20,7 +20,7 @@ This quickstart assumes that you have started minikube or created a local kind | ||||||
| cluster. Note that you can also use built-in K8s support in the Docker Desktop | cluster. Note that you can also use built-in K8s support in the Docker Desktop | ||||||
| for Mac to follow the steps of this tutorial. You would have to replace | for Mac to follow the steps of this tutorial. You would have to replace | ||||||
| `minikube start` and `minikube delete` with your launch actions for the Docker | `minikube start` and `minikube delete` with your launch actions for the Docker | ||||||
| built-in K8s support. | Desktop built-in K8s support. | ||||||
| 
 | 
 | ||||||
| ## Configuration Options | ## Configuration Options | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -107,8 +107,13 @@ Those are top-level keys, containing both leaf keys and groups. | ||||||
| * **kubernetes_use_configmaps** | * **kubernetes_use_configmaps** | ||||||
|   Select if setup uses endpoints (default), or configmaps to manage leader when |   Select if setup uses endpoints (default), or configmaps to manage leader when | ||||||
|   DCS is kubernetes (not etcd or similar). In OpenShift it is not possible to |   DCS is kubernetes (not etcd or similar). In OpenShift it is not possible to | ||||||
|   use endpoints option, and configmaps is required. By default, |   use endpoints option, and configmaps is required. Starting with K8s 1.33, | ||||||
|   `kubernetes_use_configmaps: false`, meaning endpoints will be used. |   endpoints are marked as deprecated. It's recommended to switch to config maps | ||||||
|  |   instead. But, to do so make sure you scale the Postgres cluster down to just | ||||||
|  |   one primary pod (e.g. using `max_instances` option). Otherwise, you risk | ||||||
|  |   running into a split-brain scenario. | ||||||
|  |   By default, `kubernetes_use_configmaps: false`, meaning endpoints will be used. | ||||||
|  |   Starting from v1.16.0 the default will be changed to `true`. | ||||||
| 
 | 
 | ||||||
| * **docker_image** | * **docker_image** | ||||||
|   Spilo Docker image for Postgres instances. For production, don't rely on the |   Spilo Docker image for Postgres instances. For production, don't rely on the | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										6
									
								
								go.mod
								
								
								
								
							|  | @ -3,6 +3,7 @@ module github.com/zalando/postgres-operator | ||||||
| go 1.25.0 | go 1.25.0 | ||||||
| 
 | 
 | ||||||
| require ( | require ( | ||||||
|  | 	github.com/Masterminds/semver v1.5.0 | ||||||
| 	github.com/aws/aws-sdk-go v1.53.8 | 	github.com/aws/aws-sdk-go v1.53.8 | ||||||
| 	github.com/golang/mock v1.6.0 | 	github.com/golang/mock v1.6.0 | ||||||
| 	github.com/lib/pq v1.10.9 | 	github.com/lib/pq v1.10.9 | ||||||
|  | @ -12,7 +13,6 @@ require ( | ||||||
| 	github.com/sirupsen/logrus v1.9.3 | 	github.com/sirupsen/logrus v1.9.3 | ||||||
| 	github.com/stretchr/testify v1.9.0 | 	github.com/stretchr/testify v1.9.0 | ||||||
| 	golang.org/x/crypto v0.41.0 | 	golang.org/x/crypto v0.41.0 | ||||||
| 	golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 |  | ||||||
| 	gopkg.in/yaml.v2 v2.4.0 | 	gopkg.in/yaml.v2 v2.4.0 | ||||||
| 	k8s.io/api v0.30.4 | 	k8s.io/api v0.30.4 | ||||||
| 	k8s.io/apiextensions-apiserver v0.25.9 | 	k8s.io/apiextensions-apiserver v0.25.9 | ||||||
|  | @ -21,10 +21,7 @@ require ( | ||||||
| 	k8s.io/code-generator v0.25.9 | 	k8s.io/code-generator v0.25.9 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| require golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect |  | ||||||
| 
 |  | ||||||
| require ( | require ( | ||||||
| 	github.com/Masterminds/semver v1.5.0 |  | ||||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||||
| 	github.com/emicklei/go-restful/v3 v3.11.0 // indirect | 	github.com/emicklei/go-restful/v3 v3.11.0 // indirect | ||||||
| 	github.com/evanphx/json-patch v4.12.0+incompatible // indirect | 	github.com/evanphx/json-patch v4.12.0+incompatible // indirect | ||||||
|  | @ -62,6 +59,7 @@ require ( | ||||||
| 	golang.org/x/text v0.28.0 // indirect | 	golang.org/x/text v0.28.0 // indirect | ||||||
| 	golang.org/x/time v0.3.0 // indirect | 	golang.org/x/time v0.3.0 // indirect | ||||||
| 	golang.org/x/tools v0.36.0 // indirect | 	golang.org/x/tools v0.36.0 // indirect | ||||||
|  | 	golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect | ||||||
| 	google.golang.org/appengine v1.6.7 // indirect | 	google.golang.org/appengine v1.6.7 // indirect | ||||||
| 	google.golang.org/protobuf v1.33.0 // indirect | 	google.golang.org/protobuf v1.33.0 // indirect | ||||||
| 	gopkg.in/inf.v0 v0.9.1 // indirect | 	gopkg.in/inf.v0 v0.9.1 // indirect | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										2
									
								
								go.sum
								
								
								
								
							|  | @ -121,8 +121,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U | ||||||
| golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||||
| golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= | golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= | ||||||
| golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= | golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= | ||||||
| golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= |  | ||||||
| golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= |  | ||||||
| golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||||
| golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||||
| golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||||
|  |  | ||||||
|  | @ -122,7 +122,21 @@ function aws_upload { | ||||||
| function gcs_upload { | function gcs_upload { | ||||||
|     PATH_TO_BACKUP=gs://$LOGICAL_BACKUP_S3_BUCKET"/"$LOGICAL_BACKUP_S3_BUCKET_PREFIX"/"$SCOPE$LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX"/logical_backups/"$(date +%s).sql.gz |     PATH_TO_BACKUP=gs://$LOGICAL_BACKUP_S3_BUCKET"/"$LOGICAL_BACKUP_S3_BUCKET_PREFIX"/"$SCOPE$LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX"/logical_backups/"$(date +%s).sql.gz | ||||||
| 
 | 
 | ||||||
|     gsutil -o Credentials:gs_service_key_file=$LOGICAL_BACKUP_GOOGLE_APPLICATION_CREDENTIALS cp - "$PATH_TO_BACKUP" |     #Set local LOGICAL_GOOGLE_APPLICATION_CREDENTIALS to nothing or | ||||||
|  |     #value of LOGICAL_GOOGLE_APPLICATION_CREDENTIALS env var. Needed | ||||||
|  |     #because `set -o nounset` is globally set | ||||||
|  |     local LOGICAL_BACKUP_GOOGLE_APPLICATION_CREDENTIALS=${LOGICAL_BACKUP_GOOGLE_APPLICATION_CREDENTIALS:-} | ||||||
|  | 
 | ||||||
|  |     GSUTIL_OPTIONS=("-o" "Credentials:gs_service_key_file=$LOGICAL_BACKUP_GOOGLE_APPLICATION_CREDENTIALS") | ||||||
|  | 
 | ||||||
|  |     #If GOOGLE_APPLICATION_CREDENTIALS is not set try to get | ||||||
|  |     #creds from metadata | ||||||
|  |     if [[ -z $LOGICAL_BACKUP_GOOGLE_APPLICATION_CREDENTIALS ]] | ||||||
|  |     then | ||||||
|  | 	    GSUTIL_OPTIONS[1]="GoogleCompute:service_account=default" | ||||||
|  |     fi | ||||||
|  | 
 | ||||||
|  |     gsutil ${GSUTIL_OPTIONS[@]} cp - "$PATH_TO_BACKUP" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function upload { | function upload { | ||||||
|  |  | ||||||
|  | @ -59,13 +59,20 @@ rules: | ||||||
|   - get |   - get | ||||||
|   - patch |   - patch | ||||||
|   - update |   - update | ||||||
| # to read configuration from ConfigMaps | # to read configuration from ConfigMaps and help Patroni manage the cluster if endpoints are not used | ||||||
| - apiGroups: | - apiGroups: | ||||||
|   - "" |   - "" | ||||||
|   resources: |   resources: | ||||||
|   - configmaps |   - configmaps | ||||||
|   verbs: |   verbs: | ||||||
|  |   - create | ||||||
|  |   - delete | ||||||
|  |   - deletecollection | ||||||
|   - get |   - get | ||||||
|  |   - list | ||||||
|  |   - patch | ||||||
|  |   - update | ||||||
|  |   - watch | ||||||
| # to send events to the CRs | # to send events to the CRs | ||||||
| - apiGroups: | - apiGroups: | ||||||
|   - "" |   - "" | ||||||
|  | @ -78,7 +85,7 @@ rules: | ||||||
|   - patch |   - patch | ||||||
|   - update |   - update | ||||||
|   - watch |   - watch | ||||||
| # to manage endpoints which are also used by Patroni | # to manage endpoints which are also used by Patroni (if it is using config maps) | ||||||
| - apiGroups: | - apiGroups: | ||||||
|   - "" |   - "" | ||||||
|   resources: |   resources: | ||||||
|  | @ -249,7 +256,21 @@ kind: ClusterRole | ||||||
| metadata: | metadata: | ||||||
|   name: postgres-pod |   name: postgres-pod | ||||||
| rules: | rules: | ||||||
| # Patroni needs to watch and manage endpoints | # Patroni needs to watch and manage config maps (or endpoints) | ||||||
|  | - apiGroups: | ||||||
|  |   - "" | ||||||
|  |   resources: | ||||||
|  |   - configmaps | ||||||
|  |   verbs: | ||||||
|  |   - create | ||||||
|  |   - delete | ||||||
|  |   - deletecollection | ||||||
|  |   - get | ||||||
|  |   - list | ||||||
|  |   - patch | ||||||
|  |   - update | ||||||
|  |   - watch | ||||||
|  | # Patroni needs to watch and manage endpoints (or config maps) | ||||||
| - apiGroups: | - apiGroups: | ||||||
|   - "" |   - "" | ||||||
|   resources: |   resources: | ||||||
|  |  | ||||||
|  | @ -846,6 +846,14 @@ func (c *Cluster) compareServices(old, new *v1.Service) (bool, string) { | ||||||
| 		return false, "new service's owner references do not match the current ones" | 		return false, "new service's owner references do not match the current ones" | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if !reflect.DeepEqual(old.Spec.Selector, new.Spec.Selector) { | ||||||
|  | 		return false, "new service's selector does not match the current one" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if old.Spec.ExternalTrafficPolicy != new.Spec.ExternalTrafficPolicy { | ||||||
|  | 		return false, "new service's ExternalTrafficPolicy does not match the current one" | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return true, "" | 	return true, "" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1341,14 +1341,21 @@ func TestCompareEnv(t *testing.T) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func newService(ann map[string]string, svcT v1.ServiceType, lbSr []string) *v1.Service { | func newService( | ||||||
|  | 	annotations map[string]string, | ||||||
|  | 	svcType v1.ServiceType, | ||||||
|  | 	sourceRanges []string, | ||||||
|  | 	selector map[string]string, | ||||||
|  | 	policy v1.ServiceExternalTrafficPolicyType) *v1.Service { | ||||||
| 	svc := &v1.Service{ | 	svc := &v1.Service{ | ||||||
| 		Spec: v1.ServiceSpec{ | 		Spec: v1.ServiceSpec{ | ||||||
| 			Type:                     svcT, | 			Selector:                 selector, | ||||||
| 			LoadBalancerSourceRanges: lbSr, | 			Type:                     svcType, | ||||||
|  | 			LoadBalancerSourceRanges: sourceRanges, | ||||||
|  | 			ExternalTrafficPolicy:    policy, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 	svc.Annotations = ann | 	svc.Annotations = annotations | ||||||
| 	return svc | 	return svc | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1365,13 +1372,18 @@ func TestCompareServices(t *testing.T) { | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	defaultPolicy := v1.ServiceExternalTrafficPolicyTypeCluster | ||||||
|  | 
 | ||||||
| 	serviceWithOwnerReference := newService( | 	serviceWithOwnerReference := newService( | ||||||
| 		map[string]string{ | 		map[string]string{ | ||||||
| 			constants.ZalandoDNSNameAnnotation: "clstr.acid.zalan.do", | 			constants.ZalandoDNSNameAnnotation: "clstr.acid.zalan.do", | ||||||
| 			constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | 			constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | ||||||
| 		}, | 		}, | ||||||
| 		v1.ServiceTypeClusterIP, | 		v1.ServiceTypeClusterIP, | ||||||
| 		[]string{"128.141.0.0/16", "137.138.0.0/16"}) | 		[]string{"128.141.0.0/16", "137.138.0.0/16"}, | ||||||
|  | 		nil, | ||||||
|  | 		defaultPolicy, | ||||||
|  | 	) | ||||||
| 
 | 
 | ||||||
| 	ownerRef := metav1.OwnerReference{ | 	ownerRef := metav1.OwnerReference{ | ||||||
| 		APIVersion: "acid.zalan.do/v1", | 		APIVersion: "acid.zalan.do/v1", | ||||||
|  | @ -1397,14 +1409,16 @@ func TestCompareServices(t *testing.T) { | ||||||
| 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | ||||||
| 				}, | 				}, | ||||||
| 				v1.ServiceTypeClusterIP, | 				v1.ServiceTypeClusterIP, | ||||||
| 				[]string{"128.141.0.0/16", "137.138.0.0/16"}), | 				[]string{"128.141.0.0/16", "137.138.0.0/16"}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
| 			new: newService( | 			new: newService( | ||||||
| 				map[string]string{ | 				map[string]string{ | ||||||
| 					constants.ZalandoDNSNameAnnotation: "clstr.acid.zalan.do", | 					constants.ZalandoDNSNameAnnotation: "clstr.acid.zalan.do", | ||||||
| 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | ||||||
| 				}, | 				}, | ||||||
| 				v1.ServiceTypeClusterIP, | 				v1.ServiceTypeClusterIP, | ||||||
| 				[]string{"128.141.0.0/16", "137.138.0.0/16"}), | 				[]string{"128.141.0.0/16", "137.138.0.0/16"}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
| 			match: true, | 			match: true, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
|  | @ -1415,14 +1429,16 @@ func TestCompareServices(t *testing.T) { | ||||||
| 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | ||||||
| 				}, | 				}, | ||||||
| 				v1.ServiceTypeClusterIP, | 				v1.ServiceTypeClusterIP, | ||||||
| 				[]string{"128.141.0.0/16", "137.138.0.0/16"}), | 				[]string{"128.141.0.0/16", "137.138.0.0/16"}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
| 			new: newService( | 			new: newService( | ||||||
| 				map[string]string{ | 				map[string]string{ | ||||||
| 					constants.ZalandoDNSNameAnnotation: "clstr.acid.zalan.do", | 					constants.ZalandoDNSNameAnnotation: "clstr.acid.zalan.do", | ||||||
| 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | ||||||
| 				}, | 				}, | ||||||
| 				v1.ServiceTypeLoadBalancer, | 				v1.ServiceTypeLoadBalancer, | ||||||
| 				[]string{"128.141.0.0/16", "137.138.0.0/16"}), | 				[]string{"128.141.0.0/16", "137.138.0.0/16"}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
| 			match:  false, | 			match:  false, | ||||||
| 			reason: `new service's type "LoadBalancer" does not match the current one "ClusterIP"`, | 			reason: `new service's type "LoadBalancer" does not match the current one "ClusterIP"`, | ||||||
| 		}, | 		}, | ||||||
|  | @ -1434,14 +1450,16 @@ func TestCompareServices(t *testing.T) { | ||||||
| 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | ||||||
| 				}, | 				}, | ||||||
| 				v1.ServiceTypeLoadBalancer, | 				v1.ServiceTypeLoadBalancer, | ||||||
| 				[]string{"128.141.0.0/16", "137.138.0.0/16"}), | 				[]string{"128.141.0.0/16", "137.138.0.0/16"}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
| 			new: newService( | 			new: newService( | ||||||
| 				map[string]string{ | 				map[string]string{ | ||||||
| 					constants.ZalandoDNSNameAnnotation: "clstr.acid.zalan.do", | 					constants.ZalandoDNSNameAnnotation: "clstr.acid.zalan.do", | ||||||
| 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | ||||||
| 				}, | 				}, | ||||||
| 				v1.ServiceTypeLoadBalancer, | 				v1.ServiceTypeLoadBalancer, | ||||||
| 				[]string{"185.249.56.0/22"}), | 				[]string{"185.249.56.0/22"}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
| 			match:  false, | 			match:  false, | ||||||
| 			reason: `new service's LoadBalancerSourceRange does not match the current one`, | 			reason: `new service's LoadBalancerSourceRange does not match the current one`, | ||||||
| 		}, | 		}, | ||||||
|  | @ -1453,14 +1471,16 @@ func TestCompareServices(t *testing.T) { | ||||||
| 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | ||||||
| 				}, | 				}, | ||||||
| 				v1.ServiceTypeLoadBalancer, | 				v1.ServiceTypeLoadBalancer, | ||||||
| 				[]string{"128.141.0.0/16", "137.138.0.0/16"}), | 				[]string{"128.141.0.0/16", "137.138.0.0/16"}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
| 			new: newService( | 			new: newService( | ||||||
| 				map[string]string{ | 				map[string]string{ | ||||||
| 					constants.ZalandoDNSNameAnnotation: "clstr.acid.zalan.do", | 					constants.ZalandoDNSNameAnnotation: "clstr.acid.zalan.do", | ||||||
| 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | ||||||
| 				}, | 				}, | ||||||
| 				v1.ServiceTypeLoadBalancer, | 				v1.ServiceTypeLoadBalancer, | ||||||
| 				[]string{}), | 				[]string{}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
| 			match:  false, | 			match:  false, | ||||||
| 			reason: `new service's LoadBalancerSourceRange does not match the current one`, | 			reason: `new service's LoadBalancerSourceRange does not match the current one`, | ||||||
| 		}, | 		}, | ||||||
|  | @ -1472,10 +1492,39 @@ func TestCompareServices(t *testing.T) { | ||||||
| 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | 					constants.ElbTimeoutAnnotationName: constants.ElbTimeoutAnnotationValue, | ||||||
| 				}, | 				}, | ||||||
| 				v1.ServiceTypeClusterIP, | 				v1.ServiceTypeClusterIP, | ||||||
| 				[]string{"128.141.0.0/16", "137.138.0.0/16"}), | 				[]string{"128.141.0.0/16", "137.138.0.0/16"}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
| 			new:   serviceWithOwnerReference, | 			new:   serviceWithOwnerReference, | ||||||
| 			match: false, | 			match: false, | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			about: "new service has a label selector", | ||||||
|  | 			current: newService( | ||||||
|  | 				map[string]string{}, | ||||||
|  | 				v1.ServiceTypeClusterIP, | ||||||
|  | 				[]string{}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
|  | 			new: newService( | ||||||
|  | 				map[string]string{}, | ||||||
|  | 				v1.ServiceTypeClusterIP, | ||||||
|  | 				[]string{}, | ||||||
|  | 				map[string]string{"cluster-name": "clstr", "spilo-role": "master"}, defaultPolicy), | ||||||
|  | 			match: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			about: "services differ on external traffic policy", | ||||||
|  | 			current: newService( | ||||||
|  | 				map[string]string{}, | ||||||
|  | 				v1.ServiceTypeClusterIP, | ||||||
|  | 				[]string{}, | ||||||
|  | 				nil, defaultPolicy), | ||||||
|  | 			new: newService( | ||||||
|  | 				map[string]string{}, | ||||||
|  | 				v1.ServiceTypeClusterIP, | ||||||
|  | 				[]string{}, | ||||||
|  | 				nil, v1.ServiceExternalTrafficPolicyTypeLocal), | ||||||
|  | 			match: false, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for _, tt := range tests { | 	for _, tt := range tests { | ||||||
|  |  | ||||||
|  | @ -4,7 +4,9 @@ import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"maps" | ||||||
| 	"path" | 	"path" | ||||||
|  | 	"slices" | ||||||
| 	"sort" | 	"sort" | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
|  | @ -12,19 +14,16 @@ import ( | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| 
 | 
 | ||||||
| 	appsv1 "k8s.io/api/apps/v1" | 	appsv1 "k8s.io/api/apps/v1" | ||||||
|  | 	batchv1 "k8s.io/api/batch/v1" | ||||||
| 	v1 "k8s.io/api/core/v1" | 	v1 "k8s.io/api/core/v1" | ||||||
| 	policyv1 "k8s.io/api/policy/v1" | 	policyv1 "k8s.io/api/policy/v1" | ||||||
| 	apierrors "k8s.io/apimachinery/pkg/api/errors" | 	apierrors "k8s.io/apimachinery/pkg/api/errors" | ||||||
| 	"k8s.io/apimachinery/pkg/api/resource" | 	"k8s.io/apimachinery/pkg/api/resource" | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
|  | 	"k8s.io/apimachinery/pkg/labels" | ||||||
| 	"k8s.io/apimachinery/pkg/types" | 	"k8s.io/apimachinery/pkg/types" | ||||||
| 	"k8s.io/apimachinery/pkg/util/intstr" | 	"k8s.io/apimachinery/pkg/util/intstr" | ||||||
| 
 | 
 | ||||||
| 	"golang.org/x/exp/maps" |  | ||||||
| 	"golang.org/x/exp/slices" |  | ||||||
| 	batchv1 "k8s.io/api/batch/v1" |  | ||||||
| 	"k8s.io/apimachinery/pkg/labels" |  | ||||||
| 
 |  | ||||||
| 	acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" | 	acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" | ||||||
| 	"github.com/zalando/postgres-operator/pkg/spec" | 	"github.com/zalando/postgres-operator/pkg/spec" | ||||||
| 	"github.com/zalando/postgres-operator/pkg/util" | 	"github.com/zalando/postgres-operator/pkg/util" | ||||||
|  | @ -1941,7 +1940,7 @@ func (c *Cluster) generateSingleUserSecret(pgUser spec.PgUser) *v1.Secret { | ||||||
| 
 | 
 | ||||||
| 	// if secret lives in another namespace we cannot set ownerReferences
 | 	// if secret lives in another namespace we cannot set ownerReferences
 | ||||||
| 	var ownerReferences []metav1.OwnerReference | 	var ownerReferences []metav1.OwnerReference | ||||||
| 	if c.Config.OpConfig.EnableCrossNamespaceSecret && strings.Contains(username, ".") { | 	if c.Config.OpConfig.EnableCrossNamespaceSecret && c.Postgresql.ObjectMeta.Namespace != pgUser.Namespace { | ||||||
| 		ownerReferences = nil | 		ownerReferences = nil | ||||||
| 	} else { | 	} else { | ||||||
| 		ownerReferences = c.ownerReferences() | 		ownerReferences = c.ownerReferences() | ||||||
|  |  | ||||||
|  | @ -3,12 +3,11 @@ package cluster | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"slices" | ||||||
| 	"sort" | 	"sort" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"golang.org/x/exp/slices" |  | ||||||
| 
 |  | ||||||
| 	appsv1 "k8s.io/api/apps/v1" | 	appsv1 "k8s.io/api/apps/v1" | ||||||
| 	v1 "k8s.io/api/core/v1" | 	v1 "k8s.io/api/core/v1" | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
|  |  | ||||||
|  | @ -4,8 +4,10 @@ import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"maps" | ||||||
| 	"reflect" | 	"reflect" | ||||||
| 	"regexp" | 	"regexp" | ||||||
|  | 	"slices" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
|  | @ -15,8 +17,6 @@ import ( | ||||||
| 	"github.com/zalando/postgres-operator/pkg/util" | 	"github.com/zalando/postgres-operator/pkg/util" | ||||||
| 	"github.com/zalando/postgres-operator/pkg/util/constants" | 	"github.com/zalando/postgres-operator/pkg/util/constants" | ||||||
| 	"github.com/zalando/postgres-operator/pkg/util/k8sutil" | 	"github.com/zalando/postgres-operator/pkg/util/k8sutil" | ||||||
| 	"golang.org/x/exp/maps" |  | ||||||
| 	"golang.org/x/exp/slices" |  | ||||||
| 	batchv1 "k8s.io/api/batch/v1" | 	batchv1 "k8s.io/api/batch/v1" | ||||||
| 	v1 "k8s.io/api/core/v1" | 	v1 "k8s.io/api/core/v1" | ||||||
| 	policyv1 "k8s.io/api/policy/v1" | 	policyv1 "k8s.io/api/policy/v1" | ||||||
|  |  | ||||||
|  | @ -2,15 +2,14 @@ package cluster | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
|  | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"slices" | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"context" |  | ||||||
| 
 |  | ||||||
| 	"golang.org/x/exp/slices" |  | ||||||
| 	v1 "k8s.io/api/core/v1" | 	v1 "k8s.io/api/core/v1" | ||||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
| 	"k8s.io/apimachinery/pkg/types" | 	"k8s.io/apimachinery/pkg/types" | ||||||
|  |  | ||||||
|  | @ -9,6 +9,6 @@ jq==1.7.0 | ||||||
| json_delta>=2.0.2 | json_delta>=2.0.2 | ||||||
| kubernetes==11.0.0 | kubernetes==11.0.0 | ||||||
| python-json-logger==2.0.7 | python-json-logger==2.0.7 | ||||||
| requests==2.32.2 | requests==2.32.4 | ||||||
| stups-tokens>=1.1.19 | stups-tokens>=1.1.19 | ||||||
| werkzeug==3.0.6 | werkzeug==3.0.6 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue