From a7aaad0a0b9517bb46077f2925eb80ae8ebe1a0c Mon Sep 17 00:00:00 2001 From: Felix Kunde Date: Thu, 30 Jul 2026 12:43:52 +0200 Subject: [PATCH 01/13] update helm chart index (#3148) --- charts/postgres-operator/index.yaml | 38 +++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/charts/postgres-operator/index.yaml b/charts/postgres-operator/index.yaml index d85e6f3c0..fc1b8b73b 100644 --- a/charts/postgres-operator/index.yaml +++ b/charts/postgres-operator/index.yaml @@ -1,9 +1,31 @@ apiVersion: v1 entries: postgres-operator: + - apiVersion: v2 + appVersion: 2.0.1 + created: "2026-07-30T05:31:19.462094+02:00" + description: Postgres Operator creates and manages PostgreSQL clusters running + in Kubernetes + digest: bb54c367441fe36cefc08d1c83e52e4baaea3522e32da14d40ea45eba4669ff1 + home: https://github.com/zalando/postgres-operator + keywords: + - postgres + - operator + - cloud-native + - patroni + - spilo + maintainers: + - email: opensource@zalando.de + name: Zalando + name: postgres-operator + sources: + - https://github.com/zalando/postgres-operator + urls: + - postgres-operator-2.0.1.tgz + version: 2.0.1 - apiVersion: v2 appVersion: 2.0.0 - created: "2026-07-28T16:30:13.110262+02:00" + created: "2026-07-30T05:31:19.460757+02:00" description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes digest: 2622899b573e4c46cd2a70677d5941a9e5da24c7db2a0ff774ddc49ad9d5c544 @@ -25,7 +47,7 @@ entries: version: 2.0.0 - apiVersion: v2 appVersion: 1.15.1 - created: "2026-07-28T16:30:13.108848+02:00" + created: "2026-07-30T05:31:19.45921+02:00" description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes digest: 9f3edc3d796105c02c04eaae28a78e58fb08c1847a9de012245fd6ac2c0d2c00 @@ -47,7 +69,7 @@ entries: version: 1.15.1 - apiVersion: v2 appVersion: 1.15.0 - created: "2026-07-28T16:30:13.108147+02:00" + created: "2026-07-30T05:31:19.458416+02:00" description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes digest: 002dd47647bf51fbba023bd1762d807be478cf37de7a44b80cd01ac1f20bd94a @@ -69,7 +91,7 @@ entries: version: 1.15.0 - apiVersion: v2 appVersion: 1.14.0 - created: "2026-07-28T16:30:13.107421+02:00" + created: "2026-07-30T05:31:19.457596+02:00" description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes digest: 36e1571f3f455b213f16cdda7b1158648e8e84deb804ba47ed6b9b6d19263ba8 @@ -91,7 +113,7 @@ entries: version: 1.14.0 - apiVersion: v2 appVersion: 1.13.0 - created: "2026-07-28T16:30:13.106643+02:00" + created: "2026-07-30T05:31:19.456373+02:00" description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes digest: a839601689aea0a7e6bc0712a5244d435683cf3314c95794097ff08540e1dfef @@ -113,7 +135,7 @@ entries: version: 1.13.0 - apiVersion: v2 appVersion: 1.12.2 - created: "2026-07-28T16:30:13.105204+02:00" + created: "2026-07-30T05:31:19.45558+02:00" description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes digest: 65858d14a40d7fd90c32bd9fc60021acc9555c161079f43a365c70171eaf21d8 @@ -135,7 +157,7 @@ entries: version: 1.12.2 - apiVersion: v2 appVersion: 1.11.0 - created: "2026-07-28T16:30:13.104449+02:00" + created: "2026-07-30T05:31:19.454725+02:00" description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes digest: 3914b5e117bda0834f05c9207f007e2ac372864cf6e86dcc2e1362bbe46c14d9 @@ -155,4 +177,4 @@ entries: urls: - postgres-operator-1.11.0.tgz version: 1.11.0 -generated: "2026-07-28T16:30:13.103286+02:00" +generated: "2026-07-30T05:31:19.453397+02:00" From bd8e361f652000e4020572bf10f8672f9cb3db17 Mon Sep 17 00:00:00 2001 From: Jan Mussler Date: Tue, 11 Aug 2026 09:14:13 +0200 Subject: [PATCH 02/13] Add deployment strategy type 'Recreate' (#3164) Add deployment strategy type 'Recreate' --- charts/postgres-operator/templates/deployment.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/charts/postgres-operator/templates/deployment.yaml b/charts/postgres-operator/templates/deployment.yaml index c2eb0ba23..5a87f0224 100644 --- a/charts/postgres-operator/templates/deployment.yaml +++ b/charts/postgres-operator/templates/deployment.yaml @@ -10,6 +10,8 @@ metadata: namespace: {{ .Release.Namespace }} spec: replicas: 1 + strategy: + type: "Recreate" selector: matchLabels: app.kubernetes.io/name: {{ template "postgres-operator.name" . }} From b43c7be1d0fd5c144bc245406f91ab11247675f3 Mon Sep 17 00:00:00 2001 From: rasoanaivo-r Date: Tue, 11 Aug 2026 17:10:05 +0200 Subject: [PATCH 03/13] fix operatorconfigurations CRD: render sidecars as array (#3160) configuration.sidecars was annotated with kubebuilder:validation:Type=object while SidecarContainers is a []v1.Container, so the generated schema rejected every list value and global sidecars could not be configured at all. Drop the hand-written Schemaless/Type=object markers and let controller-gen derive the schema from the Go type, the same way spec.initContainers is already handled in the Postgresql CRD. The field now renders as type: array with a full Container schema for its items. Fixes #3159 Co-authored-by: Claude Opus 5 (1M context) --- .../crds/operatorconfigurations.yaml | 1523 ++++++++++++++++- manifests/operatorconfiguration.crd.yaml | 1523 ++++++++++++++++- .../v1/operator_configuration_type.go | 4 +- .../v1/operatorconfiguration.crd.yaml | 1523 ++++++++++++++++- 4 files changed, 4564 insertions(+), 9 deletions(-) diff --git a/charts/postgres-operator/crds/operatorconfigurations.yaml b/charts/postgres-operator/crds/operatorconfigurations.yaml index 84d58cc8b..0f21f7cf4 100644 --- a/charts/postgres-operator/crds/operatorconfigurations.yaml +++ b/charts/postgres-operator/crds/operatorconfigurations.yaml @@ -779,8 +779,1527 @@ spec: type: string type: object sidecars: - type: object - x-kubernetes-preserve-unknown-fields: true + items: + description: A single application container that you want to run + within a pod. + properties: + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + description: |- + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: |- + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + description: |- + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + imagePullPolicy: + description: |- + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + lifecycle: + description: |- + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to execute in + the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to + perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration that the container + should sleep. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to execute in + the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to + perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration that the container + should sleep. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: + description: |- + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute in the + container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + 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: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection to a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network port in a + single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute in the + container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + 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: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection to a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. + items: + description: ContainerResizePolicy represents resource resize + policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This overrides the pod-level restart policy. When this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + x-kubernetes-list-type: atomic + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute in the + container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + 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: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection to a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices to be + used by the container. + items: + description: volumeDevice describes a mapping of a raw block + device within a container. + properties: + devicePath: + description: devicePath is the path inside of the container + that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + 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 + field is set to Enabled, the mount is made recursively read-only if it is + 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: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object + nullable: true + type: array teams_api: description: TeamsAPIConfiguration defines the configuration of TeamsAPI properties: diff --git a/manifests/operatorconfiguration.crd.yaml b/manifests/operatorconfiguration.crd.yaml index 84d58cc8b..0f21f7cf4 100644 --- a/manifests/operatorconfiguration.crd.yaml +++ b/manifests/operatorconfiguration.crd.yaml @@ -779,8 +779,1527 @@ spec: type: string type: object sidecars: - type: object - x-kubernetes-preserve-unknown-fields: true + items: + description: A single application container that you want to run + within a pod. + properties: + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + description: |- + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: |- + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + description: |- + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + imagePullPolicy: + description: |- + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + lifecycle: + description: |- + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to execute in + the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to + perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration that the container + should sleep. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to execute in + the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to + perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration that the container + should sleep. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: + description: |- + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute in the + container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + 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: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection to a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network port in a + single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute in the + container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + 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: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection to a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. + items: + description: ContainerResizePolicy represents resource resize + policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This overrides the pod-level restart policy. When this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + x-kubernetes-list-type: atomic + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute in the + container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + 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: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection to a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices to be + used by the container. + items: + description: volumeDevice describes a mapping of a raw block + device within a container. + properties: + devicePath: + description: devicePath is the path inside of the container + that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + 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 + field is set to Enabled, the mount is made recursively read-only if it is + 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: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object + nullable: true + type: array teams_api: description: TeamsAPIConfiguration defines the configuration of TeamsAPI properties: 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 d14ffc26e..23db5b196 100644 --- a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go +++ b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go @@ -430,9 +430,7 @@ type OperatorConfigurationData struct { // +kubebuilder:default=true ShmVolume *bool `json:"enable_shm_volume,omitempty"` SidecarImages map[string]string `json:"sidecar_docker_images,omitempty"` // deprecated in favour of SidecarContainers - // +kubebuilder:validation:XPreserveUnknownFields - // +kubebuilder:validation:Type=object - // +kubebuilder:validation:Schemaless + // +nullable SidecarContainers []v1.Container `json:"sidecars,omitempty"` // +optional PostgresUsersConfiguration PostgresUsersConfiguration `json:"users"` diff --git a/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml b/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml index 84d58cc8b..0f21f7cf4 100644 --- a/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml +++ b/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml @@ -779,8 +779,1527 @@ spec: type: string type: object sidecars: - type: object - x-kubernetes-preserve-unknown-fields: true + items: + description: A single application container that you want to run + within a pod. + properties: + args: + description: |- + Arguments to the entrypoint. + The container image's CMD is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + description: |- + Entrypoint array. Not executed within a shell. + The container image's ENTRYPOINT is used if this is not provided. + Variable references $(VAR_NAME) are expanded using the container's environment. If a variable + cannot be resolved, the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will + produce the string literal "$(VAR_NAME)". Escaped references will never be expanded, regardless + of whether the variable exists or not. Cannot be updated. + More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + description: |- + List of environment variables to set in the container. + Cannot be updated. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + default: false + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing + the env file. + type: string + required: + - key + - path + - volumeName + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + description: |- + List of sources to populate environment variables in the container. + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple + sources, the value associated with the last source will take precedence. + Values defined by an Env with a duplicate key will take precedence. + Cannot be updated. + items: + description: EnvFromSource represents the source of a set + of ConfigMaps or Secrets + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap must be + defined + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. + type: string + secretRef: + description: The Secret to select from + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret must be defined + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + description: |- + Container image name. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + imagePullPolicy: + description: |- + Image pull policy. + One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/containers/images#updating-images + type: string + lifecycle: + description: |- + Actions that the management system should take in response to container lifecycle events. + Cannot be updated. + properties: + postStart: + description: |- + PostStart is called immediately after a container is created. If the handler fails, + the container is terminated and restarted according to its restart policy. + Other management of the container blocks until the hook completes. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to execute in + the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to + perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration that the container + should sleep. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: |- + PreStop is called immediately before a container is terminated due to an + API request or management event such as liveness/startup probe failure, + preemption, resource contention, etc. The handler is not called if the + container crashes or exits. The Pod's termination grace period countdown begins before the + PreStop hook is executed. Regardless of the outcome of the handler, the + container will eventually terminate within the Pod's termination grace + period (unless delayed by finalizers). Other management of the container blocks until the hook completes + or until the termination grace period is reached. + More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks + properties: + exec: + description: Exec specifies a command to execute in + the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to + perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + sleep: + description: Sleep represents a duration that the container + should sleep. + properties: + seconds: + description: Seconds is the number of seconds to + sleep. + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + description: |- + Deprecated. TCPSocket is NOT supported as a LifecycleHandler and kept + for backward compatibility. There is no validation of this field and + lifecycle hooks will fail at runtime when it is specified. + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + description: |- + StopSignal defines which signal will be sent to a container when it is being stopped. + If not specified, the default is defined by the container runtime in use. + StopSignal can only be set for Pods with a non-empty .spec.os.name + type: string + type: object + livenessProbe: + description: |- + Periodic probe of container liveness. + Container will be restarted if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute in the + container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + 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: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection to a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + name: + description: |- + Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: |- + List of ports to expose from the container. Not specifying a port here + DOES NOT prevent that port from being exposed. Any port which is + listening on the default "0.0.0.0" address inside a container will be + accessible from the network. + Modifying this array with strategic merge patch may corrupt the data. + For more information See https://github.com/kubernetes/kubernetes/issues/108255. + Cannot be updated. + items: + description: ContainerPort represents a network port in a + single container. + properties: + containerPort: + description: |- + Number of port to expose on the pod's IP address. + This must be a valid port number, 0 < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port to. + type: string + hostPort: + description: |- + Number of port to expose on the host. + If specified, this must be a valid port number, 0 < x < 65536. + If HostNetwork is specified, this must match ContainerPort. + Most containers do not need this. + format: int32 + type: integer + name: + description: |- + If specified, this must be an IANA_SVC_NAME and unique within the pod. Each + named port in a pod must have a unique name. Name for the port that can be + referred to by services. + type: string + protocol: + default: TCP + description: |- + Protocol for port. Must be UDP, TCP, or SCTP. + Defaults to "TCP". + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: |- + Periodic probe of container service readiness. + Container will be removed from service endpoints if the probe fails. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute in the + container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + 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: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection to a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + resizePolicy: + description: |- + Resources resize policy for the container. + This field cannot be set on ephemeral containers. + items: + description: ContainerResizePolicy represents resource resize + policy for the container. + properties: + resourceName: + description: |- + Name of the resource to which this resource resize policy applies. + Supported values: cpu, memory. + type: string + restartPolicy: + description: |- + Restart policy to apply when specified resource is resized. + If not specified, it defaults to NotRequired. + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Compute Resources required by this container. + Cannot be updated. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + restartPolicy: + description: |- + RestartPolicy defines the restart behavior of individual containers in a pod. + This overrides the pod-level restart policy. When this field is not specified, + the restart behavior is defined by the Pod's restart policy and the container type. + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: + this init container will be continually restarted on + exit until all regular containers have terminated. Once all regular + containers have completed, all init containers with restartPolicy "Always" + will be shut down. This lifecycle differs from normal init containers and + is often referred to as a "sidecar" container. Although this init + container still starts in the init container sequence, it does not wait + for the container to complete before proceeding to the next init + container. Instead, the next init container starts immediately after this + init container is started, or after any startupProbe has successfully + completed. + type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + items: + description: ContainerRestartRule describes how a container + exit is handled. + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container + exits. + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + items: + format: int32 + type: integer + type: array + x-kubernetes-list-type: set + required: + - operator + type: object + required: + - action + type: object + type: array + x-kubernetes-list-type: atomic + securityContext: + description: |- + SecurityContext defines the security options the container should be run with. + If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + properties: + allowPrivilegeEscalation: + description: |- + AllowPrivilegeEscalation controls whether a process can gain more + privileges than its parent process. This bool directly controls if + the no_new_privs flag will be set on the container process. + AllowPrivilegeEscalation is true always when the container is: + 1) run as Privileged + 2) has CAP_SYS_ADMIN + Note that this field cannot be set when spec.os.name is windows. + type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object + capabilities: + description: |- + The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container runtime. + Note that this field cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + x-kubernetes-list-type: atomic + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + description: |- + Run container in privileged mode. + Processes in privileged containers are essentially equivalent to root on the host. + Defaults to false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: |- + procMount denotes the type of proc mount to use for the containers. + The default value is Default which uses the container runtime defaults for + readonly paths and masked paths. + Note that this field cannot be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: |- + Whether this container has a read-only root filesystem. + Default is false. + Note that this field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: |- + The GID to run the entrypoint of the container process. + Uses runtime default if unset. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: |- + Indicates that the container must run as a non-root user. + If true, the Kubelet will validate the image at runtime to ensure that it + does not run as UID 0 (root) and fail to start the container if it does. + If unset or false, no such validation will be performed. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: |- + The UID to run the entrypoint of the container process. + Defaults to user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: |- + The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random SELinux context for each + container. May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: |- + The seccomp options to use by this container. If seccomp options are + provided at both the pod & container level, the container options + override the pod options. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile defined in a file on the node should be used. + The profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's configured seccomp profile location. + Must be set if type is "Localhost". Must NOT be set for any other type. + type: string + type: + description: |- + type indicates which kind of seccomp profile will be applied. + Valid options are: + + Localhost - a profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile should be used. + Unconfined - no profile should be applied. + type: string + required: + - type + type: object + windowsOptions: + description: |- + The Windows specific settings applied to all containers. + If unspecified, the options from the PodSecurityContext will be used. + If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: |- + GMSACredentialSpec is where the GMSA admission webhook + (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the + GMSA credential spec named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: |- + HostProcess determines if a container should be run as a 'Host Process' container. + All of a Pod's containers must have the same effective HostProcess value + (it is not allowed to have a mix of HostProcess containers and non-HostProcess containers). + In addition, if HostProcess is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: |- + The UserName in Windows to run the entrypoint of the container process. + Defaults to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: |- + StartupProbe indicates that the Pod has successfully initialized. + If specified, no other probes are executed until this completes successfully. + If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. + This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, + when it might take a long time to load data or warm a cache, than during steady-state operation. + This cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + properties: + exec: + description: Exec specifies a command to execute in the + container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. Number + must be in the range 1 to 65535. + 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: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection to a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + stdin: + description: |- + Whether this container should allocate a buffer for stdin in the container runtime. If this + is not set, reads from stdin in the container will always result in EOF. + Default is false. + type: boolean + stdinOnce: + description: |- + Whether the container runtime should close the stdin channel after it has been opened by + a single attach. When stdin is true the stdin stream will remain open across multiple attach + sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the + first client attaches to stdin, and then remains open and accepts data until the client disconnects, + at which time stdin is closed and remains closed until the container is restarted. If this + flag is false, a container processes that reads from stdin will never receive an EOF. + Default is false + type: boolean + terminationMessagePath: + description: |- + Optional: Path at which the file to which the container's termination message + will be written is mounted into the container's filesystem. + Message written is intended to be brief final status, such as an assertion failure message. + Will be truncated by the node if greater than 4096 bytes. The total message length across + all containers will be limited to 12kb. + Defaults to /dev/termination-log. + Cannot be updated. + type: string + terminationMessagePolicy: + description: |- + Indicate how the termination message should be populated. File will use the contents of + terminationMessagePath to populate the container status message on both success and failure. + FallbackToLogsOnError will use the last chunk of container log output if the termination + message file is empty and the container exited with an error. + The log output is limited to 2048 bytes or 80 lines, whichever is smaller. + Defaults to File. + Cannot be updated. + type: string + tty: + description: |- + Whether this container should allocate a TTY for itself, also requires 'stdin' to be true. + Default is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices to be + used by the container. + items: + description: volumeDevice describes a mapping of a raw block + device within a container. + properties: + devicePath: + description: devicePath is the path inside of the container + that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + description: |- + Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: |- + Path within the container at which the volume should be mounted. Must + not contain ':'. + type: string + mountPropagation: + description: |- + mountPropagation determines how mounts are propagated from the host + to container and the other way around. + When not set, MountPropagationNone is used. + This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: |- + Mounted read-only if true, read-write otherwise (false or unspecified). + Defaults to false. + type: boolean + recursiveReadOnly: + description: |- + 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 + field is set to Enabled, the mount is made recursively read-only if it is + 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: + description: |- + Path within the volume from which the container's volume should be mounted. + Defaults to "" (volume's root). + type: string + subPathExpr: + description: |- + Expanded path within the volume from which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. + Defaults to "" (volume's root). + SubPathExpr and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + description: |- + Container's working directory. + If not specified, the container runtime's default will be used, which + might be configured in the container image. + Cannot be updated. + type: string + required: + - name + type: object + nullable: true + type: array teams_api: description: TeamsAPIConfiguration defines the configuration of TeamsAPI properties: From bbc3eab7e01008139d9ad115f5cdd2607af943b5 Mon Sep 17 00:00:00 2001 From: adshin21 <45573407+adshin21@users.noreply.github.com> Date: Tue, 11 Aug 2026 20:52:39 +0530 Subject: [PATCH 04/13] Skip owner references on user secrets when secret deletion is disabled (#3165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Skip owner references on user secrets when secret deletion is disabled Kubernetes garbage-collects owner-referenced secrets as soon as the owning Postgresql resource is deleted, regardless of the operator's own EnableSecretsDeletion check in Delete() (which only guards the operator's explicit deleteSecrets() call, not GC). This made enable_secrets_deletion=false ineffective whenever enable_owner_references was also enabled, since GC removed the credential secrets anyway. Now the generated secrets are not removed when enable_owner_references: true, enable_secrets_deletion: false. * Document skip-owner-refs on user secrets when deletion disabled - refresh inline comment in generateSingleUserSecret - extend enable_owner_references / enable_secrets_deletion docs in operator_parameters.md to describe the interaction - clarify in operator_parameters.md that the protection takes effect on the cluster's next sync after the setting is applied - add third exception in administrator.md "Owner References and Finalizers" - add TestGenerateSingleUserSecret_OwnerReferences covering all four flag combinations plus the cross-namespace cases --------- Co-authored-by: Serdar Dalgıç --- docs/administrator.md | 3 +- docs/reference/operator_parameters.md | 18 +++- pkg/cluster/k8sres.go | 10 +- pkg/cluster/k8sres_test.go | 128 ++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 6 deletions(-) diff --git a/docs/administrator.md b/docs/administrator.md index e9c1b88b9..289bef8fb 100644 --- a/docs/administrator.md +++ b/docs/administrator.md @@ -285,11 +285,12 @@ will differ and trigger a rolling update of the pods. ## Owner References and Finalizers The Postgres Operator can set [owner references](https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/) to most of a cluster's child resources to improve -monitoring with GitOps tools and enable cascading deletes. There are two +monitoring with GitOps tools and enable cascading deletes. There are three exceptions: * Persistent Volume Claims, because they are handled by the [PV Reclaim Policy]https://kubernetes.io/docs/tasks/administer-cluster/change-pv-reclaim-policy/ of the Stateful Set * Cross-namespace secrets, because owner references are not allowed across namespaces by design +* User-credential secrets when [`enable_secrets_deletion`](reference/operator_parameters.md#enable_secrets_deletion) is `false`, so Kubernetes garbage collection does not cascade-delete them after the Postgresql resource is removed (the `enable_secrets_deletion` flag alone only suppresses the operator's own delete path, not K8s GC) The operator would clean these resources up with its regular delete loop unless they got synced correctly. If for some reason the initial cluster sync diff --git a/docs/reference/operator_parameters.md b/docs/reference/operator_parameters.md index 0f8cb3d55..e0b1aea79 100644 --- a/docs/reference/operator_parameters.md +++ b/docs/reference/operator_parameters.md @@ -289,8 +289,12 @@ configuration they are grouped under the `kubernetes` key. * **enable_owner_references** The operator can set owner references on its child resources (except PVCs, Patroni config service/endpoint, cross-namespace secrets) to improve cluster - monitoring and enable cascading deletion. The default is `false`. Warning, - enabling this option disables configured delete protection checks (see below). + monitoring and enable cascading deletion. User-credential secrets are also + excluded from controller owner references whenever + [enable_secrets_deletion](#enable_secrets_deletion) is `false`, so that + Kubernetes garbage collection does not cascade-delete them when the + Postgresql resource is removed. The default is `false`. Warning, enabling + this option disables configured delete protection checks (see below). * **delete_annotation_date_key** key name for annotation that compares manifest value with current date in the @@ -381,7 +385,15 @@ configuration they are grouped under the `kubernetes` key. * **enable_secrets_deletion** By default, the operator deletes secrets when removing the Postgres cluster - manifest. To keep secrets, set this option to `false`. The default is `true`. + manifest. To keep secrets, set this option to `false`. Note that this only + guards the operator's own deletion logic; Kubernetes garbage collection can + still remove user-credential secrets when + [enable_owner_references](#enable_owner_references) is `true` because the + Postgresql resource acts as a controller owner. To prevent that, the + operator skips the controller owner reference on user-credential secrets + whenever `enable_secrets_deletion` is `false`, so the two settings work + together. This protection takes effect on the cluster's next sync after + the setting is applied. The default is `true`. * **enable_persistent_volume_claim_deletion** By default, the operator deletes persistent volume claims when removing the diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index 5af6ead45..86d14f17b 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -1931,9 +1931,15 @@ func (c *Cluster) generateSingleUserSecret(pgUser spec.PgUser) *v1.Secret { lbls = c.connectionPoolerLabels("", false).MatchLabels } - // if secret lives in another namespace we cannot set ownerReferences + // Skip a controller ownerReference on user-credential secrets when the + // operator is configured to keep them (enable_secrets_deletion=false); + // otherwise Kubernetes garbage collection would still cascade-delete them + // once the owning Postgresql CR is removed, defeating that setting. + // Cross-namespace secrets also have no ownerReference because K8s forbids + // cross-namespace ownerRefs by design. var ownerReferences []metav1.OwnerReference - if c.Config.OpConfig.EnableCrossNamespaceSecret && c.Postgresql.ObjectMeta.Namespace != pgUser.Namespace { + secretsDeletionDisabled := c.OpConfig.EnableSecretsDeletion != nil && !*c.OpConfig.EnableSecretsDeletion + if secretsDeletionDisabled || (c.Config.OpConfig.EnableCrossNamespaceSecret && c.Postgresql.ObjectMeta.Namespace != pgUser.Namespace) { ownerReferences = nil } else { ownerReferences = c.ownerReferences() diff --git a/pkg/cluster/k8sres_test.go b/pkg/cluster/k8sres_test.go index d7afd80cc..013b09c07 100644 --- a/pkg/cluster/k8sres_test.go +++ b/pkg/cluster/k8sres_test.go @@ -2829,6 +2829,134 @@ func TestGeneratePodDisruptionBudget(t *testing.T) { } } +func TestGenerateSingleUserSecret_OwnerReferences(t *testing.T) { + testName := "Test generateSingleUserSecret owner references" + + newCluster := func(ownerRefs, secretsDeletion *bool, crossNamespaceSecret bool) *Cluster { + cfg := Config{ + OpConfig: config.Config{ + Resources: config.Resources{ + ClusterNameLabel: "cluster-name", + PodRoleLabel: "spilo-role", + EnableOwnerReferences: ownerRefs, + }, + EnableSecretsDeletion: secretsDeletion, + EnableCrossNamespaceSecret: crossNamespaceSecret, + }, + } + pg := acidv1.Postgresql{ + ObjectMeta: metav1.ObjectMeta{ + Name: "myapp-database", + Namespace: "myapp", + UID: types.UID("myapp-database-uid"), + }, + Spec: acidv1.PostgresSpec{TeamID: "myapp", NumberOfInstances: 1}, + } + return New(cfg, k8sutil.KubernetesClient{}, pg, logger, eventRecorder) + } + + newPgUser := func(namespace string) spec.PgUser { + return spec.PgUser{ + Name: "app_user", + Namespace: namespace, + Password: "secret", + } + } + + hasControllerOwnerRef := func(cluster *Cluster) func(*v1.Secret) error { + return func(secret *v1.Secret) error { + for _, ref := range secret.OwnerReferences { + if ref.UID == cluster.Postgresql.ObjectMeta.UID && + ref.Name == cluster.Postgresql.ObjectMeta.Name && + ref.Controller != nil && *ref.Controller { + return nil + } + } + return fmt.Errorf("expected a controller owner reference pointing at the Postgresql CR, got %#v", + secret.OwnerReferences) + } + } + + hasNoControllerOwnerRef := func(cluster *Cluster) func(*v1.Secret) error { + return func(secret *v1.Secret) error { + for _, ref := range secret.OwnerReferences { + if ref.UID == cluster.Postgresql.ObjectMeta.UID && ref.Controller != nil && *ref.Controller { + return fmt.Errorf("expected no controller owner reference, got %#v", secret.OwnerReferences) + } + } + return nil + } + } + + tests := []struct { + scenario string + cluster *Cluster + pgUser spec.PgUser + expectControllerOwner bool + }{ + { + scenario: "owner refs + secrets deletion enabled (default)", + cluster: newCluster(util.True(), util.True(), false), + pgUser: newPgUser("myapp"), + expectControllerOwner: true, + }, + { + scenario: "owner refs enabled, secrets deletion disabled (skip owner ref)", + cluster: newCluster(util.True(), util.False(), false), + pgUser: newPgUser("myapp"), + expectControllerOwner: false, + }, + { + scenario: "owner refs enabled, secrets deletion unset (default true)", + cluster: newCluster(util.True(), nil, false), + pgUser: newPgUser("myapp"), + expectControllerOwner: true, + }, + { + scenario: "owner refs disabled, secrets deletion enabled", + cluster: newCluster(util.False(), util.True(), false), + pgUser: newPgUser("myapp"), + expectControllerOwner: false, + }, + { + scenario: "owner refs disabled, secrets deletion disabled", + cluster: newCluster(util.False(), util.False(), false), + pgUser: newPgUser("myapp"), + expectControllerOwner: false, + }, + { + scenario: "cross-namespace secret, owner refs + secrets deletion enabled", + cluster: newCluster(util.True(), util.True(), true), + pgUser: newPgUser("other-ns"), + expectControllerOwner: false, + }, + { + scenario: "cross-namespace secret, owner refs enabled, secrets deletion disabled", + cluster: newCluster(util.True(), util.False(), true), + pgUser: newPgUser("other-ns"), + expectControllerOwner: false, + }, + } + + for _, tt := range tests { + secret := tt.cluster.generateSingleUserSecret(tt.pgUser) + if secret == nil { + t.Errorf("%s [%s]: expected a non-nil secret", testName, tt.scenario) + continue + } + + var check func(*v1.Secret) error + if tt.expectControllerOwner { + check = hasControllerOwnerRef(tt.cluster) + } else { + check = hasNoControllerOwnerRef(tt.cluster) + } + if err := check(secret); err != nil { + t.Errorf("%s [%s]: %+v", testName, tt.scenario, err) + } + } +} + func TestGenerateService(t *testing.T) { var spec acidv1.PostgresSpec var cluster *Cluster From 6143460c4e5a1c62bdb3bdbdfb2f5b2ab923cbde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Aug 2026 16:25:43 +0200 Subject: [PATCH 05/13] Bump js-yaml from 4.3.0 to 4.3.1 in /ui/app (#3166) Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.3.0 to 4.3.1. - [Changelog](https://github.com/nodeca/js-yaml/blob/4.3.1/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.3.0...4.3.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.3.1 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- ui/app/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/package.json b/ui/app/package.json index 16e760ae5..e0c8564d0 100644 --- a/ui/app/package.json +++ b/ui/app/package.json @@ -38,7 +38,7 @@ "brfs": "^2.0.2", "dedent-js": "1.0.1", "eslint": "^8.32.0", - "js-yaml": "4.3.0", + "js-yaml": "4.3.1", "pug": "^3.0.2", "rimraf": "^4.1.2", "riot": "^3.13.2", From 6fbf962b1c4207592aa7dae9d88e9382a66bd345 Mon Sep 17 00:00:00 2001 From: Benjamin Ritter <7373184+l0wl3vel@users.noreply.github.com> Date: Fri, 14 Aug 2026 12:56:00 +0200 Subject: [PATCH 06/13] fix: rename module to github.com/zalando/postgres-operator/v2 (#3156) * fix: rename module to github.com/zalando/postgres-operator/v2 Upgrade performed using https://github.com/icholy/gomajor ``` gomajor path -version v2 ``` Signed-off-by: Benjamin Ritter * fix: make fmt Signed-off-by: Benjamin Ritter * fix: adjust codegen module name Signed-off-by: Benjamin Ritter --------- Signed-off-by: Benjamin Ritter Co-authored-by: Felix Kunde --- cmd/main.go | 6 +- go.mod | 2 +- hack/update-codegen.sh | 2 +- .../v1/operator_configuration_type.go | 4 +- pkg/apis/acid.zalan.do/v1/register.go | 2 +- .../acid.zalan.do/v1/zz_generated.deepcopy.go | 2 +- pkg/apis/zalando.org/v1/fabriceventstream.go | 2 +- pkg/apis/zalando.org/v1/register.go | 2 +- pkg/apiserver/apiserver.go | 8 +- pkg/cluster/cluster.go | 26 +- pkg/cluster/cluster_test.go | 18 +- pkg/cluster/connection_pooler.go | 14 +- pkg/cluster/connection_pooler_test.go | 12 +- pkg/cluster/database.go | 8 +- pkg/cluster/exec.go | 4 +- pkg/cluster/filesystems.go | 6 +- pkg/cluster/k8sres.go | 16 +- pkg/cluster/k8sres_test.go | 14 +- pkg/cluster/majorversionupgrade.go | 4 +- pkg/cluster/pod.go | 10 +- pkg/cluster/pod_test.go | 12 +- pkg/cluster/resources.go | 6 +- pkg/cluster/streams.go | 10 +- pkg/cluster/streams_test.go | 14 +- pkg/cluster/sync.go | 10 +- pkg/cluster/sync_test.go | 18 +- pkg/cluster/types.go | 2 +- pkg/cluster/util.go | 16 +- pkg/cluster/util_test.go | 14 +- pkg/cluster/volumes.go | 10 +- pkg/cluster/volumes_test.go | 12 +- pkg/controller/controller.go | 22 +- pkg/controller/logs_and_api.go | 8 +- pkg/controller/node.go | 6 +- pkg/controller/node_test.go | 2 +- pkg/controller/operator_config.go | 10 +- pkg/controller/pod.go | 6 +- pkg/controller/postgresql.go | 12 +- pkg/controller/postgresql_test.go | 4 +- pkg/controller/types.go | 2 +- pkg/controller/util.go | 12 +- pkg/controller/util_test.go | 6 +- .../clientset/versioned/clientset.go | 4 +- .../versioned/fake/clientset_generated.go | 10 +- .../clientset/versioned/fake/register.go | 4 +- .../clientset/versioned/scheme/register.go | 4 +- .../acid.zalan.do/v1/acid.zalan.do_client.go | 4 +- .../v1/fake/fake_acid.zalan.do_client.go | 2 +- .../v1/fake/fake_operatorconfiguration.go | 4 +- .../acid.zalan.do/v1/fake/fake_postgresql.go | 4 +- .../v1/fake/fake_postgresteam.go | 4 +- .../acid.zalan.do/v1/operatorconfiguration.go | 4 +- .../typed/acid.zalan.do/v1/postgresql.go | 4 +- .../typed/acid.zalan.do/v1/postgresteam.go | 4 +- .../typed/zalando.org/v1/fabriceventstream.go | 4 +- .../v1/fake/fake_fabriceventstream.go | 4 +- .../v1/fake/fake_zalando.org_client.go | 2 +- .../zalando.org/v1/zalando.org_client.go | 4 +- .../acid.zalan.do/interface.go | 4 +- .../acid.zalan.do/v1/interface.go | 2 +- .../acid.zalan.do/v1/operatorconfiguration.go | 8 +- .../acid.zalan.do/v1/postgresql.go | 8 +- .../acid.zalan.do/v1/postgresteam.go | 8 +- .../informers/externalversions/factory.go | 8 +- .../informers/externalversions/generic.go | 4 +- .../internalinterfaces/factory_interfaces.go | 2 +- .../externalversions/zalando.org/interface.go | 4 +- .../zalando.org/v1/fabriceventstream.go | 8 +- .../zalando.org/v1/interface.go | 2 +- .../acid.zalan.do/v1/operatorconfiguration.go | 2 +- .../listers/acid.zalan.do/v1/postgresql.go | 2 +- .../listers/acid.zalan.do/v1/postgresteam.go | 2 +- .../zalando.org/v1/fabriceventstream.go | 2 +- pkg/teams/postgres_team.go | 4 +- pkg/teams/postgres_team_test.go | 4 +- pkg/util/config/config.go | 4 +- pkg/util/filesystems/ext234.go | 2 +- pkg/util/k8sutil/k8sutil.go | 10 +- pkg/util/patroni/patroni.go | 6 +- pkg/util/patroni/patroni_test.go | 4 +- pkg/util/teams/teams_test.go | 486 +++++++++--------- pkg/util/users/users.go | 6 +- pkg/util/util.go | 2 +- pkg/util/util_test.go | 2 +- pkg/util/volumes/ebs.go | 4 +- pkg/util/volumes/ebs_test.go | 4 +- 86 files changed, 523 insertions(+), 523 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index adbf0cce5..3d65b9c50 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -10,9 +10,9 @@ import ( log "github.com/sirupsen/logrus" - "github.com/zalando/postgres-operator/pkg/controller" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/controller" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" ) var ( diff --git a/go.mod b/go.mod index 8e8d27f78..5c0a6408b 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/zalando/postgres-operator +module github.com/zalando/postgres-operator/v2 go 1.26.4 diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index fa3efb599..d652e87e7 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -19,7 +19,7 @@ set -o nounset set -o pipefail SRC="github.com" -GOPKG="$SRC/zalando/postgres-operator" +GOPKG="$SRC/zalando/postgres-operator/v2" CUSTOM_RESOURCE_NAME_ZAL="zalando.org" CUSTOM_RESOURCE_NAME_ACID="acid.zalan.do" CUSTOM_RESOURCE_VERSION="v1" 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 23db5b196..4f380944e 100644 --- a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go +++ b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go @@ -3,9 +3,9 @@ package v1 // Operator configuration CRD definition, please use snake_case for field names. import ( - "github.com/zalando/postgres-operator/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/spec" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/apis/acid.zalan.do/v1/register.go b/pkg/apis/acid.zalan.do/v1/register.go index 9dcbf2baf..5c260416f 100644 --- a/pkg/apis/acid.zalan.do/v1/register.go +++ b/pkg/apis/acid.zalan.do/v1/register.go @@ -1,7 +1,7 @@ package v1 import ( - acidzalando "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do" + acidzalando "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go b/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go index 2a3fefd00..9f5e93976 100644 --- a/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go +++ b/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go @@ -28,7 +28,7 @@ SOFTWARE. package v1 import ( - config "github.com/zalando/postgres-operator/pkg/util/config" + config "github.com/zalando/postgres-operator/v2/pkg/util/config" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" diff --git a/pkg/apis/zalando.org/v1/fabriceventstream.go b/pkg/apis/zalando.org/v1/fabriceventstream.go index cb2ccdef5..d2d4a01df 100644 --- a/pkg/apis/zalando.org/v1/fabriceventstream.go +++ b/pkg/apis/zalando.org/v1/fabriceventstream.go @@ -1,7 +1,7 @@ package v1 import ( - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/apis/zalando.org/v1/register.go b/pkg/apis/zalando.org/v1/register.go index 33a2c718b..289aa1701 100644 --- a/pkg/apis/zalando.org/v1/register.go +++ b/pkg/apis/zalando.org/v1/register.go @@ -1,7 +1,7 @@ package v1 import ( - "github.com/zalando/postgres-operator/pkg/apis/zalando.org" + "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index 97e389970..14d2f0cc0 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -12,10 +12,10 @@ import ( "time" "github.com/sirupsen/logrus" - "github.com/zalando/postgres-operator/pkg/cluster" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/cluster" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" ) const ( diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index cb5b2a839..d65aae20d 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -14,20 +14,20 @@ import ( "time" "github.com/sirupsen/logrus" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - zalandov1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + zalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" - "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/scheme" - "github.com/zalando/postgres-operator/pkg/spec" - pgteams "github.com/zalando/postgres-operator/pkg/teams" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/patroni" - "github.com/zalando/postgres-operator/pkg/util/teams" - "github.com/zalando/postgres-operator/pkg/util/users" - "github.com/zalando/postgres-operator/pkg/util/volumes" + "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/scheme" + "github.com/zalando/postgres-operator/v2/pkg/spec" + pgteams "github.com/zalando/postgres-operator/v2/pkg/teams" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/patroni" + "github.com/zalando/postgres-operator/v2/pkg/util/teams" + "github.com/zalando/postgres-operator/v2/pkg/util/users" + "github.com/zalando/postgres-operator/v2/pkg/util/volumes" appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" v1 "k8s.io/api/core/v1" diff --git a/pkg/cluster/cluster_test.go b/pkg/cluster/cluster_test.go index d651bea12..6c058498b 100644 --- a/pkg/cluster/cluster_test.go +++ b/pkg/cluster/cluster_test.go @@ -11,15 +11,15 @@ import ( "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/fake" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/patroni" - "github.com/zalando/postgres-operator/pkg/util/teams" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + fakeacidv1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/fake" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/patroni" + "github.com/zalando/postgres-operator/v2/pkg/util/teams" batchv1 "k8s.io/api/batch/v1" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" diff --git a/pkg/cluster/connection_pooler.go b/pkg/cluster/connection_pooler.go index 61cd9b041..89325e1fc 100644 --- a/pkg/cluster/connection_pooler.go +++ b/pkg/cluster/connection_pooler.go @@ -10,8 +10,8 @@ import ( "github.com/r3labs/diff" "github.com/sirupsen/logrus" - acidzalando "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + acidzalando "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -19,11 +19,11 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/retryutil" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/retryutil" ) var poolerRunAsUser = int64(100) diff --git a/pkg/cluster/connection_pooler_test.go b/pkg/cluster/connection_pooler_test.go index 1b41cbb02..688d96d18 100644 --- a/pkg/cluster/connection_pooler_test.go +++ b/pkg/cluster/connection_pooler_test.go @@ -7,12 +7,12 @@ import ( "testing" "github.com/stretchr/testify/assert" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/fake" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + fakeacidv1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/fake" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" diff --git a/pkg/cluster/database.go b/pkg/cluster/database.go index 56b5f3638..d46dc6067 100644 --- a/pkg/cluster/database.go +++ b/pkg/cluster/database.go @@ -11,10 +11,10 @@ import ( "github.com/lib/pq" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/retryutil" - "github.com/zalando/postgres-operator/pkg/util/users" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/retryutil" + "github.com/zalando/postgres-operator/v2/pkg/util/users" ) const ( diff --git a/pkg/cluster/exec.go b/pkg/cluster/exec.go index 5605a70f6..5ba016ef1 100644 --- a/pkg/cluster/exec.go +++ b/pkg/cluster/exec.go @@ -11,8 +11,8 @@ import ( "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/tools/remotecommand" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" ) // ExecCommand executes arbitrary command inside the pod diff --git a/pkg/cluster/filesystems.go b/pkg/cluster/filesystems.go index a34e5a90e..f1b711499 100644 --- a/pkg/cluster/filesystems.go +++ b/pkg/cluster/filesystems.go @@ -4,9 +4,9 @@ import ( "fmt" "strings" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/filesystems" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/filesystems" ) func (c *Cluster) getPostgresFilesystemInfo(podName *spec.NamespacedName) (device, fstype string, err error) { diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index 86d14f17b..7ed3cd4d6 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -24,14 +24,14 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" - 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/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/patroni" - "github.com/zalando/postgres-operator/pkg/util/retryutil" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/patroni" + "github.com/zalando/postgres-operator/v2/pkg/util/retryutil" ) const ( diff --git a/pkg/cluster/k8sres_test.go b/pkg/cluster/k8sres_test.go index 013b09c07..6cb0e085c 100644 --- a/pkg/cluster/k8sres_test.go +++ b/pkg/cluster/k8sres_test.go @@ -9,13 +9,13 @@ import ( "github.com/stretchr/testify/assert" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/fake" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + fakeacidv1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/fake" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" diff --git a/pkg/cluster/majorversionupgrade.go b/pkg/cluster/majorversionupgrade.go index 6995c50b5..dae5db2e8 100644 --- a/pkg/cluster/majorversionupgrade.go +++ b/pkg/cluster/majorversionupgrade.go @@ -8,8 +8,8 @@ import ( "strings" "github.com/Masterminds/semver/v3" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" diff --git a/pkg/cluster/pod.go b/pkg/cluster/pod.go index c18054aad..2ce53b1ae 100644 --- a/pkg/cluster/pod.go +++ b/pkg/cluster/pod.go @@ -13,11 +13,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - 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/util" - "github.com/zalando/postgres-operator/pkg/util/patroni" - "github.com/zalando/postgres-operator/pkg/util/retryutil" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/patroni" + "github.com/zalando/postgres-operator/v2/pkg/util/retryutil" ) func (c *Cluster) listPods() ([]v1.Pod, error) { diff --git a/pkg/cluster/pod_test.go b/pkg/cluster/pod_test.go index 0eb1791e2..0123cce45 100644 --- a/pkg/cluster/pod_test.go +++ b/pkg/cluster/pod_test.go @@ -9,12 +9,12 @@ import ( "time" "github.com/golang/mock/gomock" - "github.com/zalando/postgres-operator/mocks" - 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/util/config" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/patroni" + "github.com/zalando/postgres-operator/v2/mocks" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/patroni" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/cluster/resources.go b/pkg/cluster/resources.go index 6053de471..d862de2c6 100644 --- a/pkg/cluster/resources.go +++ b/pkg/cluster/resources.go @@ -13,9 +13,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/retryutil" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/retryutil" ) const ( diff --git a/pkg/cluster/streams.go b/pkg/cluster/streams.go index bf9be3fb4..575b4f6b9 100644 --- a/pkg/cluster/streams.go +++ b/pkg/cluster/streams.go @@ -8,11 +8,11 @@ import ( "sort" "strings" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - zalandov1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + zalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ) diff --git a/pkg/cluster/streams_test.go b/pkg/cluster/streams_test.go index 934f2bfd4..9ea25e49d 100644 --- a/pkg/cluster/streams_test.go +++ b/pkg/cluster/streams_test.go @@ -9,13 +9,13 @@ import ( "testing" "github.com/stretchr/testify/assert" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - zalandov1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" - fakezalandov1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/fake" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + zalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" + fakezalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/fake" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" diff --git a/pkg/cluster/sync.go b/pkg/cluster/sync.go index 6e9f9348a..664c67b7e 100644 --- a/pkg/cluster/sync.go +++ b/pkg/cluster/sync.go @@ -12,11 +12,11 @@ import ( "strings" "time" - 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/util" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" batchv1 "k8s.io/api/batch/v1" v1 "k8s.io/api/core/v1" policyv1 "k8s.io/api/policy/v1" diff --git a/pkg/cluster/sync_test.go b/pkg/cluster/sync_test.go index 1d21d1536..1c705ea44 100644 --- a/pkg/cluster/sync_test.go +++ b/pkg/cluster/sync_test.go @@ -20,15 +20,15 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" - "github.com/zalando/postgres-operator/mocks" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/fake" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/patroni" + "github.com/zalando/postgres-operator/v2/mocks" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + fakeacidv1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/fake" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/patroni" "k8s.io/client-go/kubernetes/fake" ) diff --git a/pkg/cluster/types.go b/pkg/cluster/types.go index 17c4e705e..06c1674e3 100644 --- a/pkg/cluster/types.go +++ b/pkg/cluster/types.go @@ -3,7 +3,7 @@ package cluster import ( "time" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" policyv1 "k8s.io/api/policy/v1" diff --git a/pkg/cluster/util.go b/pkg/cluster/util.go index c2a847ba4..bc452c22d 100644 --- a/pkg/cluster/util.go +++ b/pkg/cluster/util.go @@ -20,14 +20,14 @@ import ( "k8s.io/apimachinery/pkg/labels" "github.com/sirupsen/logrus" - acidzalando "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do" - 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/util" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/nicediff" - "github.com/zalando/postgres-operator/pkg/util/retryutil" + acidzalando "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/nicediff" + "github.com/zalando/postgres-operator/v2/pkg/util/retryutil" ) // OAuthTokenGetter provides the method for fetching OAuth tokens diff --git a/pkg/cluster/util_test.go b/pkg/cluster/util_test.go index dfae6237a..9fc8cd551 100644 --- a/pkg/cluster/util_test.go +++ b/pkg/cluster/util_test.go @@ -13,13 +13,13 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" - "github.com/zalando/postgres-operator/mocks" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/fake" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/patroni" + "github.com/zalando/postgres-operator/v2/mocks" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + fakeacidv1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/fake" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/patroni" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" diff --git a/pkg/cluster/volumes.go b/pkg/cluster/volumes.go index e4451a12c..653a05aed 100644 --- a/pkg/cluster/volumes.go +++ b/pkg/cluster/volumes.go @@ -11,11 +11,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/filesystems" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/volumes" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/filesystems" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/volumes" ) func (c *Cluster) syncVolumes() error { diff --git a/pkg/cluster/volumes_test.go b/pkg/cluster/volumes_test.go index 51ac92e06..66b081edf 100644 --- a/pkg/cluster/volumes_test.go +++ b/pkg/cluster/volumes_test.go @@ -14,12 +14,12 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" - "github.com/zalando/postgres-operator/mocks" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/volumes" + "github.com/zalando/postgres-operator/v2/mocks" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/volumes" "k8s.io/client-go/kubernetes/fake" ) diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 63434efed..0d4638318 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -11,17 +11,17 @@ import ( "time" "github.com/sirupsen/logrus" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - "github.com/zalando/postgres-operator/pkg/apiserver" - "github.com/zalando/postgres-operator/pkg/cluster" - acidv1informer "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/acid.zalan.do/v1" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/teams" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/ringlog" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/apiserver" + "github.com/zalando/postgres-operator/v2/pkg/cluster" + acidv1informer "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/teams" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/ringlog" v1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/controller/logs_and_api.go b/pkg/controller/logs_and_api.go index 24881f9d7..49b9138af 100644 --- a/pkg/controller/logs_and_api.go +++ b/pkg/controller/logs_and_api.go @@ -7,10 +7,10 @@ import ( "github.com/sirupsen/logrus" - "github.com/zalando/postgres-operator/pkg/cluster" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/cluster" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" "k8s.io/apimachinery/pkg/types" ) diff --git a/pkg/controller/node.go b/pkg/controller/node.go index 978fda130..d962190be 100644 --- a/pkg/controller/node.go +++ b/pkg/controller/node.go @@ -5,13 +5,13 @@ import ( "fmt" "time" - "github.com/zalando/postgres-operator/pkg/util/retryutil" + "github.com/zalando/postgres-operator/v2/pkg/util/retryutil" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "github.com/zalando/postgres-operator/pkg/cluster" - "github.com/zalando/postgres-operator/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/cluster" + "github.com/zalando/postgres-operator/v2/pkg/util" ) func (c *Controller) nodeAdd(obj interface{}) { diff --git a/pkg/controller/node_test.go b/pkg/controller/node_test.go index a9616e256..b9326d9ef 100644 --- a/pkg/controller/node_test.go +++ b/pkg/controller/node_test.go @@ -3,7 +3,7 @@ package controller import ( "testing" - "github.com/zalando/postgres-operator/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/spec" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/controller/operator_config.go b/pkg/controller/operator_config.go index 6ee4522d8..f32b471d7 100644 --- a/pkg/controller/operator_config.go +++ b/pkg/controller/operator_config.go @@ -4,11 +4,11 @@ import ( "context" "fmt" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/controller/pod.go b/pkg/controller/pod.go index 1aaa307ea..f3d1c882d 100644 --- a/pkg/controller/pod.go +++ b/pkg/controller/pod.go @@ -3,9 +3,9 @@ package controller import ( v1 "k8s.io/api/core/v1" - "github.com/zalando/postgres-operator/pkg/cluster" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/cluster" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" "k8s.io/apimachinery/pkg/types" ) diff --git a/pkg/controller/postgresql.go b/pkg/controller/postgresql.go index e6f04fe6b..d2c7b535f 100644 --- a/pkg/controller/postgresql.go +++ b/pkg/controller/postgresql.go @@ -17,12 +17,12 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/cache" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - "github.com/zalando/postgres-operator/pkg/cluster" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" - "github.com/zalando/postgres-operator/pkg/util/ringlog" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/cluster" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/util/ringlog" ) func (c *Controller) clusterResync(stopCh <-chan struct{}, wg *sync.WaitGroup) { diff --git a/pkg/controller/postgresql_test.go b/pkg/controller/postgresql_test.go index e6645e188..68dea4bd9 100644 --- a/pkg/controller/postgresql_test.go +++ b/pkg/controller/postgresql_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - "github.com/zalando/postgres-operator/pkg/spec" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/spec" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/controller/types.go b/pkg/controller/types.go index b598014c9..b70feaae7 100644 --- a/pkg/controller/types.go +++ b/pkg/controller/types.go @@ -5,7 +5,7 @@ import ( "k8s.io/apimachinery/pkg/types" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" ) // EventType contains type of the events for the TPRs and Pods received from Kubernetes diff --git a/pkg/controller/util.go b/pkg/controller/util.go index 6296e5341..eeacfac10 100644 --- a/pkg/controller/util.go +++ b/pkg/controller/util.go @@ -10,12 +10,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/wait" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - "github.com/zalando/postgres-operator/pkg/cluster" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/cluster" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" "gopkg.in/yaml.v3" ) diff --git a/pkg/controller/util_test.go b/pkg/controller/util_test.go index 4c3a9b356..c07e7f44b 100644 --- a/pkg/controller/util_test.go +++ b/pkg/controller/util_test.go @@ -8,9 +8,9 @@ import ( b64 "encoding/base64" "github.com/stretchr/testify/assert" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util/config" - "github.com/zalando/postgres-operator/pkg/util/k8sutil" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util/config" + "github.com/zalando/postgres-operator/v2/pkg/util/k8sutil" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/generated/clientset/versioned/clientset.go b/pkg/generated/clientset/versioned/clientset.go index e2a14718a..15d96814e 100644 --- a/pkg/generated/clientset/versioned/clientset.go +++ b/pkg/generated/clientset/versioned/clientset.go @@ -28,8 +28,8 @@ import ( fmt "fmt" http "net/http" - acidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" - zalandov1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/zalando.org/v1" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" + zalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/zalando.org/v1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" diff --git a/pkg/generated/clientset/versioned/fake/clientset_generated.go b/pkg/generated/clientset/versioned/fake/clientset_generated.go index f7f61ddea..c66937564 100644 --- a/pkg/generated/clientset/versioned/fake/clientset_generated.go +++ b/pkg/generated/clientset/versioned/fake/clientset_generated.go @@ -25,11 +25,11 @@ SOFTWARE. package fake import ( - clientset "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned" - acidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" - fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake" - zalandov1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/zalando.org/v1" - fakezalandov1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake" + clientset "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" + fakeacidv1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake" + zalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/zalando.org/v1" + fakezalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/generated/clientset/versioned/fake/register.go b/pkg/generated/clientset/versioned/fake/register.go index d6bf8f312..4a7d8fda3 100644 --- a/pkg/generated/clientset/versioned/fake/register.go +++ b/pkg/generated/clientset/versioned/fake/register.go @@ -25,8 +25,8 @@ SOFTWARE. package fake import ( - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - zalandov1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + zalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/generated/clientset/versioned/scheme/register.go b/pkg/generated/clientset/versioned/scheme/register.go index 45a31ab41..99f2f2ff4 100644 --- a/pkg/generated/clientset/versioned/scheme/register.go +++ b/pkg/generated/clientset/versioned/scheme/register.go @@ -25,8 +25,8 @@ SOFTWARE. package scheme import ( - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - zalandov1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + zalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/acid.zalan.do_client.go b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/acid.zalan.do_client.go index 93564ec3b..648af313c 100644 --- a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/acid.zalan.do_client.go +++ b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/acid.zalan.do_client.go @@ -27,8 +27,8 @@ package v1 import ( http "net/http" - acidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - scheme "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/scheme" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + scheme "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/scheme" rest "k8s.io/client-go/rest" ) diff --git a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_acid.zalan.do_client.go b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_acid.zalan.do_client.go index 643b8fd26..4dad7e508 100644 --- a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_acid.zalan.do_client.go +++ b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_acid.zalan.do_client.go @@ -25,7 +25,7 @@ SOFTWARE. package fake import ( - v1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" + v1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" rest "k8s.io/client-go/rest" testing "k8s.io/client-go/testing" ) diff --git a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_operatorconfiguration.go b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_operatorconfiguration.go index 66db8ec40..144b72938 100644 --- a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_operatorconfiguration.go +++ b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_operatorconfiguration.go @@ -25,8 +25,8 @@ SOFTWARE. package fake import ( - v1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - acidzalandov1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" + v1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" gentype "k8s.io/client-go/gentype" ) diff --git a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_postgresql.go b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_postgresql.go index b2ac1e9e1..1daddb088 100644 --- a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_postgresql.go +++ b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_postgresql.go @@ -25,8 +25,8 @@ SOFTWARE. package fake import ( - v1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - acidzalandov1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" + v1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" gentype "k8s.io/client-go/gentype" ) diff --git a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_postgresteam.go b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_postgresteam.go index 3067aac18..0ab34eccc 100644 --- a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_postgresteam.go +++ b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_postgresteam.go @@ -25,8 +25,8 @@ SOFTWARE. package fake import ( - v1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - acidzalandov1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" + v1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" gentype "k8s.io/client-go/gentype" ) diff --git a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/operatorconfiguration.go b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/operatorconfiguration.go index 292fa2fce..bbee66241 100644 --- a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/operatorconfiguration.go +++ b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/operatorconfiguration.go @@ -27,8 +27,8 @@ package v1 import ( context "context" - acidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - scheme "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/scheme" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + scheme "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/scheme" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/postgresql.go b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/postgresql.go index 75793c57a..3ec5fe19a 100644 --- a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/postgresql.go +++ b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/postgresql.go @@ -27,8 +27,8 @@ package v1 import ( context "context" - acidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - scheme "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/scheme" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + scheme "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/scheme" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/postgresteam.go b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/postgresteam.go index 99df6b6cc..9cca69db7 100644 --- a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/postgresteam.go +++ b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/postgresteam.go @@ -27,8 +27,8 @@ package v1 import ( context "context" - acidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - scheme "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/scheme" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + scheme "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/scheme" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/generated/clientset/versioned/typed/zalando.org/v1/fabriceventstream.go b/pkg/generated/clientset/versioned/typed/zalando.org/v1/fabriceventstream.go index 2681ac467..620c89f7e 100644 --- a/pkg/generated/clientset/versioned/typed/zalando.org/v1/fabriceventstream.go +++ b/pkg/generated/clientset/versioned/typed/zalando.org/v1/fabriceventstream.go @@ -27,8 +27,8 @@ package v1 import ( context "context" - zalandoorgv1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" - scheme "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/scheme" + zalandoorgv1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" + scheme "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/scheme" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake/fake_fabriceventstream.go b/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake/fake_fabriceventstream.go index c3ae49663..95d978e61 100644 --- a/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake/fake_fabriceventstream.go +++ b/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake/fake_fabriceventstream.go @@ -25,8 +25,8 @@ SOFTWARE. package fake import ( - v1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" - zalandoorgv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/zalando.org/v1" + v1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" + zalandoorgv1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/zalando.org/v1" gentype "k8s.io/client-go/gentype" ) diff --git a/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake/fake_zalando.org_client.go b/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake/fake_zalando.org_client.go index 588a2bb94..b3b4b0488 100644 --- a/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake/fake_zalando.org_client.go +++ b/pkg/generated/clientset/versioned/typed/zalando.org/v1/fake/fake_zalando.org_client.go @@ -25,7 +25,7 @@ SOFTWARE. package fake import ( - v1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/zalando.org/v1" + v1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/zalando.org/v1" rest "k8s.io/client-go/rest" testing "k8s.io/client-go/testing" ) diff --git a/pkg/generated/clientset/versioned/typed/zalando.org/v1/zalando.org_client.go b/pkg/generated/clientset/versioned/typed/zalando.org/v1/zalando.org_client.go index 803aee179..6751be27a 100644 --- a/pkg/generated/clientset/versioned/typed/zalando.org/v1/zalando.org_client.go +++ b/pkg/generated/clientset/versioned/typed/zalando.org/v1/zalando.org_client.go @@ -27,8 +27,8 @@ package v1 import ( http "net/http" - zalandoorgv1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" - scheme "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/scheme" + zalandoorgv1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" + scheme "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/scheme" rest "k8s.io/client-go/rest" ) diff --git a/pkg/generated/informers/externalversions/acid.zalan.do/interface.go b/pkg/generated/informers/externalversions/acid.zalan.do/interface.go index a75e6ae2b..6c41921dc 100644 --- a/pkg/generated/informers/externalversions/acid.zalan.do/interface.go +++ b/pkg/generated/informers/externalversions/acid.zalan.do/interface.go @@ -25,8 +25,8 @@ SOFTWARE. package acid import ( - v1 "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/acid.zalan.do/v1" - internalinterfaces "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/internalinterfaces" + v1 "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/acid.zalan.do/v1" + internalinterfaces "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/internalinterfaces" ) // Interface provides access to each of this group's versions. diff --git a/pkg/generated/informers/externalversions/acid.zalan.do/v1/interface.go b/pkg/generated/informers/externalversions/acid.zalan.do/v1/interface.go index d176a2b35..766fa193a 100644 --- a/pkg/generated/informers/externalversions/acid.zalan.do/v1/interface.go +++ b/pkg/generated/informers/externalversions/acid.zalan.do/v1/interface.go @@ -25,7 +25,7 @@ SOFTWARE. package v1 import ( - internalinterfaces "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/internalinterfaces" + internalinterfaces "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/internalinterfaces" ) // Interface provides access to all the informers in this group version. diff --git a/pkg/generated/informers/externalversions/acid.zalan.do/v1/operatorconfiguration.go b/pkg/generated/informers/externalversions/acid.zalan.do/v1/operatorconfiguration.go index e2fee1a4e..d3d8f729e 100644 --- a/pkg/generated/informers/externalversions/acid.zalan.do/v1/operatorconfiguration.go +++ b/pkg/generated/informers/externalversions/acid.zalan.do/v1/operatorconfiguration.go @@ -28,10 +28,10 @@ import ( context "context" time "time" - apisacidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - versioned "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned" - internalinterfaces "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/internalinterfaces" - acidzalandov1 "github.com/zalando/postgres-operator/pkg/generated/listers/acid.zalan.do/v1" + apisacidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + versioned "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned" + internalinterfaces "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/internalinterfaces" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/listers/acid.zalan.do/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/generated/informers/externalversions/acid.zalan.do/v1/postgresql.go b/pkg/generated/informers/externalversions/acid.zalan.do/v1/postgresql.go index c1b58ff05..0d16ba6ac 100644 --- a/pkg/generated/informers/externalversions/acid.zalan.do/v1/postgresql.go +++ b/pkg/generated/informers/externalversions/acid.zalan.do/v1/postgresql.go @@ -28,10 +28,10 @@ import ( context "context" time "time" - apisacidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - versioned "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned" - internalinterfaces "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/internalinterfaces" - acidzalandov1 "github.com/zalando/postgres-operator/pkg/generated/listers/acid.zalan.do/v1" + apisacidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + versioned "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned" + internalinterfaces "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/internalinterfaces" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/listers/acid.zalan.do/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/generated/informers/externalversions/acid.zalan.do/v1/postgresteam.go b/pkg/generated/informers/externalversions/acid.zalan.do/v1/postgresteam.go index 954dfd19f..12ec74fe1 100644 --- a/pkg/generated/informers/externalversions/acid.zalan.do/v1/postgresteam.go +++ b/pkg/generated/informers/externalversions/acid.zalan.do/v1/postgresteam.go @@ -28,10 +28,10 @@ import ( context "context" time "time" - apisacidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - versioned "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned" - internalinterfaces "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/internalinterfaces" - acidzalandov1 "github.com/zalando/postgres-operator/pkg/generated/listers/acid.zalan.do/v1" + apisacidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + versioned "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned" + internalinterfaces "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/internalinterfaces" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/listers/acid.zalan.do/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/generated/informers/externalversions/factory.go b/pkg/generated/informers/externalversions/factory.go index fb9ba76ac..22f6a5ebd 100644 --- a/pkg/generated/informers/externalversions/factory.go +++ b/pkg/generated/informers/externalversions/factory.go @@ -30,10 +30,10 @@ import ( sync "sync" time "time" - versioned "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned" - acidzalando "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/acid.zalan.do" - internalinterfaces "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/internalinterfaces" - zalandoorg "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/zalando.org" + versioned "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned" + acidzalando "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/acid.zalan.do" + internalinterfaces "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/internalinterfaces" + zalandoorg "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/zalando.org" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/generated/informers/externalversions/generic.go b/pkg/generated/informers/externalversions/generic.go index f5953bde6..7c723d958 100644 --- a/pkg/generated/informers/externalversions/generic.go +++ b/pkg/generated/informers/externalversions/generic.go @@ -27,8 +27,8 @@ package externalversions import ( fmt "fmt" - v1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - zalandoorgv1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" + v1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + zalandoorgv1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" ) diff --git a/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go index b8c3e7e51..bfb9af868 100644 --- a/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/pkg/generated/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -27,7 +27,7 @@ package internalinterfaces import ( time "time" - versioned "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned" + versioned "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" cache "k8s.io/client-go/tools/cache" diff --git a/pkg/generated/informers/externalversions/zalando.org/interface.go b/pkg/generated/informers/externalversions/zalando.org/interface.go index a05b7ea7d..e1bdb3234 100644 --- a/pkg/generated/informers/externalversions/zalando.org/interface.go +++ b/pkg/generated/informers/externalversions/zalando.org/interface.go @@ -25,8 +25,8 @@ SOFTWARE. package zalando import ( - internalinterfaces "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/internalinterfaces" - v1 "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/zalando.org/v1" + internalinterfaces "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/internalinterfaces" + v1 "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/zalando.org/v1" ) // Interface provides access to each of this group's versions. diff --git a/pkg/generated/informers/externalversions/zalando.org/v1/fabriceventstream.go b/pkg/generated/informers/externalversions/zalando.org/v1/fabriceventstream.go index 675058f80..f95629734 100644 --- a/pkg/generated/informers/externalversions/zalando.org/v1/fabriceventstream.go +++ b/pkg/generated/informers/externalversions/zalando.org/v1/fabriceventstream.go @@ -28,10 +28,10 @@ import ( context "context" time "time" - apiszalandoorgv1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" - versioned "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned" - internalinterfaces "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/internalinterfaces" - zalandoorgv1 "github.com/zalando/postgres-operator/pkg/generated/listers/zalando.org/v1" + apiszalandoorgv1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" + versioned "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned" + internalinterfaces "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/internalinterfaces" + zalandoorgv1 "github.com/zalando/postgres-operator/v2/pkg/generated/listers/zalando.org/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/pkg/generated/informers/externalversions/zalando.org/v1/interface.go b/pkg/generated/informers/externalversions/zalando.org/v1/interface.go index 825e5f4a4..95207079c 100644 --- a/pkg/generated/informers/externalversions/zalando.org/v1/interface.go +++ b/pkg/generated/informers/externalversions/zalando.org/v1/interface.go @@ -25,7 +25,7 @@ SOFTWARE. package v1 import ( - internalinterfaces "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/internalinterfaces" + internalinterfaces "github.com/zalando/postgres-operator/v2/pkg/generated/informers/externalversions/internalinterfaces" ) // Interface provides access to all the informers in this group version. diff --git a/pkg/generated/listers/acid.zalan.do/v1/operatorconfiguration.go b/pkg/generated/listers/acid.zalan.do/v1/operatorconfiguration.go index c00599718..e52c8f50a 100644 --- a/pkg/generated/listers/acid.zalan.do/v1/operatorconfiguration.go +++ b/pkg/generated/listers/acid.zalan.do/v1/operatorconfiguration.go @@ -25,7 +25,7 @@ SOFTWARE. package v1 import ( - acidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" labels "k8s.io/apimachinery/pkg/labels" listers "k8s.io/client-go/listers" cache "k8s.io/client-go/tools/cache" diff --git a/pkg/generated/listers/acid.zalan.do/v1/postgresql.go b/pkg/generated/listers/acid.zalan.do/v1/postgresql.go index b2fe09749..0f9849e28 100644 --- a/pkg/generated/listers/acid.zalan.do/v1/postgresql.go +++ b/pkg/generated/listers/acid.zalan.do/v1/postgresql.go @@ -25,7 +25,7 @@ SOFTWARE. package v1 import ( - acidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" labels "k8s.io/apimachinery/pkg/labels" listers "k8s.io/client-go/listers" cache "k8s.io/client-go/tools/cache" diff --git a/pkg/generated/listers/acid.zalan.do/v1/postgresteam.go b/pkg/generated/listers/acid.zalan.do/v1/postgresteam.go index 74fcc81d0..e5736b816 100644 --- a/pkg/generated/listers/acid.zalan.do/v1/postgresteam.go +++ b/pkg/generated/listers/acid.zalan.do/v1/postgresteam.go @@ -25,7 +25,7 @@ SOFTWARE. package v1 import ( - acidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + acidzalandov1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" labels "k8s.io/apimachinery/pkg/labels" listers "k8s.io/client-go/listers" cache "k8s.io/client-go/tools/cache" diff --git a/pkg/generated/listers/zalando.org/v1/fabriceventstream.go b/pkg/generated/listers/zalando.org/v1/fabriceventstream.go index 25e57e56e..a8ac77e5a 100644 --- a/pkg/generated/listers/zalando.org/v1/fabriceventstream.go +++ b/pkg/generated/listers/zalando.org/v1/fabriceventstream.go @@ -25,7 +25,7 @@ SOFTWARE. package v1 import ( - zalandoorgv1 "github.com/zalando/postgres-operator/pkg/apis/zalando.org/v1" + zalandoorgv1 "github.com/zalando/postgres-operator/v2/pkg/apis/zalando.org/v1" labels "k8s.io/apimachinery/pkg/labels" listers "k8s.io/client-go/listers" cache "k8s.io/client-go/tools/cache" diff --git a/pkg/teams/postgres_team.go b/pkg/teams/postgres_team.go index b682585ab..e241ee78a 100644 --- a/pkg/teams/postgres_team.go +++ b/pkg/teams/postgres_team.go @@ -1,8 +1,8 @@ package teams import ( - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - "github.com/zalando/postgres-operator/pkg/util" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/util" ) // PostgresTeamMap is the operator's internal representation of all PostgresTeam CRDs diff --git a/pkg/teams/postgres_team_test.go b/pkg/teams/postgres_team_test.go index fe45ade05..23694532d 100644 --- a/pkg/teams/postgres_team_test.go +++ b/pkg/teams/postgres_team_test.go @@ -3,8 +3,8 @@ package teams import ( "testing" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - "github.com/zalando/postgres-operator/pkg/util" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + "github.com/zalando/postgres-operator/v2/pkg/util" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go index 749fdaa90..3de7f4252 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -6,8 +6,8 @@ import ( "fmt" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/util/filesystems/ext234.go b/pkg/util/filesystems/ext234.go index fcd4053fc..ed37d5910 100644 --- a/pkg/util/filesystems/ext234.go +++ b/pkg/util/filesystems/ext234.go @@ -17,7 +17,7 @@ const ( resize2fs = "resize2fs" ) -//Ext234Resize implements the FilesystemResizer interface for the ext4/3/2fs. +// Ext234Resize implements the FilesystemResizer interface for the ext4/3/2fs. type Ext234Resize struct { } diff --git a/pkg/util/k8sutil/k8sutil.go b/pkg/util/k8sutil/k8sutil.go index 8515027ab..62248ce49 100644 --- a/pkg/util/k8sutil/k8sutil.go +++ b/pkg/util/k8sutil/k8sutil.go @@ -7,11 +7,11 @@ import ( b64 "encoding/base64" "encoding/json" - apiacidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" - zalandoclient "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned" - acidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" - zalandov1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/zalando.org/v1" - "github.com/zalando/postgres-operator/pkg/spec" + apiacidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" + zalandoclient "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1" + zalandov1 "github.com/zalando/postgres-operator/v2/pkg/generated/clientset/versioned/typed/zalando.org/v1" + "github.com/zalando/postgres-operator/v2/pkg/spec" apiappsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" diff --git a/pkg/util/patroni/patroni.go b/pkg/util/patroni/patroni.go index 2129f1acc..36648ce77 100644 --- a/pkg/util/patroni/patroni.go +++ b/pkg/util/patroni/patroni.go @@ -11,11 +11,11 @@ import ( "strconv" "time" - "github.com/zalando/postgres-operator/pkg/util/constants" - httpclient "github.com/zalando/postgres-operator/pkg/util/httpclient" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + httpclient "github.com/zalando/postgres-operator/v2/pkg/util/httpclient" "github.com/sirupsen/logrus" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" v1 "k8s.io/api/core/v1" ) diff --git a/pkg/util/patroni/patroni_test.go b/pkg/util/patroni/patroni_test.go index 39b498d2e..cd72ea877 100644 --- a/pkg/util/patroni/patroni_test.go +++ b/pkg/util/patroni/patroni_test.go @@ -12,9 +12,9 @@ import ( "github.com/golang/mock/gomock" "github.com/sirupsen/logrus" - "github.com/zalando/postgres-operator/mocks" + "github.com/zalando/postgres-operator/v2/mocks" - acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + acidv1 "github.com/zalando/postgres-operator/v2/pkg/apis/acid.zalan.do/v1" v1 "k8s.io/api/core/v1" ) diff --git a/pkg/util/teams/teams_test.go b/pkg/util/teams/teams_test.go index da9f497c1..ecf22a4e3 100644 --- a/pkg/util/teams/teams_test.go +++ b/pkg/util/teams/teams_test.go @@ -1,243 +1,243 @@ -package teams - -import ( - "fmt" - "net/http" - "net/http/httptest" - "reflect" - "testing" - - "github.com/sirupsen/logrus" -) - -var ( - logger = logrus.New().WithField("pkg", "teamsapi") - token = "ec45b1cfbe7100c6315d183a3eb6cec0M2U1LWJkMzEtZDgzNzNmZGQyNGM3IiwiYXV0aF90aW1lIjoxNDkzNzMwNzQ1LCJpc3MiOiJodHRwcz" - input = `{ - "dn": "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", - "id": "acid", - "id_name": "acid", - "team_id": "111222", - "type": "official", - "name": "Acid team name", - "mail": [ - "email1@example.com", - "email2@example.com" - ], - "alias": [ - "acid" - ], - "member": [ - "member1", - "member2", - "member3" - ], - "infrastructure-accounts": [ - { - "id": "1234512345", - "name": "acid", - "provider": "aws", - "type": "aws", - "description": "", - "owner": "acid", - "owner_dn": "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", - "disabled": false - }, - { - "id": "5432154321", - "name": "db", - "provider": "aws", - "type": "aws", - "description": "", - "owner": "acid", - "owner_dn": "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", - "disabled": false - } - ], - "cost_center": "00099999", - "delivery_lead": "member4", - "parent_team_id": "111221" - }` -) -var teamsAPItc = []struct { - in string - inCode int - inTeam string - out *Team - err error -}{ - { - input, - 200, - "acid", - &Team{ - Dn: "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", - ID: "acid", - TeamName: "acid", - TeamID: "111222", - Type: "official", - FullName: "Acid team name", - Aliases: []string{"acid"}, - Mails: []string{"email1@example.com", "email2@example.com"}, - Members: []string{"member1", "member2", "member3"}, - CostCenter: "00099999", - DeliveryLead: "member4", - ParentTeamID: "111221", - InfrastructureAccounts: []infrastructureAccount{ - { - ID: "1234512345", - Name: "acid", - Provider: "aws", - Type: "aws", - Description: "", - Owner: "acid", - OwnerDn: "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", - Disabled: false}, - { - ID: "5432154321", - Name: "db", - Provider: "aws", - Type: "aws", - Description: "", - Owner: "acid", - OwnerDn: "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", - Disabled: false}, - }, - }, - nil}, { - `{"error": "Access Token not valid"}`, - 401, - "acid", - nil, - fmt.Errorf(`team API query failed with status code 401 and message: '"Access Token not valid"'`), - }, - { - `{"status": "I'm a teapot'"}`, - 418, - "acid", - nil, - fmt.Errorf(`team API query failed with status code 418`), - }, - { - `{"status": "I'm a teapot`, - 418, - "acid", - nil, - fmt.Errorf(`team API query failed with status code 418 and malformed response: unexpected EOF`), - }, - { - `{"status": "I'm a teapot`, - 200, - "acid", - nil, - fmt.Errorf(`could not parse team API response: unexpected EOF`), - }, - { - input, - 404, - "banana", - nil, - fmt.Errorf(`team API query failed with status code 404`), - }, -} - -var requestsURLtc = []struct { - url string - err error -}{ - { - "coffee://localhost/", - fmt.Errorf(`Get "coffee://localhost/teams/acid": unsupported protocol scheme "coffee"`), - }, - { - "http://192.168.0.%31/", - fmt.Errorf(`parse "http://192.168.0.%%31/teams/acid": invalid URL escape "%%31"`), - }, -} - -func TestInfo(t *testing.T) { - for _, tc := range teamsAPItc { - func() { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Header.Get("Authorization") != "Bearer "+token { - t.Errorf("authorization token is wrong or not provided") - } - w.WriteHeader(tc.inCode) - if _, err := fmt.Fprint(w, tc.in); err != nil { - t.Errorf("error writing teams api response %v", err) - } - })) - defer ts.Close() - api := NewTeamsAPI(ts.URL, logger) - - actual, statusCode, err := api.TeamInfo(tc.inTeam, token) - if err != nil && err.Error() != tc.err.Error() { - t.Errorf("expected error: %v, got: %v", tc.err, err) - return - } - - if !reflect.DeepEqual(actual, tc.out) { - t.Errorf("expected %#v, got: %#v", tc.out, actual) - } - - if statusCode != tc.inCode { - t.Errorf("expected %d, got: %d", tc.inCode, statusCode) - } - }() - } -} - -type mockHTTPClient struct { -} - -type mockBody struct { -} - -func (b *mockBody) Read(p []byte) (n int, err error) { - return 2, nil -} - -func (b *mockBody) Close() error { - return fmt.Errorf("close error") -} - -func (c *mockHTTPClient) Do(req *http.Request) (*http.Response, error) { - resp := http.Response{ - Status: "200 OK", - StatusCode: 200, - ContentLength: 2, - Close: false, - Request: req, - } - resp.Body = &mockBody{} - - return &resp, nil -} - -func TestHttpClientClose(t *testing.T) { - ts := httptest.NewServer(nil) - - api := NewTeamsAPI(ts.URL, logger) - api.httpClient = &mockHTTPClient{} - - _, _, err := api.TeamInfo("acid", token) - expError := fmt.Errorf("error when closing response: close error") - if err.Error() != expError.Error() { - t.Errorf("expected error: %v, got: %v", expError, err) - } -} - -func TestRequest(t *testing.T) { - for _, tc := range requestsURLtc { - api := NewTeamsAPI(tc.url, logger) - resp, _, err := api.TeamInfo("acid", token) - if resp != nil { - t.Errorf("response expected to be nil") - continue - } - - if err.Error() != tc.err.Error() { - t.Errorf("expected error: %v, got: %v", tc.err, err) - } - } -} +package teams + +import ( + "fmt" + "net/http" + "net/http/httptest" + "reflect" + "testing" + + "github.com/sirupsen/logrus" +) + +var ( + logger = logrus.New().WithField("pkg", "teamsapi") + token = "ec45b1cfbe7100c6315d183a3eb6cec0M2U1LWJkMzEtZDgzNzNmZGQyNGM3IiwiYXV0aF90aW1lIjoxNDkzNzMwNzQ1LCJpc3MiOiJodHRwcz" + input = `{ + "dn": "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", + "id": "acid", + "id_name": "acid", + "team_id": "111222", + "type": "official", + "name": "Acid team name", + "mail": [ + "email1@example.com", + "email2@example.com" + ], + "alias": [ + "acid" + ], + "member": [ + "member1", + "member2", + "member3" + ], + "infrastructure-accounts": [ + { + "id": "1234512345", + "name": "acid", + "provider": "aws", + "type": "aws", + "description": "", + "owner": "acid", + "owner_dn": "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", + "disabled": false + }, + { + "id": "5432154321", + "name": "db", + "provider": "aws", + "type": "aws", + "description": "", + "owner": "acid", + "owner_dn": "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", + "disabled": false + } + ], + "cost_center": "00099999", + "delivery_lead": "member4", + "parent_team_id": "111221" + }` +) +var teamsAPItc = []struct { + in string + inCode int + inTeam string + out *Team + err error +}{ + { + input, + 200, + "acid", + &Team{ + Dn: "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", + ID: "acid", + TeamName: "acid", + TeamID: "111222", + Type: "official", + FullName: "Acid team name", + Aliases: []string{"acid"}, + Mails: []string{"email1@example.com", "email2@example.com"}, + Members: []string{"member1", "member2", "member3"}, + CostCenter: "00099999", + DeliveryLead: "member4", + ParentTeamID: "111221", + InfrastructureAccounts: []infrastructureAccount{ + { + ID: "1234512345", + Name: "acid", + Provider: "aws", + Type: "aws", + Description: "", + Owner: "acid", + OwnerDn: "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", + Disabled: false}, + { + ID: "5432154321", + Name: "db", + Provider: "aws", + Type: "aws", + Description: "", + Owner: "acid", + OwnerDn: "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", + Disabled: false}, + }, + }, + nil}, { + `{"error": "Access Token not valid"}`, + 401, + "acid", + nil, + fmt.Errorf(`team API query failed with status code 401 and message: '"Access Token not valid"'`), + }, + { + `{"status": "I'm a teapot'"}`, + 418, + "acid", + nil, + fmt.Errorf(`team API query failed with status code 418`), + }, + { + `{"status": "I'm a teapot`, + 418, + "acid", + nil, + fmt.Errorf(`team API query failed with status code 418 and malformed response: unexpected EOF`), + }, + { + `{"status": "I'm a teapot`, + 200, + "acid", + nil, + fmt.Errorf(`could not parse team API response: unexpected EOF`), + }, + { + input, + 404, + "banana", + nil, + fmt.Errorf(`team API query failed with status code 404`), + }, +} + +var requestsURLtc = []struct { + url string + err error +}{ + { + "coffee://localhost/", + fmt.Errorf(`Get "coffee://localhost/teams/acid": unsupported protocol scheme "coffee"`), + }, + { + "http://192.168.0.%31/", + fmt.Errorf(`parse "http://192.168.0.%%31/teams/acid": invalid URL escape "%%31"`), + }, +} + +func TestInfo(t *testing.T) { + for _, tc := range teamsAPItc { + func() { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Authorization") != "Bearer "+token { + t.Errorf("authorization token is wrong or not provided") + } + w.WriteHeader(tc.inCode) + if _, err := fmt.Fprint(w, tc.in); err != nil { + t.Errorf("error writing teams api response %v", err) + } + })) + defer ts.Close() + api := NewTeamsAPI(ts.URL, logger) + + actual, statusCode, err := api.TeamInfo(tc.inTeam, token) + if err != nil && err.Error() != tc.err.Error() { + t.Errorf("expected error: %v, got: %v", tc.err, err) + return + } + + if !reflect.DeepEqual(actual, tc.out) { + t.Errorf("expected %#v, got: %#v", tc.out, actual) + } + + if statusCode != tc.inCode { + t.Errorf("expected %d, got: %d", tc.inCode, statusCode) + } + }() + } +} + +type mockHTTPClient struct { +} + +type mockBody struct { +} + +func (b *mockBody) Read(p []byte) (n int, err error) { + return 2, nil +} + +func (b *mockBody) Close() error { + return fmt.Errorf("close error") +} + +func (c *mockHTTPClient) Do(req *http.Request) (*http.Response, error) { + resp := http.Response{ + Status: "200 OK", + StatusCode: 200, + ContentLength: 2, + Close: false, + Request: req, + } + resp.Body = &mockBody{} + + return &resp, nil +} + +func TestHttpClientClose(t *testing.T) { + ts := httptest.NewServer(nil) + + api := NewTeamsAPI(ts.URL, logger) + api.httpClient = &mockHTTPClient{} + + _, _, err := api.TeamInfo("acid", token) + expError := fmt.Errorf("error when closing response: close error") + if err.Error() != expError.Error() { + t.Errorf("expected error: %v, got: %v", expError, err) + } +} + +func TestRequest(t *testing.T) { + for _, tc := range requestsURLtc { + api := NewTeamsAPI(tc.url, logger) + resp, _, err := api.TeamInfo("acid", token) + if resp != nil { + t.Errorf("response expected to be nil") + continue + } + + if err.Error() != tc.err.Error() { + t.Errorf("expected error: %v, got: %v", tc.err, err) + } + } +} diff --git a/pkg/util/users/users.go b/pkg/util/users/users.go index b3b60df04..02130fb23 100644 --- a/pkg/util/users/users.go +++ b/pkg/util/users/users.go @@ -7,9 +7,9 @@ import ( "reflect" - "github.com/zalando/postgres-operator/pkg/spec" - "github.com/zalando/postgres-operator/pkg/util" - "github.com/zalando/postgres-operator/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/util" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" ) const ( diff --git a/pkg/util/util.go b/pkg/util/util.go index 79ff52282..8df951189 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -21,7 +21,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/zalando/postgres-operator/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/spec" "golang.org/x/crypto/pbkdf2" ) diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index 37e41f1cf..f5dc38989 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -8,7 +8,7 @@ import ( "regexp" - "github.com/zalando/postgres-operator/pkg/spec" + "github.com/zalando/postgres-operator/v2/pkg/spec" ) var pgUsers = []struct { diff --git a/pkg/util/volumes/ebs.go b/pkg/util/volumes/ebs.go index 7962a50b3..acaa03fb9 100644 --- a/pkg/util/volumes/ebs.go +++ b/pkg/util/volumes/ebs.go @@ -10,8 +10,8 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ec2/types" v1 "k8s.io/api/core/v1" - "github.com/zalando/postgres-operator/pkg/util/constants" - "github.com/zalando/postgres-operator/pkg/util/retryutil" + "github.com/zalando/postgres-operator/v2/pkg/util/constants" + "github.com/zalando/postgres-operator/v2/pkg/util/retryutil" ) // EBSVolumeResizer implements volume resizing interface for AWS EBS volumes. diff --git a/pkg/util/volumes/ebs_test.go b/pkg/util/volumes/ebs_test.go index 6f722ff7b..073ce2197 100644 --- a/pkg/util/volumes/ebs_test.go +++ b/pkg/util/volumes/ebs_test.go @@ -2,9 +2,9 @@ package volumes import ( "fmt" - "testing" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "testing" ) func TestGetProviderVolumeID(t *testing.T) { @@ -88,7 +88,7 @@ func TestVolumeBelongsToProvider(t *testing.T) { name: "AWS EBS volume handle", pv: &v1.PersistentVolume{ ObjectMeta: metav1.ObjectMeta{ - Annotations: map[string]string { + Annotations: map[string]string{ "pv.kubernetes.io/provisioned-by": "kubernetes.io/aws-ebs", }, }, From ad3f4340bbf83dc4002b54e7ab79c4726448da56 Mon Sep 17 00:00:00 2001 From: g2px1 Date: Thu, 20 Aug 2026 10:05:19 +0300 Subject: [PATCH 07/13] Skip ALTER ROLE when the stored SCRAM verifier already matches the password (#3171) * Skip ALTER ROLE when the stored SCRAM verifier already matches the password With password_encryption = scram-sha-256, syncSecrets compared the stored rolpassword with a freshly generated verifier. SCRAM verifiers embed a random salt, so the strings never match and every sync cycle re-issued ALTER ROLE ... PASSWORD for every managed role, re-salting the verifier each time. Besides the WAL and audit noise, this invalidates SCRAM pass-through credentials cached by connection poolers (e.g. pgbouncer behind auth_query), causing a short window of 'password authentication failed' server logins after every sync. Verify the stored hash against the desired password instead: for SCRAM verifiers the salt and iteration count are taken from the stored value and the derived keys are compared. Hashes whose type does not match the configured password_encryption are still reported as outdated, so switching between md5 and scram-sha-256 keeps re-hashing roles as before. Co-Authored-By: Claude Fable 5 * Update pkg/util/util.go --------- Co-authored-by: Claude Fable 5 Co-authored-by: Ida Novindasari Co-authored-by: Felix Kunde --- pkg/util/users/users.go | 10 +++-- pkg/util/util.go | 99 ++++++++++++++++++++++++++++++++++++++++- pkg/util/util_test.go | 35 +++++++++++++++ 3 files changed, 138 insertions(+), 6 deletions(-) diff --git a/pkg/util/users/users.go b/pkg/util/users/users.go index 02130fb23..d9117b4bc 100644 --- a/pkg/util/users/users.go +++ b/pkg/util/users/users.go @@ -60,11 +60,13 @@ func (strategy DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserM } } else { r := spec.PgSyncUserRequest{} - newMD5Password := util.NewEncryptor(strategy.PasswordEncryption).PGUserPassword(newUser) - // do not compare for roles coming from docker image - if dbUser.Password != newMD5Password { - r.User.Password = newMD5Password + // A plain string comparison with a freshly generated hash would + // re-issue ALTER ROLE on every sync for SCRAM-SHA-256, because + // each generated verifier embeds a new random salt. Verify the + // stored hash against the desired password instead. + if !util.PGUserPasswordUpToDate(newUser, dbUser.Password, strategy.PasswordEncryption) { + r.User.Password = util.NewEncryptor(strategy.PasswordEncryption).PGUserPassword(newUser) r.Kind = spec.PGsyncUserAlter } if addNewRoles, equal := util.SubstractStringSlices(newUser.MemberOf, dbUser.MemberOf); !equal { diff --git a/pkg/util/util.go b/pkg/util/util.go index 8df951189..bfd28a0a6 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -13,6 +13,7 @@ import ( "reflect" "regexp" "sort" + "strconv" "strings" "time" @@ -94,14 +95,21 @@ func NewEncryptor(encryption string) *Encryptor { } func (e *Encryptor) PGUserPassword(user spec.PgUser) string { - if (len(user.Password) == md5.Size*2+len(md5prefix) && user.Password[:3] == md5prefix) || - (len(user.Password) > len(scramsha256prefix) && user.Password[:len(scramsha256prefix)] == scramsha256prefix) || user.Password == "" { + if isMD5Hash(user.Password) || isScramHash(user.Password) || user.Password == "" { // Avoid processing already encrypted or empty passwords return user.Password } return e.encrypt(user) } +func isMD5Hash(password string) bool { + return len(password) == md5.Size*2+len(md5prefix) && password[:3] == md5prefix +} + +func isScramHash(password string) bool { + return len(password) > len(scramsha256prefix) && password[:len(scramsha256prefix)] == scramsha256prefix +} + func (e *Encryptor) PGUserPasswordMD5(user spec.PgUser) string { s := md5.Sum([]byte(user.Password + user.Name)) // #nosec, using md5 since PostgreSQL uses it for hashing passwords. return md5prefix + hex.EncodeToString(s[:]) @@ -127,6 +135,93 @@ func (e *Encryptor) PGUserPasswordScramSHA256(user spec.PgUser) string { return pass } +// PGUserPasswordUpToDate reports whether the password hash stored in the +// database already corresponds to the user's desired password and the +// configured password encryption, i.e. whether ALTER ROLE ... PASSWORD can +// be skipped during role sync. +// +// A SCRAM-SHA-256 verifier embeds a random salt, so regenerating one from +// the plaintext and comparing strings never matches. Instead, the salt and +// iteration count are taken from the stored verifier and the derived keys +// are compared. A stored hash whose type differs from the configured +// encryption is reported as outdated so that changing password_encryption +// still re-hashes the roles. +func PGUserPasswordUpToDate(user spec.PgUser, storedPassword, encryption string) bool { + // Empty and pre-hashed desired passwords can only be compared verbatim, + // mirroring the early return in PGUserPassword. + if user.Password == "" || isMD5Hash(user.Password) || isScramHash(user.Password) { + return user.Password == storedPassword + } + + switch { + case isMD5Hash(storedPassword): + if encryption != "md5" { + return false + } + return NewEncryptor(encryption).PGUserPassword(user) == storedPassword + case isScramHash(storedPassword): + if encryption == "md5" { + return false + } + return scramVerifierMatches(user.Password, storedPassword) + } + + return false +} + +// scramVerifierMatches verifies a plaintext password against a stored +// SCRAM-SHA-256 verifier of the form +// SCRAM-SHA-256$:$: +// by re-deriving the keys with the stored salt and iteration count. +func scramVerifierMatches(password, verifier string) bool { + rest := strings.TrimPrefix(verifier, scramsha256prefix+"$") + if rest == verifier { + return false + } + + saltedParams, keys, found := strings.Cut(rest, "$") + if !found { + return false + } + iterationsPart, saltPart, found := strings.Cut(saltedParams, ":") + if !found { + return false + } + storedKeyPart, serverKeyPart, found := strings.Cut(keys, ":") + if !found { + return false + } + + iterationCount, err := strconv.Atoi(iterationsPart) + if err != nil || iterationCount < 1 { + return false + } + salt, err := base64.StdEncoding.DecodeString(saltPart) + if err != nil { + return false + } + storedKey, err := base64.StdEncoding.DecodeString(storedKeyPart) + if err != nil { + return false + } + serverKey, err := base64.StdEncoding.DecodeString(serverKeyPart) + if err != nil { + return false + } + + key := pbkdf2.Key([]byte(password), salt, iterationCount, 32, sha256.New) + + serverMAC := hmac.New(sha256.New, key) + serverMAC.Write([]byte("Server Key")) + derivedServerKey := serverMAC.Sum(nil) + + clientMAC := hmac.New(sha256.New, key) + clientMAC.Write([]byte("Client Key")) + derivedStoredKey := sha256.Sum256(clientMAC.Sum(nil)) + + return hmac.Equal(derivedServerKey, serverKey) && hmac.Equal(derivedStoredKey[:], storedKey) +} + // Diff returns diffs between 2 objects func Diff(a, b interface{}) []string { return pretty.Diff(a, b) diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index f5dc38989..bb6786577 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -162,6 +162,41 @@ func TestPGUserPassword(t *testing.T) { } } +func TestPGUserPasswordUpToDate(t *testing.T) { + user := spec.PgUser{Name: "someuser", Password: "password"} + md5Hash := NewEncryptor("md5").PGUserPassword(user) + // real generation path: random salt in the verifier + scramHash := NewEncryptor("scram-sha-256").PGUserPassword(user) + + tests := []struct { + name string + user spec.PgUser + stored string + encryption string + want bool + }{ + {"scram verifier matches its plaintext", user, scramHash, "scram-sha-256", true}, + {"a differently salted verifier of the same password matches", user, NewEncryptor("scram-sha-256").PGUserPassword(user), "scram-sha-256", true}, + {"scram verifier of another password does not match", spec.PgUser{Name: "someuser", Password: "different"}, scramHash, "scram-sha-256", false}, + {"md5 hash matches its plaintext", user, md5Hash, "md5", true}, + {"md5 hash of another password does not match", spec.PgUser{Name: "someuser", Password: "different"}, md5Hash, "md5", false}, + {"stored md5 is outdated when scram is configured", user, md5Hash, "scram-sha-256", false}, + {"stored scram is outdated when md5 is configured", user, scramHash, "md5", false}, + {"pre-hashed desired password compares verbatim", spec.PgUser{Name: "someuser", Password: md5Hash}, md5Hash, "md5", true}, + {"pre-hashed desired password differs from stored", spec.PgUser{Name: "someuser", Password: md5Hash}, scramHash, "md5", false}, + {"empty desired password matches empty stored", spec.PgUser{Name: "someuser"}, "", "scram-sha-256", true}, + {"empty desired password differs from stored hash", spec.PgUser{Name: "someuser"}, scramHash, "scram-sha-256", false}, + {"malformed stored hash is outdated", user, "not-a-hash", "scram-sha-256", false}, + {"truncated scram verifier is outdated", user, "SCRAM-SHA-256$4096:c2FsdA==", "scram-sha-256", false}, + {"scram verifier with bad base64 is outdated", user, "SCRAM-SHA-256$4096:!!$aaaa:bbbb", "scram-sha-256", false}, + } + for _, tt := range tests { + if got := PGUserPasswordUpToDate(tt.user, tt.stored, tt.encryption); got != tt.want { + t.Errorf("%s: PGUserPasswordUpToDate expected %v, got %v", tt.name, tt.want, got) + } + } +} + func TestPrettyDiff(t *testing.T) { for _, tt := range prettyDiffTest { if actual := PrettyDiff(tt.inA, tt.inB); actual != tt.out { From 7649aaf79a1eec47b1388313cdc8409a4c183834 Mon Sep 17 00:00:00 2001 From: Felix Kunde Date: Thu, 20 Aug 2026 16:49:29 +0200 Subject: [PATCH 08/13] prepare v2.0.2 release (#3167) --- .../postgres-operator-issue-template.md | 2 +- README.md | 2 +- charts/postgres-operator-ui/Chart.yaml | 4 +- charts/postgres-operator-ui/index.yaml | 39 +++++++++++++---- .../postgres-operator-ui-2.0.2.tgz | Bin 0 -> 3787 bytes charts/postgres-operator-ui/values.yaml | 2 +- charts/postgres-operator/Chart.yaml | 4 +- .../crds/operatorconfigurations.yaml | 4 +- charts/postgres-operator/index.yaml | 40 ++++++++++++++---- .../postgres-operator-2.0.2.tgz | Bin 0 -> 53560 bytes charts/postgres-operator/values.yaml | 6 +-- docs/administrator.md | 2 +- docs/reference/operator_parameters.md | 4 +- manifests/configmap.yaml | 4 +- manifests/minimal-fake-pooler-deployment.yaml | 2 +- manifests/operatorconfiguration.crd.yaml | 4 +- manifests/postgres-operator.yaml | 2 +- ...gresql-operator-default-configuration.yaml | 4 +- .../v1/operator_configuration_type.go | 4 +- .../v1/operatorconfiguration.crd.yaml | 4 +- pkg/cluster/cluster_test.go | 4 +- pkg/controller/operator_config.go | 4 +- pkg/util/config/config.go | 4 +- ui/app/package.json | 2 +- ui/manifests/deployment.yaml | 2 +- 25 files changed, 97 insertions(+), 52 deletions(-) create mode 100644 charts/postgres-operator-ui/postgres-operator-ui-2.0.2.tgz create mode 100644 charts/postgres-operator/postgres-operator-2.0.2.tgz diff --git a/.github/ISSUE_TEMPLATE/postgres-operator-issue-template.md b/.github/ISSUE_TEMPLATE/postgres-operator-issue-template.md index 18568899d..3a9d402bf 100644 --- a/.github/ISSUE_TEMPLATE/postgres-operator-issue-template.md +++ b/.github/ISSUE_TEMPLATE/postgres-operator-issue-template.md @@ -9,7 +9,7 @@ assignees: '' Please, answer some short questions which should help us to understand your problem / question better? -- **Which image of the operator are you using?** e.g. ghcr.io/zalando/postgres-operator:v2.0.1 +- **Which image of the operator are you using?** e.g. ghcr.io/zalando/postgres-operator:v2.0.2 - **Where do you run it - cloud or metal? Kubernetes or OpenShift?** [AWS K8s | GCP ... | Bare Metal K8s] - **Are you running Postgres Operator in production?** [yes | no] - **Type of issue?** [Bug report, question, feature request, etc.] diff --git a/README.md b/README.md index 3454ec41c..a0c107078 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ production for over five years. | Release | Postgres versions | K8s versions | Golang | | :-------- | :---------------: | :---------------: | :-----: | -| v2.0.1 | 14 → 18 | 1.27+ | 1.26.4 | +| v2.0.2 | 14 → 18 | 1.27+ | 1.26.4 | | v1.15.1 | 13 → 17 | 1.27+ | 1.25.3 | | v1.14.0 | 13 → 17 | 1.27+ | 1.23.4 | | v1.13.0 | 12 → 16 | 1.27+ | 1.22.5 | diff --git a/charts/postgres-operator-ui/Chart.yaml b/charts/postgres-operator-ui/Chart.yaml index 759738933..45b2429f7 100644 --- a/charts/postgres-operator-ui/Chart.yaml +++ b/charts/postgres-operator-ui/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: postgres-operator-ui -version: 2.0.1 -appVersion: 2.0.1 +version: 2.0.2 +appVersion: 2.0.2 home: https://github.com/zalando/postgres-operator description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience keywords: diff --git a/charts/postgres-operator-ui/index.yaml b/charts/postgres-operator-ui/index.yaml index ff4456cbb..c76c25f0a 100644 --- a/charts/postgres-operator-ui/index.yaml +++ b/charts/postgres-operator-ui/index.yaml @@ -1,9 +1,32 @@ apiVersion: v1 entries: postgres-operator-ui: + - apiVersion: v2 + appVersion: 2.0.2 + created: "2026-08-12T16:14:09.689921+02:00" + description: Postgres Operator UI provides a graphical interface for a convenient + database-as-a-service user experience + digest: 2dea5c2768a611ec90f3531e32336c2be988e4a6cf2c4cc231835290b2863017 + home: https://github.com/zalando/postgres-operator + keywords: + - postgres + - operator + - ui + - cloud-native + - patroni + - spilo + maintainers: + - email: opensource@zalando.de + name: Zalando + name: postgres-operator-ui + sources: + - https://github.com/zalando/postgres-operator + urls: + - postgres-operator-ui-2.0.2.tgz + version: 2.0.2 - apiVersion: v2 appVersion: 2.0.1 - created: "2026-07-28T19:23:51.430413+02:00" + created: "2026-08-12T16:14:09.689744+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: 9bd0cfb82bc9e849fc01fe5a2d14e42941d102d719ff6a182a5a63237138c2a3 @@ -26,7 +49,7 @@ entries: version: 2.0.1 - apiVersion: v2 appVersion: 2.0.0 - created: "2026-07-28T19:23:51.429462+02:00" + created: "2026-08-12T16:14:09.689359+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: 80098eb9290d77fcaaf813347386c3b7d34de0d4e846b50ac177d4ac4a9e2ecb @@ -49,7 +72,7 @@ entries: version: 2.0.0 - apiVersion: v2 appVersion: 1.15.1 - created: "2026-07-28T19:23:51.429214+02:00" + created: "2026-08-12T16:14:09.688865+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: 4bbb750934366038d692711f924151182b7be131b6822d011f5a4e51cf609482 @@ -72,7 +95,7 @@ entries: version: 1.15.1 - apiVersion: v2 appVersion: 1.14.0 - created: "2026-07-28T19:23:51.428962+02:00" + created: "2026-08-12T16:14:09.688617+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: e87ed898079a852957a67a4caf3fbd27b9098e413f5d961b7a771a6ae8b3e17c @@ -95,7 +118,7 @@ entries: version: 1.14.0 - apiVersion: v2 appVersion: 1.13.0 - created: "2026-07-28T19:23:51.428701+02:00" + created: "2026-08-12T16:14:09.688362+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: e0444e516b50f82002d1a733527813c51759a627cefdd1005cea73659f824ea8 @@ -118,7 +141,7 @@ entries: version: 1.13.0 - apiVersion: v2 appVersion: 1.12.2 - created: "2026-07-28T19:23:51.428173+02:00" + created: "2026-08-12T16:14:09.68809+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: cbcef400c23ccece27d97369ad629278265c013e0a45c0b7f33e7568a082fedd @@ -141,7 +164,7 @@ entries: version: 1.12.2 - apiVersion: v2 appVersion: 1.11.0 - created: "2026-07-28T19:23:51.427892+02:00" + created: "2026-08-12T16:14:09.687752+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: a45f2284045c2a9a79750a36997386444f39b01ac722b17c84b431457577a3a2 @@ -162,4 +185,4 @@ entries: urls: - postgres-operator-ui-1.11.0.tgz version: 1.11.0 -generated: "2026-07-28T19:23:51.42722+02:00" +generated: "2026-08-12T16:14:09.687119+02:00" diff --git a/charts/postgres-operator-ui/postgres-operator-ui-2.0.2.tgz b/charts/postgres-operator-ui/postgres-operator-ui-2.0.2.tgz new file mode 100644 index 0000000000000000000000000000000000000000..0c226f835f05b93fb3cc9125aa8cad314e8a951d GIT binary patch literal 3787 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 G>IDGh>W?G< literal 0 HcmV?d00001 diff --git a/charts/postgres-operator/values.yaml b/charts/postgres-operator/values.yaml index 7b383f63a..2563a1f79 100644 --- a/charts/postgres-operator/values.yaml +++ b/charts/postgres-operator/values.yaml @@ -1,7 +1,7 @@ image: registry: ghcr.io repository: zalando/postgres-operator - tag: v2.0.1 + tag: v2.0.2 pullPolicy: "IfNotPresent" # Optionally specify an array of imagePullSecrets. @@ -385,7 +385,7 @@ configLogicalBackup: # logical_backup_memory_request: "" # image for pods of the logical backup job (example runs pg_dumpall) - logical_backup_docker_image: "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1" + logical_backup_docker_image: "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.2" # path of google cloud service account json file # logical_backup_google_application_credentials: "" @@ -463,7 +463,7 @@ configConnectionPooler: # db user for pooler to use connection_pooler_user: "pooler" # docker image - connection_pooler_image: "ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1" + connection_pooler_image: "ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.2" # max db connections the pooler should hold connection_pooler_max_db_connections: 60 # default pooling mode diff --git a/docs/administrator.md b/docs/administrator.md index 289bef8fb..66831bf99 100644 --- a/docs/administrator.md +++ b/docs/administrator.md @@ -1578,7 +1578,7 @@ make docker # build in image in minikube docker env eval $(minikube docker-env) -docker buildx build --load -t ghcr.io/zalando/postgres-operator-ui:v2.0.1 . +docker buildx build --load -t ghcr.io/zalando/postgres-operator-ui:v2.0.2 . # apply UI manifests next to a running Postgres Operator kubectl apply -f manifests/ diff --git a/docs/reference/operator_parameters.md b/docs/reference/operator_parameters.md index e0b1aea79..5b56d98af 100644 --- a/docs/reference/operator_parameters.md +++ b/docs/reference/operator_parameters.md @@ -851,7 +851,7 @@ grouped under the `logical_backup` key. runs `pg_dumpall` on a replica if possible and uploads compressed results to an S3 bucket under the key `////logical_backups`. The default image is the same image built with the Zalando-internal CI - pipeline. Default: "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1" + pipeline. Default: "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.2" * **logical_backup_google_application_credentials** Specifies the path of the google cloud service account json file. Default is empty. @@ -1092,7 +1092,7 @@ operator being able to provide some reasonable defaults. * **connection_pooler_image** Docker image to use for connection pooler deployment. - Default: "ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1" + Default: "ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.2" * **connection_pooler_max_db_connections** How many connections the pooler can max hold. This value is divided among the diff --git a/manifests/configmap.yaml b/manifests/configmap.yaml index b9628ebbc..53d6c71a3 100644 --- a/manifests/configmap.yaml +++ b/manifests/configmap.yaml @@ -17,7 +17,7 @@ data: connection_pooler_default_cpu_request: "500m" connection_pooler_default_memory_limit: 100Mi connection_pooler_default_memory_request: 100Mi - connection_pooler_image: "ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1" + connection_pooler_image: "ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.2" connection_pooler_max_db_connections: "60" connection_pooler_mode: "transaction" connection_pooler_number_of_instances: "2" @@ -86,7 +86,7 @@ data: # logical_backup_cpu_limit: "" # logical_backup_cpu_request: "" logical_backup_cronjob_environment_secret: "" - logical_backup_docker_image: "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1" + logical_backup_docker_image: "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.2" # logical_backup_google_application_credentials: "" logical_backup_job_prefix: "logical-backup-" # logical_backup_memory_limit: "" diff --git a/manifests/minimal-fake-pooler-deployment.yaml b/manifests/minimal-fake-pooler-deployment.yaml index 0de2dc57d..933a9145c 100644 --- a/manifests/minimal-fake-pooler-deployment.yaml +++ b/manifests/minimal-fake-pooler-deployment.yaml @@ -23,7 +23,7 @@ spec: serviceAccountName: postgres-operator containers: - name: postgres-operator - image: ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1 + image: ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.2 imagePullPolicy: IfNotPresent resources: requests: diff --git a/manifests/operatorconfiguration.crd.yaml b/manifests/operatorconfiguration.crd.yaml index 0f21f7cf4..40994c4d6 100644 --- a/manifests/operatorconfiguration.crd.yaml +++ b/manifests/operatorconfiguration.crd.yaml @@ -98,7 +98,7 @@ spec: pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ type: string connection_pooler_image: - default: ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1 + default: ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.2 type: string connection_pooler_max_db_connections: format: int32 @@ -606,7 +606,7 @@ spec: logical_backup_cronjob_environment_secret: type: string logical_backup_docker_image: - default: ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1 + default: ghcr.io/zalando/postgres-operator/logical-backup:v2.0.2 type: string logical_backup_failed_jobs_history_limit: default: 3 diff --git a/manifests/postgres-operator.yaml b/manifests/postgres-operator.yaml index 7e2705dea..7264256c1 100644 --- a/manifests/postgres-operator.yaml +++ b/manifests/postgres-operator.yaml @@ -19,7 +19,7 @@ spec: serviceAccountName: postgres-operator containers: - name: postgres-operator - image: ghcr.io/zalando/postgres-operator:v2.0.1 + image: ghcr.io/zalando/postgres-operator:v2.0.2 imagePullPolicy: IfNotPresent resources: requests: diff --git a/manifests/postgresql-operator-default-configuration.yaml b/manifests/postgresql-operator-default-configuration.yaml index 80d848e6b..c3f379f80 100644 --- a/manifests/postgresql-operator-default-configuration.yaml +++ b/manifests/postgresql-operator-default-configuration.yaml @@ -182,7 +182,7 @@ configuration: # logical_backup_cpu_request: "" # logical_backup_memory_limit: "" # logical_backup_memory_request: "" - logical_backup_docker_image: "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1" + logical_backup_docker_image: "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.2" # logical_backup_google_application_credentials: "" logical_backup_job_prefix: "logical-backup-" logical_backup_provider: "s3" @@ -227,7 +227,7 @@ configuration: connection_pooler_default_cpu_request: "500m" connection_pooler_default_memory_limit: 100Mi connection_pooler_default_memory_request: 100Mi - connection_pooler_image: "ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1" + connection_pooler_image: "ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.2" # connection_pooler_max_db_connections: 60 connection_pooler_mode: "transaction" connection_pooler_number_of_instances: 2 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 4f380944e..20e3efeec 100644 --- a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go +++ b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go @@ -331,7 +331,7 @@ type ConnectionPoolerConfiguration struct { Schema string `json:"connection_pooler_schema,omitempty"` // +kubebuilder:default=pooler User string `json:"connection_pooler_user,omitempty"` - // +kubebuilder:default="ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1" + // +kubebuilder:default="ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.2" Image string `json:"connection_pooler_image,omitempty"` // +kubebuilder:validation:Enum=session;transaction // +kubebuilder:default=transaction @@ -352,7 +352,7 @@ type OperatorLogicalBackupConfiguration struct { // +kubebuilder:validation:Pattern=`^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$` // +kubebuilder:default="30 00 * * *" Schedule string `json:"logical_backup_schedule,omitempty"` - // +kubebuilder:default="ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1" + // +kubebuilder:default="ghcr.io/zalando/postgres-operator/logical-backup:v2.0.2" DockerImage string `json:"logical_backup_docker_image,omitempty"` // +kubebuilder:validation:Enum=az;gcs;s3 // +kubebuilder:default=s3 diff --git a/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml b/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml index 0f21f7cf4..40994c4d6 100644 --- a/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml +++ b/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml @@ -98,7 +98,7 @@ spec: pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ type: string connection_pooler_image: - default: ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1 + default: ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.2 type: string connection_pooler_max_db_connections: format: int32 @@ -606,7 +606,7 @@ spec: logical_backup_cronjob_environment_secret: type: string logical_backup_docker_image: - default: ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1 + default: ghcr.io/zalando/postgres-operator/logical-backup:v2.0.2 type: string logical_backup_failed_jobs_history_limit: default: 3 diff --git a/pkg/cluster/cluster_test.go b/pkg/cluster/cluster_test.go index 6c058498b..c36dc4b30 100644 --- a/pkg/cluster/cluster_test.go +++ b/pkg/cluster/cluster_test.go @@ -1692,8 +1692,8 @@ func newCronJob(image, schedule string, vars []v1.EnvVar, mounts []v1.VolumeMoun func TestCompareLogicalBackupJob(t *testing.T) { - img1 := "ghcr.io/zalando/postgres-operator/logical-backup:v1.15.1" - img2 := "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1" + img1 := "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1" + img2 := "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.2" clientSet := fake.NewSimpleClientset() acidClientSet := fakeacidv1.NewSimpleClientset() diff --git a/pkg/controller/operator_config.go b/pkg/controller/operator_config.go index f32b471d7..b8edd399c 100644 --- a/pkg/controller/operator_config.go +++ b/pkg/controller/operator_config.go @@ -184,7 +184,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur // logical backup config result.LogicalBackupSchedule = util.Coalesce(fromCRD.LogicalBackup.Schedule, "30 00 * * *") - result.LogicalBackupDockerImage = util.Coalesce(fromCRD.LogicalBackup.DockerImage, "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1") + result.LogicalBackupDockerImage = util.Coalesce(fromCRD.LogicalBackup.DockerImage, "ghcr.io/zalando/postgres-operator/logical-backup:v2.0.2") result.LogicalBackupProvider = util.Coalesce(fromCRD.LogicalBackup.BackupProvider, "s3") result.LogicalBackupAzureStorageAccountName = fromCRD.LogicalBackup.AzureStorageAccountName result.LogicalBackupAzureStorageAccountKey = fromCRD.LogicalBackup.AzureStorageAccountKey @@ -270,7 +270,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur result.ConnectionPooler.Image = util.Coalesce( fromCRD.ConnectionPooler.Image, - "ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1") + "ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.2") result.ConnectionPooler.Mode = util.Coalesce( fromCRD.ConnectionPooler.Mode, diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go index 3de7f4252..e5ca0a36c 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -128,7 +128,7 @@ type Scalyr struct { // LogicalBackup defines configuration for logical backup type LogicalBackup struct { LogicalBackupSchedule string `name:"logical_backup_schedule" default:"30 00 * * *"` - LogicalBackupDockerImage string `name:"logical_backup_docker_image" default:"ghcr.io/zalando/postgres-operator/logical-backup:v2.0.1"` + LogicalBackupDockerImage string `name:"logical_backup_docker_image" default:"ghcr.io/zalando/postgres-operator/logical-backup:v2.0.2"` LogicalBackupProvider string `name:"logical_backup_provider" default:"s3"` LogicalBackupAzureStorageAccountName string `name:"logical_backup_azure_storage_account_name" default:""` LogicalBackupAzureStorageContainer string `name:"logical_backup_azure_storage_container" default:""` @@ -158,7 +158,7 @@ type ConnectionPooler struct { NumberOfInstances *int32 `name:"connection_pooler_number_of_instances" default:"2"` Schema string `name:"connection_pooler_schema" default:"pooler"` User string `name:"connection_pooler_user" default:"pooler"` - Image string `name:"connection_pooler_image" default:"ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.1"` + Image string `name:"connection_pooler_image" default:"ghcr.io/zalando/postgres-operator/pgbouncer:v2.0.2"` Mode string `name:"connection_pooler_mode" default:"transaction"` MaxDBConnections *int32 `name:"connection_pooler_max_db_connections" default:"60"` ConnectionPoolerDefaultCPURequest string `name:"connection_pooler_default_cpu_request"` diff --git a/ui/app/package.json b/ui/app/package.json index e0c8564d0..97dab9561 100644 --- a/ui/app/package.json +++ b/ui/app/package.json @@ -1,6 +1,6 @@ { "name": "postgres-operator-ui", - "version": "2.0.1", + "version": "2.0.2", "description": "PostgreSQL Operator UI", "main": "src/app.js", "config": { diff --git a/ui/manifests/deployment.yaml b/ui/manifests/deployment.yaml index b34ca5465..5bbc047df 100644 --- a/ui/manifests/deployment.yaml +++ b/ui/manifests/deployment.yaml @@ -18,7 +18,7 @@ spec: serviceAccountName: postgres-operator-ui containers: - name: "service" - image: ghcr.io/zalando/postgres-operator-ui:v2.0.1 + image: ghcr.io/zalando/postgres-operator-ui:v2.0.2 ports: - containerPort: 8081 protocol: "TCP" From cabc2f811777fbcba40ceb7963e08a6246c5a17e Mon Sep 17 00:00:00 2001 From: Ida Novindasari Date: Tue, 1 Sep 2026 17:22:32 +0200 Subject: [PATCH 09/13] pgbouncer: change auth_type to use scram sha 256 (#3177) --- pooler/pgbouncer.ini.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pooler/pgbouncer.ini.tmpl b/pooler/pgbouncer.ini.tmpl index c26cf1453..285caac36 100644 --- a/pooler/pgbouncer.ini.tmpl +++ b/pooler/pgbouncer.ini.tmpl @@ -13,7 +13,7 @@ stats_users = $INFRASTRUCTURE_ROLES auth_dbname = postgres auth_file = /etc/pgbouncer/userlist.txt auth_query = SELECT * FROM $PGSCHEMA.user_lookup($1) -auth_type = md5 +auth_type = scram-sha-256 logfile = /var/log/pgbouncer/pgbouncer.log pidfile = /var/run/pgbouncer/pgbouncer.pid From 6e85bc044d26da532e4f18a4c3daf2abd7c10bde Mon Sep 17 00:00:00 2001 From: Tiago Condeixa Date: Thu, 3 Sep 2026 11:00:49 +0200 Subject: [PATCH 10/13] Pass CLONE_AWS_REGION and STANDBY_AWS_REGION when using IRSA (#3180) --- pkg/cluster/k8sres.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index 7ed3cd4d6..44bd64e07 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -2226,6 +2226,7 @@ func (c *Cluster) generateCloneEnvironment(description *acidv1.CloneDescription) if c.OpConfig.IRSARoleARN != "" { result = append(result, v1.EnvVar{Name: "CLONE_AWS_ROLE_ARN", Value: c.OpConfig.IRSARoleARN}) result = append(result, v1.EnvVar{Name: "CLONE_AWS_WEB_IDENTITY_TOKEN_FILE", Value: "/var/run/secrets/eks.amazonaws.com/serviceaccount/token"}) + result = append(result, v1.EnvVar{Name: "CLONE_AWS_REGION", Value: c.OpConfig.AWSRegion}) } return result @@ -2276,6 +2277,7 @@ func (c *Cluster) generateStandbyEnvironment(description *acidv1.StandbyDescript if c.OpConfig.IRSARoleARN != "" { result = append(result, v1.EnvVar{Name: "STANDBY_AWS_ROLE_ARN", Value: c.OpConfig.IRSARoleARN}) result = append(result, v1.EnvVar{Name: "STANDBY_AWS_WEB_IDENTITY_TOKEN_FILE", Value: "/var/run/secrets/eks.amazonaws.com/serviceaccount/token"}) + result = append(result, v1.EnvVar{Name: "STANDBY_AWS_REGION", Value: c.OpConfig.AWSRegion}) } return result From c35324d4e725f8c4626f7271351834d88534d2cc Mon Sep 17 00:00:00 2001 From: Tiago Condeixa Date: Wed, 16 Sep 2026 14:41:27 +0200 Subject: [PATCH 11/13] Set SPILO_PROVIDER=aws when IRSA is configured (#3185) Signed-off-by: tcondeixa --- pkg/cluster/k8sres.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index 44bd64e07..2353e464f 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -1101,6 +1101,10 @@ func (c *Cluster) generateSpiloPodEnvVars( opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "LOG_BUCKET_SCOPE_PREFIX", Value: ""}) } + if c.OpConfig.IRSARoleARN != "" { + opConfigEnvVars = append(opConfigEnvVars, v1.EnvVar{Name: "SPILO_PROVIDER", Value: "aws"}) + } + envVars = appendEnvVars(envVars, opConfigEnvVars...) return envVars, nil From 4c2366a8d8cc444dc14d46e1109e60e9243b1e11 Mon Sep 17 00:00:00 2001 From: Felix Kunde Date: Tue, 22 Sep 2026 11:24:43 +0200 Subject: [PATCH 12/13] make sure values.yaml file is included in ui chart (#3178) --- charts/postgres-operator-ui/index.yaml | 62 +++--------------- .../postgres-operator-ui-2.0.0.tgz | Bin 5087 -> 0 bytes .../postgres-operator-ui-2.0.1.tgz | Bin 5091 -> 0 bytes .../postgres-operator-ui-2.0.2.tgz | Bin 3787 -> 5223 bytes 4 files changed, 8 insertions(+), 54 deletions(-) delete mode 100644 charts/postgres-operator-ui/postgres-operator-ui-2.0.0.tgz delete mode 100644 charts/postgres-operator-ui/postgres-operator-ui-2.0.1.tgz diff --git a/charts/postgres-operator-ui/index.yaml b/charts/postgres-operator-ui/index.yaml index c76c25f0a..ced2f08db 100644 --- a/charts/postgres-operator-ui/index.yaml +++ b/charts/postgres-operator-ui/index.yaml @@ -3,10 +3,10 @@ entries: postgres-operator-ui: - apiVersion: v2 appVersion: 2.0.2 - created: "2026-08-12T16:14:09.689921+02:00" + created: "2026-09-01T16:41:12.626492+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience - digest: 2dea5c2768a611ec90f3531e32336c2be988e4a6cf2c4cc231835290b2863017 + digest: 748ca68be5f190ecf2f80b547f3d3d4e473b9ea0735feb7f39692eb22f682d8e home: https://github.com/zalando/postgres-operator keywords: - postgres @@ -24,55 +24,9 @@ entries: urls: - postgres-operator-ui-2.0.2.tgz version: 2.0.2 - - apiVersion: v2 - appVersion: 2.0.1 - created: "2026-08-12T16:14:09.689744+02:00" - description: Postgres Operator UI provides a graphical interface for a convenient - database-as-a-service user experience - digest: 9bd0cfb82bc9e849fc01fe5a2d14e42941d102d719ff6a182a5a63237138c2a3 - home: https://github.com/zalando/postgres-operator - keywords: - - postgres - - operator - - ui - - cloud-native - - patroni - - spilo - maintainers: - - email: opensource@zalando.de - name: Zalando - name: postgres-operator-ui - sources: - - https://github.com/zalando/postgres-operator - urls: - - postgres-operator-ui-2.0.1.tgz - version: 2.0.1 - - apiVersion: v2 - appVersion: 2.0.0 - created: "2026-08-12T16:14:09.689359+02:00" - description: Postgres Operator UI provides a graphical interface for a convenient - database-as-a-service user experience - digest: 80098eb9290d77fcaaf813347386c3b7d34de0d4e846b50ac177d4ac4a9e2ecb - home: https://github.com/zalando/postgres-operator - keywords: - - postgres - - operator - - ui - - cloud-native - - patroni - - spilo - maintainers: - - email: opensource@zalando.de - name: Zalando - name: postgres-operator-ui - sources: - - https://github.com/zalando/postgres-operator - urls: - - postgres-operator-ui-2.0.0.tgz - version: 2.0.0 - apiVersion: v2 appVersion: 1.15.1 - created: "2026-08-12T16:14:09.688865+02:00" + created: "2026-09-01T16:41:12.626235+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: 4bbb750934366038d692711f924151182b7be131b6822d011f5a4e51cf609482 @@ -95,7 +49,7 @@ entries: version: 1.15.1 - apiVersion: v2 appVersion: 1.14.0 - created: "2026-08-12T16:14:09.688617+02:00" + created: "2026-09-01T16:41:12.625981+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: e87ed898079a852957a67a4caf3fbd27b9098e413f5d961b7a771a6ae8b3e17c @@ -118,7 +72,7 @@ entries: version: 1.14.0 - apiVersion: v2 appVersion: 1.13.0 - created: "2026-08-12T16:14:09.688362+02:00" + created: "2026-09-01T16:41:12.625703+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: e0444e516b50f82002d1a733527813c51759a627cefdd1005cea73659f824ea8 @@ -141,7 +95,7 @@ entries: version: 1.13.0 - apiVersion: v2 appVersion: 1.12.2 - created: "2026-08-12T16:14:09.68809+02:00" + created: "2026-09-01T16:41:12.625439+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: cbcef400c23ccece27d97369ad629278265c013e0a45c0b7f33e7568a082fedd @@ -164,7 +118,7 @@ entries: version: 1.12.2 - apiVersion: v2 appVersion: 1.11.0 - created: "2026-08-12T16:14:09.687752+02:00" + created: "2026-09-01T16:41:12.625156+02:00" description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience digest: a45f2284045c2a9a79750a36997386444f39b01ac722b17c84b431457577a3a2 @@ -185,4 +139,4 @@ entries: urls: - postgres-operator-ui-1.11.0.tgz version: 1.11.0 -generated: "2026-08-12T16:14:09.687119+02:00" +generated: "2026-09-01T16:41:12.624491+02:00" diff --git a/charts/postgres-operator-ui/postgres-operator-ui-2.0.0.tgz b/charts/postgres-operator-ui/postgres-operator-ui-2.0.0.tgz deleted file mode 100644 index 66886b83a3376adcdccb005518e8406f8f1b4954..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5087 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 B_RIhP diff --git a/charts/postgres-operator-ui/postgres-operator-ui-2.0.1.tgz b/charts/postgres-operator-ui/postgres-operator-ui-2.0.1.tgz deleted file mode 100644 index fc12a17ff9192143029b78468bfdf8b26e3e41e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5091 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 From 470f4157a44544bfe1f7961f26f43bb3874787f3 Mon Sep 17 00:00:00 2001 From: Pooja Dixit Date: Tue, 22 Sep 2026 02:30:55 -0700 Subject: [PATCH 13/13] Retry moveMasterPodsOffNode on failure instead of aborting (#3179) attemptToMoveMasterPodsOffNode's transient errors (e.g. no synced standby available yet) were treated as terminal, so the retry loop gave up after a single ~4-5s attempt instead of retrying over master_pod_move_timeout. This left masters stuck on draining nodes indefinitely once a PodDisruptionBudget started rejecting evictions. Log the failure and return (false, nil) so the retry loop keeps polling every minute until the timeout expires. Fixes #3176 --- docs/reference/operator_parameters.md | 7 +++--- pkg/controller/node.go | 3 ++- pkg/controller/node_test.go | 36 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/docs/reference/operator_parameters.md b/docs/reference/operator_parameters.md index 5b56d98af..f120dfce0 100644 --- a/docs/reference/operator_parameters.md +++ b/docs/reference/operator_parameters.md @@ -556,9 +556,10 @@ configuration they are grouped under the `kubernetes` key. * **master_pod_move_timeout** The period of time to wait for the success of migration of master pods from an unschedulable node. The migration includes Patroni switchovers to - respective replicas on healthy nodes. The situation where master pods still - exist on the old node after this timeout expires has to be fixed manually. - The default is 20 minutes. + respective replicas on healthy nodes. A failed migration attempt is retried + every minute until this timeout expires. The situation where master pods + still exist on the old node after this timeout expires has to be fixed + manually. The default is 20 minutes. * **enable_pod_antiaffinity** toggles [pod anti affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) diff --git a/pkg/controller/node.go b/pkg/controller/node.go index d962190be..416e2f6c0 100644 --- a/pkg/controller/node.go +++ b/pkg/controller/node.go @@ -156,7 +156,8 @@ func (c *Controller) moveMasterPodsOffNode(node *v1.Node) { func() (bool, error) { err := c.attemptToMoveMasterPodsOffNode(node) if err != nil { - return false, err + c.logger.Warningf("attempt to move master pods off node %q failed, will retry: %v", node.Name, err) + return false, nil } return true, nil }, diff --git a/pkg/controller/node_test.go b/pkg/controller/node_test.go index b9326d9ef..9afaee040 100644 --- a/pkg/controller/node_test.go +++ b/pkg/controller/node_test.go @@ -1,11 +1,18 @@ package controller import ( + "fmt" + "strings" "testing" + "time" + logrustest "github.com/sirupsen/logrus/hooks/test" "github.com/zalando/postgres-operator/v2/pkg/spec" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" + k8stesting "k8s.io/client-go/testing" ) const ( @@ -93,3 +100,32 @@ func TestNodeIsReady(t *testing.T) { } } } + +// TestMoveMasterPodsOffNodeRetriesOnError ensures a failed attempt to move +// master pods off a node is retried rather than aborting the whole retry +// loop on the first error. +func TestMoveMasterPodsOffNodeRetriesOnError(t *testing.T) { + clientSet := fake.NewSimpleClientset() + clientSet.PrependReactor("list", "pods", func(action k8stesting.Action) (bool, runtime.Object, error) { + return true, nil, fmt.Errorf("could not list pods") + }) + + controller := newNodeTestController() + controller.KubeClient.PodsGetter = clientSet.CoreV1() + // timeout == the retry interval hardcoded in moveMasterPodsOffNode, so + // the single retry attempt resolves synchronously without a real sleep. + controller.opConfig.MasterPodMoveTimeout = &metav1.Duration{Duration: 1 * time.Minute} + + logger, hook := logrustest.NewNullLogger() + controller.logger = logger.WithField("pkg", "controller") + + controller.moveMasterPodsOffNode(makeNode(map[string]string{}, false)) + + lastEntry := hook.LastEntry() + if lastEntry == nil { + t.Fatal("expected moveMasterPodsOffNode to log a warning") + } + if !strings.Contains(lastEntry.Message, "still failing after") { + t.Errorf("expected the retry loop to run out of attempts instead of aborting on the first error, got log message: %q", lastEntry.Message) + } +}