Merge branch 'master' into validate-resources
This commit is contained in:
		
						commit
						25ab3d0df6
					
				
							
								
								
									
										2
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										2
									
								
								Makefile
								
								
								
								
							|  | @ -88,7 +88,7 @@ vet: | |||
| 	@go vet $(PKG) | ||||
| 	@staticcheck $(PKG) | ||||
| 
 | ||||
| deps: | ||||
| deps: tools | ||||
| 	GO111MODULE=on go mod vendor | ||||
| 
 | ||||
| test: | ||||
|  |  | |||
|  | @ -0,0 +1,300 @@ | |||
| apiVersion: apiextensions.k8s.io/v1beta1 | ||||
| kind: CustomResourceDefinition | ||||
| metadata: | ||||
|   name: operatorconfigurations.acid.zalan.do | ||||
|   labels: | ||||
|     app.kubernetes.io/name: postgres-operator | ||||
|   annotations: | ||||
|     "helm.sh/hook": crd-install | ||||
| spec: | ||||
|   group: acid.zalan.do | ||||
|   names: | ||||
|     kind: OperatorConfiguration | ||||
|     listKind: OperatorConfigurationList | ||||
|     plural: operatorconfigurations | ||||
|     singular: operatorconfiguration | ||||
|     shortNames: | ||||
|     - opconfig | ||||
|   additionalPrinterColumns: | ||||
|   - name: Image | ||||
|     type: string | ||||
|     description: Spilo image to be used for Pods | ||||
|     JSONPath: .configuration.docker_image | ||||
|   - name: Cluster-Label | ||||
|     type: string | ||||
|     description: Label for K8s resources created by operator | ||||
|     JSONPath: .configuration.kubernetes.cluster_name_label | ||||
|   - name: Service-Account | ||||
|     type: string | ||||
|     description: Name of service account to be used | ||||
|     JSONPath: .configuration.kubernetes.pod_service_account_name | ||||
|   - name: Min-Instances | ||||
|     type: integer | ||||
|     description: Minimum number of instances per Postgres cluster | ||||
|     JSONPath: .configuration.min_instances | ||||
|   - name: Age | ||||
|     type: date | ||||
|     JSONPath: .metadata.creationTimestamp | ||||
|   scope: Namespaced | ||||
|   subresources: | ||||
|     status: {} | ||||
|   version: v1 | ||||
|   validation: | ||||
|     openAPIV3Schema: | ||||
|       type: object | ||||
|       required: | ||||
|         - kind | ||||
|         - apiVersion | ||||
|         - configuration | ||||
|       properties: | ||||
|         kind: | ||||
|           type: string | ||||
|           enum: | ||||
|             - OperatorConfiguration | ||||
|         apiVersion: | ||||
|           type: string | ||||
|           enum: | ||||
|             - acid.zalan.do/v1 | ||||
|         configuration: | ||||
|           type: object | ||||
|           properties: | ||||
|             docker_image: | ||||
|               type: string | ||||
|             enable_crd_validation: | ||||
|               type: boolean | ||||
|             enable_shm_volume: | ||||
|               type: boolean | ||||
|             etcd_host: | ||||
|               type: string | ||||
|             max_instances: | ||||
|               type: integer | ||||
|               minimum: -1  # -1 = disabled | ||||
|             min_instances: | ||||
|               type: integer | ||||
|               minimum: -1  # -1 = disabled | ||||
|             resync_period: | ||||
|               type: string | ||||
|             repair_period: | ||||
|               type: string | ||||
|             set_memory_request_to_limit: | ||||
|               type: boolean | ||||
|             sidecar_docker_images: | ||||
|               type: object | ||||
|               additionalProperties: | ||||
|                 type: string | ||||
|             workers: | ||||
|               type: integer | ||||
|               minimum: 1 | ||||
|             users: | ||||
|               type: object | ||||
|               properties: | ||||
|                 replication_username: | ||||
|                    type: string | ||||
|                 super_username: | ||||
|                    type: string | ||||
|             kubernetes: | ||||
|               type: object | ||||
|               properties: | ||||
|                 cluster_domain: | ||||
|                   type: string | ||||
|                 cluster_labels: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 cluster_name_label: | ||||
|                   type: string | ||||
|                 custom_pod_annotations: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 enable_pod_antiaffinity: | ||||
|                   type: boolean | ||||
|                 enable_pod_disruption_budget: | ||||
|                   type: boolean | ||||
|                 infrastructure_roles_secret_name: | ||||
|                   type: string | ||||
|                 inherited_labels: | ||||
|                   type: array | ||||
|                   items: | ||||
|                     type: string | ||||
|                 node_readiness_label: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 oauth_token_secret_name: | ||||
|                   type: string | ||||
|                 pdb_name_format: | ||||
|                   type: string | ||||
|                 pod_antiaffinity_topology_key: | ||||
|                   type: string | ||||
|                 pod_environment_configmap: | ||||
|                   type: string | ||||
|                 pod_management_policy: | ||||
|                   type: string | ||||
|                   enum: | ||||
|                     - "ordered_ready" | ||||
|                     - "parallel" | ||||
|                 pod_role_label: | ||||
|                   type: string | ||||
|                 pod_service_account_name: | ||||
|                   type: string | ||||
|                 pod_terminate_grace_period: | ||||
|                   type: string | ||||
|                 secret_name_template: | ||||
|                   type: string | ||||
|                 spilo_fsgroup: | ||||
|                   type: integer | ||||
|                 spilo_privileged: | ||||
|                   type: boolean | ||||
|                 toleration: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 watched_namespace: | ||||
|                   type: string | ||||
|             postgres_pod_resources: | ||||
|               type: object | ||||
|               properties: | ||||
|                 default_cpu_limit: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+m|\d+(\.\d{1,3})?)$' | ||||
|                 default_cpu_request: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+m|\d+(\.\d{1,3})?)$' | ||||
|                 default_memory_limit: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                 default_memory_request: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|             timeouts: | ||||
|               type: object | ||||
|               properties: | ||||
|                 pod_label_wait_timeout: | ||||
|                   type: string | ||||
|                 pod_deletion_wait_timeout: | ||||
|                   type: string | ||||
|                 ready_wait_interval: | ||||
|                   type: string | ||||
|                 ready_wait_timeout: | ||||
|                   type: string | ||||
|                 resource_check_interval: | ||||
|                   type: string | ||||
|                 resource_check_timeout: | ||||
|                   type: string | ||||
|             load_balancer: | ||||
|               type: object | ||||
|               properties: | ||||
|                 db_hosted_zone: | ||||
|                   type: string | ||||
|                 enable_master_load_balancer: | ||||
|                   type: boolean | ||||
|                 enable_replica_load_balancer: | ||||
|                   type: boolean | ||||
|                 custom_service_annotations: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 master_dns_name_format: | ||||
|                   type: string | ||||
|                 replica_dns_name_format: | ||||
|                   type: string | ||||
|             aws_or_gcp: | ||||
|               type: object | ||||
|               properties: | ||||
|                 additional_secret_mount: | ||||
|                   type: string | ||||
|                 additional_secret_mount_path: | ||||
|                   type: string | ||||
|                 aws_region: | ||||
|                   type: string | ||||
|                 kube_iam_role: | ||||
|                   type: string | ||||
|                 log_s3_bucket: | ||||
|                   type: string | ||||
|                 wal_s3_bucket: | ||||
|                   type: string | ||||
|             logical_backup: | ||||
|               type: object | ||||
|               properties: | ||||
|                 logical_backup_schedule: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$' | ||||
|                 logical_backup_docker_image: | ||||
|                   type: string | ||||
|                 logical_backup_s3_bucket: | ||||
|                   type: string | ||||
|                 logical_backup_s3_endpoint: | ||||
|                   type: string | ||||
|                 logical_backup_s3_sse: | ||||
|                   type: string | ||||
|                 logical_backup_s3_access_key_id: | ||||
|                   type: string | ||||
|                 logical_backup_s3_secret_access_key: | ||||
|                   type: string | ||||
|             debug: | ||||
|               type: object | ||||
|               properties: | ||||
|                 debug_logging: | ||||
|                   type: boolean | ||||
|                 enable_database_access: | ||||
|                   type: boolean | ||||
|             teams_api: | ||||
|               type: object | ||||
|               properties: | ||||
|                 enable_admin_role_for_users: | ||||
|                   type: boolean | ||||
|                 enable_team_superuser: | ||||
|                   type: boolean | ||||
|                 enable_teams_api: | ||||
|                   type: boolean | ||||
|                 pam_configuration: | ||||
|                   type: string | ||||
|                 pam_role_name: | ||||
|                   type: string | ||||
|                 postgres_superuser_teams: | ||||
|                   type: array | ||||
|                   items: | ||||
|                     type: string | ||||
|                 protected_role_names: | ||||
|                   type: array | ||||
|                   items: | ||||
|                     type: string | ||||
|                 team_admin_role: | ||||
|                   type: string | ||||
|                 team_api_role_configuration: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 teams_api_url: | ||||
|                   type: string | ||||
|             logging_rest_api: | ||||
|               type: object | ||||
|               properties: | ||||
|                 api_port: | ||||
|                   type: integer | ||||
|                 cluster_history_entries: | ||||
|                   type: integer | ||||
|                 ring_log_lines: | ||||
|                   type: integer | ||||
|             scalyr: | ||||
|               type: object | ||||
|               properties: | ||||
|                 scalyr_api_key: | ||||
|                   type: string | ||||
|                 scalyr_cpu_limit: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+m|\d+(\.\d{1,3})?)$' | ||||
|                 scalyr_cpu_request: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+m|\d+(\.\d{1,3})?)$' | ||||
|                 scalyr_image: | ||||
|                   type: string | ||||
|                 scalyr_memory_limit: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                 scalyr_memory_request: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                 scalyr_server_url: | ||||
|                   type: string | ||||
|  | @ -0,0 +1,363 @@ | |||
| apiVersion: apiextensions.k8s.io/v1beta1 | ||||
| kind: CustomResourceDefinition | ||||
| metadata: | ||||
|   name: postgresqls.acid.zalan.do | ||||
|   labels: | ||||
|     app.kubernetes.io/name: postgres-operator | ||||
|   annotations: | ||||
|     "helm.sh/hook": crd-install | ||||
| spec: | ||||
|   group: acid.zalan.do | ||||
|   names: | ||||
|     kind: postgresql | ||||
|     listKind: postgresqlList | ||||
|     plural: postgresqls | ||||
|     singular: postgresql | ||||
|     shortNames: | ||||
|     - pg | ||||
|   additionalPrinterColumns: | ||||
|   - name: Team | ||||
|     type: string | ||||
|     description: Team responsible for Postgres CLuster | ||||
|     JSONPath: .spec.teamId | ||||
|   - name: Version | ||||
|     type: string | ||||
|     description: PostgreSQL version | ||||
|     JSONPath: .spec.postgresql.version | ||||
|   - name: Pods | ||||
|     type: integer | ||||
|     description: Number of Pods per Postgres cluster | ||||
|     JSONPath: .spec.numberOfInstances | ||||
|   - name: Volume | ||||
|     type: string | ||||
|     description: Size of the bound volume | ||||
|     JSONPath: .spec.volume.size | ||||
|   - name: CPU-Request | ||||
|     type: string | ||||
|     description: Requested CPU for Postgres containers | ||||
|     JSONPath: .spec.resources.requests.cpu | ||||
|   - name: Memory-Request | ||||
|     type: string | ||||
|     description: Requested memory for Postgres containers | ||||
|     JSONPath: .spec.resources.requests.memory | ||||
|   - name: Age | ||||
|     type: date | ||||
|     JSONPath: .metadata.creationTimestamp | ||||
|   - name: Status | ||||
|     type: string | ||||
|     description: Current sync status of postgresql resource | ||||
|     JSONPath: .status.PostgresClusterStatus | ||||
|   scope: Namespaced | ||||
|   subresources: | ||||
|     status: {} | ||||
|   version: v1 | ||||
|   validation: | ||||
|     openAPIV3Schema: | ||||
|       type: object | ||||
|       required: | ||||
|         - kind | ||||
|         - apiVersion | ||||
|         - spec | ||||
|       properties: | ||||
|         kind: | ||||
|           type: string | ||||
|           enum: | ||||
|             - postgresql | ||||
|         apiVersion: | ||||
|           type: string | ||||
|           enum: | ||||
|             - acid.zalan.do/v1 | ||||
|         spec: | ||||
|           type: object | ||||
|           required: | ||||
|             - numberOfInstances | ||||
|             - teamId | ||||
|             - postgresql | ||||
|           properties: | ||||
|             allowedSourceRanges: | ||||
|               type: array | ||||
|               nullable: true | ||||
|               items: | ||||
|                 type: string | ||||
|                 pattern: '^(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\/(\d|[1-2]\d|3[0-2])$' | ||||
|             clone: | ||||
|               type: object | ||||
|               required: | ||||
|                 - cluster | ||||
|               properties: | ||||
|                 cluster: | ||||
|                   type: string | ||||
|                 s3_endpoint: | ||||
|                   type: string | ||||
|                 s3_access_key_id: | ||||
|                   type: string | ||||
|                 s3_secret_access_key: | ||||
|                   type: string | ||||
|                 s3_force_path_style: | ||||
|                   type: string | ||||
|                 s3_wal_path: | ||||
|                   type: string | ||||
|                 timestamp: | ||||
|                   type: string | ||||
|                   pattern: '^([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([+-]([01][0-9]|2[0-3]):[0-5][0-9]))$' | ||||
|                   # The regexp matches the date-time format (RFC 3339 Section 5.6) that specifies a timezone as an offset relative to UTC | ||||
|                   # Example: 1996-12-19T16:39:57-08:00 | ||||
|                   # Note: this field requires a timezone | ||||
|                 uid: | ||||
|                   format: uuid | ||||
|                   type: string | ||||
|             databases: | ||||
|               type: object | ||||
|               additionalProperties: | ||||
|                 type: string | ||||
|               # Note: usernames specified here as database owners must be declared in the users key of the spec key. | ||||
|             dockerImage: | ||||
|               type: string | ||||
|             enableLogicalBackup: | ||||
|               type: boolean | ||||
|             enableMasterLoadBalancer: | ||||
|               type: boolean | ||||
|             enableReplicaLoadBalancer: | ||||
|               type: boolean | ||||
|             enableShmVolume: | ||||
|               type: boolean | ||||
|             init_containers:  # deprecated | ||||
|               type: array | ||||
|               nullable: true | ||||
|               items: | ||||
|                 type: object | ||||
|                 additionalProperties: true | ||||
|             initContainers: | ||||
|               type: array | ||||
|               nullable: true | ||||
|               items: | ||||
|                 type: object | ||||
|                 additionalProperties: true | ||||
|             logicalBackupSchedule: | ||||
|               type: string | ||||
|               pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$' | ||||
|             maintenanceWindows: | ||||
|               type: array | ||||
|               items: | ||||
|                 type: string | ||||
|                 pattern: '^\ *((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))-((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))\ *$' | ||||
|             numberOfInstances: | ||||
|               type: integer | ||||
|               minimum: 0 | ||||
|             patroni: | ||||
|               type: object | ||||
|               properties: | ||||
|                 initdb: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 pg_hba: | ||||
|                   type: array | ||||
|                   items: | ||||
|                     type: string | ||||
|                 slots: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: object | ||||
|                     additionalProperties: | ||||
|                       type: string | ||||
|                 ttl: | ||||
|                   type: integer | ||||
|                 loop_wait: | ||||
|                   type: integer | ||||
|                 retry_timeout: | ||||
|                   type: integer | ||||
|                 maximum_lag_on_failover: | ||||
|                   type: integer | ||||
|             podAnnotations: | ||||
|               type: object | ||||
|               additionalProperties: | ||||
|                 type: string | ||||
|             pod_priority_class_name:  # deprecated | ||||
|               type: string | ||||
|             podPriorityClassName: | ||||
|               type: string | ||||
|             postgresql: | ||||
|               type: object | ||||
|               required: | ||||
|                 - version | ||||
|               properties: | ||||
|                 version: | ||||
|                   type: string | ||||
|                   enum: | ||||
|                     - "9.3" | ||||
|                     - "9.4" | ||||
|                     - "9.5" | ||||
|                     - "9.6" | ||||
|                     - "10" | ||||
|                     - "11" | ||||
|                     - "12" | ||||
|                 parameters: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|             replicaLoadBalancer:  # deprecated | ||||
|               type: boolean | ||||
|             resources: | ||||
|               type: object | ||||
|               required: | ||||
|                 - requests | ||||
|                 - limits | ||||
|               properties: | ||||
|                 limits: | ||||
|                   type: object | ||||
|                   required: | ||||
|                     - cpu | ||||
|                     - memory | ||||
|                   properties: | ||||
|                     cpu: | ||||
|                       type: string | ||||
|                       # Decimal natural followed by m, or decimal natural followed by | ||||
|                       # dot followed by up to three decimal digits. | ||||
|                       # | ||||
|                       # This is because the Kubernetes CPU resource has millis as the | ||||
|                       # maximum precision.  The actual values are checked in code | ||||
|                       # because the regular expression would be huge and horrible and | ||||
|                       # not very helpful in validation error messages; this one checks | ||||
|                       # only the format of the given number. | ||||
|                       # | ||||
|                       # https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu | ||||
|                       pattern: '^(\d+m|\d+\.\d{1,3})$' | ||||
|                       # Note: the value specified here must not be zero or be lower | ||||
|                       # than the corresponding request. | ||||
|                     memory: | ||||
|                       type: string | ||||
|                       # You can express memory as a plain integer or as a fixed-point | ||||
|                       # integer using one of these suffixes: E, P, T, G, M, k. You can | ||||
|                       # also use the power-of-two equivalents: Ei, Pi, Ti, Gi, Mi, Ki | ||||
|                       # | ||||
|                       # https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory | ||||
|                       pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                       # Note: the value specified here must not be zero or be lower | ||||
|                       # than the corresponding request. | ||||
|                 requests: | ||||
|                   type: object | ||||
|                   required: | ||||
|                     - cpu | ||||
|                     - memory | ||||
|                   properties: | ||||
|                     cpu: | ||||
|                       type: string | ||||
|                       # Decimal natural followed by m, or decimal natural followed by | ||||
|                       # dot followed by up to three decimal digits. | ||||
|                       # | ||||
|                       # This is because the Kubernetes CPU resource has millis as the | ||||
|                       # maximum precision.  The actual values are checked in code | ||||
|                       # because the regular expression would be huge and horrible and | ||||
|                       # not very helpful in validation error messages; this one checks | ||||
|                       # only the format of the given number. | ||||
|                       # | ||||
|                       # https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu | ||||
|                       pattern: '^(\d+m|\d+\.\d{1,3})$' | ||||
|                       # Note: the value specified here must not be zero or be higher | ||||
|                       # than the corresponding limit. | ||||
|                     memory: | ||||
|                       type: string | ||||
|                       # You can express memory as a plain integer or as a fixed-point | ||||
|                       # integer using one of these suffixes: E, P, T, G, M, k. You can | ||||
|                       # also use the power-of-two equivalents: Ei, Pi, Ti, Gi, Mi, Ki | ||||
|                       # | ||||
|                       # https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory | ||||
|                       pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                       # Note: the value specified here must not be zero or be higher | ||||
|                       # than the corresponding limit. | ||||
|             sidecars: | ||||
|               type: array | ||||
|               nullable: true | ||||
|               items: | ||||
|                 type: object | ||||
|                 additionalProperties: true | ||||
|             spiloFSGroup: | ||||
|               type: integer | ||||
|             standby: | ||||
|               type: object | ||||
|               required: | ||||
|                 - s3_wal_path | ||||
|               properties: | ||||
|                 s3_wal_path: | ||||
|                   type: string | ||||
|             teamId: | ||||
|               type: string | ||||
|             tolerations: | ||||
|               type: array | ||||
|               items: | ||||
|                 type: object | ||||
|                 required: | ||||
|                   - key | ||||
|                   - operator | ||||
|                   - effect | ||||
|                 properties: | ||||
|                   key: | ||||
|                     type: string | ||||
|                   operator: | ||||
|                     type: string | ||||
|                     enum: | ||||
|                       - Equal | ||||
|                       - Exists | ||||
|                   value: | ||||
|                     type: string | ||||
|                   effect: | ||||
|                     type: string | ||||
|                     enum: | ||||
|                       - NoExecute | ||||
|                       - NoSchedule | ||||
|                       - PreferNoSchedule | ||||
|                   tolerationSeconds: | ||||
|                     type: integer | ||||
|             useLoadBalancer:  # deprecated | ||||
|               type: boolean | ||||
|             users: | ||||
|               type: object | ||||
|               additionalProperties: | ||||
|                 type: array | ||||
|                 nullable: true | ||||
|                 description: "Role flags specified here must not contradict each other" | ||||
|                 items: | ||||
|                   type: string | ||||
|                   enum: | ||||
|                   - bypassrls | ||||
|                   - BYPASSRLS | ||||
|                   - nobypassrls | ||||
|                   - NOBYPASSRLS | ||||
|                   - createdb | ||||
|                   - CREATEDB | ||||
|                   - nocreatedb | ||||
|                   - NOCREATEDB | ||||
|                   - createrole | ||||
|                   - CREATEROLE | ||||
|                   - nocreaterole | ||||
|                   - NOCREATEROLE | ||||
|                   - inherit | ||||
|                   - INHERIT | ||||
|                   - noinherit | ||||
|                   - NOINHERIT | ||||
|                   - login | ||||
|                   - LOGIN | ||||
|                   - nologin | ||||
|                   - NOLOGIN | ||||
|                   - replication | ||||
|                   - REPLICATION | ||||
|                   - noreplication | ||||
|                   - NOREPLICATION | ||||
|                   - superuser | ||||
|                   - SUPERUSER | ||||
|                   - nosuperuser | ||||
|                   - NOSUPERUSER | ||||
|             volume: | ||||
|               type: object | ||||
|               required: | ||||
|                 - size | ||||
|               properties: | ||||
|                 size: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                   # Note: the value specified here must not be zero. | ||||
|                 storageClass: | ||||
|                   type: string | ||||
|                 subPath: | ||||
|                   type: string | ||||
|  | @ -0,0 +1,6 @@ | |||
| {{ if .Values.crd.create }} | ||||
| {{- range $path, $bytes := .Files.Glob "crds/*.yaml" }} | ||||
| {{ $.Files.Get $path }} | ||||
| --- | ||||
| {{- end }} | ||||
| {{- end }} | ||||
|  | @ -1,103 +0,0 @@ | |||
| {{ if .Values.crd.create }} | ||||
| apiVersion: apiextensions.k8s.io/v1beta1 | ||||
| kind: CustomResourceDefinition | ||||
| metadata: | ||||
|   name: postgresqls.acid.zalan.do | ||||
|   labels: | ||||
|     app.kubernetes.io/name: {{ template "postgres-operator.name" . }} | ||||
|     helm.sh/chart: {{ template "postgres-operator.chart" . }} | ||||
|     app.kubernetes.io/managed-by: {{ .Release.Service }} | ||||
|     app.kubernetes.io/instance: {{ .Release.Name }} | ||||
|   annotations: | ||||
|     "helm.sh/hook": crd-install | ||||
| spec: | ||||
|   group: acid.zalan.do | ||||
|   names: | ||||
|     kind: postgresql | ||||
|     listKind: postgresqlList | ||||
|     plural: postgresqls | ||||
|     singular: postgresql | ||||
|     shortNames: | ||||
|     - pg | ||||
|   additionalPrinterColumns: | ||||
|   - name: Team | ||||
|     type: string | ||||
|     description: Team responsible for Postgres CLuster | ||||
|     JSONPath: .spec.teamId | ||||
|   - name: Version | ||||
|     type: string | ||||
|     description: PostgreSQL version | ||||
|     JSONPath: .spec.postgresql.version | ||||
|   - name: Pods | ||||
|     type: integer | ||||
|     description: Number of Pods per Postgres cluster | ||||
|     JSONPath: .spec.numberOfInstances | ||||
|   - name: Volume | ||||
|     type: string | ||||
|     description: Size of the bound volume | ||||
|     JSONPath: .spec.volume.size | ||||
|   - name: CPU-Request | ||||
|     type: string | ||||
|     description: Requested CPU for Postgres containers | ||||
|     JSONPath: .spec.resources.requests.cpu | ||||
|   - name: Memory-Request | ||||
|     type: string | ||||
|     description: Requested memory for Postgres containers | ||||
|     JSONPath: .spec.resources.requests.memory | ||||
|   - name: Age | ||||
|     type: date | ||||
|     JSONPath: .metadata.creationTimestamp | ||||
|   - name: Status | ||||
|     type: string | ||||
|     description: Current sync status of postgresql resource | ||||
|     JSONPath: .status.PostgresClusterStatus | ||||
|   scope: Namespaced | ||||
|   subresources: | ||||
|     status: {} | ||||
|   version: v1 | ||||
| --- | ||||
| apiVersion: apiextensions.k8s.io/v1beta1 | ||||
| kind: CustomResourceDefinition | ||||
| metadata: | ||||
|   name: operatorconfigurations.acid.zalan.do | ||||
|   labels: | ||||
|     app.kubernetes.io/name: {{ template "postgres-operator.name" . }} | ||||
|     helm.sh/chart: {{ template "postgres-operator.chart" . }} | ||||
|     app.kubernetes.io/managed-by: {{ .Release.Service }} | ||||
|     app.kubernetes.io/instance: {{ .Release.Name }} | ||||
|   annotations: | ||||
|     "helm.sh/hook": crd-install | ||||
| spec: | ||||
|   group: acid.zalan.do | ||||
|   names: | ||||
|     kind: OperatorConfiguration | ||||
|     listKind: OperatorConfigurationList | ||||
|     plural: operatorconfigurations | ||||
|     singular: operatorconfiguration | ||||
|     shortNames: | ||||
|     - opconfig | ||||
|   additionalPrinterColumns: | ||||
|   - name: Image | ||||
|     type: string | ||||
|     description: Spilo image to be used for Pods | ||||
|     JSONPath: .configuration.docker_image | ||||
|   - name: Cluster-Label | ||||
|     type: string | ||||
|     description: Label for K8s resources created by operator | ||||
|     JSONPath: .configuration.kubernetes.cluster_name_label | ||||
|   - name: Service-Account | ||||
|     type: string | ||||
|     description: Name of service account to be used | ||||
|     JSONPath: .configuration.kubernetes.pod_service_account_name | ||||
|   - name: Min-Instances | ||||
|     type: integer | ||||
|     description: Minimum number of instances per Postgres cluster | ||||
|     JSONPath: .configuration.min_instances | ||||
|   - name: Age | ||||
|     type: date | ||||
|     JSONPath: .metadata.creationTimestamp | ||||
|   scope: Namespaced | ||||
|   subresources: | ||||
|     status: {} | ||||
|   version: v1 | ||||
| {{ end }} | ||||
|  | @ -14,7 +14,7 @@ configuration: | |||
| {{ toYaml .Values.configUsers | indent 4 }} | ||||
|   kubernetes: | ||||
|     oauth_token_secret_name: {{ template "postgres-operator.fullname" . }} | ||||
|     pod_service_account_name: operator | ||||
|     pod_service_account_name: {{ include "postgres-operator.serviceAccountName" . }} | ||||
| {{ toYaml .Values.configKubernetes | indent 4 }} | ||||
|   postgres_pod_resources: | ||||
| {{ toYaml .Values.configPostgresPodResources | indent 4 }} | ||||
|  |  | |||
|  | @ -17,6 +17,8 @@ configTarget: "OperatorConfigurationCRD" | |||
| 
 | ||||
| # general top-level configuration parameters | ||||
| configGeneral: | ||||
|   # choose if deployment creates/updates CRDs with OpenAPIV3Validation | ||||
|   enable_crd_validation: true | ||||
|   # start any new database pod without limitations on shm memory | ||||
|   enable_shm_volume: true | ||||
|   # etcd connection string for Patroni. Empty uses K8s-native DCS. | ||||
|  | @ -57,7 +59,10 @@ configKubernetes: | |||
|   # label assigned to Kubernetes objects created by the operator | ||||
|   cluster_name_label: cluster-name | ||||
|   # additional annotations to add to every database pod | ||||
|   custom_pod_annotations: | ||||
|   # custom_pod_annotations: | ||||
|   #   keya: valuea | ||||
|   #   keyb: valueb | ||||
| 
 | ||||
|   # toggles pod anti affinity on the Postgres pods | ||||
|   enable_pod_antiaffinity: false | ||||
|   # toggles PDB to set to MinAvailabe 0 or 1 | ||||
|  | @ -74,7 +79,8 @@ configKubernetes: | |||
|   # master_pod_move_timeout: 20m | ||||
| 
 | ||||
|   # set of labels that a running and active node should possess to be considered ready | ||||
|   # node_readiness_label: "" | ||||
|   # node_readiness_label: | ||||
|   #   status: ready | ||||
| 
 | ||||
|   # name of the secret containing the OAuth2 token to pass to the teams API | ||||
|   # oauth_token_secret_name: postgresql-operator | ||||
|  | @ -184,12 +190,20 @@ configAwsOrGcp: | |||
| 
 | ||||
| # configure K8s cron job managed by the operator | ||||
| configLogicalBackup: | ||||
|   # backup schedule in the cron format | ||||
|   logical_backup_schedule: "30 00 * * *" | ||||
|   # image for pods of the logical backup job (example runs pg_dumpall) | ||||
|   logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup" | ||||
|   # S3 Access Key ID | ||||
|   logical_backup_s3_access_key_id: "" | ||||
|   # S3 bucket to store backup results | ||||
|   logical_backup_s3_bucket: "my-bucket-url" | ||||
|   # S3 endpoint url when not using AWS | ||||
|   logical_backup_s3_endpoint: "" | ||||
|   # S3 Secret Access Key | ||||
|   logical_backup_s3_secret_access_key: "" | ||||
|   # S3 server side encription | ||||
|   logical_backup_s3_sse: "AES256" | ||||
|   # backup schedule in the cron format | ||||
|   logical_backup_schedule: "30 00 * * *" | ||||
| 
 | ||||
| # automate creation of human users with teams API service | ||||
| configTeamsApi: | ||||
|  | @ -206,7 +220,8 @@ configTeamsApi: | |||
|   # operator will add all team member roles to this group and add a pg_hba line | ||||
|   pam_role_name: zalandos | ||||
|   # List of teams which members need the superuser role in each Postgres cluster | ||||
|   # postgres_superuser_teams: "postgres_superusers" | ||||
|   # postgres_superuser_teams: | ||||
|   # - postgres_superusers | ||||
| 
 | ||||
|   # List of roles that cannot be overwritten by an application, team or infrastructure role | ||||
|   protected_role_names: | ||||
|  | @ -220,7 +235,7 @@ configTeamsApi: | |||
|   # teams_api_url: http://fake-teams-api.default.svc.cluster.local | ||||
| 
 | ||||
| # Scalyr is a log management tool that Zalando uses as a sidecar | ||||
| scalyr: | ||||
| configScalyr: | ||||
|   # API key for the Scalyr sidecar | ||||
|   # scalyr_api_key: "" | ||||
| 
 | ||||
|  | @ -249,9 +264,7 @@ serviceAccount: | |||
|   create: true | ||||
|   # The name of the ServiceAccount to use. | ||||
|   # If not set and create is true, a name is generated using the fullname template | ||||
|   # When relying solely on the OperatorConfiguration CRD, this value has to be "operator" | ||||
|   # Otherwise, the operator tries to use the "default" service account which is forbidden | ||||
|   name: operator | ||||
|   name: | ||||
| 
 | ||||
| priorityClassName: "" | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,6 +17,8 @@ configTarget: "ConfigMap" | |||
| 
 | ||||
| # general configuration parameters | ||||
| configGeneral: | ||||
|   # choose if deployment creates/updates CRDs with OpenAPIV3Validation | ||||
|   enable_crd_validation: "true" | ||||
|   # start any new database pod without limitations on shm memory | ||||
|   enable_shm_volume: "true" | ||||
|   # etcd connection string for Patroni. Empty uses K8s-native DCS. | ||||
|  | @ -55,7 +57,8 @@ configKubernetes: | |||
|   # label assigned to Kubernetes objects created by the operator | ||||
|   cluster_name_label: version | ||||
|   # annotations attached to each database pod | ||||
|   # custom_pod_annotations: keya:valuea | ||||
|   # custom_pod_annotations: keya:valuea,keyb:valueb | ||||
| 
 | ||||
|   # toggles pod anti affinity on the Postgres pods | ||||
|   enable_pod_antiaffinity: "false" | ||||
|   # toggles PDB to set to MinAvailabe 0 or 1 | ||||
|  | @ -136,9 +139,9 @@ configLoadBalancer: | |||
|   # toggles service type load balancer pointing to the replica pod of the cluster | ||||
|   enable_replica_load_balancer: "false" | ||||
|   # defines the DNS name string template for the master load balancer cluster | ||||
|   master_dns_name_format: '{cluster}.{team}.staging.{hostedzone}' | ||||
|   master_dns_name_format: '{cluster}.{team}.{hostedzone}' | ||||
|   # defines the DNS name string template for the replica load balancer cluster | ||||
|   replica_dns_name_format: '{cluster}-repl.{team}.staging.{hostedzone}' | ||||
|   replica_dns_name_format: '{cluster}-repl.{team}.{hostedzone}' | ||||
| 
 | ||||
| # options to aid debugging of the operator itself | ||||
| configDebug: | ||||
|  | @ -178,12 +181,20 @@ configAwsOrGcp: | |||
| 
 | ||||
| # configure K8s cron job managed by the operator | ||||
| configLogicalBackup: | ||||
|   # backup schedule in the cron format | ||||
|   logical_backup_schedule: "30 00 * * *" | ||||
|   # image for pods of the logical backup job (example runs pg_dumpall) | ||||
|   logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup" | ||||
|   # S3 Access Key ID | ||||
|   logical_backup_s3_access_key_id: "" | ||||
|   # S3 bucket to store backup results | ||||
|   logical_backup_s3_bucket: "my-bucket-url" | ||||
|   # S3 endpoint url when not using AWS | ||||
|   logical_backup_s3_endpoint: "" | ||||
|   # S3 Secret Access Key | ||||
|   logical_backup_s3_secret_access_key: "" | ||||
|   # S3 server side encription | ||||
|   logical_backup_s3_sse: "AES256" | ||||
|   # backup schedule in the cron format | ||||
|   logical_backup_schedule: "30 00 * * *" | ||||
| 
 | ||||
| # automate creation of human users with teams API service | ||||
| configTeamsApi: | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ pipeline: | |||
|               IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator-test | ||||
|             fi | ||||
|             export IMAGE | ||||
|             make tools deps docker | ||||
|             make deps docker | ||||
|         - desc: 'Run unit tests' | ||||
|           cmd: | | ||||
|             export PATH=$PATH:$HOME/go/bin | ||||
|  |  | |||
|  | @ -38,11 +38,13 @@ function aws_upload { | |||
|     # NB: $LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX already contains the leading "/" when set by the Postgres Operator | ||||
|     PATH_TO_BACKUP=s3://$LOGICAL_BACKUP_S3_BUCKET"/spilo/"$SCOPE$LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX"/logical_backups/"$(date +%s).sql.gz | ||||
| 
 | ||||
|     if [ -z "$EXPECTED_SIZE" ]; then | ||||
|         aws s3 cp - "$PATH_TO_BACKUP" --debug --sse="AES256" | ||||
|     else | ||||
|         aws s3 cp - "$PATH_TO_BACKUP" --debug --expected-size "$EXPECTED_SIZE" --sse="AES256" | ||||
|     fi; | ||||
|     args=() | ||||
| 
 | ||||
|     [[ ! -z "$EXPECTED_SIZE" ]] && args+=("--expected-size=$EXPECTED_SIZE") | ||||
|     [[ ! -z "$LOGICAL_BACKUP_S3_ENDPOINT" ]] && args+=("--endpoint-url=\"$LOGICAL_BACKUP_S3_ENDPOINT\"") | ||||
|     [[ ! "$LOGICAL_BACKUP_S3_SSE" == "" ]] && args+=("--sse=\"$LOGICAL_BACKUP_S3_SSE\"") | ||||
| 
 | ||||
|     aws s3 cp - "$PATH_TO_BACKUP" "${args[@]//\'/}" --debug | ||||
| } | ||||
| 
 | ||||
| function get_pods { | ||||
|  |  | |||
|  | @ -3,6 +3,30 @@ | |||
| Learn how to configure and manage the Postgres Operator in your Kubernetes (K8s) | ||||
| environment. | ||||
| 
 | ||||
| ## CRD Validation | ||||
| 
 | ||||
| [CustomResourceDefinitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions) | ||||
| will be registered with schema validation by default when the operator is | ||||
| deployed. The `OperatorConfiguration` CRD will only get created if the | ||||
| `POSTGRES_OPERATOR_CONFIGURATION_OBJECT` [environment variable](../manifests/postgres-operator.yaml#L36) | ||||
| in the deployment yaml is set and not empty. | ||||
| 
 | ||||
| When submitting manifests of [`postgresql`](../manifests/postgresql.crd.yaml) or | ||||
| [`OperatorConfiguration`](../manifests/operatorconfiguration.crd.yaml) custom | ||||
| resources with kubectl, validation can be bypassed with `--validate=false`. The | ||||
| operator can also be configured to not register CRDs with validation on `ADD` or | ||||
| `UPDATE` events. Running instances are not affected when enabling the validation | ||||
| afterwards unless the manifests is not changed then. Note, that the provided CRD | ||||
| manifests contain the validation for users to understand what schema is | ||||
| enforced. | ||||
| 
 | ||||
| Once the validation is enabled it can only be disabled manually by editing or | ||||
| patching the CRD manifest: | ||||
| 
 | ||||
| ```bash | ||||
| zk8 patch crd postgresqls.acid.zalan.do -p '{"spec":{"validation": null}}' | ||||
| ``` | ||||
| 
 | ||||
| ## Namespaces | ||||
| 
 | ||||
| ### Select the namespace to deploy to | ||||
|  | @ -32,7 +56,7 @@ By default, the operator watches the namespace it is deployed to. You can | |||
| change this by setting the `WATCHED_NAMESPACE` var in the `env` section of the | ||||
| [operator deployment](../manifests/postgres-operator.yaml) manifest or by | ||||
| altering the `watched_namespace` field in the operator | ||||
| [ConfigMap](../manifests/configmap.yaml#L79). | ||||
| [configuration](../manifests/postgresql-operator-default-configuration.yaml#L49). | ||||
| In the case both are set, the env var takes the precedence. To make the | ||||
| operator listen to all namespaces, explicitly set the field/env var to "`*`". | ||||
| 
 | ||||
|  | @ -115,7 +139,7 @@ that are aggregated into the K8s [default roles](https://kubernetes.io/docs/refe | |||
| 
 | ||||
| To ensure Postgres pods are running on nodes without any other application pods, | ||||
| you can use [taints and tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) | ||||
| and configure the required toleration in the operator ConfigMap. | ||||
| and configure the required toleration in the operator configuration. | ||||
| 
 | ||||
| As an example you can set following node taint: | ||||
| 
 | ||||
|  | @ -136,6 +160,21 @@ data: | |||
|   ... | ||||
| ``` | ||||
| 
 | ||||
| For an OperatorConfiguration resource the toleration should be defined like | ||||
| this: | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: "acid.zalan.do/v1" | ||||
| kind: OperatorConfiguration | ||||
| metadata: | ||||
|   name: postgresql-configuration | ||||
| configuration: | ||||
|   kubernetes: | ||||
|     toleration: | ||||
|       postgres: "key:postgres,operator:Exists,effect:NoSchedule" | ||||
|   ... | ||||
| ``` | ||||
| 
 | ||||
| Note that the K8s version 1.13 brings [taint-based eviction](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/#taint-based-evictions) | ||||
| to the beta stage and enables it by default. Postgres pods by default receive | ||||
| tolerations for `unreachable` and `noExecute` taints with the timeout of `5m`. | ||||
|  | @ -148,7 +187,7 @@ completely, specify the toleration by leaving out the `tolerationSeconds` value | |||
| 
 | ||||
| To ensure Postgres pods are running on different topologies, you can use | ||||
| [pod anti affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/) | ||||
| and configure the required topology in the operator ConfigMap. | ||||
| and configure the required topology in the operator configuration. | ||||
| 
 | ||||
| Enable pod anti affinity by adding following line to the operator ConfigMap: | ||||
| 
 | ||||
|  | @ -161,21 +200,22 @@ data: | |||
|   enable_pod_antiaffinity: "true" | ||||
| ``` | ||||
| 
 | ||||
| By default the topology key for the pod anti affinity is set to | ||||
| `kubernetes.io/hostname`, you can set another topology key e.g. | ||||
| `failure-domain.beta.kubernetes.io/zone` by adding following line to the | ||||
| operator ConfigMap, see [built-in node labels](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#interlude-built-in-node-labels) for available topology keys: | ||||
| Likewise, when using an OperatorConfiguration resource add: | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: v1 | ||||
| kind: ConfigMap | ||||
| apiVersion: "acid.zalan.do/v1" | ||||
| kind: OperatorConfiguration | ||||
| metadata: | ||||
|   name: postgres-operator | ||||
| data: | ||||
|   enable_pod_antiaffinity: "true" | ||||
|   pod_antiaffinity_topology_key: "failure-domain.beta.kubernetes.io/zone" | ||||
|   name: postgresql-configuration | ||||
| configuration: | ||||
|   kubernetes: | ||||
|     enable_pod_antiaffinity: true | ||||
| ``` | ||||
| 
 | ||||
| By default the topology key for the pod anti affinity is set to | ||||
| `kubernetes.io/hostname`, you can set another topology key e.g. | ||||
| `failure-domain.beta.kubernetes.io/zone`. See [built-in node labels](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#interlude-built-in-node-labels) for available topology keys. | ||||
| 
 | ||||
| ## Pod Disruption Budget | ||||
| 
 | ||||
| By default the operator uses a PodDisruptionBudget (PDB) to protect the cluster | ||||
|  | @ -280,6 +320,20 @@ data: | |||
|   ... | ||||
| ``` | ||||
| 
 | ||||
| **OperatorConfiguration** | ||||
| 
 | ||||
| ```yaml | ||||
| apiVersion: "acid.zalan.do/v1" | ||||
| kind: OperatorConfiguration | ||||
| metadata: | ||||
|   name: postgresql-operator-configuration | ||||
| configuration: | ||||
|   kubernetes: | ||||
|     # referencing config map with custom settings | ||||
|     pod_environment_configmap: postgres-pod-config | ||||
|     ... | ||||
| ``` | ||||
| 
 | ||||
| **referenced ConfigMap `postgres-pod-config`** | ||||
| 
 | ||||
| ```yaml | ||||
|  | @ -312,7 +366,7 @@ services: one for the master pod and one for replica pods. To expose these | |||
| services to an outer network, one can attach load balancers to them by setting | ||||
| `enableMasterLoadBalancer` and/or `enableReplicaLoadBalancer` to `true` in the | ||||
| cluster manifest. In the case any of these variables are omitted from the | ||||
| manifest, the operator configmap's settings `enable_master_load_balancer` and | ||||
| manifest, the operator configuration settings `enable_master_load_balancer` and | ||||
| `enable_replica_load_balancer` apply. Note that the operator settings affect | ||||
| all Postgresql services running in all namespaces watched by the operator. | ||||
| 
 | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ by setting the `GO111MODULE` environment variable to `on`. The make targets do | |||
| this for you, so simply run | ||||
| 
 | ||||
| ```bash | ||||
| make tools deps | ||||
| make deps | ||||
| ``` | ||||
| 
 | ||||
| This would take a while to complete. You have to redo `make deps` every time | ||||
|  | @ -284,6 +284,7 @@ manifest files: | |||
| 
 | ||||
| Postgres manifest parameters are defined in the [api package](../pkg/apis/acid.zalan.do/v1/postgresql_type.go). | ||||
| The operator behavior has to be implemented at least in [k8sres.go](../pkg/cluster/k8sres.go). | ||||
| Validation of CRD parameters is controlled in [crd.go](../pkg/apis/acid.zalan.do/v1/crds.go). | ||||
| Please, reflect your changes in tests, for example in: | ||||
| * [config_test.go](../pkg/util/config/config_test.go) | ||||
| * [k8sres_test.go](../pkg/cluster/k8sres_test.go) | ||||
|  | @ -294,6 +295,7 @@ Please, reflect your changes in tests, for example in: | |||
| For the CRD-based configuration, please update the following files: | ||||
| * the default [OperatorConfiguration](../manifests/postgresql-operator-default-configuration.yaml) | ||||
| * the Helm chart's [values-crd file](../charts/postgres-operator/values.yaml) | ||||
| * the CRD's [validation](../manifests/operatorconfiguration.crd.yaml) | ||||
| 
 | ||||
| Reflect the changes in the ConfigMap configuration as well (note that numeric | ||||
| and boolean parameters have to use double quotes here): | ||||
|  |  | |||
|  | @ -55,8 +55,8 @@ kubectl create -f manifests/postgres-operator.yaml  # deployment | |||
| ``` | ||||
| 
 | ||||
| There is a [Kustomization](https://github.com/kubernetes-sigs/kustomize) | ||||
| manifest that [combines the mentioned resources](../manifests/kustomization.yaml) - | ||||
| it can be used with kubectl 1.14 or newer as easy as: | ||||
| manifest that [combines the mentioned resources](../manifests/kustomization.yaml) | ||||
| (except for the CRD) - it can be used with kubectl 1.14 or newer as easy as: | ||||
| 
 | ||||
| ```bash | ||||
| kubectl apply -k github.com/zalando/postgres-operator/manifests | ||||
|  | @ -73,22 +73,23 @@ manifest. | |||
| ### Helm chart | ||||
| 
 | ||||
| Alternatively, the operator can be installed by using the provided [Helm](https://helm.sh/) | ||||
| chart which saves you the manual steps. Therefore, install the helm CLI on your | ||||
| machine. After initializing helm (and its server component Tiller) in your local | ||||
| cluster you can install the operator chart. You can define a release name that | ||||
| is prepended to the operator resource's names. | ||||
| 
 | ||||
| Use `--name zalando` to match with the default service account name as older | ||||
| operator versions do not support custom names for service accounts. To use | ||||
| CRD-based configuration you need to specify the [values-crd yaml file](../charts/postgres-operator/values-crd.yaml). | ||||
| chart which saves you the manual steps. Clone this repo and change directory to | ||||
| the repo root. With Helm v3 installed you should be able to run: | ||||
| 
 | ||||
| ```bash | ||||
| # 1) initialize helm | ||||
| helm init | ||||
| # 2) install postgres-operator chart | ||||
| helm install --name zalando ./charts/postgres-operator | ||||
| helm install postgres-operator ./charts/postgres-operator | ||||
| ``` | ||||
| 
 | ||||
| To use CRD-based configuration you need to specify the [values-crd yaml file](../charts/postgres-operator/values-crd.yaml). | ||||
| 
 | ||||
| ```bash | ||||
| helm install postgres-operator ./charts/postgres-operator -f ./charts/postgres-operator/values-crd.yaml | ||||
| ``` | ||||
| 
 | ||||
| The chart works with both Helm 2 and Helm 3. The `crd-install` hook from v2 will | ||||
| be skipped with warning when using v3. Documentation for installing applications | ||||
| with Helm 2 can be found in the [v2 docs](https://v2.helm.sh/docs/). | ||||
| 
 | ||||
| ### Operator Lifecycle Manager (OLM) | ||||
| 
 | ||||
| The [Operator Lifecycle Manager (OLM)](https://github.com/operator-framework/operator-lifecycle-manager) | ||||
|  | @ -119,15 +120,15 @@ kubectl get pod -l app.kubernetes.io/name=postgres-operator | |||
| kubectl create -f manifests/minimal-postgres-manifest.yaml | ||||
| ``` | ||||
| 
 | ||||
| After the cluster manifest is submitted the operator will create Service and | ||||
| Endpoint resources and a StatefulSet which spins up new Pod(s) given the number | ||||
| of instances specified in the manifest. All resources are named like the | ||||
| cluster. The database pods can be identified by their number suffix, starting | ||||
| from `-0`. They run the [Spilo](https://github.com/zalando/spilo) container | ||||
| image by Zalando. As for the services and endpoints, there will be one for the | ||||
| master pod and another one for all the replicas (`-repl` suffix). Check if all | ||||
| components are coming up. Use the label `application=spilo` to filter and list | ||||
| the label `spilo-role` to see who is currently the master. | ||||
| After the cluster manifest is submitted and passed the validation the operator | ||||
| will create Service and Endpoint resources and a StatefulSet which spins up new | ||||
| Pod(s) given the number of instances specified in the manifest. All resources | ||||
| are named like the cluster. The database pods can be identified by their number | ||||
| suffix, starting from `-0`. They run the [Spilo](https://github.com/zalando/spilo) | ||||
| container image by Zalando. As for the services and endpoints, there will be one | ||||
| for the master pod and another one for all the replicas (`-repl` suffix). Check | ||||
| if all components are coming up. Use the label `application=spilo` to filter and | ||||
| list the label `spilo-role` to see who is currently the master. | ||||
| 
 | ||||
| ```bash | ||||
| # check the deployed cluster | ||||
|  |  | |||
|  | @ -29,21 +29,20 @@ configuration. | |||
| 
 | ||||
|   To test the CRD-based configuration locally, use the following | ||||
|   ```bash | ||||
|   kubectl create -f manifests/operatorconfiguration.crd.yaml # registers the CRD | ||||
|   kubectl create -f manifests/postgresql-operator-default-configuration.yaml | ||||
| 
 | ||||
|   kubectl create -f manifests/operator-service-account-rbac.yaml | ||||
|   kubectl create -f manifests/postgres-operator.yaml # set the env var as mentioned above | ||||
|   kubectl create -f manifests/postgresql-operator-default-configuration.yaml | ||||
| 
 | ||||
|   kubectl get operatorconfigurations postgresql-operator-default-configuration -o yaml | ||||
|   ``` | ||||
|   Note that the operator first attempts to register the CRD of the | ||||
|   `OperatorConfiguration` and then waits for an instance to be created. In | ||||
|   between these two event the operator pod may be failing since it cannot fetch | ||||
|   the not-yet-existing `OperatorConfiguration` instance. | ||||
| 
 | ||||
| The CRD-based configuration is more powerful than the one based on ConfigMaps | ||||
| and should be used unless there is a compatibility requirement to use an already | ||||
| existing configuration. Even in that case, it should be rather straightforward | ||||
| to convert the configmap based configuration into the CRD-based one and restart | ||||
| the operator. The ConfigMaps-based configuration will be deprecated and | ||||
| to convert the ConfigMap-based configuration into the CRD-based one and restart | ||||
| the operator. The ConfigMap-based configuration will be deprecated and | ||||
| subsequently removed in future releases. | ||||
| 
 | ||||
| Note that for the CRD-based configuration groups of configuration options below | ||||
|  | @ -71,6 +70,11 @@ Variable names are underscore-separated words. | |||
| 
 | ||||
| Those are top-level keys, containing both leaf keys and groups. | ||||
| 
 | ||||
| * **enable_crd_validation** | ||||
|   toggles if the operator will create or update CRDs with | ||||
|   [OpenAPI v3 schema validation](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#validation) | ||||
|   The default is `true`. | ||||
| 
 | ||||
| * **etcd_host** | ||||
|   Etcd connection string for Patroni defined as `host:port`. Not required when | ||||
|   Patroni native Kubernetes support is used. The default is empty (use | ||||
|  | @ -441,6 +445,19 @@ grouped under the `logical_backup` key. | |||
|   S3 bucket to store backup results. The bucket has to be present and | ||||
|   accessible by Postgres pods. Default: empty. | ||||
| 
 | ||||
| * **logical_backup_s3_endpoint** | ||||
|   When using non-AWS S3 storage, endpoint can be set as a ENV variable. | ||||
| 
 | ||||
| * **logical_backup_s3_sse** | ||||
|   Specify server side encription that S3 storage is using. If empty string | ||||
|   is specified, no argument will be passed to `aws s3` command. Default: "AES256". | ||||
| 
 | ||||
| * **logical_backup_s3_access_key_id** | ||||
|   When set, value will be in AWS_ACCESS_KEY_ID env variable. The Default is empty. | ||||
| 
 | ||||
| * **logical_backup_s3_secret_access_key** | ||||
|   When set, value will be in AWS_SECRET_ACCESS_KEY env variable. The Default is empty. | ||||
| 
 | ||||
| ## Debugging the operator | ||||
| 
 | ||||
| Options to aid debugging of the operator itself. Grouped under the `debug` key. | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ spec: | |||
|   teamId: "ACID" | ||||
|   volume: | ||||
|     size: 1Gi | ||||
| #   storageClass: my-sc | ||||
| #    storageClass: my-sc | ||||
|   numberOfInstances: 2 | ||||
|   users:  # Application/Robot users | ||||
|     zalando: | ||||
|  | @ -30,7 +30,7 @@ spec: | |||
| # Expert section | ||||
| 
 | ||||
|   enableShmVolume: true | ||||
| # spiloFSGroup: 103 | ||||
| #  spiloFSGroup: 103 | ||||
|   postgresql: | ||||
|     version: "11" | ||||
|     parameters: | ||||
|  | @ -52,13 +52,13 @@ spec: | |||
|     pg_hba: | ||||
|     - hostssl all all 0.0.0.0/0 md5 | ||||
|     - host    all all 0.0.0.0/0 md5 | ||||
| #   slots: | ||||
| #     - permanent_physical_1: | ||||
| #         type: physical | ||||
| #     - permanent_logical_1: | ||||
| #         type: logical | ||||
| #         database: foo | ||||
| #         plugin: pgoutput | ||||
| #    slots: | ||||
| #      permanent_physical_1: | ||||
| #        type: physical | ||||
| #      permanent_logical_1: | ||||
| #        type: logical | ||||
| #        database: foo | ||||
| #        plugin: pgoutput | ||||
|     ttl: 30 | ||||
|     loop_wait: &loop_wait 10 | ||||
|     retry_timeout: 10 | ||||
|  | @ -66,28 +66,28 @@ spec: | |||
| # restore a Postgres DB with point-in-time-recovery | ||||
| # with a non-empty timestamp, clone from an S3 bucket using the latest backup before the timestamp | ||||
| # with an empty/absent timestamp, clone from an existing alive cluster using pg_basebackup | ||||
| # clone: | ||||
| #   uid: "efd12e58-5786-11e8-b5a7-06148230260c" | ||||
| #   cluster: "acid-batman" | ||||
| #   timestamp: "2017-12-19T12:40:33+01:00"  # timezone required (offset relative to UTC, see RFC 3339 section 5.6) | ||||
| #   s3_wal_path: "s3://custom/path/to/bucket" | ||||
| #  clone: | ||||
| #    uid: "efd12e58-5786-11e8-b5a7-06148230260c" | ||||
| #    cluster: "acid-batman" | ||||
| #    timestamp: "2017-12-19T12:40:33+01:00"  # timezone required (offset relative to UTC, see RFC 3339 section 5.6) | ||||
| #    s3_wal_path: "s3://custom/path/to/bucket" | ||||
| 
 | ||||
| # run periodic backups with k8s cron jobs | ||||
| # enableLogicalBackup: true | ||||
| # logicalBackupSchedule: "30 00 * * *" | ||||
| #  enableLogicalBackup: true | ||||
| #  logicalBackupSchedule: "30 00 * * *" | ||||
|   maintenanceWindows: | ||||
|   - 01:00-06:00  #UTC | ||||
|   - Sat:00:00-04:00 | ||||
| # sidecars: | ||||
| #   - name: "telegraf-sidecar" | ||||
| #     image: "telegraf:latest" | ||||
| #     resources: | ||||
| #       limits: | ||||
| #         cpu: 500m | ||||
| #         memory: 500Mi | ||||
| #       requests: | ||||
| #         cpu: 100m | ||||
| #         memory: 100Mi | ||||
| #  sidecars: | ||||
| #    - name: "telegraf-sidecar" | ||||
| #      image: "telegraf:latest" | ||||
| #      resources: | ||||
| #        limits: | ||||
| #          cpu: 500m | ||||
| #          memory: 500Mi | ||||
| #        requests: | ||||
| #          cpu: 100m | ||||
| #          memory: 100Mi | ||||
| #      env: | ||||
| #        - name: "USEFUL_VAR" | ||||
| #          value: "perhaps-true" | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ data: | |||
|   cluster_labels: application:spilo | ||||
|   cluster_name_label: version | ||||
|   # custom_service_annotations: "keyx:valuez,keya:valuea" | ||||
|   # custom_pod_annotations: "keya:valuea" | ||||
|   # custom_pod_annotations: "keya:valuea,keyb:valueb" | ||||
|   db_hosted_zone: db.example.com | ||||
|   debug_logging: "true" | ||||
|   # default_cpu_limit: "3" | ||||
|  | @ -21,6 +21,7 @@ data: | |||
|   # default_memory_request: 100Mi | ||||
|   docker_image: registry.opensource.zalan.do/acid/spilo-11:1.6-p1 | ||||
|   # enable_admin_role_for_users: "true" | ||||
|   # enable_crd_validation: "true" | ||||
|   # enable_database_access: "true" | ||||
|   enable_master_load_balancer: "false" | ||||
|   # enable_pod_antiaffinity: "false" | ||||
|  | @ -35,9 +36,13 @@ data: | |||
|   # kube_iam_role: "" | ||||
|   # log_s3_bucket: "" | ||||
|   # logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup" | ||||
|   # logical_backup_s3_access_key_id: "" | ||||
|   # logical_backup_s3_bucket: "my-bucket-url" | ||||
|   # logical_backup_s3_endpoint: "" | ||||
|   # logical_backup_s3_secret_access_key: "" | ||||
|   # logical_backup_s3_sse: "AES256" | ||||
|   # logical_backup_schedule: "30 00 * * *" | ||||
|   master_dns_name_format: "{cluster}.{team}.staging.{hostedzone}" | ||||
|   master_dns_name_format: "{cluster}.{team}.{hostedzone}" | ||||
|   # master_pod_move_timeout: 10m | ||||
|   # max_instances: "-1" | ||||
|   # min_instances: "-1" | ||||
|  | @ -60,11 +65,11 @@ data: | |||
|   ready_wait_interval: 3s | ||||
|   ready_wait_timeout: 30s | ||||
|   repair_period: 5m | ||||
|   replica_dns_name_format: "{cluster}-repl.{team}.staging.{hostedzone}" | ||||
|   replica_dns_name_format: "{cluster}-repl.{team}.{hostedzone}" | ||||
|   replication_username: standby | ||||
|   resource_check_interval: 3s | ||||
|   resource_check_timeout: 10m | ||||
|   resync_period: 5m | ||||
|   resync_period: 30m | ||||
|   ring_log_lines: "100" | ||||
|   secret_name_template: "{username}.{cluster}.credentials" | ||||
|   # sidecar_docker_images: "" | ||||
|  |  | |||
|  | @ -0,0 +1,276 @@ | |||
| apiVersion: apiextensions.k8s.io/v1beta1 | ||||
| kind: CustomResourceDefinition | ||||
| metadata: | ||||
|   name: operatorconfigurations.acid.zalan.do | ||||
| spec: | ||||
|   group: acid.zalan.do | ||||
|   names: | ||||
|     kind: OperatorConfiguration | ||||
|     listKind: OperatorConfigurationList | ||||
|     plural: operatorconfigurations | ||||
|     singular: operatorconfiguration | ||||
|     shortNames: | ||||
|     - opconfig | ||||
|   scope: Namespaced | ||||
|   subresources: | ||||
|     status: {} | ||||
|   version: v1 | ||||
|   validation: | ||||
|     openAPIV3Schema: | ||||
|       type: object | ||||
|       required: | ||||
|         - kind | ||||
|         - apiVersion | ||||
|         - configuration | ||||
|       properties: | ||||
|         kind: | ||||
|           type: string | ||||
|           enum: | ||||
|             - OperatorConfiguration | ||||
|         apiVersion: | ||||
|           type: string | ||||
|           enum: | ||||
|             - acid.zalan.do/v1 | ||||
|         configuration: | ||||
|           type: object | ||||
|           properties: | ||||
|             docker_image: | ||||
|               type: string | ||||
|             enable_crd_validation: | ||||
|               type: boolean | ||||
|             enable_shm_volume: | ||||
|               type: boolean | ||||
|             etcd_host: | ||||
|               type: string | ||||
|             max_instances: | ||||
|               type: integer | ||||
|               minimum: -1  # -1 = disabled | ||||
|             min_instances: | ||||
|               type: integer | ||||
|               minimum: -1  # -1 = disabled | ||||
|             resync_period: | ||||
|               type: string | ||||
|             repair_period: | ||||
|               type: string | ||||
|             set_memory_request_to_limit: | ||||
|               type: boolean | ||||
|             sidecar_docker_images: | ||||
|               type: object | ||||
|               additionalProperties: | ||||
|                 type: string | ||||
|             workers: | ||||
|               type: integer | ||||
|               minimum: 1 | ||||
|             users: | ||||
|               type: object | ||||
|               properties: | ||||
|                 replication_username: | ||||
|                    type: string | ||||
|                 super_username: | ||||
|                    type: string | ||||
|             kubernetes: | ||||
|               type: object | ||||
|               properties: | ||||
|                 cluster_domain: | ||||
|                   type: string | ||||
|                 cluster_labels: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 cluster_name_label: | ||||
|                   type: string | ||||
|                 custom_pod_annotations: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 enable_pod_antiaffinity: | ||||
|                   type: boolean | ||||
|                 enable_pod_disruption_budget: | ||||
|                   type: boolean | ||||
|                 infrastructure_roles_secret_name: | ||||
|                   type: string | ||||
|                 inherited_labels: | ||||
|                   type: array | ||||
|                   items: | ||||
|                     type: string | ||||
|                 node_readiness_label: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 oauth_token_secret_name: | ||||
|                   type: string | ||||
|                 pdb_name_format: | ||||
|                   type: string | ||||
|                 pod_antiaffinity_topology_key: | ||||
|                   type: string | ||||
|                 pod_environment_configmap: | ||||
|                   type: string | ||||
|                 pod_management_policy: | ||||
|                   type: string | ||||
|                   enum: | ||||
|                     - "ordered_ready" | ||||
|                     - "parallel" | ||||
|                 pod_role_label: | ||||
|                   type: string | ||||
|                 pod_service_account_name: | ||||
|                   type: string | ||||
|                 pod_terminate_grace_period: | ||||
|                   type: string | ||||
|                 secret_name_template: | ||||
|                   type: string | ||||
|                 spilo_fsgroup: | ||||
|                   type: integer | ||||
|                 spilo_privileged: | ||||
|                   type: boolean | ||||
|                 toleration: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 watched_namespace: | ||||
|                   type: string | ||||
|             postgres_pod_resources: | ||||
|               type: object | ||||
|               properties: | ||||
|                 default_cpu_limit: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+m|\d+(\.\d{1,3})?)$' | ||||
|                 default_cpu_request: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+m|\d+(\.\d{1,3})?)$' | ||||
|                 default_memory_limit: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                 default_memory_request: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|             timeouts: | ||||
|               type: object | ||||
|               properties: | ||||
|                 pod_label_wait_timeout: | ||||
|                   type: string | ||||
|                 pod_deletion_wait_timeout: | ||||
|                   type: string | ||||
|                 ready_wait_interval: | ||||
|                   type: string | ||||
|                 ready_wait_timeout: | ||||
|                   type: string | ||||
|                 resource_check_interval: | ||||
|                   type: string | ||||
|                 resource_check_timeout: | ||||
|                   type: string | ||||
|             load_balancer: | ||||
|               type: object | ||||
|               properties: | ||||
|                 db_hosted_zone: | ||||
|                   type: string | ||||
|                 enable_master_load_balancer: | ||||
|                   type: boolean | ||||
|                 enable_replica_load_balancer: | ||||
|                   type: boolean | ||||
|                 custom_service_annotations: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 master_dns_name_format: | ||||
|                   type: string | ||||
|                 replica_dns_name_format: | ||||
|                   type: string | ||||
|             aws_or_gcp: | ||||
|               type: object | ||||
|               properties: | ||||
|                 additional_secret_mount: | ||||
|                   type: string | ||||
|                 additional_secret_mount_path: | ||||
|                   type: string | ||||
|                 aws_region: | ||||
|                   type: string | ||||
|                 kube_iam_role: | ||||
|                   type: string | ||||
|                 log_s3_bucket: | ||||
|                   type: string | ||||
|                 wal_s3_bucket: | ||||
|                   type: string | ||||
|             logical_backup: | ||||
|               type: object | ||||
|               properties: | ||||
|                 logical_backup_schedule: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$' | ||||
|                 logical_backup_docker_image: | ||||
|                   type: string | ||||
|                 logical_backup_s3_bucket: | ||||
|                   type: string | ||||
|                 logical_backup_s3_endpoint: | ||||
|                   type: string | ||||
|                 logical_backup_s3_sse: | ||||
|                   type: string | ||||
|                 logical_backup_s3_access_key_id: | ||||
|                   type: string | ||||
|                 logical_backup_s3_secret_access_key: | ||||
|                   type: string | ||||
|             debug: | ||||
|               type: object | ||||
|               properties: | ||||
|                 debug_logging: | ||||
|                   type: boolean | ||||
|                 enable_database_access: | ||||
|                   type: boolean | ||||
|             teams_api: | ||||
|               type: object | ||||
|               properties: | ||||
|                 enable_admin_role_for_users: | ||||
|                   type: boolean | ||||
|                 enable_team_superuser: | ||||
|                   type: boolean | ||||
|                 enable_teams_api: | ||||
|                   type: boolean | ||||
|                 pam_configuration: | ||||
|                   type: string | ||||
|                 pam_role_name: | ||||
|                   type: string | ||||
|                 postgres_superuser_teams: | ||||
|                   type: array | ||||
|                   items: | ||||
|                     type: string | ||||
|                 protected_role_names: | ||||
|                   type: array | ||||
|                   items: | ||||
|                     type: string | ||||
|                 team_admin_role: | ||||
|                   type: string | ||||
|                 team_api_role_configuration: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 teams_api_url: | ||||
|                   type: string | ||||
|             logging_rest_api: | ||||
|               type: object | ||||
|               properties: | ||||
|                 api_port: | ||||
|                   type: integer | ||||
|                 cluster_history_entries: | ||||
|                   type: integer | ||||
|                 ring_log_lines: | ||||
|                   type: integer | ||||
|             scalyr: | ||||
|               type: object | ||||
|               properties: | ||||
|                 scalyr_api_key: | ||||
|                   type: string | ||||
|                 scalyr_cpu_limit: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+m|\d+(\.\d{1,3})?)$' | ||||
|                 scalyr_cpu_request: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+m|\d+(\.\d{1,3})?)$' | ||||
|                 scalyr_image: | ||||
|                   type: string | ||||
|                 scalyr_memory_limit: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                 scalyr_memory_request: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                 scalyr_server_url: | ||||
|                   type: string | ||||
|  | @ -3,6 +3,7 @@ kind: OperatorConfiguration | |||
| metadata: | ||||
|   name: postgresql-operator-default-configuration | ||||
| configuration: | ||||
|   # enable_crd_validation: true | ||||
|   etcd_host: "" | ||||
|   docker_image: registry.opensource.zalan.do/acid/spilo-11:1.6-p1 | ||||
|   # enable_shm_volume: true | ||||
|  | @ -27,24 +28,25 @@ configuration: | |||
|     #   keyb: valueb | ||||
|     enable_pod_antiaffinity: false | ||||
|     enable_pod_disruption_budget: true | ||||
|     # infrastructure_roles_secret_name: "" | ||||
|     # infrastructure_roles_secret_name: postgresql-infrastructure-roles | ||||
|     # inherited_labels: | ||||
|     # - application | ||||
|     # - environment | ||||
|     # node_readiness_label: "" | ||||
|     # node_readiness_label: | ||||
|     #  status: ready | ||||
|     oauth_token_secret_name: postgresql-operator | ||||
|     pdb_name_format: "postgres-{cluster}-pdb" | ||||
|     pod_antiaffinity_topology_key: "kubernetes.io/hostname" | ||||
|     # pod_environment_configmap: "" | ||||
|     pod_management_policy: "ordered_ready" | ||||
|     pod_role_label: spilo-role | ||||
|     pod_service_account_name: operator | ||||
|     pod_service_account_name: zalando-postgres-operator | ||||
|     pod_terminate_grace_period: 5m | ||||
|     secret_name_template: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}" | ||||
|     # spilo_fsgroup: 103 | ||||
|     spilo_privileged: false | ||||
|     # toleration: {} | ||||
|     # watched_namespace:"" | ||||
|     # watched_namespace: "" | ||||
|   postgres_pod_resources: | ||||
|     default_cpu_limit: "3" | ||||
|     default_cpu_request: 100m | ||||
|  | @ -74,9 +76,13 @@ configuration: | |||
|     # log_s3_bucket: "" | ||||
|     # wal_s3_bucket: "" | ||||
|   logical_backup: | ||||
|     logical_backup_schedule: "30 00 * * *" | ||||
|     logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup" | ||||
|     logical_backup_s3_access_key_id: "" | ||||
|     logical_backup_s3_bucket: "my-bucket-url" | ||||
|     logical_backup_s3_endpoint: "" | ||||
|     logical_backup_s3_secret_access_key: "" | ||||
|     logical_backup_s3_sse: "AES256" | ||||
|     logical_backup_schedule: "30 00 * * *" | ||||
|   debug: | ||||
|     debug_logging: true | ||||
|     enable_database_access: true | ||||
|  | @ -86,9 +92,10 @@ configuration: | |||
|     enable_teams_api: false | ||||
|     # pam_configuration: "" | ||||
|     pam_role_name: zalandos | ||||
|     # postgres_superuser_teams: "postgres_superusers" | ||||
|     # postgres_superuser_teams: | ||||
|     # - postgres_superusers | ||||
|     protected_role_names: | ||||
|       - admin | ||||
|     - admin | ||||
|     team_admin_role: admin | ||||
|     team_api_role_configuration: | ||||
|       log_statement: all | ||||
|  |  | |||
|  | @ -0,0 +1,327 @@ | |||
| apiVersion: apiextensions.k8s.io/v1beta1 | ||||
| kind: CustomResourceDefinition | ||||
| metadata: | ||||
|   name: postgresqls.acid.zalan.do | ||||
| spec: | ||||
|   group: acid.zalan.do | ||||
|   names: | ||||
|     kind: postgresql | ||||
|     listKind: postgresqlList | ||||
|     plural: postgresqls | ||||
|     singular: postgresql | ||||
|     shortNames: | ||||
|     - pg | ||||
|   scope: Namespaced | ||||
|   subresources: | ||||
|     status: {} | ||||
|   version: v1 | ||||
|   validation: | ||||
|     openAPIV3Schema: | ||||
|       type: object | ||||
|       required: | ||||
|         - kind | ||||
|         - apiVersion | ||||
|         - spec | ||||
|       properties: | ||||
|         kind: | ||||
|           type: string | ||||
|           enum: | ||||
|             - postgresql | ||||
|         apiVersion: | ||||
|           type: string | ||||
|           enum: | ||||
|             - acid.zalan.do/v1 | ||||
|         spec: | ||||
|           type: object | ||||
|           required: | ||||
|             - numberOfInstances | ||||
|             - teamId | ||||
|             - postgresql | ||||
|           properties: | ||||
|             allowedSourceRanges: | ||||
|               type: array | ||||
|               nullable: true | ||||
|               items: | ||||
|                 type: string | ||||
|                 pattern: '^(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\/(\d|[1-2]\d|3[0-2])$' | ||||
|             clone: | ||||
|               type: object | ||||
|               required: | ||||
|                 - cluster | ||||
|               properties: | ||||
|                 cluster: | ||||
|                   type: string | ||||
|                 s3_endpoint: | ||||
|                   type: string | ||||
|                 s3_access_key_id: | ||||
|                   type: string | ||||
|                 s3_secret_access_key: | ||||
|                   type: string | ||||
|                 s3_force_path_style: | ||||
|                   type: string | ||||
|                 s3_wal_path: | ||||
|                   type: string | ||||
|                 timestamp: | ||||
|                   type: string | ||||
|                   pattern: '^([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([+-]([01][0-9]|2[0-3]):[0-5][0-9]))$' | ||||
|                   # The regexp matches the date-time format (RFC 3339 Section 5.6) that specifies a timezone as an offset relative to UTC | ||||
|                   # Example: 1996-12-19T16:39:57-08:00 | ||||
|                   # Note: this field requires a timezone | ||||
|                 uid: | ||||
|                   format: uuid | ||||
|                   type: string | ||||
|             databases: | ||||
|               type: object | ||||
|               additionalProperties: | ||||
|                 type: string | ||||
|               # Note: usernames specified here as database owners must be declared in the users key of the spec key. | ||||
|             dockerImage: | ||||
|               type: string | ||||
|             enableLogicalBackup: | ||||
|               type: boolean | ||||
|             enableMasterLoadBalancer: | ||||
|               type: boolean | ||||
|             enableReplicaLoadBalancer: | ||||
|               type: boolean | ||||
|             enableShmVolume: | ||||
|               type: boolean | ||||
|             init_containers:  # deprecated | ||||
|               type: array | ||||
|               nullable: true | ||||
|               items: | ||||
|                 type: object | ||||
|                 additionalProperties: true | ||||
|             initContainers: | ||||
|               type: array | ||||
|               nullable: true | ||||
|               items: | ||||
|                 type: object | ||||
|                 additionalProperties: true | ||||
|             logicalBackupSchedule: | ||||
|               type: string | ||||
|               pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$' | ||||
|             maintenanceWindows: | ||||
|               type: array | ||||
|               items: | ||||
|                 type: string | ||||
|                 pattern: '^\ *((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))-((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))\ *$' | ||||
|             numberOfInstances: | ||||
|               type: integer | ||||
|               minimum: 0 | ||||
|             patroni: | ||||
|               type: object | ||||
|               properties: | ||||
|                 initdb: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|                 pg_hba: | ||||
|                   type: array | ||||
|                   items: | ||||
|                     type: string | ||||
|                 slots: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: object | ||||
|                     additionalProperties: | ||||
|                       type: string | ||||
|                 ttl: | ||||
|                   type: integer | ||||
|                 loop_wait: | ||||
|                   type: integer | ||||
|                 retry_timeout: | ||||
|                   type: integer | ||||
|                 maximum_lag_on_failover: | ||||
|                   type: integer | ||||
|             podAnnotations: | ||||
|               type: object | ||||
|               additionalProperties: | ||||
|                 type: string | ||||
|             pod_priority_class_name:  # deprecated | ||||
|               type: string | ||||
|             podPriorityClassName: | ||||
|               type: string | ||||
|             postgresql: | ||||
|               type: object | ||||
|               required: | ||||
|                 - version | ||||
|               properties: | ||||
|                 version: | ||||
|                   type: string | ||||
|                   enum: | ||||
|                     - "9.3" | ||||
|                     - "9.4" | ||||
|                     - "9.5" | ||||
|                     - "9.6" | ||||
|                     - "10" | ||||
|                     - "11" | ||||
|                     - "12" | ||||
|                 parameters: | ||||
|                   type: object | ||||
|                   additionalProperties: | ||||
|                     type: string | ||||
|             replicaLoadBalancer:  # deprecated | ||||
|               type: boolean | ||||
|             resources: | ||||
|               type: object | ||||
|               required: | ||||
|                 - requests | ||||
|                 - limits | ||||
|               properties: | ||||
|                 limits: | ||||
|                   type: object | ||||
|                   required: | ||||
|                     - cpu | ||||
|                     - memory | ||||
|                   properties: | ||||
|                     cpu: | ||||
|                       type: string | ||||
|                       # Decimal natural followed by m, or decimal natural followed by | ||||
|                       # dot followed by up to three decimal digits. | ||||
|                       # | ||||
|                       # This is because the Kubernetes CPU resource has millis as the | ||||
|                       # maximum precision.  The actual values are checked in code | ||||
|                       # because the regular expression would be huge and horrible and | ||||
|                       # not very helpful in validation error messages; this one checks | ||||
|                       # only the format of the given number. | ||||
|                       # | ||||
|                       # https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu | ||||
|                       pattern: '^(\d+m|\d+\.\d{1,3})$' | ||||
|                       # Note: the value specified here must not be zero or be lower | ||||
|                       # than the corresponding request. | ||||
|                     memory: | ||||
|                       type: string | ||||
|                       # You can express memory as a plain integer or as a fixed-point | ||||
|                       # integer using one of these suffixes: E, P, T, G, M, k. You can | ||||
|                       # also use the power-of-two equivalents: Ei, Pi, Ti, Gi, Mi, Ki | ||||
|                       # | ||||
|                       # https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory | ||||
|                       pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                       # Note: the value specified here must not be zero or be lower | ||||
|                       # than the corresponding request. | ||||
|                 requests: | ||||
|                   type: object | ||||
|                   required: | ||||
|                     - cpu | ||||
|                     - memory | ||||
|                   properties: | ||||
|                     cpu: | ||||
|                       type: string | ||||
|                       # Decimal natural followed by m, or decimal natural followed by | ||||
|                       # dot followed by up to three decimal digits. | ||||
|                       # | ||||
|                       # This is because the Kubernetes CPU resource has millis as the | ||||
|                       # maximum precision.  The actual values are checked in code | ||||
|                       # because the regular expression would be huge and horrible and | ||||
|                       # not very helpful in validation error messages; this one checks | ||||
|                       # only the format of the given number. | ||||
|                       # | ||||
|                       # https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu | ||||
|                       pattern: '^(\d+m|\d+\.\d{1,3})$' | ||||
|                       # Note: the value specified here must not be zero or be higher | ||||
|                       # than the corresponding limit. | ||||
|                     memory: | ||||
|                       type: string | ||||
|                       # You can express memory as a plain integer or as a fixed-point | ||||
|                       # integer using one of these suffixes: E, P, T, G, M, k. You can | ||||
|                       # also use the power-of-two equivalents: Ei, Pi, Ti, Gi, Mi, Ki | ||||
|                       # | ||||
|                       # https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory | ||||
|                       pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                       # Note: the value specified here must not be zero or be higher | ||||
|                       # than the corresponding limit. | ||||
|             sidecars: | ||||
|               type: array | ||||
|               nullable: true | ||||
|               items: | ||||
|                 type: object | ||||
|                 additionalProperties: true | ||||
|             spiloFSGroup: | ||||
|               type: integer | ||||
|             standby: | ||||
|               type: object | ||||
|               required: | ||||
|                 - s3_wal_path | ||||
|               properties: | ||||
|                 s3_wal_path: | ||||
|                   type: string | ||||
|             teamId: | ||||
|               type: string | ||||
|             tolerations: | ||||
|               type: array | ||||
|               items: | ||||
|                 type: object | ||||
|                 required: | ||||
|                   - key | ||||
|                   - operator | ||||
|                   - effect | ||||
|                 properties: | ||||
|                   key: | ||||
|                     type: string | ||||
|                   operator: | ||||
|                     type: string | ||||
|                     enum: | ||||
|                       - Equal | ||||
|                       - Exists | ||||
|                   value: | ||||
|                     type: string | ||||
|                   effect: | ||||
|                     type: string | ||||
|                     enum: | ||||
|                       - NoExecute | ||||
|                       - NoSchedule | ||||
|                       - PreferNoSchedule | ||||
|                   tolerationSeconds: | ||||
|                     type: integer | ||||
|             useLoadBalancer:  # deprecated | ||||
|               type: boolean | ||||
|             users: | ||||
|               type: object | ||||
|               additionalProperties: | ||||
|                 type: array | ||||
|                 nullable: true | ||||
|                 description: "Role flags specified here must not contradict each other" | ||||
|                 items: | ||||
|                   type: string | ||||
|                   enum: | ||||
|                   - bypassrls | ||||
|                   - BYPASSRLS | ||||
|                   - nobypassrls | ||||
|                   - NOBYPASSRLS | ||||
|                   - createdb | ||||
|                   - CREATEDB | ||||
|                   - nocreatedb | ||||
|                   - NOCREATEDB | ||||
|                   - createrole | ||||
|                   - CREATEROLE | ||||
|                   - nocreaterole | ||||
|                   - NOCREATEROLE | ||||
|                   - inherit | ||||
|                   - INHERIT | ||||
|                   - noinherit | ||||
|                   - NOINHERIT | ||||
|                   - login | ||||
|                   - LOGIN | ||||
|                   - nologin | ||||
|                   - NOLOGIN | ||||
|                   - replication | ||||
|                   - REPLICATION | ||||
|                   - noreplication | ||||
|                   - NOREPLICATION | ||||
|                   - superuser | ||||
|                   - SUPERUSER | ||||
|                   - nosuperuser | ||||
|                   - NOSUPERUSER | ||||
|             volume: | ||||
|               type: object | ||||
|               required: | ||||
|                 - size | ||||
|               properties: | ||||
|                 size: | ||||
|                   type: string | ||||
|                   pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' | ||||
|                   # Note: the value specified here must not be zero. | ||||
|                 storageClass: | ||||
|                   type: string | ||||
|                 subPath: | ||||
|                   type: string | ||||
|  | @ -1,7 +1,7 @@ | |||
| package v1 | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do" | ||||
| 	acidzalando "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do" | ||||
| 	apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| ) | ||||
|  | @ -103,7 +103,902 @@ var OperatorConfigCRDResourceColumns = []apiextv1beta1.CustomResourceColumnDefin | |||
| 	}, | ||||
| } | ||||
| 
 | ||||
| func buildCRD(name, kind, plural, short string, columns []apiextv1beta1.CustomResourceColumnDefinition) *apiextv1beta1.CustomResourceDefinition { | ||||
| var min0 = 0.0 | ||||
| var min1 = 1.0 | ||||
| var minDisable = -1.0 | ||||
| 
 | ||||
| // PostgresCRDResourceValidation to check applied manifest parameters
 | ||||
| var PostgresCRDResourceValidation = apiextv1beta1.CustomResourceValidation{ | ||||
| 	OpenAPIV3Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 		Type:     "object", | ||||
| 		Required: []string{"kind", "apiVersion", "spec"}, | ||||
| 		Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 			"kind": { | ||||
| 				Type: "string", | ||||
| 				Enum: []apiextv1beta1.JSON{ | ||||
| 					{ | ||||
| 						Raw: []byte(`"postgresql"`), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			"apiVersion": { | ||||
| 				Type: "string", | ||||
| 				Enum: []apiextv1beta1.JSON{ | ||||
| 					{ | ||||
| 						Raw: []byte(`"acid.zalan.do/v1"`), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			"spec": { | ||||
| 				Type:     "object", | ||||
| 				Required: []string{"numberOfInstances", "teamId", "postgresql"}, | ||||
| 				Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 					"allowedSourceRanges": { | ||||
| 						Type:     "array", | ||||
| 						Nullable: true, | ||||
| 						Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 							Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\/(\\d|[1-2]\\d|3[0-2])$", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"clone": { | ||||
| 						Type:     "object", | ||||
| 						Required: []string{"cluster"}, | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"cluster": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"s3_endpoint": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"s3_access_key_id": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"s3_secret_access_key": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"s3_force_path_style": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"s3_wal_path": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"timestamp": { | ||||
| 								Type:        "string", | ||||
| 								Description: "Date-time format that specifies a timezone as an offset relative to UTC e.g. 1996-12-19T16:39:57-08:00", | ||||
| 								Pattern:     "^([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?(([Zz])|([+-]([01][0-9]|2[0-3]):[0-5][0-9]))$", | ||||
| 							}, | ||||
| 							"uid": { | ||||
| 								Type:   "string", | ||||
| 								Format: "uuid", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"databases": { | ||||
| 						Type: "object", | ||||
| 						AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 							Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 								Type:        "string", | ||||
| 								Description: "User names specified here as database owners must be declared in the users key of the spec key", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"dockerImage": { | ||||
| 						Type: "string", | ||||
| 					}, | ||||
| 					"enableLogicalBackup": { | ||||
| 						Type: "boolean", | ||||
| 					}, | ||||
| 					"enableMasterLoadBalancer": { | ||||
| 						Type: "boolean", | ||||
| 					}, | ||||
| 					"enableReplicaLoadBalancer": { | ||||
| 						Type: "boolean", | ||||
| 					}, | ||||
| 					"enableShmVolume": { | ||||
| 						Type: "boolean", | ||||
| 					}, | ||||
| 					"init_containers": { | ||||
| 						Type:        "array", | ||||
| 						Description: "Deprecated", | ||||
| 						Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 							Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Allows: true, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"initContainers": { | ||||
| 						Type: "array", | ||||
| 						Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 							Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Allows: true, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"logicalBackupSchedule": { | ||||
| 						Type:    "string", | ||||
| 						Pattern: "^(\\d+|\\*)(/\\d+)?(\\s+(\\d+|\\*)(/\\d+)?){4}$", | ||||
| 					}, | ||||
| 					"maintenanceWindows": { | ||||
| 						Type: "array", | ||||
| 						Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 							Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^\\ *((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\\d):([0-5]?\\d)|(2[0-3]|[01]?\\d):([0-5]?\\d))-((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\\d):([0-5]?\\d)|(2[0-3]|[01]?\\d):([0-5]?\\d))\\ *$", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"numberOfInstances": { | ||||
| 						Type:    "integer", | ||||
| 						Minimum: &min0, | ||||
| 					}, | ||||
| 					"patroni": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"initdb": { | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"pg_hba": { | ||||
| 								Type: "array", | ||||
| 								Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"slots": { | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "object", | ||||
| 										AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 											Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 												Type: "string", | ||||
| 											}, | ||||
| 										}, | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"ttl": { | ||||
| 								Type: "integer", | ||||
| 							}, | ||||
| 							"loop_wait": { | ||||
| 								Type: "integer", | ||||
| 							}, | ||||
| 							"retry_timeout": { | ||||
| 								Type: "integer", | ||||
| 							}, | ||||
| 							"maximum_lag_on_failover": { | ||||
| 								Type: "integer", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"podAnnotations": { | ||||
| 						Type: "object", | ||||
| 						AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 							Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"pod_priority_class_name": { | ||||
| 						Type:        "string", | ||||
| 						Description: "Deprecated", | ||||
| 					}, | ||||
| 					"podPriorityClassName": { | ||||
| 						Type: "string", | ||||
| 					}, | ||||
| 					"postgresql": { | ||||
| 						Type:     "object", | ||||
| 						Required: []string{"version"}, | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"version": { | ||||
| 								Type: "string", | ||||
| 								Enum: []apiextv1beta1.JSON{ | ||||
| 									{ | ||||
| 										Raw: []byte(`"9.3"`), | ||||
| 									}, | ||||
| 									{ | ||||
| 										Raw: []byte(`"9.4"`), | ||||
| 									}, | ||||
| 									{ | ||||
| 										Raw: []byte(`"9.5"`), | ||||
| 									}, | ||||
| 									{ | ||||
| 										Raw: []byte(`"9.6"`), | ||||
| 									}, | ||||
| 									{ | ||||
| 										Raw: []byte(`"10"`), | ||||
| 									}, | ||||
| 									{ | ||||
| 										Raw: []byte(`"11"`), | ||||
| 									}, | ||||
| 									{ | ||||
| 										Raw: []byte(`"12"`), | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"parameters": { | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"replicaLoadBalancer": { | ||||
| 						Type:        "boolean", | ||||
| 						Description: "Deprecated", | ||||
| 					}, | ||||
| 					"resources": { | ||||
| 						Type:     "object", | ||||
| 						Required: []string{"requests", "limits"}, | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"limits": { | ||||
| 								Type:     "object", | ||||
| 								Required: []string{"cpu", "memory"}, | ||||
| 								Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 									"cpu": { | ||||
| 										Type:        "string", | ||||
| 										Description: "Decimal natural followed by m, or decimal natural followed by dot followed by up to three decimal digits (precision used by Kubernetes). Must be greater than 0", | ||||
| 										Pattern:     "^(\\d+m|\\d+\\.\\d{1,3})$", | ||||
| 									}, | ||||
| 									"memory": { | ||||
| 										Type:        "string", | ||||
| 										Description: "Plain integer or fixed-point integer using one of these suffixes: E, P, T, G, M, k (with or without a tailing i). Must be greater than 0", | ||||
| 										Pattern:     "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"requests": { | ||||
| 								Type:     "object", | ||||
| 								Required: []string{"cpu", "memory"}, | ||||
| 								Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 									"cpu": { | ||||
| 										Type:        "string", | ||||
| 										Description: "Decimal natural followed by m, or decimal natural followed by dot followed by up to three decimal digits (precision used by Kubernetes). Must be greater than 0", | ||||
| 										Pattern:     "^(\\d+m|\\d+\\.\\d{1,3})$", | ||||
| 									}, | ||||
| 									"memory": { | ||||
| 										Type:        "string", | ||||
| 										Description: "Plain integer or fixed-point integer using one of these suffixes: E, P, T, G, M, k (with or without a tailing i). Must be greater than 0", | ||||
| 										Pattern:     "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"sidecars": { | ||||
| 						Type: "array", | ||||
| 						Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 							Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Allows: true, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"spiloFSGroup": { | ||||
| 						Type: "integer", | ||||
| 					}, | ||||
| 					"standby": { | ||||
| 						Type:     "object", | ||||
| 						Required: []string{"s3_wal_path"}, | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"s3_wal_path": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"teamId": { | ||||
| 						Type: "string", | ||||
| 					}, | ||||
| 					"tolerations": { | ||||
| 						Type: "array", | ||||
| 						Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 							Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 								Type:     "object", | ||||
| 								Required: []string{"key", "operator", "effect"}, | ||||
| 								Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 									"key": { | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 									"operator": { | ||||
| 										Type: "string", | ||||
| 										Enum: []apiextv1beta1.JSON{ | ||||
| 											{ | ||||
| 												Raw: []byte(`"Equal"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"Exists"`), | ||||
| 											}, | ||||
| 										}, | ||||
| 									}, | ||||
| 									"value": { | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 									"effect": { | ||||
| 										Type: "string", | ||||
| 										Enum: []apiextv1beta1.JSON{ | ||||
| 											{ | ||||
| 												Raw: []byte(`"NoExecute"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"NoSchedule"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"PreferNoSchedule"`), | ||||
| 											}, | ||||
| 										}, | ||||
| 									}, | ||||
| 									"tolerationSeconds": { | ||||
| 										Type: "integer", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"useLoadBalancer": { | ||||
| 						Type:        "boolean", | ||||
| 						Description: "Deprecated", | ||||
| 					}, | ||||
| 					"users": { | ||||
| 						Type: "object", | ||||
| 						AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 							Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 								Type:        "array", | ||||
| 								Description: "Role flags specified here must not contradict each other", | ||||
| 								Nullable:    true, | ||||
| 								Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 										Enum: []apiextv1beta1.JSON{ | ||||
| 											{ | ||||
| 												Raw: []byte(`"bypassrls"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"BYPASSRLS"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"nobypassrls"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"NOBYPASSRLS"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"createdb"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"CREATEDB"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"nocreatedb"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"NOCREATEDB"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"createrole"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"CREATEROLE"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"nocreaterole"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"NOCREATEROLE"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"inherit"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"INHERIT"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"noinherit"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"NOINHERIT"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"login"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"LOGIN"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"nologin"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"NOLOGIN"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"replication"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"REPLICATION"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"noreplication"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"NOREPLICATION"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"superuser"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"SUPERUSER"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"nosuperuser"`), | ||||
| 											}, | ||||
| 											{ | ||||
| 												Raw: []byte(`"NOSUPERUSER"`), | ||||
| 											}, | ||||
| 										}, | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"volume": { | ||||
| 						Type:     "object", | ||||
| 						Required: []string{"size"}, | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"size": { | ||||
| 								Type:        "string", | ||||
| 								Description: "Value must not be zero", | ||||
| 								Pattern:     "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", | ||||
| 							}, | ||||
| 							"storageClass": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"subPath": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, | ||||
| } | ||||
| 
 | ||||
| // OperatorConfigCRDResourceValidation to check applied manifest parameters
 | ||||
| var OperatorConfigCRDResourceValidation = apiextv1beta1.CustomResourceValidation{ | ||||
| 	OpenAPIV3Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 		Type:     "object", | ||||
| 		Required: []string{"kind", "apiVersion", "configuration"}, | ||||
| 		Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 			"kind": { | ||||
| 				Type: "string", | ||||
| 				Enum: []apiextv1beta1.JSON{ | ||||
| 					{ | ||||
| 						Raw: []byte(`"OperatorConfiguration"`), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			"apiVersion": { | ||||
| 				Type: "string", | ||||
| 				Enum: []apiextv1beta1.JSON{ | ||||
| 					{ | ||||
| 						Raw: []byte(`"acid.zalan.do/v1"`), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			"configuration": { | ||||
| 				Type: "object", | ||||
| 				Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 					"docker_image": { | ||||
| 						Type: "string", | ||||
| 					}, | ||||
| 					"enable_crd_validation": { | ||||
| 						Type: "boolean", | ||||
| 					}, | ||||
| 					"enable_shm_volume": { | ||||
| 						Type: "boolean", | ||||
| 					}, | ||||
| 					"etcd_host": { | ||||
| 						Type: "string", | ||||
| 					}, | ||||
| 					"max_instances": { | ||||
| 						Type:        "integer", | ||||
| 						Description: "-1 = disabled", | ||||
| 						Minimum:     &minDisable, | ||||
| 					}, | ||||
| 					"min_instances": { | ||||
| 						Type:        "integer", | ||||
| 						Description: "-1 = disabled", | ||||
| 						Minimum:     &minDisable, | ||||
| 					}, | ||||
| 					"resync_period": { | ||||
| 						Type: "string", | ||||
| 					}, | ||||
| 					"repair_period": { | ||||
| 						Type: "string", | ||||
| 					}, | ||||
| 					"set_memory_request_to_limit": { | ||||
| 						Type: "boolean", | ||||
| 					}, | ||||
| 					"sidecar_docker_images": { | ||||
| 						Type: "object", | ||||
| 						AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 							Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"workers": { | ||||
| 						Type:    "integer", | ||||
| 						Minimum: &min1, | ||||
| 					}, | ||||
| 					"users": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"replication_username": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"super_username": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"kubernetes": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"cluster_domain": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"cluster_labels": { | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"cluster_name_label": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"custom_pod_annotations": { | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"enable_pod_antiaffinity": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 							"enable_pod_disruption_budget": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 							"infrastructure_roles_secret_name": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"inherited_labels": { | ||||
| 								Type: "array", | ||||
| 								Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"node_readiness_label": { | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"oauth_token_secret_name": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"pdb_name_format": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"pod_antiaffinity_topology_key": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"pod_environment_configmap": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"pod_management_policy": { | ||||
| 								Type: "string", | ||||
| 								Enum: []apiextv1beta1.JSON{ | ||||
| 									{ | ||||
| 										Raw: []byte(`"ordered_ready"`), | ||||
| 									}, | ||||
| 									{ | ||||
| 										Raw: []byte(`"parallel"`), | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"pod_role_label": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"pod_service_account_name": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"pod_terminate_grace_period": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"secret_name_template": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"spilo_fsgroup": { | ||||
| 								Type: "integer", | ||||
| 							}, | ||||
| 							"spilo_privileged": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 							"toleration": { | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"watched_namespace": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"postgres_pod_resources": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"default_cpu_limit": { | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$", | ||||
| 							}, | ||||
| 							"default_cpu_request": { | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$", | ||||
| 							}, | ||||
| 							"default_memory_limit": { | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", | ||||
| 							}, | ||||
| 							"default_memory_request": { | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"timeouts": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"pod_label_wait_timeout": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"pod_deletion_wait_timeout": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"ready_wait_interval": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"ready_wait_timeout": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"resource_check_interval": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"resource_check_timeout": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"load_balancer": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"db_hosted_zone": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"enable_master_load_balancer": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 							"enable_replica_load_balancer": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 							"custom_service_annotations": { | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"master_dns_name_format": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"replica_dns_name_format": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"aws_or_gcp": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"additional_secret_mount": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"additional_secret_mount_path": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"aws_region": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"kube_iam_role": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"log_s3_bucket": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"wal_s3_bucket": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"logical_backup": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"logical_backup_schedule": { | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^(\\d+|\\*)(/\\d+)?(\\s+(\\d+|\\*)(/\\d+)?){4}$", | ||||
| 							}, | ||||
| 							"logical_backup_docker_image": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"logical_backup_s3_bucket": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"logical_backup_s3_endpoint": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"logical_backup_s3_sse": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"logical_backup_s3_access_key_id": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"logical_backup_s3_secret_access_key": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"debug": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"debug_logging": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 							"enable_database_access": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"teams_api": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"enable_admin_role_for_users": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 							"enable_team_superuser": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 							"enable_teams_api": { | ||||
| 								Type: "boolean", | ||||
| 							}, | ||||
| 							"pam_configuration": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"pam_role_name": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"postgres_superuser_teams": { | ||||
| 								Type: "array", | ||||
| 								Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"protected_role_names": { | ||||
| 								Type: "array", | ||||
| 								Items: &apiextv1beta1.JSONSchemaPropsOrArray{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"team_admin_role": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"team_api_role_configuration": { | ||||
| 								Type: "object", | ||||
| 								AdditionalProperties: &apiextv1beta1.JSONSchemaPropsOrBool{ | ||||
| 									Schema: &apiextv1beta1.JSONSchemaProps{ | ||||
| 										Type: "string", | ||||
| 									}, | ||||
| 								}, | ||||
| 							}, | ||||
| 							"teams_api_url": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"logging_rest_api": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"api_port": { | ||||
| 								Type: "integer", | ||||
| 							}, | ||||
| 							"cluster_history_entries": { | ||||
| 								Type: "integer", | ||||
| 							}, | ||||
| 							"ring_log_lines": { | ||||
| 								Type: "integer", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 					"scalyr": { | ||||
| 						Type: "object", | ||||
| 						Properties: map[string]apiextv1beta1.JSONSchemaProps{ | ||||
| 							"scalyr_api_key": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"scalyr_cpu_limit": { | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$", | ||||
| 							}, | ||||
| 							"scalyr_cpu_request": { | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$", | ||||
| 							}, | ||||
| 							"scalyr_image": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 							"scalyr_memory_limit": { | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", | ||||
| 							}, | ||||
| 							"scalyr_memory_request": { | ||||
| 								Type:    "string", | ||||
| 								Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", | ||||
| 							}, | ||||
| 							"scalyr_server_url": { | ||||
| 								Type: "string", | ||||
| 							}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, | ||||
| } | ||||
| 
 | ||||
| func buildCRD(name, kind, plural, short string, columns []apiextv1beta1.CustomResourceColumnDefinition, validation apiextv1beta1.CustomResourceValidation) *apiextv1beta1.CustomResourceDefinition { | ||||
| 	return &apiextv1beta1.CustomResourceDefinition{ | ||||
| 		ObjectMeta: metav1.ObjectMeta{ | ||||
| 			Name: name, | ||||
|  | @ -121,24 +1016,39 @@ func buildCRD(name, kind, plural, short string, columns []apiextv1beta1.CustomRe | |||
| 				Status: &apiextv1beta1.CustomResourceSubresourceStatus{}, | ||||
| 			}, | ||||
| 			AdditionalPrinterColumns: columns, | ||||
| 			Validation:               &validation, | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // PostgresCRD returns CustomResourceDefinition built from PostgresCRDResource
 | ||||
| func PostgresCRD() *apiextv1beta1.CustomResourceDefinition { | ||||
| func PostgresCRD(enableValidation *bool) *apiextv1beta1.CustomResourceDefinition { | ||||
| 	postgresCRDvalidation := apiextv1beta1.CustomResourceValidation{} | ||||
| 
 | ||||
| 	if enableValidation != nil && *enableValidation { | ||||
| 		postgresCRDvalidation = PostgresCRDResourceValidation | ||||
| 	} | ||||
| 
 | ||||
| 	return buildCRD(PostgresCRDResouceName, | ||||
| 		PostgresCRDResourceKind, | ||||
| 		PostgresCRDResourcePlural, | ||||
| 		PostgresCRDResourceShort, | ||||
| 		PostgresCRDResourceColumns) | ||||
| 		PostgresCRDResourceColumns, | ||||
| 		postgresCRDvalidation) | ||||
| } | ||||
| 
 | ||||
| // ConfigurationCRD returns CustomResourceDefinition built from OperatorConfigCRDResource
 | ||||
| func ConfigurationCRD() *apiextv1beta1.CustomResourceDefinition { | ||||
| func ConfigurationCRD(enableValidation *bool) *apiextv1beta1.CustomResourceDefinition { | ||||
| 	opconfigCRDvalidation := apiextv1beta1.CustomResourceValidation{} | ||||
| 
 | ||||
| 	if enableValidation != nil && *enableValidation { | ||||
| 		opconfigCRDvalidation = OperatorConfigCRDResourceValidation | ||||
| 	} | ||||
| 
 | ||||
| 	return buildCRD(OperatorConfigCRDResourceName, | ||||
| 		OperatorConfigCRDResouceKind, | ||||
| 		OperatorConfigCRDResourcePlural, | ||||
| 		OperatorConfigCRDResourceShort, | ||||
| 		OperatorConfigCRDResourceColumns) | ||||
| 		OperatorConfigCRDResourceColumns, | ||||
| 		opconfigCRDvalidation) | ||||
| } | ||||
|  |  | |||
|  | @ -150,6 +150,7 @@ type ScalyrConfiguration struct { | |||
| 
 | ||||
| // OperatorConfigurationData defines the operation config
 | ||||
| type OperatorConfigurationData struct { | ||||
| 	EnableCRDValidation        *bool                              `json:"enable_crd_validation,omitempty"` | ||||
| 	EtcdHost                   string                             `json:"etcd_host,omitempty"` | ||||
| 	DockerImage                string                             `json:"docker_image,omitempty"` | ||||
| 	Workers                    uint32                             `json:"workers,omitempty"` | ||||
|  | @ -184,8 +185,13 @@ type OperatorConfigurationUsers struct { | |||
| //Duration shortens this frequently used name
 | ||||
| type Duration time.Duration | ||||
| 
 | ||||
| // OperatorLogicalBackupConfiguration defines configration for logical backup
 | ||||
| type OperatorLogicalBackupConfiguration struct { | ||||
| 	Schedule    string `json:"logical_backup_schedule,omitempty"` | ||||
| 	DockerImage string `json:"logical_backup_docker_image,omitempty"` | ||||
| 	S3Bucket    string `json:"logical_backup_s3_bucket,omitempty"` | ||||
| 	Schedule          string `json:"logical_backup_schedule,omitempty"` | ||||
| 	DockerImage       string `json:"logical_backup_docker_image,omitempty"` | ||||
| 	S3Bucket          string `json:"logical_backup_s3_bucket,omitempty"` | ||||
| 	S3Endpoint        string `json:"logical_backup_s3_endpoint,omitempty"` | ||||
| 	S3AccessKeyID     string `json:"logical_backup_s3_access_key_id,omitempty"` | ||||
| 	S3SecretAccessKey string `json:"logical_backup_s3_secret_access_key,omitempty"` | ||||
| 	S3SSE             string `json:"logical_backup_s3_sse,omitempty"` | ||||
| } | ||||
|  |  | |||
|  | @ -216,6 +216,11 @@ func (in *OperatorConfiguration) DeepCopyObject() runtime.Object { | |||
| // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 | ||||
| func (in *OperatorConfigurationData) DeepCopyInto(out *OperatorConfigurationData) { | ||||
| 	*out = *in | ||||
| 	if in.EnableCRDValidation != nil { | ||||
| 		in, out := &in.EnableCRDValidation, &out.EnableCRDValidation | ||||
| 		*out = new(bool) | ||||
| 		**out = **in | ||||
| 	} | ||||
| 	if in.ShmVolume != nil { | ||||
| 		in, out := &in.ShmVolume, &out.ShmVolume | ||||
| 		*out = new(bool) | ||||
|  |  | |||
|  | @ -1575,6 +1575,14 @@ func (c *Cluster) generateLogicalBackupPodEnvVars() []v1.EnvVar { | |||
| 			Name:  "LOGICAL_BACKUP_S3_BUCKET", | ||||
| 			Value: c.OpConfig.LogicalBackup.LogicalBackupS3Bucket, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:  "LOGICAL_BACKUP_S3_ENDPOINT", | ||||
| 			Value: c.OpConfig.LogicalBackup.LogicalBackupS3Endpoint, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:  "LOGICAL_BACKUP_S3_SSE", | ||||
| 			Value: c.OpConfig.LogicalBackup.LogicalBackupS3SSE, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:  "LOGICAL_BACKUP_S3_BUCKET_SCOPE_SUFFIX", | ||||
| 			Value: getBucketScopeSuffix(string(c.Postgresql.GetUID())), | ||||
|  | @ -1613,8 +1621,15 @@ func (c *Cluster) generateLogicalBackupPodEnvVars() []v1.EnvVar { | |||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	c.logger.Debugf("Generated logical backup env vars %v", envVars) | ||||
| 	if c.OpConfig.LogicalBackup.LogicalBackupS3AccessKeyID != "" { | ||||
| 		envVars = append(envVars, v1.EnvVar{Name: "AWS_ACCESS_KEY_ID", Value: c.OpConfig.LogicalBackup.LogicalBackupS3AccessKeyID}) | ||||
| 	} | ||||
| 
 | ||||
| 	if c.OpConfig.LogicalBackup.LogicalBackupS3SecretAccessKey != "" { | ||||
| 		envVars = append(envVars, v1.EnvVar{Name: "AWS_SECRET_ACCESS_KEY", Value: c.OpConfig.LogicalBackup.LogicalBackupS3SecretAccessKey}) | ||||
| 	} | ||||
| 
 | ||||
| 	c.logger.Debugf("Generated logical backup env vars %v", envVars) | ||||
| 	return envVars | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,7 +13,6 @@ import ( | |||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| 
 | ||||
| 	"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/retryutil" | ||||
| ) | ||||
|  | @ -278,7 +277,8 @@ func (c *Cluster) replaceStatefulSet(newStatefulSet *appsv1.StatefulSet) error { | |||
| 	oldStatefulset := c.Statefulset | ||||
| 
 | ||||
| 	options := metav1.DeleteOptions{PropagationPolicy: &deletePropagationPolicy} | ||||
| 	if err := c.KubeClient.StatefulSets(oldStatefulset.Namespace).Delete(oldStatefulset.Name, &options); err != nil { | ||||
| 	err := c.KubeClient.StatefulSets(oldStatefulset.Namespace).Delete(oldStatefulset.Name, &options) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("could not delete statefulset %q: %v", statefulSetName, err) | ||||
| 	} | ||||
| 	// make sure we clear the stored statefulset status if the subsequent create fails.
 | ||||
|  | @ -286,11 +286,16 @@ func (c *Cluster) replaceStatefulSet(newStatefulSet *appsv1.StatefulSet) error { | |||
| 	// wait until the statefulset is truly deleted
 | ||||
| 	c.logger.Debugf("waiting for the statefulset to be deleted") | ||||
| 
 | ||||
| 	err := retryutil.Retry(constants.StatefulsetDeletionInterval, constants.StatefulsetDeletionTimeout, | ||||
| 	err = retryutil.Retry(c.OpConfig.ResourceCheckInterval, c.OpConfig.ResourceCheckTimeout, | ||||
| 		func() (bool, error) { | ||||
| 			_, err := c.KubeClient.StatefulSets(oldStatefulset.Namespace).Get(oldStatefulset.Name, metav1.GetOptions{}) | ||||
| 
 | ||||
| 			return err != nil, nil | ||||
| 			_, err2 := c.KubeClient.StatefulSets(oldStatefulset.Namespace).Get(oldStatefulset.Name, metav1.GetOptions{}) | ||||
| 			if err2 == nil { | ||||
| 				return false, nil | ||||
| 			} | ||||
| 			if k8sutil.ResourceNotFound(err2) { | ||||
| 				return true, nil | ||||
| 			} | ||||
| 			return false, err2 | ||||
| 		}) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("could not delete statefulset: %v", err) | ||||
|  | @ -380,13 +385,27 @@ func (c *Cluster) updateService(role PostgresRole, newService *v1.Service) error | |||
| 			return fmt.Errorf("could not delete service %q: %v", serviceName, err) | ||||
| 		} | ||||
| 
 | ||||
| 		c.Endpoints[role] = nil | ||||
| 		svc, err := c.KubeClient.Services(serviceName.Namespace).Create(newService) | ||||
| 		// wait until the service is truly deleted
 | ||||
| 		c.logger.Debugf("waiting for service to be deleted") | ||||
| 
 | ||||
| 		err = retryutil.Retry(c.OpConfig.ResourceCheckInterval, c.OpConfig.ResourceCheckTimeout, | ||||
| 			func() (bool, error) { | ||||
| 				_, err2 := c.KubeClient.Services(serviceName.Namespace).Get(serviceName.Name, metav1.GetOptions{}) | ||||
| 				if err2 == nil { | ||||
| 					return false, nil | ||||
| 				} | ||||
| 				if k8sutil.ResourceNotFound(err2) { | ||||
| 					return true, nil | ||||
| 				} | ||||
| 				return false, err2 | ||||
| 			}) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("could not create service %q: %v", serviceName, err) | ||||
| 			return fmt.Errorf("could not delete service %q: %v", serviceName, err) | ||||
| 		} | ||||
| 
 | ||||
| 		c.Services[role] = svc | ||||
| 		// make sure we clear the stored service and endpoint status if the subsequent create fails.
 | ||||
| 		c.Services[role] = nil | ||||
| 		c.Endpoints[role] = nil | ||||
| 		if role == Master { | ||||
| 			// create the new endpoint using the addresses obtained from the previous one
 | ||||
| 			endpointSpec := c.generateEndpoint(role, currentEndpoint.Subsets) | ||||
|  | @ -398,6 +417,13 @@ func (c *Cluster) updateService(role PostgresRole, newService *v1.Service) error | |||
| 			c.Endpoints[role] = ep | ||||
| 		} | ||||
| 
 | ||||
| 		svc, err := c.KubeClient.Services(serviceName.Namespace).Create(newService) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("could not create service %q: %v", serviceName, err) | ||||
| 		} | ||||
| 
 | ||||
| 		c.Services[role] = svc | ||||
| 
 | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -240,7 +240,7 @@ func (c *Controller) initController() { | |||
| 	c.initClients() | ||||
| 
 | ||||
| 	if configObjectName := os.Getenv("POSTGRES_OPERATOR_CONFIGURATION_OBJECT"); configObjectName != "" { | ||||
| 		if err := c.createConfigurationCRD(); err != nil { | ||||
| 		if err := c.createConfigurationCRD(c.opConfig.EnableCRDValidation); err != nil { | ||||
| 			c.logger.Fatalf("could not register Operator Configuration CustomResourceDefinition: %v", err) | ||||
| 		} | ||||
| 		if cfg, err := c.readOperatorConfigurationFromCRD(spec.GetOperatorNamespace(), configObjectName); err != nil { | ||||
|  | @ -256,7 +256,7 @@ func (c *Controller) initController() { | |||
| 
 | ||||
| 	c.modifyConfigFromEnvironment() | ||||
| 
 | ||||
| 	if err := c.createPostgresCRD(); err != nil { | ||||
| 	if err := c.createPostgresCRD(c.opConfig.EnableCRDValidation); err != nil { | ||||
| 		c.logger.Fatalf("could not register Postgres CustomResourceDefinition: %v", err) | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur | |||
| 	result := &config.Config{} | ||||
| 
 | ||||
| 	// general config
 | ||||
| 	result.EnableCRDValidation = fromCRD.EnableCRDValidation | ||||
| 	result.EtcdHost = fromCRD.EtcdHost | ||||
| 	result.DockerImage = fromCRD.DockerImage | ||||
| 	result.Workers = fromCRD.Workers | ||||
|  | @ -101,6 +102,10 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur | |||
| 	result.LogicalBackupSchedule = fromCRD.LogicalBackup.Schedule | ||||
| 	result.LogicalBackupDockerImage = fromCRD.LogicalBackup.DockerImage | ||||
| 	result.LogicalBackupS3Bucket = fromCRD.LogicalBackup.S3Bucket | ||||
| 	result.LogicalBackupS3Endpoint = fromCRD.LogicalBackup.S3Endpoint | ||||
| 	result.LogicalBackupS3AccessKeyID = fromCRD.LogicalBackup.S3AccessKeyID | ||||
| 	result.LogicalBackupS3SecretAccessKey = fromCRD.LogicalBackup.S3SecretAccessKey | ||||
| 	result.LogicalBackupS3SSE = fromCRD.LogicalBackup.S3SSE | ||||
| 
 | ||||
| 	// debug config
 | ||||
| 	result.DebugLogging = fromCRD.OperatorDebug.DebugLogging | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import ( | |||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"k8s.io/api/core/v1" | ||||
| 	v1 "k8s.io/api/core/v1" | ||||
| 	apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
|  | @ -91,12 +91,12 @@ func (c *Controller) createOperatorCRD(crd *apiextv1beta1.CustomResourceDefiniti | |||
| 	}) | ||||
| } | ||||
| 
 | ||||
| func (c *Controller) createPostgresCRD() error { | ||||
| 	return c.createOperatorCRD(acidv1.PostgresCRD()) | ||||
| func (c *Controller) createPostgresCRD(enableValidation *bool) error { | ||||
| 	return c.createOperatorCRD(acidv1.PostgresCRD(enableValidation)) | ||||
| } | ||||
| 
 | ||||
| func (c *Controller) createConfigurationCRD() error { | ||||
| 	return c.createOperatorCRD(acidv1.ConfigurationCRD()) | ||||
| func (c *Controller) createConfigurationCRD(enableValidation *bool) error { | ||||
| 	return c.createOperatorCRD(acidv1.ConfigurationCRD(enableValidation)) | ||||
| } | ||||
| 
 | ||||
| func readDecodedRole(s string) (*spec.PgUser, error) { | ||||
|  |  | |||
|  | @ -12,10 +12,11 @@ import ( | |||
| 
 | ||||
| // CRD describes CustomResourceDefinition specific configuration parameters
 | ||||
| type CRD struct { | ||||
| 	ReadyWaitInterval time.Duration `name:"ready_wait_interval" default:"4s"` | ||||
| 	ReadyWaitTimeout  time.Duration `name:"ready_wait_timeout" default:"30s"` | ||||
| 	ResyncPeriod      time.Duration `name:"resync_period" default:"30m"` | ||||
| 	RepairPeriod      time.Duration `name:"repair_period" default:"5m"` | ||||
| 	ReadyWaitInterval   time.Duration `name:"ready_wait_interval" default:"4s"` | ||||
| 	ReadyWaitTimeout    time.Duration `name:"ready_wait_timeout" default:"30s"` | ||||
| 	ResyncPeriod        time.Duration `name:"resync_period" default:"30m"` | ||||
| 	RepairPeriod        time.Duration `name:"repair_period" default:"5m"` | ||||
| 	EnableCRDValidation *bool         `name:"enable_crd_validation" default:"true"` | ||||
| } | ||||
| 
 | ||||
| // Resources describes kubernetes resource specific configuration parameters
 | ||||
|  | @ -68,11 +69,15 @@ type Scalyr struct { | |||
| 	ScalyrMemoryLimit   string `name:"scalyr_memory_limit" default:"1Gi"` | ||||
| } | ||||
| 
 | ||||
| // LogicalBackup
 | ||||
| // LogicalBackup defines configration for logical backup
 | ||||
| type LogicalBackup struct { | ||||
| 	LogicalBackupSchedule    string `name:"logical_backup_schedule" default:"30 00 * * *"` | ||||
| 	LogicalBackupDockerImage string `name:"logical_backup_docker_image" default:"registry.opensource.zalan.do/acid/logical-backup"` | ||||
| 	LogicalBackupS3Bucket    string `name:"logical_backup_s3_bucket" default:""` | ||||
| 	LogicalBackupSchedule          string `name:"logical_backup_schedule" default:"30 00 * * *"` | ||||
| 	LogicalBackupDockerImage       string `name:"logical_backup_docker_image" default:"registry.opensource.zalan.do/acid/logical-backup"` | ||||
| 	LogicalBackupS3Bucket          string `name:"logical_backup_s3_bucket" default:""` | ||||
| 	LogicalBackupS3Endpoint        string `name:"logical_backup_s3_endpoint" default:""` | ||||
| 	LogicalBackupS3AccessKeyID     string `name:"logical_backup_s3_access_key_id" default:""` | ||||
| 	LogicalBackupS3SecretAccessKey string `name:"logical_backup_s3_secret_access_key" default:""` | ||||
| 	LogicalBackupS3SSE             string `name:"logical_backup_s3_sse" default:"AES256"` | ||||
| } | ||||
| 
 | ||||
| // Config describes operator config
 | ||||
|  |  | |||
|  | @ -4,11 +4,9 @@ import "time" | |||
| 
 | ||||
| // General kubernetes-related constants
 | ||||
| const ( | ||||
| 	PostgresContainerName       = "postgres" | ||||
| 	PostgresContainerIdx        = 0 | ||||
| 	K8sAPIPath                  = "/apis" | ||||
| 	StatefulsetDeletionInterval = 1 * time.Second | ||||
| 	StatefulsetDeletionTimeout  = 30 * time.Second | ||||
| 	PostgresContainerName = "postgres" | ||||
| 	PostgresContainerIdx  = 0 | ||||
| 	K8sAPIPath            = "/apis" | ||||
| 
 | ||||
| 	QueueResyncPeriodPod  = 5 * time.Minute | ||||
| 	QueueResyncPeriodTPR  = 5 * time.Minute | ||||
|  |  | |||
|  | @ -98,7 +98,7 @@ function build_operator_binary(){ | |||
| 
 | ||||
|     # redirecting stderr greatly reduces non-informative output during normal builds | ||||
|     echo "Build operator binary (stderr redirected to /dev/null)..." | ||||
|     make clean tools deps local test > /dev/null 2>&1 | ||||
|     make clean deps local test > /dev/null 2>&1 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue