From a664816c0910975e10e573094172011ccb7fc3ab Mon Sep 17 00:00:00 2001 From: Felix Kunde Date: Mon, 22 Jun 2026 10:44:46 +0200 Subject: [PATCH] auto-generate configuration CRD (#3102) * auto-generate configuration CRD * make all subconfig optional * remove field enable crd validation * update field descriptions which use proxy types --- LICENSE | 2 +- Makefile | 4 +- .../crds/operatorconfigurations.yaml | 1025 ++++++++------- docs/reference/operator_parameters.md | 5 - manifests/configmap.yaml | 1 - manifests/operatorconfiguration.crd.yaml | 1036 ++++++++------- pkg/apis/acid.zalan.do/v1/crds.go | 1143 +---------------- .../v1/operator_configuration_type.go | 500 ++++--- .../v1/operatorconfiguration.crd.yaml | 971 ++++++++++++++ .../acid.zalan.do/v1/zz_generated.deepcopy.go | 5 - pkg/controller/operator_config.go | 1 - pkg/controller/util.go | 6 +- .../v1/fake/fake_operatorconfiguration.go | 12 +- .../acid.zalan.do/v1/operatorconfiguration.go | 14 +- .../acid.zalan.do/v1/interface.go | 7 + .../acid.zalan.do/v1/operatorconfiguration.go | 96 ++ .../informers/externalversions/generic.go | 2 + .../acid.zalan.do/v1/expansion_generated.go | 8 + .../acid.zalan.do/v1/operatorconfiguration.go | 76 ++ pkg/util/config/config.go | 1 - 20 files changed, 2664 insertions(+), 2251 deletions(-) create mode 100644 pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml create mode 100644 pkg/generated/informers/externalversions/acid.zalan.do/v1/operatorconfiguration.go create mode 100644 pkg/generated/listers/acid.zalan.do/v1/operatorconfiguration.go diff --git a/LICENSE b/LICENSE index 2141e8bcb..2f94edc31 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2025 Zalando SE +Copyright (c) 2026 Zalando SE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index c1becbc99..323b51892 100644 --- a/Makefile +++ b/Makefile @@ -66,15 +66,15 @@ $(GENERATED): go.mod $(CRD_SOURCES) $(GENERATED_CRDS): $(GENERATED) go tool controller-gen crd:crdVersions=v1,allowDangerousTypes=true paths=./pkg/apis/acid.zalan.do/... output:crd:dir=manifests - # only generate postgresteam.crd.yaml and postgresql.crd.yaml for now - @rm manifests/acid.zalan.do_operatorconfigurations.yaml @mv manifests/acid.zalan.do_postgresqls.yaml manifests/postgresql.crd.yaml @# hack to use lowercase kind and listKind @sed -i -e 's/kind: Postgresql/kind: postgresql/' manifests/postgresql.crd.yaml @sed -i -e 's/listKind: PostgresqlList/listKind: postgresqlList/' manifests/postgresql.crd.yaml @hack/adjust_postgresql_crd.sh + @mv manifests/acid.zalan.do_operatorconfigurations.yaml manifests/operatorconfiguration.crd.yaml @mv manifests/acid.zalan.do_postgresteams.yaml manifests/postgresteam.crd.yaml @cp manifests/postgresql.crd.yaml pkg/apis/acid.zalan.do/v1/postgresql.crd.yaml + @cp manifests/operatorconfiguration.crd.yaml pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml local: ${SOURCES} $(GENERATED_CRDS) CGO_ENABLED=${CGO_ENABLED} go build -o build/${BINARY} $(LOCAL_BUILD_FLAGS) -ldflags "$(LDFLAGS)" $(SOURCES) diff --git a/charts/postgres-operator/crds/operatorconfigurations.yaml b/charts/postgres-operator/crds/operatorconfigurations.yaml index 1414366ff..5875b5808 100644 --- a/charts/postgres-operator/crds/operatorconfigurations.yaml +++ b/charts/postgres-operator/crds/operatorconfigurations.yaml @@ -7,281 +7,286 @@ metadata: spec: group: acid.zalan.do names: + categories: + - all kind: OperatorConfiguration listKind: OperatorConfigurationList plural: operatorconfigurations - singular: operatorconfiguration shortNames: - opconfig - categories: - - all + singular: operatorconfiguration scope: Namespaced versions: - - name: v1 - served: true - storage: true - subresources: - status: {} - additionalPrinterColumns: - - name: Image - type: string - description: Spilo image to be used for Pods + - additionalPrinterColumns: + - description: Spilo image to be used for Pods jsonPath: .configuration.docker_image - - name: Cluster-Label + name: Image type: string - description: Label for K8s resources created by operator + - description: Label for K8s resources created by operator jsonPath: .configuration.kubernetes.cluster_name_label - - name: Service-Account + name: Cluster-Label type: string - description: Name of service account to be used + - 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 + name: Service-Account + type: string + - description: Minimum number of instances per Postgres cluster jsonPath: .configuration.min_instances - - name: Age - type: date + name: Min-Instances + type: integer + - description: Age of the OperatorConfiguration resource jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 schema: openAPIV3Schema: - type: object - required: - - kind - - apiVersion - - configuration + description: OperatorConfiguration defines the specification for the OperatorConfiguration. properties: - kind: - type: string - enum: - - OperatorConfiguration apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string - enum: - - acid.zalan.do/v1 configuration: - type: object + description: OperatorConfigurationData defines the operation config properties: + aws_or_gcp: + description: AWSGCPConfiguration defines the configuration for AWS + properties: + additional_secret_mount: + type: string + additional_secret_mount_path: + type: string + aws_region: + default: eu-central-1 + type: string + enable_ebs_gp3_migration: + type: boolean + enable_ebs_gp3_migration_max_size: + format: int64 + type: integer + gcp_credentials: + type: string + kube_iam_role: + type: string + log_s3_bucket: + type: string + wal_az_storage_account: + type: string + wal_gs_bucket: + type: string + wal_s3_bucket: + type: string + type: object + connection_pooler: + description: ConnectionPoolerConfiguration defines default configuration + for connection pooler + properties: + connection_pooler_default_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + connection_pooler_default_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + connection_pooler_default_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + connection_pooler_default_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + connection_pooler_image: + default: ghcr.io/zalando/postgres-operator/pgbouncer:latest + type: string + connection_pooler_max_db_connections: + format: int32 + type: integer + connection_pooler_mode: + default: transaction + enum: + - session + - transaction + type: string + connection_pooler_number_of_instances: + default: 2 + format: int32 + minimum: 1 + type: integer + connection_pooler_schema: + default: pooler + type: string + connection_pooler_user: + default: pooler + type: string + type: object crd_categories: - type: array - nullable: true items: type: string + type: array + debug: + description: OperatorDebugConfiguration defines options for the debug + mode + properties: + debug_logging: + default: true + type: boolean + enable_database_access: + default: true + type: boolean + type: object docker_image: + default: ghcr.io/zalando/spilo-18:4.1-p1 type: string - default: "ghcr.io/zalando/spilo-18:4.1-p1" enable_crd_registration: - type: boolean default: true - enable_crd_validation: type: boolean - description: deprecated - default: true enable_lazy_spilo_upgrade: type: boolean - default: false enable_maintenance_windows: - type: boolean default: true + type: boolean enable_pgversion_env_var: - type: boolean default: true + type: boolean enable_shm_volume: - type: boolean default: true + type: boolean enable_spilo_wal_path_compat: type: boolean - default: false enable_team_id_clustername_prefix: type: boolean - default: false etcd_host: - type: string default: "" + type: string ignore_instance_limits_annotation_key: type: string ignore_resources_limits_annotation_key: type: string - kubernetes_use_configmaps: - type: boolean - default: false - maintenance_windows: - items: - pattern: '^\ *((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))-((2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))\ *$' - type: string - type: array - max_instances: - type: integer - description: "-1 = disabled" - minimum: -1 - default: -1 - min_instances: - type: integer - description: "-1 = disabled" - minimum: -1 - default: -1 - resync_period: - type: string - default: "30m" - repair_period: - type: string - default: "5m" - set_memory_request_to_limit: - type: boolean - default: false - sidecar_docker_images: - type: object - additionalProperties: - type: string - sidecars: - type: array - nullable: true - items: - type: object - x-kubernetes-preserve-unknown-fields: true - workers: - type: integer - minimum: 1 - default: 8 - users: - type: object - properties: - additional_owner_roles: - type: array - nullable: true - items: - type: string - enable_password_rotation: - type: boolean - default: false - password_rotation_interval: - type: integer - default: 90 - password_rotation_user_retention: - type: integer - default: 180 - replication_username: - type: string - default: standby - super_username: - type: string - default: postgres - major_version_upgrade: - type: object - properties: - major_version_upgrade_mode: - type: string - default: "manual" - major_version_upgrade_team_allow_list: - type: array - items: - type: string - minimal_major_version: - type: string - default: "14" - target_major_version: - type: string - default: "18" kubernetes: - type: object + description: KubernetesMetaConfiguration defines k8s conf required + for all Postgres clusters and the operator itself properties: additional_pod_capabilities: - type: array items: type: string + type: array cluster_domain: + default: cluster.local type: string - default: "cluster.local" cluster_labels: - type: object additionalProperties: type: string default: application: spilo - cluster_name_label: - type: string - default: "cluster-name" - custom_pod_annotations: type: object + cluster_name_label: + default: cluster-name + type: string + custom_pod_annotations: additionalProperties: type: string + type: object delete_annotation_date_key: type: string delete_annotation_name_key: type: string downscaler_annotations: - type: array items: type: string + type: array enable_cross_namespace_secret: type: boolean - default: false enable_finalizers: type: boolean - default: false enable_init_containers: - type: boolean default: true + type: boolean enable_owner_references: type: boolean - default: false enable_persistent_volume_claim_deletion: - type: boolean default: true + type: boolean enable_pod_antiaffinity: type: boolean - default: false enable_pod_disruption_budget: - type: boolean default: true + type: boolean enable_readiness_probe: type: boolean - default: false enable_secrets_deletion: - type: boolean default: true + type: boolean enable_sidecars: - type: boolean default: true + type: boolean ignored_annotations: - type: array items: type: string - infrastructure_roles_secret_name: - type: string - infrastructure_roles_secrets: type: array - nullable: true + infrastructure_roles_secret_name: + description: |- + NamespacedName comprises a resource name, with a mandatory namespace, + rendered as "/". Being a type captures intent and + helps make sure that UIDs, namespaced names and non-namespaced names + do not get conflated in code. For most use cases, namespace and name + will already have been format validated at the API entry point, so we + don't do that here. Where that's not the case (e.g. in testing), + consider using NamespacedNameOrDie() in testing.go in this package. + + from: https://github.com/kubernetes/apimachinery/blob/master/pkg/types/namespacedname.go + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + infrastructure_roles_secrets: + description: namespaced name of the secret containing infrastructure + roles names and passwords items: - type: object - required: - - secretname - - userkey - - passwordkey properties: - secretname: + defaultrolevalue: type: string - userkey: + defaultuservalue: + type: string + details: + description: This field point out the detailed yaml definition + of the role, if exists type: string passwordkey: type: string rolekey: type: string - defaultuservalue: - type: string - defaultrolevalue: - type: string - details: - type: string + secretname: + description: |- + Name of a secret which describes the role, and optionally name of a + configmap with an extra information + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object template: type: boolean + userkey: + type: string + type: object + type: array inherited_annotations: - type: array items: type: string + type: array inherited_labels: - type: array items: type: string + type: array liveness_probe: description: |- Probe describes a health check to be performed against a container to determine whether it is @@ -336,11 +341,11 @@ spec: "Host" in httpHeaders instead. type: string httpHeaders: - description: Custom headers to set in the request. HTTP allows - repeated headers. + description: Custom headers to set in the request. HTTP + allows repeated headers. items: - description: HTTPHeader describes a custom header to be - used in HTTP probes + description: HTTPHeader describes a custom header to + be used in HTTP probes properties: name: description: |- @@ -436,274 +441,236 @@ spec: type: integer type: object master_pod_move_timeout: - type: string - default: "20m" + default: 20m + description: timeout for successful migration of master pods from + unschedulable node + format: int64 + type: integer node_readiness_label: - type: object additionalProperties: type: string - node_readiness_label_merge: - type: string - enum: - - "AND" - - "OR" - oauth_token_secret_name: - type: string - default: "postgresql-operator" - pdb_master_label_selector: - type: boolean - default: true - pdb_name_format: - type: string - default: "postgres-{cluster}-pdb" - persistent_volume_claim_retention_policy: type: object + node_readiness_label_merge: + enum: + - AND + - OR + type: string + oauth_token_secret_name: + default: postgres-operator + description: namespaced name of the secret containing the OAuth2 + token to pass to the teams API properties: - when_deleted: + name: type: string - enum: - - "delete" - - "retain" - when_scaled: + namespace: type: string - enum: - - "delete" - - "retain" + required: + - name + type: object + pdb_master_label_selector: + default: true + type: boolean + pdb_name_format: + default: postgres-{cluster}-pdb + description: defines the template for PDB names + type: string + persistent_volume_claim_retention_policy: + additionalProperties: + type: string + type: object pod_antiaffinity_preferred_during_scheduling: type: boolean - default: false pod_antiaffinity_topology_key: + default: kubernetes.io/hostname type: string - default: "kubernetes.io/hostname" pod_environment_configmap: - type: string + description: namespaced name of the ConfigMap with environment + variables to populate on every pod + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object pod_environment_secret: type: string pod_management_policy: - type: string + default: ordered_ready enum: - - "ordered_ready" - - "parallel" - default: "ordered_ready" + - ordered_ready + - parallel + type: string pod_priority_class_name: type: string pod_role_label: + default: spilo-role type: string - default: "spilo-role" pod_service_account_definition: type: string - default: "" pod_service_account_name: + default: postgres-pod type: string - default: "postgres-pod" pod_service_account_role_binding_definition: type: string - default: "" pod_terminate_grace_period: - type: string - default: "5m" + default: 5m + description: Postgres pods are terminated forcefully after this + timeout + format: int64 + type: integer secret_name_template: + default: '{username}.{cluster}.credentials.{tprkind}.{tprgroup}' + description: |- + template for database user secrets generated by the operator, + here username contains the namespace in the format namespace.username + if the user is in different namespace than cluster and cross namespace secrets + are enabled via `enable_cross_namespace_secret` flag in the configuration. type: string - default: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}" share_pgsocket_with_sidecars: type: boolean - default: false spilo_allow_privilege_escalation: - type: boolean default: true - spilo_runasuser: - type: integer - spilo_runasgroup: - type: integer + type: boolean spilo_fsgroup: + format: int64 type: integer spilo_privileged: type: boolean - default: false + spilo_runasgroup: + format: int64 + type: integer + spilo_runasuser: + format: int64 + type: integer storage_resize_mode: - type: string + default: pvc enum: - - "ebs" - - "mixed" - - "pvc" - - "off" - default: "pvc" + - ebs + - mixed + - pvc + - "off" + type: string toleration: - type: object additionalProperties: type: string + type: object 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?)$|^$' - max_cpu_request: - type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$|^$' - max_memory_request: - type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$|^$' - min_cpu_limit: - type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$|^$' - min_memory_limit: - type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$|^$' - timeouts: - type: object - properties: - patroni_api_check_interval: - type: string - default: "1s" - patroni_api_check_timeout: - type: string - default: "5s" - pod_label_wait_timeout: - type: string - default: "10m" - pod_deletion_wait_timeout: - type: string - default: "10m" - ready_wait_interval: - type: string - default: "4s" - ready_wait_timeout: - type: string - default: "30s" - resource_check_interval: - type: string - default: "3s" - resource_check_timeout: - type: string - default: "10m" + kubernetes_use_configmaps: + default: true + type: boolean load_balancer: - type: object + description: LoadBalancerConfiguration defines the LB configuration properties: custom_service_annotations: - type: object additionalProperties: type: string + type: object db_hosted_zone: type: string - default: "db.example.com" enable_master_load_balancer: type: boolean - default: true - enable_master_pooler_load_balancer: - type: boolean - default: false - enable_replica_load_balancer: - type: boolean - default: false - enable_replica_pooler_load_balancer: - type: boolean - default: false enable_master_node_port: type: boolean - default: false + enable_master_pooler_load_balancer: + type: boolean enable_master_pooler_node_port: type: boolean - default: false + enable_replica_load_balancer: + type: boolean enable_replica_node_port: type: boolean - default: false + enable_replica_pooler_load_balancer: + type: boolean enable_replica_pooler_node_port: type: boolean - default: false external_traffic_policy: - type: string + default: Cluster enum: - - "Cluster" - - "Local" - default: "Cluster" + - Cluster + - Local + type: string master_dns_name_format: + default: '{cluster}.{namespace}.{hostedzone}' + description: defines the DNS name string template for the master + load balancer cluster type: string - default: "{cluster}.{namespace}.{hostedzone}" master_legacy_dns_name_format: + default: '{cluster}.{team}.{hostedzone}' + description: deprecated DNS template for master load balancer + using team name type: string - default: "{cluster}.{team}.{hostedzone}" replica_dns_name_format: + default: '{cluster}-repl.{namespace}.{hostedzone}' + description: defines the DNS name string template for the replica + load balancer cluster type: string - default: "{cluster}-repl.{namespace}.{hostedzone}" replica_legacy_dns_name_format: + default: '{cluster}-repl.{team}.{hostedzone}' + description: deprecated DNS template for replica load balancer + using team name type: string - default: "{cluster}-repl.{team}.{hostedzone}" - aws_or_gcp: type: object + logging_rest_api: + description: LoggingRESTAPIConfiguration defines Logging API conf properties: - additional_secret_mount: - type: string - additional_secret_mount_path: - type: string - aws_region: - type: string - default: "eu-central-1" - enable_ebs_gp3_migration: - type: boolean - default: false - enable_ebs_gp3_migration_max_size: + api_port: + default: 8080 type: integer + cluster_history_entries: default: 1000 - gcp_credentials: - type: string - kube_iam_role: - type: string - log_s3_bucket: - type: string - wal_az_storage_account: - type: string - wal_gs_bucket: - type: string - wal_s3_bucket: - type: string - logical_backup: + type: integer + ring_log_lines: + default: 100 + type: integer type: object + logical_backup: + description: OperatorLogicalBackupConfiguration defines configuration + for logical backup properties: + logical_backup_azure_storage_account_key: + type: string logical_backup_azure_storage_account_name: type: string logical_backup_azure_storage_container: type: string - logical_backup_azure_storage_account_key: - type: string logical_backup_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' logical_backup_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + logical_backup_cronjob_environment_secret: type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' logical_backup_docker_image: + default: ghcr.io/zalando/postgres-operator/logical-backup:v1.15.1 type: string - default: "ghcr.io/zalando/postgres-operator/logical-backup:v1.15.1" + logical_backup_failed_jobs_history_limit: + default: 3 + format: int32 + minimum: 0 + type: integer logical_backup_google_application_credentials: type: string logical_backup_job_prefix: + default: logical-backup- type: string - default: "logical-backup-" logical_backup_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' logical_backup_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' logical_backup_provider: - type: string + default: s3 enum: - - "az" - - "gcs" - - "s3" - default: "s3" + - az + - gcs + - s3 + type: string logical_backup_s3_access_key_id: type: string logical_backup_s3_bucket: @@ -714,174 +681,290 @@ spec: type: string logical_backup_s3_region: type: string + logical_backup_s3_retention_time: + type: string logical_backup_s3_secret_access_key: type: string logical_backup_s3_sse: type: string - logical_backup_s3_retention_time: - type: string logical_backup_schedule: + default: 30 00 * * * + pattern: ^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$ type: string - pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$' - default: "30 00 * * *" - logical_backup_cronjob_environment_secret: - type: string - logical_backup_failed_jobs_history_limit: - type: integer - minimum: 0 - default: 3 logical_backup_successful_jobs_history_limit: - type: integer - minimum: 0 default: 3 - logical_backup_ttl_seconds_after_finished: - type: integer + format: int32 minimum: 0 + type: integer + logical_backup_ttl_seconds_after_finished: default: 86400 - debug: + format: int32 + minimum: 0 + type: integer type: object + maintenance_windows: + type: array + major_version_upgrade: + description: MajorVersionUpgradeConfiguration defines how to execute + major version upgrades of Postgres. properties: - debug_logging: - type: boolean - default: true - enable_database_access: - type: boolean - default: true - teams_api: - type: object - properties: - enable_admin_role_for_users: - type: boolean - default: true - enable_postgres_team_crd: - type: boolean - default: true - enable_postgres_team_crd_superusers: - type: boolean - default: false - enable_team_member_deprecation: - type: boolean - default: false - enable_team_superuser: - type: boolean - default: false - enable_teams_api: - type: boolean - default: true - pam_configuration: + major_version_upgrade_mode: + default: manual + enum: + - "off" + - manual + - full type: string - default: "https://info.example.com/oauth2/tokeninfo?access_token= uid realm=/employees" - pam_role_name: - type: string - default: "zalandos" - postgres_superuser_teams: - type: array + major_version_upgrade_team_allow_list: items: type: string - protected_role_names: type: array - items: - type: string - default: - - admin - - cron_admin - role_deletion_suffix: + minimal_major_version: + default: "14" type: string - default: "_deleted" - team_admin_role: + target_major_version: + default: "18" type: string - default: "admin" - team_api_role_configuration: - type: object - additionalProperties: - type: string - default: - log_statement: all - teams_api_url: - type: string - default: "https://teams.example.com/api/" - logging_rest_api: type: object + max_instances: + default: -1 + description: -1 = disabled + format: int32 + minimum: -1 + type: integer + min_instances: + default: -1 + description: -1 = disabled + format: int32 + minimum: -1 + type: integer + patroni: + description: PatroniConfiguration defines configuration for Patroni properties: - api_port: - type: integer - default: 8080 - cluster_history_entries: - type: integer - default: 1000 - ring_log_lines: - type: integer - default: 100 - scalyr: # deprecated + enable_patroni_failsafe_mode: + type: boolean type: object + postgres_pod_resources: + description: PostgresPodResourcesDefaults defines the spec of default + resources + properties: + default_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + default_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + default_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + default_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + max_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + max_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + min_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + min_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + type: object + repair_period: + default: 5m + description: period between consecutive repair requests + format: int64 + type: integer + resync_period: + default: 30m + description: period between consecutive sync requests + format: int64 + type: integer + scalyr: + description: ScalyrConfiguration defines the configuration for ScalyrAPI properties: scalyr_api_key: type: string scalyr_cpu_limit: - type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' default: "1" - scalyr_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + scalyr_cpu_request: + default: 100m + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' - default: "100m" scalyr_image: type: string scalyr_memory_limit: + default: 500Mi + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' - default: "500Mi" scalyr_memory_request: + default: 50Mi + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' - default: "50Mi" scalyr_server_url: + default: https://upload.eu.scalyr.com type: string - default: "https://upload.eu.scalyr.com" - connection_pooler: type: object - properties: - connection_pooler_schema: - type: string - default: "pooler" - connection_pooler_user: - type: string - default: "pooler" - connection_pooler_image: - type: string - default: "ghcr.io/zalando/postgres-operator/pgbouncer:latest" - connection_pooler_max_db_connections: - type: integer - default: 60 - connection_pooler_mode: - type: string - enum: - - "session" - - "transaction" - default: "transaction" - connection_pooler_number_of_instances: - type: integer - minimum: 1 - default: 2 - connection_pooler_default_cpu_limit: - type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' - connection_pooler_default_cpu_request: - type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' - connection_pooler_default_memory_limit: - type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' - connection_pooler_default_memory_request: - type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' - patroni: + set_memory_request_to_limit: + type: boolean + sidecar_docker_images: + additionalProperties: + type: string type: object + sidecars: + type: object + x-kubernetes-preserve-unknown-fields: true + teams_api: + description: TeamsAPIConfiguration defines the configuration of TeamsAPI properties: - enable_patroni_failsafe_mode: + enable_admin_role_for_users: + default: true type: boolean - default: false - status: + enable_postgres_team_crd: + default: true + type: boolean + enable_postgres_team_crd_superusers: + type: boolean + enable_team_member_deprecation: + type: boolean + enable_team_superuser: + type: boolean + enable_teams_api: + type: boolean + pam_configuration: + default: https://info.example.com/oauth2/tokeninfo?access_token= + uid realm=/employees + type: string + pam_role_name: + default: zalandos + type: string + postgres_superuser_teams: + items: + type: string + type: array + protected_role_names: + default: '["admin", "cron_admin"]' + items: + type: string + type: array + role_deletion_suffix: + default: _deleted + type: string + team_admin_role: + default: admin + type: string + team_api_role_configuration: + additionalProperties: + type: string + default: + log_statement: all + type: object + teams_api_url: + default: https://teams.example.com/api/ + type: string + type: object + timeouts: + description: OperatorTimeouts defines the timeout of ResourceCheck, + PodWait, ReadyWait + properties: + patroni_api_check_interval: + default: 1s + description: interval between consecutive attempts of operator + calling the Patroni API + format: int64 + type: integer + patroni_api_check_timeout: + default: 5s + description: timeout when waiting for successful response from + Patroni API + format: int64 + type: integer + pod_deletion_wait_timeout: + default: 10m + description: timeout when waiting for the Postgres pods to be + deleted + format: int64 + type: integer + pod_label_wait_timeout: + default: 10m + description: timeout when waiting for pod role and cluster labels + format: int64 + type: integer + ready_wait_interval: + default: 4s + description: interval between consecutive attempts waiting for + postgresql CRD to be created + format: int64 + type: integer + ready_wait_timeout: + default: 30s + description: timeout for the complete postgres CRD creation + format: int64 + type: integer + resource_check_interval: + default: 3s + description: interval to wait between consecutive attempts to + check for some K8s resources + format: int64 + type: integer + resource_check_timeout: + default: 10m + description: timeout when waiting for the presence of a certain + K8s resource + format: int64 + type: integer + type: object + users: + description: PostgresUsersConfiguration defines the system users of + Postgres. + properties: + additional_owner_roles: + items: + type: string + type: array + enable_password_rotation: + type: boolean + password_rotation_interval: + default: 90 + format: int32 + type: integer + password_rotation_user_retention: + default: 120 + format: int32 + type: integer + replication_username: + default: standby + type: string + super_username: + default: postgres + type: string + type: object + workers: + default: 8 + format: int32 + minimum: 1 + type: integer type: object - additionalProperties: - type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + required: + - configuration + - metadata + type: object + served: true + storage: true + subresources: + status: {} diff --git a/docs/reference/operator_parameters.md b/docs/reference/operator_parameters.md index d3d1fa742..13d29c950 100644 --- a/docs/reference/operator_parameters.md +++ b/docs/reference/operator_parameters.md @@ -79,11 +79,6 @@ Those are top-level keys, containing both leaf keys and groups. Instruct the operator to create/update the CRDs. If disabled the operator will rely on the CRDs being managed separately. The default is `true`. -* **enable_crd_validation** - *deprecated*: 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`. `false` will be ignored, since `apiextensions.io/v1` requires a structural schema definition. - * **crd_categories** The operator will register CRDs in the `all` category by default so that they will be returned by a `kubectl get all` call. You are free to change categories or leave them empty. diff --git a/manifests/configmap.yaml b/manifests/configmap.yaml index 1096e0265..1c663c757 100644 --- a/manifests/configmap.yaml +++ b/manifests/configmap.yaml @@ -38,7 +38,6 @@ data: # downscaler_annotations: "deployment-time,downscaler/*" enable_admin_role_for_users: "true" enable_crd_registration: "true" - enable_crd_validation: "true" enable_cross_namespace_secret: "false" enable_finalizers: "false" enable_database_access: "true" diff --git a/manifests/operatorconfiguration.crd.yaml b/manifests/operatorconfiguration.crd.yaml index fb009c459..5f347f2ac 100644 --- a/manifests/operatorconfiguration.crd.yaml +++ b/manifests/operatorconfiguration.crd.yaml @@ -1,285 +1,293 @@ +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.17.3 name: operatorconfigurations.acid.zalan.do spec: group: acid.zalan.do names: + categories: + - all kind: OperatorConfiguration listKind: OperatorConfigurationList plural: operatorconfigurations - singular: operatorconfiguration shortNames: - opconfig - categories: - - all + singular: operatorconfiguration scope: Namespaced versions: - - name: v1 - served: true - storage: true - subresources: - status: {} - additionalPrinterColumns: - - name: Image - type: string - description: Spilo image to be used for Pods + - additionalPrinterColumns: + - description: Spilo image to be used for Pods jsonPath: .configuration.docker_image - - name: Cluster-Label + name: Image type: string - description: Label for K8s resources created by operator + - description: Label for K8s resources created by operator jsonPath: .configuration.kubernetes.cluster_name_label - - name: Service-Account + name: Cluster-Label type: string - description: Name of service account to be used + - 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 + name: Service-Account + type: string + - description: Minimum number of instances per Postgres cluster jsonPath: .configuration.min_instances - - name: Age - type: date + name: Min-Instances + type: integer + - description: Age of the OperatorConfiguration resource jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 schema: openAPIV3Schema: - type: object - required: - - kind - - apiVersion - - configuration + description: OperatorConfiguration defines the specification for the OperatorConfiguration. properties: - kind: - type: string - enum: - - OperatorConfiguration apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string - enum: - - acid.zalan.do/v1 configuration: - type: object + description: OperatorConfigurationData defines the operation config properties: + aws_or_gcp: + description: AWSGCPConfiguration defines the configuration for AWS + properties: + additional_secret_mount: + type: string + additional_secret_mount_path: + type: string + aws_region: + default: eu-central-1 + type: string + enable_ebs_gp3_migration: + type: boolean + enable_ebs_gp3_migration_max_size: + format: int64 + type: integer + gcp_credentials: + type: string + kube_iam_role: + type: string + log_s3_bucket: + type: string + wal_az_storage_account: + type: string + wal_gs_bucket: + type: string + wal_s3_bucket: + type: string + type: object + connection_pooler: + description: ConnectionPoolerConfiguration defines default configuration + for connection pooler + properties: + connection_pooler_default_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + connection_pooler_default_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + connection_pooler_default_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + connection_pooler_default_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + connection_pooler_image: + default: ghcr.io/zalando/postgres-operator/pgbouncer:latest + type: string + connection_pooler_max_db_connections: + format: int32 + type: integer + connection_pooler_mode: + default: transaction + enum: + - session + - transaction + type: string + connection_pooler_number_of_instances: + default: 2 + format: int32 + minimum: 1 + type: integer + connection_pooler_schema: + default: pooler + type: string + connection_pooler_user: + default: pooler + type: string + type: object crd_categories: - type: array - nullable: true items: type: string + type: array + debug: + description: OperatorDebugConfiguration defines options for the debug + mode + properties: + debug_logging: + default: true + type: boolean + enable_database_access: + default: true + type: boolean + type: object docker_image: + default: ghcr.io/zalando/spilo-18:4.1-p1 type: string - default: "ghcr.io/zalando/spilo-18:4.1-p1" enable_crd_registration: - type: boolean default: true - enable_crd_validation: type: boolean - description: deprecated - default: true enable_lazy_spilo_upgrade: type: boolean - default: false enable_maintenance_windows: - type: boolean default: true + type: boolean enable_pgversion_env_var: - type: boolean default: true + type: boolean enable_shm_volume: - type: boolean default: true + type: boolean enable_spilo_wal_path_compat: type: boolean - default: false enable_team_id_clustername_prefix: type: boolean - default: false etcd_host: - type: string default: "" + type: string ignore_instance_limits_annotation_key: type: string ignore_resources_limits_annotation_key: type: string - kubernetes_use_configmaps: - type: boolean - default: false - maintenance_windows: - items: - pattern: '^\ *((Mon|Tue|Wed|Thu|Fri|Sat|Sun):(2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))-((2[0-3]|[01]?\d):([0-5]?\d)|(2[0-3]|[01]?\d):([0-5]?\d))\ *$' - type: string - type: array - max_instances: - type: integer - description: "-1 = disabled" - minimum: -1 - default: -1 - min_instances: - type: integer - description: "-1 = disabled" - minimum: -1 - default: -1 - resync_period: - type: string - default: "30m" - repair_period: - type: string - default: "5m" - set_memory_request_to_limit: - type: boolean - default: false - sidecar_docker_images: - type: object - additionalProperties: - type: string - sidecars: - type: array - nullable: true - items: - type: object - x-kubernetes-preserve-unknown-fields: true - workers: - type: integer - minimum: 1 - default: 8 - users: - type: object - properties: - additional_owner_roles: - type: array - nullable: true - items: - type: string - enable_password_rotation: - type: boolean - default: false - password_rotation_interval: - type: integer - default: 90 - password_rotation_user_retention: - type: integer - default: 180 - replication_username: - type: string - default: standby - super_username: - type: string - default: postgres - major_version_upgrade: - type: object - properties: - major_version_upgrade_mode: - type: string - default: "manual" - major_version_upgrade_team_allow_list: - type: array - items: - type: string - minimal_major_version: - type: string - default: "14" - target_major_version: - type: string - default: "18" kubernetes: - type: object + description: KubernetesMetaConfiguration defines k8s conf required + for all Postgres clusters and the operator itself properties: additional_pod_capabilities: - type: array items: type: string + type: array cluster_domain: + default: cluster.local type: string - default: "cluster.local" cluster_labels: - type: object additionalProperties: type: string default: application: spilo - cluster_name_label: - type: string - default: "cluster-name" - custom_pod_annotations: type: object + cluster_name_label: + default: cluster-name + type: string + custom_pod_annotations: additionalProperties: type: string + type: object delete_annotation_date_key: type: string delete_annotation_name_key: type: string downscaler_annotations: - type: array items: type: string + type: array enable_cross_namespace_secret: type: boolean - default: false enable_finalizers: type: boolean - default: false enable_init_containers: - type: boolean default: true + type: boolean enable_owner_references: type: boolean - default: false enable_persistent_volume_claim_deletion: - type: boolean default: true + type: boolean enable_pod_antiaffinity: type: boolean - default: false enable_pod_disruption_budget: - type: boolean default: true + type: boolean enable_readiness_probe: type: boolean - default: false enable_secrets_deletion: - type: boolean default: true + type: boolean enable_sidecars: - type: boolean default: true + type: boolean ignored_annotations: - type: array items: type: string - infrastructure_roles_secret_name: - type: string - infrastructure_roles_secrets: type: array - nullable: true + infrastructure_roles_secret_name: + description: |- + NamespacedName comprises a resource name, with a mandatory namespace, + rendered as "/". Being a type captures intent and + helps make sure that UIDs, namespaced names and non-namespaced names + do not get conflated in code. For most use cases, namespace and name + will already have been format validated at the API entry point, so we + don't do that here. Where that's not the case (e.g. in testing), + consider using NamespacedNameOrDie() in testing.go in this package. + + from: https://github.com/kubernetes/apimachinery/blob/master/pkg/types/namespacedname.go + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + infrastructure_roles_secrets: + description: namespaced name of the secret containing infrastructure + roles names and passwords items: - type: object - required: - - secretname - - userkey - - passwordkey properties: - secretname: + defaultrolevalue: type: string - userkey: + defaultuservalue: + type: string + details: + description: This field point out the detailed yaml definition + of the role, if exists type: string passwordkey: type: string rolekey: type: string - defaultuservalue: - type: string - defaultrolevalue: - type: string - details: - type: string + secretname: + description: |- + Name of a secret which describes the role, and optionally name of a + configmap with an extra information + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object template: type: boolean + userkey: + type: string + type: object + type: array inherited_annotations: - type: array items: type: string + type: array inherited_labels: - type: array items: type: string + type: array liveness_probe: description: |- Probe describes a health check to be performed against a container to determine whether it is @@ -334,11 +342,11 @@ spec: "Host" in httpHeaders instead. type: string httpHeaders: - description: Custom headers to set in the request. HTTP allows - repeated headers. + description: Custom headers to set in the request. HTTP + allows repeated headers. items: - description: HTTPHeader describes a custom header to be - used in HTTP probes + description: HTTPHeader describes a custom header to + be used in HTTP probes properties: name: description: |- @@ -434,262 +442,236 @@ spec: type: integer type: object master_pod_move_timeout: - type: string - default: "20m" + default: 20m + description: timeout for successful migration of master pods from + unschedulable node + format: int64 + type: integer node_readiness_label: - type: object additionalProperties: type: string - node_readiness_label_merge: - type: string - enum: - - "AND" - - "OR" - oauth_token_secret_name: - type: string - default: "postgresql-operator" - pdb_master_label_selector: - type: boolean - default: true - pdb_name_format: - type: string - default: "postgres-{cluster}-pdb" - persistent_volume_claim_retention_policy: type: object + node_readiness_label_merge: + enum: + - AND + - OR + type: string + oauth_token_secret_name: + default: postgres-operator + description: namespaced name of the secret containing the OAuth2 + token to pass to the teams API properties: - when_deleted: + name: type: string - enum: - - "delete" - - "retain" - when_scaled: + namespace: type: string - enum: - - "delete" - - "retain" + required: + - name + type: object + pdb_master_label_selector: + default: true + type: boolean + pdb_name_format: + default: postgres-{cluster}-pdb + description: defines the template for PDB names + type: string + persistent_volume_claim_retention_policy: + additionalProperties: + type: string + type: object pod_antiaffinity_preferred_during_scheduling: type: boolean - default: false pod_antiaffinity_topology_key: + default: kubernetes.io/hostname type: string - default: "kubernetes.io/hostname" pod_environment_configmap: - type: string + description: namespaced name of the ConfigMap with environment + variables to populate on every pod + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object pod_environment_secret: type: string pod_management_policy: - type: string + default: ordered_ready enum: - - "ordered_ready" - - "parallel" - default: "ordered_ready" + - ordered_ready + - parallel + type: string pod_priority_class_name: type: string pod_role_label: + default: spilo-role type: string - default: "spilo-role" pod_service_account_definition: type: string - default: "" pod_service_account_name: + default: postgres-pod type: string - default: "postgres-pod" pod_service_account_role_binding_definition: type: string - default: "" pod_terminate_grace_period: - type: string - default: "5m" + default: 5m + description: Postgres pods are terminated forcefully after this + timeout + format: int64 + type: integer secret_name_template: + default: '{username}.{cluster}.credentials.{tprkind}.{tprgroup}' + description: |- + template for database user secrets generated by the operator, + here username contains the namespace in the format namespace.username + if the user is in different namespace than cluster and cross namespace secrets + are enabled via `enable_cross_namespace_secret` flag in the configuration. type: string - default: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}" share_pgsocket_with_sidecars: type: boolean - default: false spilo_allow_privilege_escalation: - type: boolean default: true - spilo_runasuser: - type: integer - spilo_runasgroup: - type: integer + type: boolean spilo_fsgroup: + format: int64 type: integer spilo_privileged: type: boolean - default: false + spilo_runasgroup: + format: int64 + type: integer + spilo_runasuser: + format: int64 + type: integer storage_resize_mode: - type: string + default: pvc enum: - - "ebs" - - "mixed" - - "pvc" - - "off" - default: "pvc" + - ebs + - mixed + - pvc + - "off" + type: string toleration: - type: object additionalProperties: type: string + type: object 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?)$|^$' - max_cpu_request: - type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$|^$' - max_memory_request: - type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$|^$' - min_cpu_limit: - type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$|^$' - min_memory_limit: - type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$|^$' - timeouts: - type: object - properties: - patroni_api_check_interval: - type: string - default: "1s" - patroni_api_check_timeout: - type: string - default: "5s" - pod_label_wait_timeout: - type: string - default: "10m" - pod_deletion_wait_timeout: - type: string - default: "10m" - ready_wait_interval: - type: string - default: "4s" - ready_wait_timeout: - type: string - default: "30s" - resource_check_interval: - type: string - default: "3s" - resource_check_timeout: - type: string - default: "10m" + kubernetes_use_configmaps: + default: true + type: boolean load_balancer: - type: object + description: LoadBalancerConfiguration defines the LB configuration properties: custom_service_annotations: - type: object additionalProperties: type: string + type: object db_hosted_zone: type: string - default: "db.example.com" enable_master_load_balancer: type: boolean - default: true + enable_master_node_port: + type: boolean enable_master_pooler_load_balancer: type: boolean - default: false + enable_master_pooler_node_port: + type: boolean enable_replica_load_balancer: type: boolean - default: false + enable_replica_node_port: + type: boolean enable_replica_pooler_load_balancer: type: boolean - default: false - external_traffic_policy: - type: string - enum: - - "Cluster" - - "Local" - default: "Cluster" - master_dns_name_format: - type: string - default: "{cluster}.{namespace}.{hostedzone}" - master_legacy_dns_name_format: - type: string - default: "{cluster}.{team}.{hostedzone}" - replica_dns_name_format: - type: string - default: "{cluster}-repl.{namespace}.{hostedzone}" - replica_legacy_dns_name_format: - type: string - default: "{cluster}-repl.{team}.{hostedzone}" - aws_or_gcp: - type: object - properties: - additional_secret_mount: - type: string - additional_secret_mount_path: - type: string - aws_region: - type: string - default: "eu-central-1" - enable_ebs_gp3_migration: + enable_replica_pooler_node_port: type: boolean - default: false - enable_ebs_gp3_migration_max_size: - type: integer - default: 1000 - gcp_credentials: + external_traffic_policy: + default: Cluster + enum: + - Cluster + - Local type: string - kube_iam_role: + master_dns_name_format: + default: '{cluster}.{namespace}.{hostedzone}' + description: defines the DNS name string template for the master + load balancer cluster type: string - log_s3_bucket: + master_legacy_dns_name_format: + default: '{cluster}.{team}.{hostedzone}' + description: deprecated DNS template for master load balancer + using team name type: string - wal_az_storage_account: + replica_dns_name_format: + default: '{cluster}-repl.{namespace}.{hostedzone}' + description: defines the DNS name string template for the replica + load balancer cluster type: string - wal_gs_bucket: + replica_legacy_dns_name_format: + default: '{cluster}-repl.{team}.{hostedzone}' + description: deprecated DNS template for replica load balancer + using team name type: string - wal_s3_bucket: - type: string - logical_backup: type: object + logging_rest_api: + description: LoggingRESTAPIConfiguration defines Logging API conf properties: + api_port: + default: 8080 + type: integer + cluster_history_entries: + default: 1000 + type: integer + ring_log_lines: + default: 100 + type: integer + type: object + logical_backup: + description: OperatorLogicalBackupConfiguration defines configuration + for logical backup + properties: + logical_backup_azure_storage_account_key: + type: string logical_backup_azure_storage_account_name: type: string logical_backup_azure_storage_container: type: string - logical_backup_azure_storage_account_key: - type: string logical_backup_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' logical_backup_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + logical_backup_cronjob_environment_secret: type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' logical_backup_docker_image: + default: ghcr.io/zalando/postgres-operator/logical-backup:v1.15.1 type: string - default: "ghcr.io/zalando/postgres-operator/logical-backup:v1.15.1" + logical_backup_failed_jobs_history_limit: + default: 3 + format: int32 + minimum: 0 + type: integer logical_backup_google_application_credentials: type: string logical_backup_job_prefix: + default: logical-backup- type: string - default: "logical-backup-" logical_backup_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' logical_backup_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' logical_backup_provider: - type: string + default: s3 enum: - - "az" - - "gcs" - - "s3" - default: "s3" + - az + - gcs + - s3 + type: string logical_backup_s3_access_key_id: type: string logical_backup_s3_bucket: @@ -700,174 +682,290 @@ spec: type: string logical_backup_s3_region: type: string + logical_backup_s3_retention_time: + type: string logical_backup_s3_secret_access_key: type: string logical_backup_s3_sse: type: string - logical_backup_s3_retention_time: - type: string logical_backup_schedule: + default: 30 00 * * * + pattern: ^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$ type: string - pattern: '^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$' - default: "30 00 * * *" - logical_backup_cronjob_environment_secret: - type: string - logical_backup_failed_jobs_history_limit: - type: integer - minimum: 0 - default: 3 logical_backup_successful_jobs_history_limit: - type: integer - minimum: 0 default: 3 - logical_backup_ttl_seconds_after_finished: - type: integer + format: int32 minimum: 0 + type: integer + logical_backup_ttl_seconds_after_finished: default: 86400 - debug: + format: int32 + minimum: 0 + type: integer type: object + maintenance_windows: + type: array + major_version_upgrade: + description: MajorVersionUpgradeConfiguration defines how to execute + major version upgrades of Postgres. properties: - debug_logging: - type: boolean - default: true - enable_database_access: - type: boolean - default: true - teams_api: - type: object - properties: - enable_admin_role_for_users: - type: boolean - default: true - enable_postgres_team_crd: - type: boolean - default: true - enable_postgres_team_crd_superusers: - type: boolean - default: false - enable_team_member_deprecation: - type: boolean - default: false - enable_team_superuser: - type: boolean - default: false - enable_teams_api: - type: boolean - default: true - pam_configuration: + major_version_upgrade_mode: + default: manual + enum: + - "off" + - manual + - full type: string - default: "https://info.example.com/oauth2/tokeninfo?access_token= uid realm=/employees" - pam_role_name: - type: string - default: "zalandos" - postgres_superuser_teams: - type: array + major_version_upgrade_team_allow_list: items: type: string - protected_role_names: type: array - items: - type: string - default: - - admin - - cron_admin - role_deletion_suffix: + minimal_major_version: + default: "14" type: string - default: "_deleted" - team_admin_role: + target_major_version: + default: "18" type: string - default: "admin" - team_api_role_configuration: - type: object - additionalProperties: - type: string - default: - log_statement: all - teams_api_url: - type: string - default: "https://teams.example.com/api/" - logging_rest_api: type: object + max_instances: + default: -1 + description: -1 = disabled + format: int32 + minimum: -1 + type: integer + min_instances: + default: -1 + description: -1 = disabled + format: int32 + minimum: -1 + type: integer + patroni: + description: PatroniConfiguration defines configuration for Patroni properties: - api_port: - type: integer - default: 8080 - cluster_history_entries: - type: integer - default: 1000 - ring_log_lines: - type: integer - default: 100 - scalyr: # deprecated + enable_patroni_failsafe_mode: + type: boolean type: object + postgres_pod_resources: + description: PostgresPodResourcesDefaults defines the spec of default + resources + properties: + default_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + default_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + default_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + default_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + max_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + max_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + min_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + min_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + type: object + repair_period: + default: 5m + description: period between consecutive repair requests + format: int64 + type: integer + resync_period: + default: 30m + description: period between consecutive sync requests + format: int64 + type: integer + scalyr: + description: ScalyrConfiguration defines the configuration for ScalyrAPI properties: scalyr_api_key: type: string scalyr_cpu_limit: - type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' default: "1" - scalyr_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + scalyr_cpu_request: + default: 100m + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' - default: "100m" scalyr_image: type: string scalyr_memory_limit: + default: 500Mi + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' - default: "500Mi" scalyr_memory_request: + default: 50Mi + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' - default: "50Mi" scalyr_server_url: + default: https://upload.eu.scalyr.com type: string - default: "https://upload.eu.scalyr.com" - connection_pooler: type: object - properties: - connection_pooler_schema: - type: string - default: "pooler" - connection_pooler_user: - type: string - default: "pooler" - connection_pooler_image: - type: string - default: "ghcr.io/zalando/postgres-operator/pgbouncer:latest" - connection_pooler_max_db_connections: - type: integer - default: 60 - connection_pooler_mode: - type: string - enum: - - "session" - - "transaction" - default: "transaction" - connection_pooler_number_of_instances: - type: integer - minimum: 1 - default: 2 - connection_pooler_default_cpu_limit: - type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' - connection_pooler_default_cpu_request: - type: string - pattern: '^(\d+m|\d+(\.\d{1,3})?)$' - connection_pooler_default_memory_limit: - type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' - connection_pooler_default_memory_request: - type: string - pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$' - patroni: + set_memory_request_to_limit: + type: boolean + sidecar_docker_images: + additionalProperties: + type: string type: object + sidecars: + type: object + x-kubernetes-preserve-unknown-fields: true + teams_api: + description: TeamsAPIConfiguration defines the configuration of TeamsAPI properties: - enable_patroni_failsafe_mode: + enable_admin_role_for_users: + default: true type: boolean - default: false - status: + enable_postgres_team_crd: + default: true + type: boolean + enable_postgres_team_crd_superusers: + type: boolean + enable_team_member_deprecation: + type: boolean + enable_team_superuser: + type: boolean + enable_teams_api: + type: boolean + pam_configuration: + default: https://info.example.com/oauth2/tokeninfo?access_token= + uid realm=/employees + type: string + pam_role_name: + default: zalandos + type: string + postgres_superuser_teams: + items: + type: string + type: array + protected_role_names: + default: '["admin", "cron_admin"]' + items: + type: string + type: array + role_deletion_suffix: + default: _deleted + type: string + team_admin_role: + default: admin + type: string + team_api_role_configuration: + additionalProperties: + type: string + default: + log_statement: all + type: object + teams_api_url: + default: https://teams.example.com/api/ + type: string + type: object + timeouts: + description: OperatorTimeouts defines the timeout of ResourceCheck, + PodWait, ReadyWait + properties: + patroni_api_check_interval: + default: 1s + description: interval between consecutive attempts of operator + calling the Patroni API + format: int64 + type: integer + patroni_api_check_timeout: + default: 5s + description: timeout when waiting for successful response from + Patroni API + format: int64 + type: integer + pod_deletion_wait_timeout: + default: 10m + description: timeout when waiting for the Postgres pods to be + deleted + format: int64 + type: integer + pod_label_wait_timeout: + default: 10m + description: timeout when waiting for pod role and cluster labels + format: int64 + type: integer + ready_wait_interval: + default: 4s + description: interval between consecutive attempts waiting for + postgresql CRD to be created + format: int64 + type: integer + ready_wait_timeout: + default: 30s + description: timeout for the complete postgres CRD creation + format: int64 + type: integer + resource_check_interval: + default: 3s + description: interval to wait between consecutive attempts to + check for some K8s resources + format: int64 + type: integer + resource_check_timeout: + default: 10m + description: timeout when waiting for the presence of a certain + K8s resource + format: int64 + type: integer + type: object + users: + description: PostgresUsersConfiguration defines the system users of + Postgres. + properties: + additional_owner_roles: + items: + type: string + type: array + enable_password_rotation: + type: boolean + password_rotation_interval: + default: 90 + format: int32 + type: integer + password_rotation_user_retention: + default: 120 + format: int32 + type: integer + replication_username: + default: standby + type: string + super_username: + default: postgres + type: string + type: object + workers: + default: 8 + format: int32 + minimum: 1 + type: integer type: object - additionalProperties: - type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + required: + - configuration + - metadata + type: object + served: true + storage: true + subresources: + status: {} diff --git a/pkg/apis/acid.zalan.do/v1/crds.go b/pkg/apis/acid.zalan.do/v1/crds.go index 867f573b3..54aea7c1b 100644 --- a/pkg/apis/acid.zalan.do/v1/crds.go +++ b/pkg/apis/acid.zalan.do/v1/crds.go @@ -2,1132 +2,17 @@ package v1 import ( _ "embed" - "fmt" - acidzalando "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do" - "github.com/zalando/postgres-operator/pkg/util" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/yaml" ) // CRDResource* define names necesssary for the k8s CRD API const ( - PostgresCRDResourceKind = "postgresql" - - OperatorConfigCRDResouceKind = "OperatorConfiguration" - OperatorConfigCRDResourcePlural = "operatorconfigurations" - OperatorConfigCRDResourceList = OperatorConfigCRDResouceKind + "List" - OperatorConfigCRDResourceName = OperatorConfigCRDResourcePlural + "." + acidzalando.GroupName - OperatorConfigCRDResourceShort = "opconfig" + PostgresCRDResourceKind = "postgresql" + OperatorConfigCRDResourceKind = "OperatorConfiguration" ) -// OperatorConfigCRDResourceColumns definition of AdditionalPrinterColumns for OperatorConfiguration CRD -var OperatorConfigCRDResourceColumns = []apiextv1.CustomResourceColumnDefinition{ - { - 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", - }, -} - -var min1 = 1.0 -var minLength1 int64 = 1 -var minDisable = -1.0 - -// OperatorConfigCRDResourceValidation to check applied manifest parameters -var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{ - OpenAPIV3Schema: &apiextv1.JSONSchemaProps{ - Type: "object", - Required: []string{"kind", "apiVersion", "configuration"}, - Properties: map[string]apiextv1.JSONSchemaProps{ - "kind": { - Type: "string", - Enum: []apiextv1.JSON{ - { - Raw: []byte(`"OperatorConfiguration"`), - }, - }, - }, - "apiVersion": { - Type: "string", - Enum: []apiextv1.JSON{ - { - Raw: []byte(`"acid.zalan.do/v1"`), - }, - }, - }, - "configuration": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "crd_categories": { - Type: "array", - Nullable: true, - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "docker_image": { - Type: "string", - }, - "enable_crd_registration": { - Type: "boolean", - }, - "enable_crd_validation": { - Type: "boolean", - Description: "deprecated", - }, - "enable_lazy_spilo_upgrade": { - Type: "boolean", - }, - "enable_maintenance_windows": { - Type: "boolean", - }, - "enable_shm_volume": { - Type: "boolean", - }, - "enable_spilo_wal_path_compat": { - Type: "boolean", - Description: "deprecated", - }, - "enable_team_id_clustername_prefix": { - Type: "boolean", - }, - "etcd_host": { - Type: "string", - }, - "ignore_instance_limits_annotation_key": { - Type: "string", - }, - "ignore_resources_limits_annotation_key": { - Type: "string", - }, - "kubernetes_use_configmaps": { - Type: "boolean", - }, - "maintenance_windows": { - Type: "array", - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.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))\\ *$", - }, - }, - }, - "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: &apiextv1.JSONSchemaPropsOrBool{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "sidecars": { - Type: "array", - Nullable: true, - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "object", - XPreserveUnknownFields: util.True(), - }, - }, - }, - "workers": { - Type: "integer", - Minimum: &min1, - }, - "users": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "additional_owner_roles": { - Type: "array", - Nullable: true, - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "enable_password_rotation": { - Type: "boolean", - }, - "password_rotation_interval": { - Type: "integer", - }, - "password_rotation_user_retention": { - Type: "integer", - }, - "replication_username": { - Type: "string", - }, - "super_username": { - Type: "string", - }, - }, - }, - "major_version_upgrade": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "major_version_upgrade_mode": { - Type: "string", - }, - "major_version_upgrade_team_allow_list": { - Type: "array", - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "minimal_major_version": { - Type: "string", - }, - "target_major_version": { - Type: "string", - }, - }, - }, - "kubernetes": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "additional_pod_capabilities": { - Type: "array", - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "cluster_domain": { - Type: "string", - }, - "cluster_labels": { - Type: "object", - AdditionalProperties: &apiextv1.JSONSchemaPropsOrBool{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "cluster_name_label": { - Type: "string", - }, - "custom_pod_annotations": { - Type: "object", - AdditionalProperties: &apiextv1.JSONSchemaPropsOrBool{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "delete_annotation_date_key": { - Type: "string", - }, - "delete_annotation_name_key": { - Type: "string", - }, - "downscaler_annotations": { - Type: "array", - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "enable_cross_namespace_secret": { - Type: "boolean", - }, - "enable_finalizers": { - Type: "boolean", - }, - "enable_init_containers": { - Type: "boolean", - }, - "enable_owner_references": { - Type: "boolean", - }, - "enable_persistent_volume_claim_deletion": { - Type: "boolean", - }, - "enable_pod_antiaffinity": { - Type: "boolean", - }, - "enable_pod_disruption_budget": { - Type: "boolean", - }, - "enable_readiness_probe": { - Type: "boolean", - }, - "enable_secrets_deletion": { - Type: "boolean", - }, - "enable_sidecars": { - Type: "boolean", - }, - "ignored_annotations": { - Type: "array", - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "infrastructure_roles_secret_name": { - Type: "string", - }, - "infrastructure_roles_secrets": { - Type: "array", - Nullable: true, - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "object", - Required: []string{"secretname", "userkey", "passwordkey"}, - Properties: map[string]apiextv1.JSONSchemaProps{ - "secretname": { - Type: "string", - }, - "userkey": { - Type: "string", - }, - "passwordkey": { - Type: "string", - }, - "rolekey": { - Type: "string", - }, - "defaultuservalue": { - Type: "string", - }, - "defaultrolevalue": { - Type: "string", - }, - "details": { - Type: "string", - }, - "template": { - Type: "boolean", - }, - }, - }, - }, - }, - "inherited_annotations": { - Type: "array", - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "inherited_labels": { - Type: "array", - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "liveness_probe": { - Description: "Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "exec": { - Description: "One and only one of the following should be specified. Exec specifies the action to take.", - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "command": { - Description: "Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy.", - Type: "array", - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - }, - }, - "failureThreshold": { - Description: "Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1.", - Type: "integer", - Format: "int32", - }, - "httpGet": { - Description: "HTTPGet specifies the http request to perform.", - Type: "object", - Required: []string{"port"}, - Properties: map[string]apiextv1.JSONSchemaProps{ - "host": { - Description: "Host name to connect to, defaults to the pod IP. You probably want to set \"Host\" in httpHeaders instead.", - Type: "string", - }, - "httpHeaders": { - Description: "Custom headers to set in the request. HTTP allows repeated headers.", - Type: "array", - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Description: "HTTPHeader describes a custom header to be used in HTTP probes", - Type: "object", - Required: []string{"name", "value"}, - Properties: map[string]apiextv1.JSONSchemaProps{ - "name": { - Description: "The header field name", - Type: "string", - }, - "value": { - Description: "The header field value", - Type: "string", - }, - }, - }, - }, - }, - "path": { - Description: "Path to access on the HTTP server.", - Type: "string", - }, - "port": { - Description: "Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.", - AnyOf: []apiextv1.JSONSchemaProps{ - { - Type: "integer", - }, - { - Type: "string", - }, - }, - XIntOrString: true, - }, - "scheme": { - Description: "Scheme to use for connecting to the host. Defaults to HTTP.", - Type: "string", - }, - }, - }, - "initialDelaySeconds": { - Description: "Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", - Type: "integer", - Format: "int32", - }, - "periodSeconds": { - Description: "How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1.", - Type: "integer", - Format: "int32", - }, - "successThreshold": { - Description: "Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1.", - Type: "integer", - Format: "int32", - }, - "tcpSocket": { - Description: "TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TODO: implement a realistic TCP lifecycle hook", - Type: "object", - Required: []string{"port"}, - Properties: map[string]apiextv1.JSONSchemaProps{ - "host": { - Description: "Optional: Host name to connect to, defaults to the pod IP.", - Type: "string", - }, - "port": { - Description: "Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.", - XIntOrString: true, - AnyOf: []apiextv1.JSONSchemaProps{ - { - Type: "integer", - }, - { - Type: "string", - }, - }, - }, - }, - }, - "terminationGracePeriodSeconds": { - Description: "Optional duration in seconds the pod needs to terminate gracefully upon probe failure. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this value overrides the value provided by the pod spec. Value must be non-negative integer. The value zero indicates stop immediately via the kill signal (no opportunity to shut down). This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset.", - Type: "integer", - Format: "int64", - }, - "timeoutSeconds": { - Description: "Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes", - Type: "integer", - Format: "int32", - }, - }, - }, - "master_pod_move_timeout": { - Type: "string", - }, - "node_readiness_label": { - Type: "object", - AdditionalProperties: &apiextv1.JSONSchemaPropsOrBool{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "node_readiness_label_merge": { - Type: "string", - Enum: []apiextv1.JSON{ - { - Raw: []byte(`"AND"`), - }, - { - Raw: []byte(`"OR"`), - }, - }, - }, - "oauth_token_secret_name": { - Type: "string", - }, - "pdb_name_format": { - Type: "string", - }, - "pdb_master_label_selector": { - Type: "boolean", - }, - "persistent_volume_claim_retention_policy": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "when_deleted": { - Type: "string", - Enum: []apiextv1.JSON{ - { - Raw: []byte(`"delete"`), - }, - { - Raw: []byte(`"retain"`), - }, - }, - }, - "when_scaled": { - Type: "string", - Enum: []apiextv1.JSON{ - { - Raw: []byte(`"delete"`), - }, - { - Raw: []byte(`"retain"`), - }, - }, - }, - }, - }, - "pod_antiaffinity_preferred_during_scheduling": { - Type: "boolean", - }, - "pod_antiaffinity_topology_key": { - Type: "string", - }, - "pod_environment_configmap": { - Type: "string", - }, - "pod_environment_secret": { - Type: "string", - }, - "pod_management_policy": { - Type: "string", - Enum: []apiextv1.JSON{ - { - Raw: []byte(`"ordered_ready"`), - }, - { - Raw: []byte(`"parallel"`), - }, - }, - }, - "pod_priority_class_name": { - Type: "string", - }, - "pod_role_label": { - Type: "string", - }, - "pod_service_account_definition": { - Type: "string", - }, - "pod_service_account_name": { - Type: "string", - }, - "pod_service_account_role_binding_definition": { - Type: "string", - }, - "pod_terminate_grace_period": { - Type: "string", - }, - "secret_name_template": { - Type: "string", - }, - "share_pgsocket_with_sidecars": { - Type: "boolean", - }, - "spilo_runasuser": { - Type: "integer", - }, - "spilo_runasgroup": { - Type: "integer", - }, - "spilo_fsgroup": { - Type: "integer", - }, - "spilo_privileged": { - Type: "boolean", - }, - "spilo_allow_privilege_escalation": { - Type: "boolean", - }, - "storage_resize_mode": { - Type: "string", - Enum: []apiextv1.JSON{ - { - Raw: []byte(`"ebs"`), - }, - { - Raw: []byte(`"mixed"`), - }, - { - Raw: []byte(`"pvc"`), - }, - { - Raw: []byte(`"off"`), - }, - }, - }, - "toleration": { - Type: "object", - AdditionalProperties: &apiextv1.JSONSchemaPropsOrBool{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "watched_namespace": { - Type: "string", - }, - }, - }, - "patroni": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "enable_patroni_failsafe_mode": { - Type: "boolean", - }, - }, - }, - "postgres_pod_resources": { - Type: "object", - Properties: map[string]apiextv1.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?)$|^$", - }, - "max_cpu_request": { - Type: "string", - Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$|^$", - }, - "max_memory_request": { - Type: "string", - Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$|^$", - }, - "min_cpu_limit": { - Type: "string", - Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$|^$", - }, - "min_memory_limit": { - Type: "string", - Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$|^$", - }, - }, - }, - "timeouts": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "patroni_api_check_interval": { - Type: "string", - }, - "patroni_api_check_timeout": { - Type: "string", - }, - "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]apiextv1.JSONSchemaProps{ - "custom_service_annotations": { - Type: "object", - AdditionalProperties: &apiextv1.JSONSchemaPropsOrBool{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "db_hosted_zone": { - Type: "string", - }, - "enable_master_load_balancer": { - Type: "boolean", - }, - "enable_master_pooler_load_balancer": { - Type: "boolean", - }, - "enable_replica_load_balancer": { - Type: "boolean", - }, - "enable_replica_pooler_load_balancer": { - Type: "boolean", - }, - "enable_master_node_port": { - Type: "boolean", - }, - "enable_master_pooler_node_port": { - Type: "boolean", - }, - "enable_replica_node_port": { - Type: "boolean", - }, - "enable_replica_pooler_node_port": { - Type: "boolean", - }, - "external_traffic_policy": { - Type: "string", - Enum: []apiextv1.JSON{ - { - Raw: []byte(`"Cluster"`), - }, - { - Raw: []byte(`"Local"`), - }, - }, - }, - "master_dns_name_format": { - Type: "string", - }, - "master_legacy_dns_name_format": { - Type: "string", - }, - "replica_dns_name_format": { - Type: "string", - }, - "replica_legacy_dns_name_format": { - Type: "string", - }, - }, - }, - "aws_or_gcp": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "additional_secret_mount": { - Type: "string", - }, - "additional_secret_mount_path": { - Type: "string", - }, - "aws_region": { - Type: "string", - }, - "enable_ebs_gp3_migration": { - Type: "boolean", - }, - "enable_ebs_gp3_migration_max_size": { - Type: "integer", - }, - "gcp_credentials": { - Type: "string", - }, - "kube_iam_role": { - Type: "string", - }, - "log_s3_bucket": { - Type: "string", - }, - "wal_s3_bucket": { - Type: "string", - }, - }, - }, - "logical_backup": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "logical_backup_azure_storage_account_name": { - Type: "string", - }, - "logical_backup_azure_storage_container": { - Type: "string", - }, - "logical_backup_azure_storage_account_key": { - Type: "string", - }, - "logical_backup_cpu_limit": { - Type: "string", - Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$", - }, - "logical_backup_cpu_request": { - Type: "string", - Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$", - }, - "logical_backup_docker_image": { - Type: "string", - }, - "logical_backup_google_application_credentials": { - Type: "string", - }, - "logical_backup_job_prefix": { - Type: "string", - }, - "logical_backup_memory_limit": { - Type: "string", - Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", - }, - "logical_backup_memory_request": { - Type: "string", - Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", - }, - "logical_backup_provider": { - Type: "string", - Enum: []apiextv1.JSON{ - { - Raw: []byte(`"az"`), - }, - { - Raw: []byte(`"gcs"`), - }, - { - Raw: []byte(`"s3"`), - }, - }, - }, - "logical_backup_s3_access_key_id": { - Type: "string", - }, - "logical_backup_s3_bucket": { - Type: "string", - }, - "logical_backup_s3_bucket_prefix": { - Type: "string", - }, - "logical_backup_s3_endpoint": { - Type: "string", - }, - "logical_backup_s3_region": { - Type: "string", - }, - "logical_backup_s3_secret_access_key": { - Type: "string", - }, - "logical_backup_s3_sse": { - Type: "string", - }, - "logical_backup_s3_retention_time": { - Type: "string", - }, - "logical_backup_schedule": { - Type: "string", - Pattern: "^(\\d+|\\*)(/\\d+)?(\\s+(\\d+|\\*)(/\\d+)?){4}$", - }, - "logical_backup_cronjob_environment_secret": { - Type: "string", - }, - "logical_backup_successful_jobs_history_limit": { - Type: "integer", - }, - "logical_backup_failed_jobs_history_limit": { - Type: "integer", - }, - "logical_backup_ttl_seconds_after_finished": { - Type: "integer", - }, - }, - }, - "debug": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "debug_logging": { - Type: "boolean", - }, - "enable_database_access": { - Type: "boolean", - }, - }, - }, - "teams_api": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "enable_admin_role_for_users": { - Type: "boolean", - }, - "enable_postgres_team_crd": { - Type: "boolean", - }, - "enable_postgres_team_crd_superusers": { - Type: "boolean", - }, - "enable_team_member_deprecation": { - 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: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "protected_role_names": { - Type: "array", - Items: &apiextv1.JSONSchemaPropsOrArray{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "role_deletion_suffix": { - Type: "string", - }, - "team_admin_role": { - Type: "string", - }, - "team_api_role_configuration": { - Type: "object", - AdditionalProperties: &apiextv1.JSONSchemaPropsOrBool{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - "teams_api_url": { - Type: "string", - }, - }, - }, - "logging_rest_api": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "api_port": { - Type: "integer", - }, - "cluster_history_entries": { - Type: "integer", - }, - "ring_log_lines": { - Type: "integer", - }, - }, - }, - "scalyr": { - Type: "object", - Properties: map[string]apiextv1.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", - }, - }, - }, - "connection_pooler": { - Type: "object", - Properties: map[string]apiextv1.JSONSchemaProps{ - "connection_pooler_default_cpu_limit": { - Type: "string", - Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$", - }, - "connection_pooler_default_cpu_request": { - Type: "string", - Pattern: "^(\\d+m|\\d+(\\.\\d{1,3})?)$", - }, - "connection_pooler_default_memory_limit": { - Type: "string", - Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", - }, - "connection_pooler_default_memory_request": { - Type: "string", - Pattern: "^(\\d+(e\\d+)?|\\d+(\\.\\d+)?(e\\d+)?[EPTGMK]i?)$", - }, - "connection_pooler_image": { - Type: "string", - }, - "connection_pooler_max_db_connections": { - Type: "integer", - }, - "connection_pooler_mode": { - Type: "string", - Enum: []apiextv1.JSON{ - { - Raw: []byte(`"session"`), - }, - { - Raw: []byte(`"transaction"`), - }, - }, - }, - "connection_pooler_number_of_instances": { - Type: "integer", - Minimum: &min1, - }, - "connection_pooler_schema": { - Type: "string", - }, - "connection_pooler_user": { - Type: "string", - }, - }, - }, - }, - }, - "status": { - Type: "object", - AdditionalProperties: &apiextv1.JSONSchemaPropsOrBool{ - Schema: &apiextv1.JSONSchemaProps{ - Type: "string", - }, - }, - }, - }, - }, -} - -func buildCRD(name, kind, plural, list, short string, - categories []string, - columns []apiextv1.CustomResourceColumnDefinition, - validation apiextv1.CustomResourceValidation) *apiextv1.CustomResourceDefinition { - return &apiextv1.CustomResourceDefinition{ - TypeMeta: metav1.TypeMeta{ - APIVersion: fmt.Sprintf("%s/%s", apiextv1.GroupName, apiextv1.SchemeGroupVersion.Version), - Kind: "CustomResourceDefinition", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Spec: apiextv1.CustomResourceDefinitionSpec{ - Group: SchemeGroupVersion.Group, - Names: apiextv1.CustomResourceDefinitionNames{ - Kind: kind, - ListKind: list, - Plural: plural, - Singular: kind, - ShortNames: []string{short}, - Categories: categories, - }, - Scope: apiextv1.NamespaceScoped, - Versions: []apiextv1.CustomResourceDefinitionVersion{ - { - Name: SchemeGroupVersion.Version, - Served: true, - Storage: true, - Subresources: &apiextv1.CustomResourceSubresources{ - Status: &apiextv1.CustomResourceSubresourceStatus{}, - }, - AdditionalPrinterColumns: columns, - Schema: &validation, - }, - }, - }, - } -} - //go:embed postgresql.crd.yaml var postgresqlCRDYAML []byte @@ -1144,14 +29,18 @@ func PostgresCRD(crdCategories []string) (*apiextv1.CustomResourceDefinition, er return &crd, nil } -// ConfigurationCRD returns CustomResourceDefinition built from OperatorConfigCRDResource -func ConfigurationCRD(crdCategories []string) *apiextv1.CustomResourceDefinition { - return buildCRD(OperatorConfigCRDResourceName, - OperatorConfigCRDResouceKind, - OperatorConfigCRDResourcePlural, - OperatorConfigCRDResourceList, - OperatorConfigCRDResourceShort, - crdCategories, - OperatorConfigCRDResourceColumns, - OperatorConfigCRDResourceValidation) +//go:embed operatorconfiguration.crd.yaml +var operatorConfigurationCRDYAML []byte + +// OperatorConfigurationCRD returns CustomResourceDefinition built from OperatorConfigurationCRDResource +func OperatorConfigurationCRD(crdCategories []string) (*apiextv1.CustomResourceDefinition, error) { + var crd apiextv1.CustomResourceDefinition + err := yaml.Unmarshal(operatorConfigurationCRDYAML, &crd) + if err != nil { + return nil, err + } + + crd.Spec.Names.Categories = crdCategories + + return &crd, nil } diff --git a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go index 5cec0ff33..60793c45c 100644 --- a/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go +++ b/pkg/apis/acid.zalan.do/v1/operator_configuration_type.go @@ -13,11 +13,17 @@ import ( ) // +genclient -// +genclient:onlyVerbs=get -// +genclient:noStatus // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // OperatorConfiguration defines the specification for the OperatorConfiguration. +// +k8s:deepcopy-gen=true +// +kubebuilder:resource:categories=all,shortName=opconfig,scope=Namespaced +// +kubebuilder:printcolumn:name="Image",type=string,JSONPath=`.configuration.docker_image`,description="Spilo image to be used for Pods" +// +kubebuilder:printcolumn:name="Cluster-Label",type=string,JSONPath=`.configuration.kubernetes.cluster_name_label`,description="Label for K8s resources created by operator" +// +kubebuilder:printcolumn:name="Service-Account",type=string,JSONPath=`.configuration.kubernetes.pod_service_account_name`,description="Name of service account to be used" +// +kubebuilder:printcolumn:name="Min-Instances",type=integer,JSONPath=`.configuration.min_instances`,description="Minimum number of instances per Postgres cluster" +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`,description="Age of the OperatorConfiguration resource" +// +kubebuilder:subresource:status type OperatorConfiguration struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` @@ -37,102 +43,170 @@ type OperatorConfigurationList struct { // PostgresUsersConfiguration defines the system users of Postgres. type PostgresUsersConfiguration struct { - SuperUsername string `json:"super_username,omitempty"` - ReplicationUsername string `json:"replication_username,omitempty"` - AdditionalOwnerRoles []string `json:"additional_owner_roles,omitempty"` - EnablePasswordRotation bool `json:"enable_password_rotation,omitempty"` - PasswordRotationInterval uint32 `json:"password_rotation_interval,omitempty"` - PasswordRotationUserRetention uint32 `json:"password_rotation_user_retention,omitempty"` + // +kubebuilder:default=postgres + SuperUsername string `json:"super_username,omitempty"` + // +kubebuilder:default=standby + ReplicationUsername string `json:"replication_username,omitempty"` + AdditionalOwnerRoles []string `json:"additional_owner_roles,omitempty"` + EnablePasswordRotation bool `json:"enable_password_rotation,omitempty"` + // +kubebuilder:default=90 + PasswordRotationInterval uint32 `json:"password_rotation_interval,omitempty"` + // +kubebuilder:default=120 + PasswordRotationUserRetention uint32 `json:"password_rotation_user_retention,omitempty"` } // MajorVersionUpgradeConfiguration defines how to execute major version upgrades of Postgres. type MajorVersionUpgradeConfiguration struct { - MajorVersionUpgradeMode string `json:"major_version_upgrade_mode" default:"manual"` // off - no actions, manual - manifest triggers action, full - manifest and minimal version violation trigger upgrade + // +kubebuilder:validation:Enum=off;manual;full + // +kubebuilder:default=manual + MajorVersionUpgradeMode string `json:"major_version_upgrade_mode,omitempty"` // off - no actions, manual - manifest triggers action, full - manifest and minimal version violation trigger upgrade MajorVersionUpgradeTeamAllowList []string `json:"major_version_upgrade_team_allow_list,omitempty"` - MinimalMajorVersion string `json:"minimal_major_version" default:"14"` - TargetMajorVersion string `json:"target_major_version" default:"18"` + // +kubebuilder:default="14" + MinimalMajorVersion string `json:"minimal_major_version,omitempty"` + // +kubebuilder:default="18" + TargetMajorVersion string `json:"target_major_version,omitempty"` } // KubernetesMetaConfiguration defines k8s conf required for all Postgres clusters and the operator itself type KubernetesMetaConfiguration struct { - EnableOwnerReferences *bool `json:"enable_owner_references,omitempty"` + EnableOwnerReferences *bool `json:"enable_owner_references,omitempty"` + // +kubebuilder:default=postgres-pod PodServiceAccountName string `json:"pod_service_account_name,omitempty"` // TODO: change it to the proper json - PodServiceAccountDefinition string `json:"pod_service_account_definition,omitempty"` - PodServiceAccountRoleBindingDefinition string `json:"pod_service_account_role_binding_definition,omitempty"` - PodTerminateGracePeriod Duration `json:"pod_terminate_grace_period,omitempty"` - LivenessProbe *v1.Probe `json:"liveness_probe"` - SpiloPrivileged bool `json:"spilo_privileged,omitempty"` - SpiloAllowPrivilegeEscalation *bool `json:"spilo_allow_privilege_escalation,omitempty"` - SpiloRunAsUser *int64 `json:"spilo_runasuser,omitempty"` - SpiloRunAsGroup *int64 `json:"spilo_runasgroup,omitempty"` - SpiloFSGroup *int64 `json:"spilo_fsgroup,omitempty"` - AdditionalPodCapabilities []string `json:"additional_pod_capabilities,omitempty"` - WatchedNamespace string `json:"watched_namespace,omitempty"` - PDBNameFormat config.StringTemplate `json:"pdb_name_format,omitempty"` - PDBMasterLabelSelector *bool `json:"pdb_master_label_selector,omitempty"` - EnablePodDisruptionBudget *bool `json:"enable_pod_disruption_budget,omitempty"` - StorageResizeMode string `json:"storage_resize_mode,omitempty"` - EnableInitContainers *bool `json:"enable_init_containers,omitempty"` - EnableSidecars *bool `json:"enable_sidecars,omitempty"` - SharePgSocketWithSidecars *bool `json:"share_pgsocket_with_sidecars,omitempty"` - SecretNameTemplate config.StringTemplate `json:"secret_name_template,omitempty"` - ClusterDomain string `json:"cluster_domain,omitempty"` - OAuthTokenSecretName spec.NamespacedName `json:"oauth_token_secret_name,omitempty"` - InfrastructureRolesSecretName spec.NamespacedName `json:"infrastructure_roles_secret_name,omitempty"` - InfrastructureRolesDefs []*config.InfrastructureRole `json:"infrastructure_roles_secrets,omitempty"` - PodRoleLabel string `json:"pod_role_label,omitempty"` - ClusterLabels map[string]string `json:"cluster_labels,omitempty"` - InheritedLabels []string `json:"inherited_labels,omitempty"` - InheritedAnnotations []string `json:"inherited_annotations,omitempty"` - DownscalerAnnotations []string `json:"downscaler_annotations,omitempty"` - IgnoredAnnotations []string `json:"ignored_annotations,omitempty"` - ClusterNameLabel string `json:"cluster_name_label,omitempty"` - DeleteAnnotationDateKey string `json:"delete_annotation_date_key,omitempty"` - DeleteAnnotationNameKey string `json:"delete_annotation_name_key,omitempty"` - NodeReadinessLabel map[string]string `json:"node_readiness_label,omitempty"` - NodeReadinessLabelMerge string `json:"node_readiness_label_merge,omitempty"` - CustomPodAnnotations map[string]string `json:"custom_pod_annotations,omitempty"` + PodServiceAccountDefinition string `json:"pod_service_account_definition,omitempty"` + PodServiceAccountRoleBindingDefinition string `json:"pod_service_account_role_binding_definition,omitempty"` + // +kubebuilder:default="5m" + // Postgres pods are terminated forcefully after this timeout + PodTerminateGracePeriod Duration `json:"pod_terminate_grace_period,omitempty"` + // +optional + LivenessProbe *v1.Probe `json:"liveness_probe"` + SpiloPrivileged bool `json:"spilo_privileged,omitempty"` + // +kubebuilder:default=true + SpiloAllowPrivilegeEscalation *bool `json:"spilo_allow_privilege_escalation,omitempty"` + SpiloRunAsUser *int64 `json:"spilo_runasuser,omitempty"` + SpiloRunAsGroup *int64 `json:"spilo_runasgroup,omitempty"` + SpiloFSGroup *int64 `json:"spilo_fsgroup,omitempty"` + AdditionalPodCapabilities []string `json:"additional_pod_capabilities,omitempty"` + WatchedNamespace string `json:"watched_namespace,omitempty"` + // +kubebuilder:default="postgres-{cluster}-pdb" + // defines the template for PDB names + PDBNameFormat config.StringTemplate `json:"pdb_name_format,omitempty"` + // +kubebuilder:default=true + PDBMasterLabelSelector *bool `json:"pdb_master_label_selector,omitempty"` + // +kubebuilder:default=true + EnablePodDisruptionBudget *bool `json:"enable_pod_disruption_budget,omitempty"` + // +kubebuilder:validation:Enum=ebs;mixed;pvc;off + // +kubebuilder:default=pvc + StorageResizeMode string `json:"storage_resize_mode,omitempty"` + // +kubebuilder:default=true + EnableInitContainers *bool `json:"enable_init_containers,omitempty"` + // +kubebuilder:default=true + EnableSidecars *bool `json:"enable_sidecars,omitempty"` + SharePgSocketWithSidecars *bool `json:"share_pgsocket_with_sidecars,omitempty"` + // +kubebuilder:default="{username}.{cluster}.credentials.{tprkind}.{tprgroup}" + // template for database user secrets generated by the operator, + // here username contains the namespace in the format namespace.username + // if the user is in different namespace than cluster and cross namespace secrets + // are enabled via `enable_cross_namespace_secret` flag in the configuration. + SecretNameTemplate config.StringTemplate `json:"secret_name_template,omitempty"` + // +kubebuilder:default="cluster.local" + ClusterDomain string `json:"cluster_domain,omitempty"` + // +kubebuilder:default=postgres-operator + // namespaced name of the secret containing the OAuth2 token to pass to the teams API + OAuthTokenSecretName spec.NamespacedName `json:"oauth_token_secret_name,omitempty"` + InfrastructureRolesSecretName spec.NamespacedName `json:"infrastructure_roles_secret_name,omitempty"` + // +kubebuilder:validation:Type=array + // namespaced name of the secret containing infrastructure roles names and passwords + InfrastructureRolesDefs []*config.InfrastructureRole `json:"infrastructure_roles_secrets,omitempty"` + // +kubebuilder:default=spilo-role + PodRoleLabel string `json:"pod_role_label,omitempty"` + // +kubebuilder:default={application: spilo} + ClusterLabels map[string]string `json:"cluster_labels,omitempty"` + InheritedLabels []string `json:"inherited_labels,omitempty"` + InheritedAnnotations []string `json:"inherited_annotations,omitempty"` + DownscalerAnnotations []string `json:"downscaler_annotations,omitempty"` + IgnoredAnnotations []string `json:"ignored_annotations,omitempty"` + // +kubebuilder:default=cluster-name + ClusterNameLabel string `json:"cluster_name_label,omitempty"` + DeleteAnnotationDateKey string `json:"delete_annotation_date_key,omitempty"` + DeleteAnnotationNameKey string `json:"delete_annotation_name_key,omitempty"` + NodeReadinessLabel map[string]string `json:"node_readiness_label,omitempty"` + // +kubebuilder:validation:Enum=AND;OR + NodeReadinessLabelMerge string `json:"node_readiness_label_merge,omitempty"` + CustomPodAnnotations map[string]string `json:"custom_pod_annotations,omitempty"` // TODO: use a proper toleration structure? - PodToleration map[string]string `json:"toleration,omitempty"` - PodEnvironmentConfigMap spec.NamespacedName `json:"pod_environment_configmap,omitempty"` - PodEnvironmentSecret string `json:"pod_environment_secret,omitempty"` - PodPriorityClassName string `json:"pod_priority_class_name,omitempty"` - MasterPodMoveTimeout Duration `json:"master_pod_move_timeout,omitempty"` - EnablePodAntiAffinity bool `json:"enable_pod_antiaffinity,omitempty"` - PodAntiAffinityPreferredDuringScheduling bool `json:"pod_antiaffinity_preferred_during_scheduling,omitempty"` - PodAntiAffinityTopologyKey string `json:"pod_antiaffinity_topology_key,omitempty"` - PodManagementPolicy string `json:"pod_management_policy,omitempty"` - PersistentVolumeClaimRetentionPolicy map[string]string `json:"persistent_volume_claim_retention_policy,omitempty"` - EnableSecretsDeletion *bool `json:"enable_secrets_deletion,omitempty"` - EnablePersistentVolumeClaimDeletion *bool `json:"enable_persistent_volume_claim_deletion,omitempty"` - EnableReadinessProbe bool `json:"enable_readiness_probe,omitempty"` - EnableCrossNamespaceSecret bool `json:"enable_cross_namespace_secret,omitempty"` - EnableFinalizers *bool `json:"enable_finalizers,omitempty"` + PodToleration map[string]string `json:"toleration,omitempty"` + // namespaced name of the ConfigMap with environment variables to populate on every pod + PodEnvironmentConfigMap spec.NamespacedName `json:"pod_environment_configmap,omitempty"` + PodEnvironmentSecret string `json:"pod_environment_secret,omitempty"` + PodPriorityClassName string `json:"pod_priority_class_name,omitempty"` + // +kubebuilder:default="20m" + // timeout for successful migration of master pods from unschedulable node + MasterPodMoveTimeout Duration `json:"master_pod_move_timeout,omitempty"` + EnablePodAntiAffinity bool `json:"enable_pod_antiaffinity,omitempty"` + PodAntiAffinityPreferredDuringScheduling bool `json:"pod_antiaffinity_preferred_during_scheduling,omitempty"` + // +kubebuilder:default="kubernetes.io/hostname" + PodAntiAffinityTopologyKey string `json:"pod_antiaffinity_topology_key,omitempty"` + // +kubebuilder:validation:Enum=ordered_ready;parallel + // +kubebuilder:default=ordered_ready + PodManagementPolicy string `json:"pod_management_policy,omitempty"` + PersistentVolumeClaimRetentionPolicy map[string]string `json:"persistent_volume_claim_retention_policy,omitempty"` + + // +kubebuilder:default=true + EnableSecretsDeletion *bool `json:"enable_secrets_deletion,omitempty"` + // +kubebuilder:default=true + EnablePersistentVolumeClaimDeletion *bool `json:"enable_persistent_volume_claim_deletion,omitempty"` + EnableReadinessProbe bool `json:"enable_readiness_probe,omitempty"` + EnableCrossNamespaceSecret bool `json:"enable_cross_namespace_secret,omitempty"` + EnableFinalizers *bool `json:"enable_finalizers,omitempty"` } // PostgresPodResourcesDefaults defines the spec of default resources type PostgresPodResourcesDefaults struct { - DefaultCPURequest string `json:"default_cpu_request,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+m|\d+(\.\d{1,3})?)$` + DefaultCPURequest string `json:"default_cpu_request,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$` DefaultMemoryRequest string `json:"default_memory_request,omitempty"` - DefaultCPULimit string `json:"default_cpu_limit,omitempty"` - DefaultMemoryLimit string `json:"default_memory_limit,omitempty"` - MinCPULimit string `json:"min_cpu_limit,omitempty"` - MinMemoryLimit string `json:"min_memory_limit,omitempty"` - MaxCPURequest string `json:"max_cpu_request,omitempty"` - MaxMemoryRequest string `json:"max_memory_request,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+m|\d+(\.\d{1,3})?)$` + DefaultCPULimit string `json:"default_cpu_limit,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$` + DefaultMemoryLimit string `json:"default_memory_limit,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+m|\d+(\.\d{1,3})?)$` + MinCPULimit string `json:"min_cpu_limit,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$` + MinMemoryLimit string `json:"min_memory_limit,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+m|\d+(\.\d{1,3})?)$` + MaxCPURequest string `json:"max_cpu_request,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$` + MaxMemoryRequest string `json:"max_memory_request,omitempty"` } // OperatorTimeouts defines the timeout of ResourceCheck, PodWait, ReadyWait type OperatorTimeouts struct { - ResourceCheckInterval Duration `json:"resource_check_interval,omitempty"` - ResourceCheckTimeout Duration `json:"resource_check_timeout,omitempty"` - PodLabelWaitTimeout Duration `json:"pod_label_wait_timeout,omitempty"` - PodDeletionWaitTimeout Duration `json:"pod_deletion_wait_timeout,omitempty"` - ReadyWaitInterval Duration `json:"ready_wait_interval,omitempty"` - ReadyWaitTimeout Duration `json:"ready_wait_timeout,omitempty"` + // +kubebuilder:default="3s" + // interval to wait between consecutive attempts to check for some K8s resources + ResourceCheckInterval Duration `json:"resource_check_interval,omitempty"` + // +kubebuilder:default="10m" + // timeout when waiting for the presence of a certain K8s resource + ResourceCheckTimeout Duration `json:"resource_check_timeout,omitempty"` + // +kubebuilder:default="10m" + // timeout when waiting for pod role and cluster labels + PodLabelWaitTimeout Duration `json:"pod_label_wait_timeout,omitempty"` + // +kubebuilder:default="10m" + // timeout when waiting for the Postgres pods to be deleted + PodDeletionWaitTimeout Duration `json:"pod_deletion_wait_timeout,omitempty"` + // +kubebuilder:default="4s" + // interval between consecutive attempts waiting for postgresql CRD to be created + ReadyWaitInterval Duration `json:"ready_wait_interval,omitempty"` + // +kubebuilder:default="30s" + // timeout for the complete postgres CRD creation + ReadyWaitTimeout Duration `json:"ready_wait_timeout,omitempty"` + // +kubebuilder:default="1s" + // interval between consecutive attempts of operator calling the Patroni API PatroniAPICheckInterval Duration `json:"patroni_api_check_interval,omitempty"` - PatroniAPICheckTimeout Duration `json:"patroni_api_check_timeout,omitempty"` + // +kubebuilder:default="5s" + // timeout when waiting for successful response from Patroni API + PatroniAPICheckTimeout Duration `json:"patroni_api_check_timeout,omitempty"` } // LoadBalancerConfiguration defines the LB configuration @@ -143,24 +217,36 @@ type LoadBalancerConfiguration struct { EnableReplicaLoadBalancer bool `json:"enable_replica_load_balancer,omitempty"` EnableReplicaPoolerLoadBalancer bool `json:"enable_replica_pooler_load_balancer,omitempty"` - // kept in LoadBalancerConfiguration because all the other parameters apply here too + // NodePort flags kept in LoadBalancerConfiguration because all the other parameters apply here too + EnableMasterNodePort bool `json:"enable_master_node_port,omitempty"` EnableMasterPoolerNodePort bool `json:"enable_master_pooler_node_port,omitempty"` EnableReplicaNodePort bool `json:"enable_replica_node_port,omitempty"` EnableReplicaPoolerNodePort bool `json:"enable_replica_pooler_node_port,omitempty"` - CustomServiceAnnotations map[string]string `json:"custom_service_annotations,omitempty"` - MasterDNSNameFormat config.StringTemplate `json:"master_dns_name_format,omitempty"` - MasterLegacyDNSNameFormat config.StringTemplate `json:"master_legacy_dns_name_format,omitempty"` - ReplicaDNSNameFormat config.StringTemplate `json:"replica_dns_name_format,omitempty"` + CustomServiceAnnotations map[string]string `json:"custom_service_annotations,omitempty"` + // +kubebuilder:default="{cluster}.{namespace}.{hostedzone}" + // defines the DNS name string template for the master load balancer cluster + MasterDNSNameFormat config.StringTemplate `json:"master_dns_name_format,omitempty"` + // +kubebuilder:default="{cluster}.{team}.{hostedzone}" + // deprecated DNS template for master load balancer using team name + MasterLegacyDNSNameFormat config.StringTemplate `json:"master_legacy_dns_name_format,omitempty"` + // +kubebuilder:default="{cluster}-repl.{namespace}.{hostedzone}" + // defines the DNS name string template for the replica load balancer cluster + ReplicaDNSNameFormat config.StringTemplate `json:"replica_dns_name_format,omitempty"` + // +kubebuilder:default="{cluster}-repl.{team}.{hostedzone}" + // deprecated DNS template for replica load balancer using team name ReplicaLegacyDNSNameFormat config.StringTemplate `json:"replica_legacy_dns_name_format,omitempty"` - ExternalTrafficPolicy string `json:"external_traffic_policy" default:"Cluster"` + // +kubebuilder:validation:Enum=Cluster;Local + // +kubebuilder:default=Cluster + ExternalTrafficPolicy string `json:"external_traffic_policy,omitempty"` } // AWSGCPConfiguration defines the configuration for AWS // TODO complete Google Cloud Platform (GCP) configuration type AWSGCPConfiguration struct { - WALES3Bucket string `json:"wal_s3_bucket,omitempty"` + WALES3Bucket string `json:"wal_s3_bucket,omitempty"` + // +kubebuilder:default=eu-central-1 AWSRegion string `json:"aws_region,omitempty"` WALGSBucket string `json:"wal_gs_bucket,omitempty"` GCPCredentials string `json:"gcp_credentials,omitempty"` @@ -169,70 +255,109 @@ type AWSGCPConfiguration struct { KubeIAMRole string `json:"kube_iam_role,omitempty"` AdditionalSecretMount string `json:"additional_secret_mount,omitempty"` AdditionalSecretMountPath string `json:"additional_secret_mount_path,omitempty"` - EnableEBSGp3Migration bool `json:"enable_ebs_gp3_migration" default:"false"` - EnableEBSGp3MigrationMaxSize int64 `json:"enable_ebs_gp3_migration_max_size" default:"1000"` + EnableEBSGp3Migration bool `json:"enable_ebs_gp3_migration,omitempty"` + EnableEBSGp3MigrationMaxSize int64 `json:"enable_ebs_gp3_migration_max_size,omitempty"` } // OperatorDebugConfiguration defines options for the debug mode type OperatorDebugConfiguration struct { - DebugLogging *bool `json:"debug_logging,omitempty"` + // +kubebuilder:default=true + DebugLogging *bool `json:"debug_logging,omitempty"` + // +kubebuilder:default=true EnableDBAccess *bool `json:"enable_database_access,omitempty"` } // TeamsAPIConfiguration defines the configuration of TeamsAPI type TeamsAPIConfiguration struct { - EnableTeamsAPI bool `json:"enable_teams_api,omitempty"` - TeamsAPIUrl string `json:"teams_api_url,omitempty"` - TeamAPIRoleConfiguration map[string]string `json:"team_api_role_configuration,omitempty"` - EnableTeamSuperuser bool `json:"enable_team_superuser,omitempty"` - EnableAdminRoleForUsers bool `json:"enable_admin_role_for_users,omitempty"` - TeamAdminRole string `json:"team_admin_role,omitempty"` - PamRoleName string `json:"pam_role_name,omitempty"` - PamConfiguration string `json:"pam_configuration,omitempty"` - ProtectedRoles []string `json:"protected_role_names,omitempty"` - PostgresSuperuserTeams []string `json:"postgres_superuser_teams,omitempty"` - EnablePostgresTeamCRD bool `json:"enable_postgres_team_crd,omitempty"` - EnablePostgresTeamCRDSuperusers bool `json:"enable_postgres_team_crd_superusers,omitempty"` - EnableTeamMemberDeprecation bool `json:"enable_team_member_deprecation,omitempty"` - RoleDeletionSuffix string `json:"role_deletion_suffix,omitempty"` + EnableTeamsAPI bool `json:"enable_teams_api,omitempty"` + // +kubebuilder:default="https://teams.example.com/api/" + TeamsAPIUrl string `json:"teams_api_url,omitempty"` + // +kubebuilder:default={log_statement: all} + TeamAPIRoleConfiguration map[string]string `json:"team_api_role_configuration,omitempty"` + EnableTeamSuperuser bool `json:"enable_team_superuser,omitempty"` + // +kubebuilder:default=true + EnableAdminRoleForUsers bool `json:"enable_admin_role_for_users,omitempty"` + // +kubebuilder:default=admin + TeamAdminRole string `json:"team_admin_role,omitempty"` + // +kubebuilder:default=zalandos + PamRoleName string `json:"pam_role_name,omitempty"` + // +kubebuilder:default="https://info.example.com/oauth2/tokeninfo?access_token= uid realm=/employees" + PamConfiguration string `json:"pam_configuration,omitempty"` + // +kubebuilder:default="[\"admin\", \"cron_admin\"]" + ProtectedRoles []string `json:"protected_role_names,omitempty"` + PostgresSuperuserTeams []string `json:"postgres_superuser_teams,omitempty"` + // +kubebuilder:default=true + EnablePostgresTeamCRD bool `json:"enable_postgres_team_crd,omitempty"` + EnablePostgresTeamCRDSuperusers bool `json:"enable_postgres_team_crd_superusers,omitempty"` + EnableTeamMemberDeprecation bool `json:"enable_team_member_deprecation,omitempty"` + // +kubebuilder:default=_deleted + RoleDeletionSuffix string `json:"role_deletion_suffix,omitempty"` } // LoggingRESTAPIConfiguration defines Logging API conf type LoggingRESTAPIConfiguration struct { - APIPort int `json:"api_port,omitempty"` - RingLogLines int `json:"ring_log_lines,omitempty"` + // +kubebuilder:default=8080 + APIPort int `json:"api_port,omitempty"` + // +kubebuilder:default=100 + RingLogLines int `json:"ring_log_lines,omitempty"` + // +kubebuilder:default=1000 ClusterHistoryEntries int `json:"cluster_history_entries,omitempty"` } // ScalyrConfiguration defines the configuration for ScalyrAPI type ScalyrConfiguration struct { - ScalyrAPIKey string `json:"scalyr_api_key,omitempty"` - ScalyrImage string `json:"scalyr_image,omitempty"` - ScalyrServerURL string `json:"scalyr_server_url,omitempty"` - ScalyrCPURequest string `json:"scalyr_cpu_request,omitempty"` + ScalyrAPIKey string `json:"scalyr_api_key,omitempty"` + ScalyrImage string `json:"scalyr_image,omitempty"` + // +kubebuilder:default="https://upload.eu.scalyr.com" + ScalyrServerURL string `json:"scalyr_server_url,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+m|\d+(\.\d{1,3})?)$` + // +kubebuilder:default="100m" + ScalyrCPURequest string `json:"scalyr_cpu_request,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$` + // +kubebuilder:default="50Mi" ScalyrMemoryRequest string `json:"scalyr_memory_request,omitempty"` - ScalyrCPULimit string `json:"scalyr_cpu_limit,omitempty"` - ScalyrMemoryLimit string `json:"scalyr_memory_limit,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+m|\d+(\.\d{1,3})?)$` + // +kubebuilder:default="1" + ScalyrCPULimit string `json:"scalyr_cpu_limit,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$` + // +kubebuilder:default="500Mi" + ScalyrMemoryLimit string `json:"scalyr_memory_limit,omitempty"` } // ConnectionPoolerConfiguration defines default configuration for connection pooler type ConnectionPoolerConfiguration struct { - NumberOfInstances *int32 `json:"connection_pooler_number_of_instances,omitempty"` - Schema string `json:"connection_pooler_schema,omitempty"` - User string `json:"connection_pooler_user,omitempty"` - Image string `json:"connection_pooler_image,omitempty"` - Mode string `json:"connection_pooler_mode,omitempty"` - MaxDBConnections *int32 `json:"connection_pooler_max_db_connections,omitempty"` - DefaultCPURequest string `json:"connection_pooler_default_cpu_request,omitempty"` + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=2 + NumberOfInstances *int32 `json:"connection_pooler_number_of_instances,omitempty"` + // +kubebuilder:default=pooler + Schema string `json:"connection_pooler_schema,omitempty"` + // +kubebuilder:default=pooler + User string `json:"connection_pooler_user,omitempty"` + // +kubebuilder:default="ghcr.io/zalando/postgres-operator/pgbouncer:latest" + Image string `json:"connection_pooler_image,omitempty"` + // +kubebuilder:validation:Enum=session;transaction + // +kubebuilder:default=transaction + Mode string `json:"connection_pooler_mode,omitempty"` + MaxDBConnections *int32 `json:"connection_pooler_max_db_connections,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+m|\d+(\.\d{1,3})?)$` + DefaultCPURequest string `json:"connection_pooler_default_cpu_request,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$` DefaultMemoryRequest string `json:"connection_pooler_default_memory_request,omitempty"` - DefaultCPULimit string `json:"connection_pooler_default_cpu_limit,omitempty"` - DefaultMemoryLimit string `json:"connection_pooler_default_memory_limit,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+m|\d+(\.\d{1,3})?)$` + DefaultCPULimit string `json:"connection_pooler_default_cpu_limit,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$` + DefaultMemoryLimit string `json:"connection_pooler_default_memory_limit,omitempty"` } // OperatorLogicalBackupConfiguration defines configuration for logical backup type OperatorLogicalBackupConfiguration struct { - Schedule string `json:"logical_backup_schedule,omitempty"` - DockerImage string `json:"logical_backup_docker_image,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$` + // +kubebuilder:default="30 00 * * *" + Schedule string `json:"logical_backup_schedule,omitempty"` + // +kubebuilder:default="ghcr.io/zalando/postgres-operator/logical-backup:v1.15.1" + DockerImage string `json:"logical_backup_docker_image,omitempty"` + // +kubebuilder:validation:Enum=az;gcs;s3 + // +kubebuilder:default=s3 BackupProvider string `json:"logical_backup_provider,omitempty"` AzureStorageAccountName string `json:"logical_backup_azure_storage_account_name,omitempty"` AzureStorageContainer string `json:"logical_backup_azure_storage_container,omitempty"` @@ -246,15 +371,26 @@ type OperatorLogicalBackupConfiguration struct { S3SSE string `json:"logical_backup_s3_sse,omitempty"` RetentionTime string `json:"logical_backup_s3_retention_time,omitempty"` GoogleApplicationCredentials string `json:"logical_backup_google_application_credentials,omitempty"` - JobPrefix string `json:"logical_backup_job_prefix,omitempty"` - CronjobEnvironmentSecret string `json:"logical_backup_cronjob_environment_secret,omitempty"` - CPURequest string `json:"logical_backup_cpu_request,omitempty"` - MemoryRequest string `json:"logical_backup_memory_request,omitempty"` - CPULimit string `json:"logical_backup_cpu_limit,omitempty"` - MemoryLimit string `json:"logical_backup_memory_limit,omitempty"` - SuccessfulJobsHistoryLimit *int32 `json:"logical_backup_successful_jobs_history_limit,omitempty"` - FailedJobsHistoryLimit *int32 `json:"logical_backup_failed_jobs_history_limit,omitempty"` - TTLSecondsAfterFinished *int32 `json:"logical_backup_ttl_seconds_after_finished,omitempty"` + // +kubebuilder:default=logical-backup- + JobPrefix string `json:"logical_backup_job_prefix,omitempty"` + CronjobEnvironmentSecret string `json:"logical_backup_cronjob_environment_secret,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+m|\d+(\.\d{1,3})?)$` + CPURequest string `json:"logical_backup_cpu_request,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$` + MemoryRequest string `json:"logical_backup_memory_request,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+m|\d+(\.\d{1,3})?)$` + CPULimit string `json:"logical_backup_cpu_limit,omitempty"` + // +kubebuilder:validation:Pattern=`^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$` + MemoryLimit string `json:"logical_backup_memory_limit,omitempty"` + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=3 + SuccessfulJobsHistoryLimit *int32 `json:"logical_backup_successful_jobs_history_limit,omitempty"` + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=3 + FailedJobsHistoryLimit *int32 `json:"logical_backup_failed_jobs_history_limit,omitempty"` + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:default=86400 + TTLSecondsAfterFinished *int32 `json:"logical_backup_ttl_seconds_after_finished,omitempty"` } // PatroniConfiguration defines configuration for Patroni @@ -264,42 +400,80 @@ type PatroniConfiguration struct { // OperatorConfigurationData defines the operation config type OperatorConfigurationData struct { - EnableCRDRegistration *bool `json:"enable_crd_registration,omitempty"` - EnableCRDValidation *bool `json:"enable_crd_validation,omitempty"` - CRDCategories []string `json:"crd_categories,omitempty"` - EnableLazySpiloUpgrade bool `json:"enable_lazy_spilo_upgrade,omitempty"` - EnablePgVersionEnvVar bool `json:"enable_pgversion_env_var,omitempty"` - EnableSpiloWalPathCompat bool `json:"enable_spilo_wal_path_compat,omitempty"` - EnableTeamIdClusternamePrefix bool `json:"enable_team_id_clustername_prefix,omitempty"` - EtcdHost string `json:"etcd_host,omitempty"` - KubernetesUseConfigMaps bool `json:"kubernetes_use_configmaps,omitempty"` - DockerImage string `json:"docker_image,omitempty"` - Workers uint32 `json:"workers,omitempty"` - ResyncPeriod Duration `json:"resync_period,omitempty"` - RepairPeriod Duration `json:"repair_period,omitempty"` - EnableMaintenanceWindows *bool `json:"enable_maintenance_windows,omitempty"` - MaintenanceWindows []MaintenanceWindow `json:"maintenance_windows,omitempty"` - SetMemoryRequestToLimit bool `json:"set_memory_request_to_limit,omitempty"` - ShmVolume *bool `json:"enable_shm_volume,omitempty"` - SidecarImages map[string]string `json:"sidecar_docker_images,omitempty"` // deprecated in favour of SidecarContainers - SidecarContainers []v1.Container `json:"sidecars,omitempty"` - PostgresUsersConfiguration PostgresUsersConfiguration `json:"users"` - MajorVersionUpgrade MajorVersionUpgradeConfiguration `json:"major_version_upgrade"` - Kubernetes KubernetesMetaConfiguration `json:"kubernetes"` - PostgresPodResources PostgresPodResourcesDefaults `json:"postgres_pod_resources"` - Timeouts OperatorTimeouts `json:"timeouts"` - LoadBalancer LoadBalancerConfiguration `json:"load_balancer"` - AWSGCP AWSGCPConfiguration `json:"aws_or_gcp"` - OperatorDebug OperatorDebugConfiguration `json:"debug"` - TeamsAPI TeamsAPIConfiguration `json:"teams_api"` - LoggingRESTAPI LoggingRESTAPIConfiguration `json:"logging_rest_api"` - Scalyr ScalyrConfiguration `json:"scalyr"` - LogicalBackup OperatorLogicalBackupConfiguration `json:"logical_backup"` - ConnectionPooler ConnectionPoolerConfiguration `json:"connection_pooler"` - Patroni PatroniConfiguration `json:"patroni"` + // +kubebuilder:default=true + EnableCRDRegistration *bool `json:"enable_crd_registration,omitempty"` + CRDCategories []string `json:"crd_categories,omitempty"` + EnableLazySpiloUpgrade bool `json:"enable_lazy_spilo_upgrade,omitempty"` + // +kubebuilder:default=true + EnablePgVersionEnvVar bool `json:"enable_pgversion_env_var,omitempty"` + EnableSpiloWalPathCompat bool `json:"enable_spilo_wal_path_compat,omitempty"` + EnableTeamIdClusternamePrefix bool `json:"enable_team_id_clustername_prefix,omitempty"` + // +kubebuilder:default="" + EtcdHost string `json:"etcd_host,omitempty"` + // +kubebuilder:default=true + KubernetesUseConfigMaps bool `json:"kubernetes_use_configmaps,omitempty"` + // +kubebuilder:default="ghcr.io/zalando/spilo-18:4.1-p1" + DockerImage string `json:"docker_image,omitempty"` + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=8 + Workers uint32 `json:"workers,omitempty"` + // +kubebuilder:default="30m" + // period between consecutive sync requests + ResyncPeriod Duration `json:"resync_period,omitempty"` + // +kubebuilder:default="5m" + // period between consecutive repair requests + RepairPeriod Duration `json:"repair_period,omitempty"` + // +kubebuilder:default=true + EnableMaintenanceWindows *bool `json:"enable_maintenance_windows,omitempty"` + // +kubebuilder:validation:Schemaless + // +kubebuilder:validation:Type=array + MaintenanceWindows []MaintenanceWindow `json:"maintenance_windows,omitempty"` + SetMemoryRequestToLimit bool `json:"set_memory_request_to_limit,omitempty"` + // +kubebuilder:default=true + ShmVolume *bool `json:"enable_shm_volume,omitempty"` + SidecarImages map[string]string `json:"sidecar_docker_images,omitempty"` // deprecated in favour of SidecarContainers + // +kubebuilder:validation:XPreserveUnknownFields + // +kubebuilder:validation:Type=object + // +kubebuilder:validation:Schemaless + SidecarContainers []v1.Container `json:"sidecars,omitempty"` + // +optional + PostgresUsersConfiguration PostgresUsersConfiguration `json:"users"` + // +optional + MajorVersionUpgrade MajorVersionUpgradeConfiguration `json:"major_version_upgrade"` + // +optional + Kubernetes KubernetesMetaConfiguration `json:"kubernetes"` + // +optional + PostgresPodResources PostgresPodResourcesDefaults `json:"postgres_pod_resources"` + // +optional + Timeouts OperatorTimeouts `json:"timeouts"` + // +optional + LoadBalancer LoadBalancerConfiguration `json:"load_balancer"` + // +optional + AWSGCP AWSGCPConfiguration `json:"aws_or_gcp"` + // +optional + OperatorDebug OperatorDebugConfiguration `json:"debug"` + // +optional + TeamsAPI TeamsAPIConfiguration `json:"teams_api"` + // +optional + LoggingRESTAPI LoggingRESTAPIConfiguration `json:"logging_rest_api"` + // +optional + Scalyr ScalyrConfiguration `json:"scalyr"` + // +optional + LogicalBackup OperatorLogicalBackupConfiguration `json:"logical_backup"` + // +optional + ConnectionPooler ConnectionPoolerConfiguration `json:"connection_pooler"` + // +optional + Patroni PatroniConfiguration `json:"patroni"` + + // +kubebuilder:validation:Minimum=-1 + // +kubebuilder:default=-1 + // -1 = disabled + MinInstances int32 `json:"min_instances,omitempty"` + // +kubebuilder:validation:Minimum=-1 + // +kubebuilder:default=-1 + // -1 = disabled + MaxInstances int32 `json:"max_instances,omitempty"` - MinInstances int32 `json:"min_instances,omitempty"` - MaxInstances int32 `json:"max_instances,omitempty"` IgnoreInstanceLimitsAnnotationKey string `json:"ignore_instance_limits_annotation_key,omitempty"` IgnoreResourcesLimitsAnnotationKey string `json:"ignore_resources_limits_annotation_key,omitempty"` } diff --git a/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml b/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml new file mode 100644 index 000000000..5f347f2ac --- /dev/null +++ b/pkg/apis/acid.zalan.do/v1/operatorconfiguration.crd.yaml @@ -0,0 +1,971 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.17.3 + name: operatorconfigurations.acid.zalan.do +spec: + group: acid.zalan.do + names: + categories: + - all + kind: OperatorConfiguration + listKind: OperatorConfigurationList + plural: operatorconfigurations + shortNames: + - opconfig + singular: operatorconfiguration + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Spilo image to be used for Pods + jsonPath: .configuration.docker_image + name: Image + type: string + - description: Label for K8s resources created by operator + jsonPath: .configuration.kubernetes.cluster_name_label + name: Cluster-Label + type: string + - description: Name of service account to be used + jsonPath: .configuration.kubernetes.pod_service_account_name + name: Service-Account + type: string + - description: Minimum number of instances per Postgres cluster + jsonPath: .configuration.min_instances + name: Min-Instances + type: integer + - description: Age of the OperatorConfiguration resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: OperatorConfiguration defines the specification for the OperatorConfiguration. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + configuration: + description: OperatorConfigurationData defines the operation config + properties: + aws_or_gcp: + description: AWSGCPConfiguration defines the configuration for AWS + properties: + additional_secret_mount: + type: string + additional_secret_mount_path: + type: string + aws_region: + default: eu-central-1 + type: string + enable_ebs_gp3_migration: + type: boolean + enable_ebs_gp3_migration_max_size: + format: int64 + type: integer + gcp_credentials: + type: string + kube_iam_role: + type: string + log_s3_bucket: + type: string + wal_az_storage_account: + type: string + wal_gs_bucket: + type: string + wal_s3_bucket: + type: string + type: object + connection_pooler: + description: ConnectionPoolerConfiguration defines default configuration + for connection pooler + properties: + connection_pooler_default_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + connection_pooler_default_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + connection_pooler_default_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + connection_pooler_default_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + connection_pooler_image: + default: ghcr.io/zalando/postgres-operator/pgbouncer:latest + type: string + connection_pooler_max_db_connections: + format: int32 + type: integer + connection_pooler_mode: + default: transaction + enum: + - session + - transaction + type: string + connection_pooler_number_of_instances: + default: 2 + format: int32 + minimum: 1 + type: integer + connection_pooler_schema: + default: pooler + type: string + connection_pooler_user: + default: pooler + type: string + type: object + crd_categories: + items: + type: string + type: array + debug: + description: OperatorDebugConfiguration defines options for the debug + mode + properties: + debug_logging: + default: true + type: boolean + enable_database_access: + default: true + type: boolean + type: object + docker_image: + default: ghcr.io/zalando/spilo-18:4.1-p1 + type: string + enable_crd_registration: + default: true + type: boolean + enable_lazy_spilo_upgrade: + type: boolean + enable_maintenance_windows: + default: true + type: boolean + enable_pgversion_env_var: + default: true + type: boolean + enable_shm_volume: + default: true + type: boolean + enable_spilo_wal_path_compat: + type: boolean + enable_team_id_clustername_prefix: + type: boolean + etcd_host: + default: "" + type: string + ignore_instance_limits_annotation_key: + type: string + ignore_resources_limits_annotation_key: + type: string + kubernetes: + description: KubernetesMetaConfiguration defines k8s conf required + for all Postgres clusters and the operator itself + properties: + additional_pod_capabilities: + items: + type: string + type: array + cluster_domain: + default: cluster.local + type: string + cluster_labels: + additionalProperties: + type: string + default: + application: spilo + type: object + cluster_name_label: + default: cluster-name + type: string + custom_pod_annotations: + additionalProperties: + type: string + type: object + delete_annotation_date_key: + type: string + delete_annotation_name_key: + type: string + downscaler_annotations: + items: + type: string + type: array + enable_cross_namespace_secret: + type: boolean + enable_finalizers: + type: boolean + enable_init_containers: + default: true + type: boolean + enable_owner_references: + type: boolean + enable_persistent_volume_claim_deletion: + default: true + type: boolean + enable_pod_antiaffinity: + type: boolean + enable_pod_disruption_budget: + default: true + type: boolean + enable_readiness_probe: + type: boolean + enable_secrets_deletion: + default: true + type: boolean + enable_sidecars: + default: true + type: boolean + ignored_annotations: + items: + type: string + type: array + infrastructure_roles_secret_name: + description: |- + NamespacedName comprises a resource name, with a mandatory namespace, + rendered as "/". Being a type captures intent and + helps make sure that UIDs, namespaced names and non-namespaced names + do not get conflated in code. For most use cases, namespace and name + will already have been format validated at the API entry point, so we + don't do that here. Where that's not the case (e.g. in testing), + consider using NamespacedNameOrDie() in testing.go in this package. + + from: https://github.com/kubernetes/apimachinery/blob/master/pkg/types/namespacedname.go + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + infrastructure_roles_secrets: + description: namespaced name of the secret containing infrastructure + roles names and passwords + items: + properties: + defaultrolevalue: + type: string + defaultuservalue: + type: string + details: + description: This field point out the detailed yaml definition + of the role, if exists + type: string + passwordkey: + type: string + rolekey: + type: string + secretname: + description: |- + Name of a secret which describes the role, and optionally name of a + configmap with an extra information + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + template: + type: boolean + userkey: + type: string + type: object + type: array + inherited_annotations: + items: + type: string + type: array + inherited_labels: + items: + type: string + type: array + liveness_probe: + description: |- + Probe describes a health check to be performed against a container to determine whether it is + alive or ready to receive traffic. + properties: + exec: + description: Exec specifies a command to execute in the container. + properties: + command: + description: |- + Command is the command line to execute inside the container, the working directory for the + command is root ('/') in the container's filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use + a shell, you need to explicitly call out to that shell. + Exit status of 0 is treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + description: |- + Minimum consecutive failures for the probe to be considered failed after having succeeded. + Defaults to 3. Minimum value is 1. + format: int32 + type: integer + grpc: + description: GRPC specifies a GRPC HealthCheckRequest. + properties: + port: + description: Port number of the gRPC service. Number must + be in the range 1 to 65535. + format: int32 + type: integer + service: + default: "" + description: |- + Service is the name of the service to place in the gRPC HealthCheckRequest + (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). + + If this is not specified, the default behavior is defined by gRPC. + type: string + required: + - port + type: object + httpGet: + description: HTTPGet specifies an HTTP GET request to perform. + properties: + host: + description: |- + Host name to connect to, defaults to the pod IP. You probably want to set + "Host" in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. HTTP + allows repeated headers. + items: + description: HTTPHeader describes a custom header to + be used in HTTP probes + properties: + name: + description: |- + The header field name. + This will be canonicalized upon output, so case-variant names will be understood as the same header. + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Name or number of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: |- + Scheme to use for connecting to the host. + Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: |- + Number of seconds after the container has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + periodSeconds: + description: |- + How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: |- + Minimum consecutive successes for the probe to be considered successful after having failed. + Defaults to 1. Must be 1 for liveness and startup. Minimum value is 1. + format: int32 + type: integer + tcpSocket: + description: TCPSocket specifies a connection to a TCP port. + properties: + host: + description: 'Optional: Host name to connect to, defaults + to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: |- + Number or name of the port to access on the container. + Number must be in the range 1 to 65535. + Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + description: |- + Optional duration in seconds the pod needs to terminate gracefully upon probe failure. + The grace period is the duration in seconds after the processes running in the pod are sent + a termination signal and the time when the processes are forcibly halted with a kill signal. + Set this value longer than the expected cleanup time for your process. + If this value is nil, the pod's terminationGracePeriodSeconds will be used. Otherwise, this + value overrides the value provided by the pod spec. + Value must be non-negative integer. The value zero indicates stop immediately via + the kill signal (no opportunity to shut down). + This is a beta field and requires enabling ProbeTerminationGracePeriod feature gate. + Minimum value is 1. spec.terminationGracePeriodSeconds is used if unset. + format: int64 + type: integer + timeoutSeconds: + description: |- + Number of seconds after which the probe times out. + Defaults to 1 second. Minimum value is 1. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes + format: int32 + type: integer + type: object + master_pod_move_timeout: + default: 20m + description: timeout for successful migration of master pods from + unschedulable node + format: int64 + type: integer + node_readiness_label: + additionalProperties: + type: string + type: object + node_readiness_label_merge: + enum: + - AND + - OR + type: string + oauth_token_secret_name: + default: postgres-operator + description: namespaced name of the secret containing the OAuth2 + token to pass to the teams API + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + pdb_master_label_selector: + default: true + type: boolean + pdb_name_format: + default: postgres-{cluster}-pdb + description: defines the template for PDB names + type: string + persistent_volume_claim_retention_policy: + additionalProperties: + type: string + type: object + pod_antiaffinity_preferred_during_scheduling: + type: boolean + pod_antiaffinity_topology_key: + default: kubernetes.io/hostname + type: string + pod_environment_configmap: + description: namespaced name of the ConfigMap with environment + variables to populate on every pod + properties: + name: + type: string + namespace: + type: string + required: + - name + type: object + pod_environment_secret: + type: string + pod_management_policy: + default: ordered_ready + enum: + - ordered_ready + - parallel + type: string + pod_priority_class_name: + type: string + pod_role_label: + default: spilo-role + type: string + pod_service_account_definition: + type: string + pod_service_account_name: + default: postgres-pod + type: string + pod_service_account_role_binding_definition: + type: string + pod_terminate_grace_period: + default: 5m + description: Postgres pods are terminated forcefully after this + timeout + format: int64 + type: integer + secret_name_template: + default: '{username}.{cluster}.credentials.{tprkind}.{tprgroup}' + description: |- + template for database user secrets generated by the operator, + here username contains the namespace in the format namespace.username + if the user is in different namespace than cluster and cross namespace secrets + are enabled via `enable_cross_namespace_secret` flag in the configuration. + type: string + share_pgsocket_with_sidecars: + type: boolean + spilo_allow_privilege_escalation: + default: true + type: boolean + spilo_fsgroup: + format: int64 + type: integer + spilo_privileged: + type: boolean + spilo_runasgroup: + format: int64 + type: integer + spilo_runasuser: + format: int64 + type: integer + storage_resize_mode: + default: pvc + enum: + - ebs + - mixed + - pvc + - "off" + type: string + toleration: + additionalProperties: + type: string + type: object + watched_namespace: + type: string + type: object + kubernetes_use_configmaps: + default: true + type: boolean + load_balancer: + description: LoadBalancerConfiguration defines the LB configuration + properties: + custom_service_annotations: + additionalProperties: + type: string + type: object + db_hosted_zone: + type: string + enable_master_load_balancer: + type: boolean + enable_master_node_port: + type: boolean + enable_master_pooler_load_balancer: + type: boolean + enable_master_pooler_node_port: + type: boolean + enable_replica_load_balancer: + type: boolean + enable_replica_node_port: + type: boolean + enable_replica_pooler_load_balancer: + type: boolean + enable_replica_pooler_node_port: + type: boolean + external_traffic_policy: + default: Cluster + enum: + - Cluster + - Local + type: string + master_dns_name_format: + default: '{cluster}.{namespace}.{hostedzone}' + description: defines the DNS name string template for the master + load balancer cluster + type: string + master_legacy_dns_name_format: + default: '{cluster}.{team}.{hostedzone}' + description: deprecated DNS template for master load balancer + using team name + type: string + replica_dns_name_format: + default: '{cluster}-repl.{namespace}.{hostedzone}' + description: defines the DNS name string template for the replica + load balancer cluster + type: string + replica_legacy_dns_name_format: + default: '{cluster}-repl.{team}.{hostedzone}' + description: deprecated DNS template for replica load balancer + using team name + type: string + type: object + logging_rest_api: + description: LoggingRESTAPIConfiguration defines Logging API conf + properties: + api_port: + default: 8080 + type: integer + cluster_history_entries: + default: 1000 + type: integer + ring_log_lines: + default: 100 + type: integer + type: object + logical_backup: + description: OperatorLogicalBackupConfiguration defines configuration + for logical backup + properties: + logical_backup_azure_storage_account_key: + type: string + logical_backup_azure_storage_account_name: + type: string + logical_backup_azure_storage_container: + type: string + logical_backup_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + logical_backup_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + logical_backup_cronjob_environment_secret: + type: string + logical_backup_docker_image: + default: ghcr.io/zalando/postgres-operator/logical-backup:v1.15.1 + type: string + logical_backup_failed_jobs_history_limit: + default: 3 + format: int32 + minimum: 0 + type: integer + logical_backup_google_application_credentials: + type: string + logical_backup_job_prefix: + default: logical-backup- + type: string + logical_backup_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + logical_backup_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + logical_backup_provider: + default: s3 + enum: + - az + - gcs + - s3 + type: string + logical_backup_s3_access_key_id: + type: string + logical_backup_s3_bucket: + type: string + logical_backup_s3_bucket_prefix: + type: string + logical_backup_s3_endpoint: + type: string + logical_backup_s3_region: + type: string + logical_backup_s3_retention_time: + type: string + logical_backup_s3_secret_access_key: + type: string + logical_backup_s3_sse: + type: string + logical_backup_schedule: + default: 30 00 * * * + pattern: ^(\d+|\*)(/\d+)?(\s+(\d+|\*)(/\d+)?){4}$ + type: string + logical_backup_successful_jobs_history_limit: + default: 3 + format: int32 + minimum: 0 + type: integer + logical_backup_ttl_seconds_after_finished: + default: 86400 + format: int32 + minimum: 0 + type: integer + type: object + maintenance_windows: + type: array + major_version_upgrade: + description: MajorVersionUpgradeConfiguration defines how to execute + major version upgrades of Postgres. + properties: + major_version_upgrade_mode: + default: manual + enum: + - "off" + - manual + - full + type: string + major_version_upgrade_team_allow_list: + items: + type: string + type: array + minimal_major_version: + default: "14" + type: string + target_major_version: + default: "18" + type: string + type: object + max_instances: + default: -1 + description: -1 = disabled + format: int32 + minimum: -1 + type: integer + min_instances: + default: -1 + description: -1 = disabled + format: int32 + minimum: -1 + type: integer + patroni: + description: PatroniConfiguration defines configuration for Patroni + properties: + enable_patroni_failsafe_mode: + type: boolean + type: object + postgres_pod_resources: + description: PostgresPodResourcesDefaults defines the spec of default + resources + properties: + default_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + default_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + default_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + default_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + max_cpu_request: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + max_memory_request: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + min_cpu_limit: + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + min_memory_limit: + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + type: object + repair_period: + default: 5m + description: period between consecutive repair requests + format: int64 + type: integer + resync_period: + default: 30m + description: period between consecutive sync requests + format: int64 + type: integer + scalyr: + description: ScalyrConfiguration defines the configuration for ScalyrAPI + properties: + scalyr_api_key: + type: string + scalyr_cpu_limit: + default: "1" + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + scalyr_cpu_request: + default: 100m + pattern: ^(\d+m|\d+(\.\d{1,3})?)$ + type: string + scalyr_image: + type: string + scalyr_memory_limit: + default: 500Mi + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + scalyr_memory_request: + default: 50Mi + pattern: ^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$ + type: string + scalyr_server_url: + default: https://upload.eu.scalyr.com + type: string + type: object + set_memory_request_to_limit: + type: boolean + sidecar_docker_images: + additionalProperties: + type: string + type: object + sidecars: + type: object + x-kubernetes-preserve-unknown-fields: true + teams_api: + description: TeamsAPIConfiguration defines the configuration of TeamsAPI + properties: + enable_admin_role_for_users: + default: true + type: boolean + enable_postgres_team_crd: + default: true + type: boolean + enable_postgres_team_crd_superusers: + type: boolean + enable_team_member_deprecation: + type: boolean + enable_team_superuser: + type: boolean + enable_teams_api: + type: boolean + pam_configuration: + default: https://info.example.com/oauth2/tokeninfo?access_token= + uid realm=/employees + type: string + pam_role_name: + default: zalandos + type: string + postgres_superuser_teams: + items: + type: string + type: array + protected_role_names: + default: '["admin", "cron_admin"]' + items: + type: string + type: array + role_deletion_suffix: + default: _deleted + type: string + team_admin_role: + default: admin + type: string + team_api_role_configuration: + additionalProperties: + type: string + default: + log_statement: all + type: object + teams_api_url: + default: https://teams.example.com/api/ + type: string + type: object + timeouts: + description: OperatorTimeouts defines the timeout of ResourceCheck, + PodWait, ReadyWait + properties: + patroni_api_check_interval: + default: 1s + description: interval between consecutive attempts of operator + calling the Patroni API + format: int64 + type: integer + patroni_api_check_timeout: + default: 5s + description: timeout when waiting for successful response from + Patroni API + format: int64 + type: integer + pod_deletion_wait_timeout: + default: 10m + description: timeout when waiting for the Postgres pods to be + deleted + format: int64 + type: integer + pod_label_wait_timeout: + default: 10m + description: timeout when waiting for pod role and cluster labels + format: int64 + type: integer + ready_wait_interval: + default: 4s + description: interval between consecutive attempts waiting for + postgresql CRD to be created + format: int64 + type: integer + ready_wait_timeout: + default: 30s + description: timeout for the complete postgres CRD creation + format: int64 + type: integer + resource_check_interval: + default: 3s + description: interval to wait between consecutive attempts to + check for some K8s resources + format: int64 + type: integer + resource_check_timeout: + default: 10m + description: timeout when waiting for the presence of a certain + K8s resource + format: int64 + type: integer + type: object + users: + description: PostgresUsersConfiguration defines the system users of + Postgres. + properties: + additional_owner_roles: + items: + type: string + type: array + enable_password_rotation: + type: boolean + password_rotation_interval: + default: 90 + format: int32 + type: integer + password_rotation_user_retention: + default: 120 + format: int32 + type: integer + replication_username: + default: standby + type: string + super_username: + default: postgres + type: string + type: object + workers: + default: 8 + format: int32 + minimum: 1 + type: integer + type: object + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + required: + - configuration + - metadata + type: object + served: true + storage: true + subresources: + status: {} diff --git a/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go b/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go index 9005b0bbe..7d18c2cf2 100644 --- a/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go +++ b/pkg/apis/acid.zalan.do/v1/zz_generated.deepcopy.go @@ -428,11 +428,6 @@ func (in *OperatorConfigurationData) DeepCopyInto(out *OperatorConfigurationData *out = new(bool) **out = **in } - if in.EnableCRDValidation != nil { - in, out := &in.EnableCRDValidation, &out.EnableCRDValidation - *out = new(bool) - **out = **in - } if in.CRDCategories != nil { in, out := &in.CRDCategories, &out.CRDCategories *out = make([]string, len(*in)) diff --git a/pkg/controller/operator_config.go b/pkg/controller/operator_config.go index 4514e7487..66fc7a731 100644 --- a/pkg/controller/operator_config.go +++ b/pkg/controller/operator_config.go @@ -31,7 +31,6 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur // general config result.EnableCRDRegistration = util.CoalesceBool(fromCRD.EnableCRDRegistration, util.True()) - result.EnableCRDValidation = util.CoalesceBool(fromCRD.EnableCRDValidation, util.True()) result.CRDCategories = util.CoalesceStrArr(fromCRD.CRDCategories, []string{"all"}) result.EnableLazySpiloUpgrade = fromCRD.EnableLazySpiloUpgrade result.EnablePgVersionEnvVar = fromCRD.EnablePgVersionEnvVar diff --git a/pkg/controller/util.go b/pkg/controller/util.go index 87962f7b9..f58c9df5a 100644 --- a/pkg/controller/util.go +++ b/pkg/controller/util.go @@ -103,7 +103,11 @@ func (c *Controller) createPostgresCRD() error { } func (c *Controller) createConfigurationCRD() error { - return c.createOperatorCRD(acidv1.ConfigurationCRD(c.opConfig.CRDCategories)) + crd, err := acidv1.OperatorConfigurationCRD(c.opConfig.CRDCategories) + if err != nil { + return fmt.Errorf("could not create OperatorConfiguration CRD object: %v", err) + } + return c.createOperatorCRD(crd) } func readDecodedRole(s string) (*spec.PgUser, error) { diff --git a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_operatorconfiguration.go b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_operatorconfiguration.go index 8c9790d18..66db8ec40 100644 --- a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_operatorconfiguration.go +++ b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/fake/fake_operatorconfiguration.go @@ -32,18 +32,26 @@ import ( // fakeOperatorConfigurations implements OperatorConfigurationInterface type fakeOperatorConfigurations struct { - *gentype.FakeClient[*v1.OperatorConfiguration] + *gentype.FakeClientWithList[*v1.OperatorConfiguration, *v1.OperatorConfigurationList] Fake *FakeAcidV1 } func newFakeOperatorConfigurations(fake *FakeAcidV1, namespace string) acidzalandov1.OperatorConfigurationInterface { return &fakeOperatorConfigurations{ - gentype.NewFakeClient[*v1.OperatorConfiguration]( + gentype.NewFakeClientWithList[*v1.OperatorConfiguration, *v1.OperatorConfigurationList]( fake.Fake, namespace, v1.SchemeGroupVersion.WithResource("operatorconfigurations"), v1.SchemeGroupVersion.WithKind("OperatorConfiguration"), func() *v1.OperatorConfiguration { return &v1.OperatorConfiguration{} }, + func() *v1.OperatorConfigurationList { return &v1.OperatorConfigurationList{} }, + func(dst, src *v1.OperatorConfigurationList) { dst.ListMeta = src.ListMeta }, + func(list *v1.OperatorConfigurationList) []*v1.OperatorConfiguration { + return gentype.ToPointerSlice(list.Items) + }, + func(list *v1.OperatorConfigurationList, items []*v1.OperatorConfiguration) { + list.Items = gentype.FromPointerSlice(items) + }, ), fake, } diff --git a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/operatorconfiguration.go b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/operatorconfiguration.go index 91dc27037..292fa2fce 100644 --- a/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/operatorconfiguration.go +++ b/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1/operatorconfiguration.go @@ -30,6 +30,8 @@ import ( acidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" scheme "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/scheme" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" gentype "k8s.io/client-go/gentype" ) @@ -41,24 +43,32 @@ type OperatorConfigurationsGetter interface { // OperatorConfigurationInterface has methods to work with OperatorConfiguration resources. type OperatorConfigurationInterface interface { + Create(ctx context.Context, operatorConfiguration *acidzalandov1.OperatorConfiguration, opts metav1.CreateOptions) (*acidzalandov1.OperatorConfiguration, error) + Update(ctx context.Context, operatorConfiguration *acidzalandov1.OperatorConfiguration, opts metav1.UpdateOptions) (*acidzalandov1.OperatorConfiguration, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error Get(ctx context.Context, name string, opts metav1.GetOptions) (*acidzalandov1.OperatorConfiguration, error) + List(ctx context.Context, opts metav1.ListOptions) (*acidzalandov1.OperatorConfigurationList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *acidzalandov1.OperatorConfiguration, err error) OperatorConfigurationExpansion } // operatorConfigurations implements OperatorConfigurationInterface type operatorConfigurations struct { - *gentype.Client[*acidzalandov1.OperatorConfiguration] + *gentype.ClientWithList[*acidzalandov1.OperatorConfiguration, *acidzalandov1.OperatorConfigurationList] } // newOperatorConfigurations returns a OperatorConfigurations func newOperatorConfigurations(c *AcidV1Client, namespace string) *operatorConfigurations { return &operatorConfigurations{ - gentype.NewClient[*acidzalandov1.OperatorConfiguration]( + gentype.NewClientWithList[*acidzalandov1.OperatorConfiguration, *acidzalandov1.OperatorConfigurationList]( "operatorconfigurations", c.RESTClient(), scheme.ParameterCodec, namespace, func() *acidzalandov1.OperatorConfiguration { return &acidzalandov1.OperatorConfiguration{} }, + func() *acidzalandov1.OperatorConfigurationList { return &acidzalandov1.OperatorConfigurationList{} }, ), } } diff --git a/pkg/generated/informers/externalversions/acid.zalan.do/v1/interface.go b/pkg/generated/informers/externalversions/acid.zalan.do/v1/interface.go index 1ea652a3f..d176a2b35 100644 --- a/pkg/generated/informers/externalversions/acid.zalan.do/v1/interface.go +++ b/pkg/generated/informers/externalversions/acid.zalan.do/v1/interface.go @@ -30,6 +30,8 @@ import ( // Interface provides access to all the informers in this group version. type Interface interface { + // OperatorConfigurations returns a OperatorConfigurationInformer. + OperatorConfigurations() OperatorConfigurationInformer // PostgresTeams returns a PostgresTeamInformer. PostgresTeams() PostgresTeamInformer // Postgresqls returns a PostgresqlInformer. @@ -47,6 +49,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// OperatorConfigurations returns a OperatorConfigurationInformer. +func (v *version) OperatorConfigurations() OperatorConfigurationInformer { + return &operatorConfigurationInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // PostgresTeams returns a PostgresTeamInformer. func (v *version) PostgresTeams() PostgresTeamInformer { return &postgresTeamInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/generated/informers/externalversions/acid.zalan.do/v1/operatorconfiguration.go b/pkg/generated/informers/externalversions/acid.zalan.do/v1/operatorconfiguration.go new file mode 100644 index 000000000..1522adc49 --- /dev/null +++ b/pkg/generated/informers/externalversions/acid.zalan.do/v1/operatorconfiguration.go @@ -0,0 +1,96 @@ +/* +Copyright 2026 Compose, Zalando SE + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + context "context" + time "time" + + apisacidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + versioned "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned" + internalinterfaces "github.com/zalando/postgres-operator/pkg/generated/informers/externalversions/internalinterfaces" + acidzalandov1 "github.com/zalando/postgres-operator/pkg/generated/listers/acid.zalan.do/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// OperatorConfigurationInformer provides access to a shared informer and lister for +// OperatorConfigurations. +type OperatorConfigurationInformer interface { + Informer() cache.SharedIndexInformer + Lister() acidzalandov1.OperatorConfigurationLister +} + +type operatorConfigurationInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewOperatorConfigurationInformer constructs a new informer for OperatorConfiguration type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewOperatorConfigurationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredOperatorConfigurationInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredOperatorConfigurationInformer constructs a new informer for OperatorConfiguration type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredOperatorConfigurationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AcidV1().OperatorConfigurations(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.AcidV1().OperatorConfigurations(namespace).Watch(context.TODO(), options) + }, + }, + &apisacidzalandov1.OperatorConfiguration{}, + resyncPeriod, + indexers, + ) +} + +func (f *operatorConfigurationInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredOperatorConfigurationInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *operatorConfigurationInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&apisacidzalandov1.OperatorConfiguration{}, f.defaultInformer) +} + +func (f *operatorConfigurationInformer) Lister() acidzalandov1.OperatorConfigurationLister { + return acidzalandov1.NewOperatorConfigurationLister(f.Informer().GetIndexer()) +} diff --git a/pkg/generated/informers/externalversions/generic.go b/pkg/generated/informers/externalversions/generic.go index ed27d5743..f5953bde6 100644 --- a/pkg/generated/informers/externalversions/generic.go +++ b/pkg/generated/informers/externalversions/generic.go @@ -60,6 +60,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=acid.zalan.do, Version=v1 + case v1.SchemeGroupVersion.WithResource("operatorconfigurations"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Acid().V1().OperatorConfigurations().Informer()}, nil case v1.SchemeGroupVersion.WithResource("postgresteams"): return &genericInformer{resource: resource.GroupResource(), informer: f.Acid().V1().PostgresTeams().Informer()}, nil case v1.SchemeGroupVersion.WithResource("postgresqls"): diff --git a/pkg/generated/listers/acid.zalan.do/v1/expansion_generated.go b/pkg/generated/listers/acid.zalan.do/v1/expansion_generated.go index b71f44767..f9b4c79e7 100644 --- a/pkg/generated/listers/acid.zalan.do/v1/expansion_generated.go +++ b/pkg/generated/listers/acid.zalan.do/v1/expansion_generated.go @@ -24,6 +24,14 @@ SOFTWARE. package v1 +// OperatorConfigurationListerExpansion allows custom methods to be added to +// OperatorConfigurationLister. +type OperatorConfigurationListerExpansion interface{} + +// OperatorConfigurationNamespaceListerExpansion allows custom methods to be added to +// OperatorConfigurationNamespaceLister. +type OperatorConfigurationNamespaceListerExpansion interface{} + // PostgresTeamListerExpansion allows custom methods to be added to // PostgresTeamLister. type PostgresTeamListerExpansion interface{} diff --git a/pkg/generated/listers/acid.zalan.do/v1/operatorconfiguration.go b/pkg/generated/listers/acid.zalan.do/v1/operatorconfiguration.go new file mode 100644 index 000000000..c00599718 --- /dev/null +++ b/pkg/generated/listers/acid.zalan.do/v1/operatorconfiguration.go @@ -0,0 +1,76 @@ +/* +Copyright 2026 Compose, Zalando SE + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + acidzalandov1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" + labels "k8s.io/apimachinery/pkg/labels" + listers "k8s.io/client-go/listers" + cache "k8s.io/client-go/tools/cache" +) + +// OperatorConfigurationLister helps list OperatorConfigurations. +// All objects returned here must be treated as read-only. +type OperatorConfigurationLister interface { + // List lists all OperatorConfigurations in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*acidzalandov1.OperatorConfiguration, err error) + // OperatorConfigurations returns an object that can list and get OperatorConfigurations. + OperatorConfigurations(namespace string) OperatorConfigurationNamespaceLister + OperatorConfigurationListerExpansion +} + +// operatorConfigurationLister implements the OperatorConfigurationLister interface. +type operatorConfigurationLister struct { + listers.ResourceIndexer[*acidzalandov1.OperatorConfiguration] +} + +// NewOperatorConfigurationLister returns a new OperatorConfigurationLister. +func NewOperatorConfigurationLister(indexer cache.Indexer) OperatorConfigurationLister { + return &operatorConfigurationLister{listers.New[*acidzalandov1.OperatorConfiguration](indexer, acidzalandov1.Resource("operatorconfiguration"))} +} + +// OperatorConfigurations returns an object that can list and get OperatorConfigurations. +func (s *operatorConfigurationLister) OperatorConfigurations(namespace string) OperatorConfigurationNamespaceLister { + return operatorConfigurationNamespaceLister{listers.NewNamespaced[*acidzalandov1.OperatorConfiguration](s.ResourceIndexer, namespace)} +} + +// OperatorConfigurationNamespaceLister helps list and get OperatorConfigurations. +// All objects returned here must be treated as read-only. +type OperatorConfigurationNamespaceLister interface { + // List lists all OperatorConfigurations in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*acidzalandov1.OperatorConfiguration, err error) + // Get retrieves the OperatorConfiguration from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*acidzalandov1.OperatorConfiguration, error) + OperatorConfigurationNamespaceListerExpansion +} + +// operatorConfigurationNamespaceLister implements the OperatorConfigurationNamespaceLister +// interface. +type operatorConfigurationNamespaceLister struct { + listers.ResourceIndexer[*acidzalandov1.OperatorConfiguration] +} diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go index 06edac439..43fa37a33 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -19,7 +19,6 @@ type CRD struct { ResyncPeriod time.Duration `name:"resync_period" default:"30m"` RepairPeriod time.Duration `name:"repair_period" default:"5m"` EnableCRDRegistration *bool `name:"enable_crd_registration" default:"true"` - EnableCRDValidation *bool `name:"enable_crd_validation" default:"true"` CRDCategories []string `name:"crd_categories" default:"all"` }