From 2cdd5abc8502d66b4f6777952efd6202e11a6899 Mon Sep 17 00:00:00 2001 From: Filippo Ledda Date: Thu, 19 Mar 2026 11:23:40 +0100 Subject: [PATCH 1/8] CH-256 feat: add PostgreSQL operator support --- .../auto-database-postgres-operator.yaml | 84 +++++++++++++++++++ .../helm/templates/auto-database.yaml | 4 + .../helm/templates/auto-network-policies.yaml | 9 ++ deployment-configuration/value-template.yaml | 4 + deployment/codefresh-test.yaml | 40 ++++----- docs/applications/databases.md | 13 +++ docs/model/DatabaseConfig.md | 3 + libraries/models/api/openapi.yaml | 10 +++ .../models/database_config.py | 10 ++- .../models/cloudharness_model/models/user.py | 14 ++-- libraries/models/docs/DatabaseConfig.md | 3 + 11 files changed, 167 insertions(+), 27 deletions(-) create mode 100644 deployment-configuration/helm/templates/auto-database-postgres-operator.yaml diff --git a/deployment-configuration/helm/templates/auto-database-postgres-operator.yaml b/deployment-configuration/helm/templates/auto-database-postgres-operator.yaml new file mode 100644 index 000000000..6cf972134 --- /dev/null +++ b/deployment-configuration/helm/templates/auto-database-postgres-operator.yaml @@ -0,0 +1,84 @@ +{{- define "deploy_utils.database.postgres.operator" }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-credentials" .app.harness.database.name | quote }} + namespace: {{ .root.Values.namespace }} + labels: + app: {{ .app.harness.database.name | quote }} +{{ include "deploy_utils.labels" .root | indent 4 }} +type: kubernetes.io/basic-auth +stringData: + username: {{ .app.harness.database.user | quote }} + password: {{ .app.harness.database.pass | quote }} +--- +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: {{ .app.harness.database.name | quote }} + namespace: {{ .root.Values.namespace }} + labels: + app: {{ .app.harness.database.name | quote }} +{{ include "deploy_utils.labels" .root | indent 4 }} +spec: + instances: {{ .app.harness.database.postgres.instances | default 1 }} + + inheritedMetadata: + labels: + app: {{ .app.harness.database.name | quote }} + service: db + + bootstrap: + initdb: + database: {{ .app.harness.database.postgres.initialdb | quote }} + owner: {{ .app.harness.database.user | quote }} + secret: + name: {{ printf "%s-credentials" .app.harness.database.name | quote }} + + storage: + size: {{ .app.harness.database.size }} + + {{- with .app.harness.database.resources }} + resources: + {{- with .requests }} + requests: + {{- with .memory }} + memory: {{ . | quote }} + {{- end }} + {{- with .cpu }} + cpu: {{ . | quote }} + {{- end }} + {{- end }} + {{- with .limits }} + limits: + {{- with .memory }} + memory: {{ . | quote }} + {{- end }} + {{- end }} + {{- end }} + + {{- if .app.harness.database.image_ref }} + imageName: {{ index (index .app "task-images") .app.harness.database.image_ref | default ("Image ref not found!" | quote) }} + {{- end }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .app.harness.database.name | quote }} + namespace: {{ .root.Values.namespace }} + labels: + app: {{ .app.harness.deployment.name | quote }} +{{ include "deploy_utils.labels" .root | indent 4 }} +spec: + type: {{ if .app.harness.database.expose }}LoadBalancer{{ else }}ClusterIP{{ end }} + selector: + app: {{ .app.harness.database.name | quote }} + cnpg.io/instanceRole: primary + ports: + {{- range $port := .app.harness.database.postgres.ports }} + - name: {{ $port.name }} + port: {{ $port.port }} + targetPort: 5432 + {{- end }} +{{- end }} diff --git a/deployment-configuration/helm/templates/auto-database.yaml b/deployment-configuration/helm/templates/auto-database.yaml index 212d763fc..a23e97a6c 100644 --- a/deployment-configuration/helm/templates/auto-database.yaml +++ b/deployment-configuration/helm/templates/auto-database.yaml @@ -14,6 +14,9 @@ spec: --- {{- end }} {{- define "deploy_utils.database" }} +{{- if and (eq .app.harness.database.type "postgres") .app.harness.database.postgres.operator }} +{{- include "deploy_utils.database.postgres.operator" . }} +{{- else }} --- kind: PersistentVolumeClaim apiVersion: v1 @@ -105,6 +108,7 @@ spec: - name: {{ $port.name }} port: {{ $port.port }} {{- end }} +{{- end }} --- {{- include "deploy_utils.database_network_policy" (dict "root" .root "app" .app) }} {{ end }} diff --git a/deployment-configuration/helm/templates/auto-network-policies.yaml b/deployment-configuration/helm/templates/auto-network-policies.yaml index 6dbf4eb03..06e80d761 100644 --- a/deployment-configuration/helm/templates/auto-network-policies.yaml +++ b/deployment-configuration/helm/templates/auto-network-policies.yaml @@ -117,6 +117,15 @@ spec: protocol: UDP - port: 53 protocol: TCP + {{- if and (eq .app.harness.database.type "postgres") .app.harness.database.postgres.operator }} + # Allow access to Kubernetes API server for CNPG operator pods + - to: + - ipBlock: + cidr: 0.0.0.0/0 + ports: + - port: 443 + protocol: TCP + {{- end }} {{- range $ns := $allowedNamespaces }} # Allow traffic to whitelisted namespace - to: diff --git a/deployment-configuration/value-template.yaml b/deployment-configuration/value-template.yaml index fef6f5a8d..b28db4ce3 100644 --- a/deployment-configuration/value-template.yaml +++ b/deployment-configuration/value-template.yaml @@ -97,6 +97,10 @@ harness: postgres: image: postgres:13 initialdb: cloudharness + # -- Use the CloudNative-PG operator instead of a plain Deployment. Requires the CNPG operator to be installed in the cluster. + operator: false + # -- Number of PostgreSQL instances managed by the CNPG operator (only used when operator is true) + instances: 1 ports: - name: http port: 5432 diff --git a/deployment/codefresh-test.yaml b/deployment/codefresh-test.yaml index b4ad6b8d3..1e418c0c4 100644 --- a/deployment/codefresh-test.yaml +++ b/deployment/codefresh-test.yaml @@ -393,7 +393,7 @@ steps: samples: type: build stage: build - dockerfile: Dockerfile + dockerfile: test.Dockerfile registry: '${{CODEFRESH_REGISTRY}}' buildkit: true build_arguments: @@ -522,13 +522,13 @@ steps: commands: - kubectl config use-context ${{CLUSTER_NAME}} - kubectl config set-context --current --namespace=test-${{NAMESPACE_BASENAME}} + - kubectl rollout status deployment/workflows - kubectl rollout status deployment/samples - kubectl rollout status deployment/samples-gk - - kubectl rollout status deployment/workflows - - kubectl rollout status deployment/common - - kubectl rollout status deployment/accounts - kubectl rollout status deployment/volumemanager - kubectl rollout status deployment/argo-gk + - kubectl rollout status deployment/common + - kubectl rollout status deployment/accounts - sleep 60 tests_api: stage: qa @@ -539,22 +539,16 @@ steps: commands: - echo $APP_NAME scale: - samples_api_test: - title: samples api test + workflows_api_test: + title: workflows api test volumes: - - '${{CF_REPO_NAME}}/applications/samples:/home/test' + - '${{CF_REPO_NAME}}/applications/workflows:/home/test' - '${{CF_REPO_NAME}}/deployment/helm/values.yaml:/opt/cloudharness/resources/allvalues.yaml' environment: - - APP_URL=https://samples.${{DOMAIN}}/api - - USERNAME=sample@testuser.com - - PASSWORD=test + - APP_URL=https://workflows.${{DOMAIN}}/api commands: - st --pre-run cloudharness_test.apitest_init run api/openapi.yaml --base-url - https://samples.${{DOMAIN}}/api -c all --skip-deprecated-operations --exclude-operation-id=submit_sync - --exclude-operation-id=submit_sync_with_results --exclude-operation-id=error - --hypothesis-suppress-health-check=too_slow --hypothesis-deadline=180000 - --request-timeout=180000 --hypothesis-max-examples=2 --show-trace --exclude-checks=ignored_auth - - pytest -v test/api + https://workflows.${{DOMAIN}}/api -c all common_api_test: title: common api test volumes: @@ -565,16 +559,22 @@ steps: commands: - st --pre-run cloudharness_test.apitest_init run api/openapi.yaml --base-url https://common.${{DOMAIN}}/api -c all - workflows_api_test: - title: workflows api test + samples_api_test: + title: samples api test volumes: - - '${{CF_REPO_NAME}}/applications/workflows:/home/test' + - '${{CF_REPO_NAME}}/applications/samples:/home/test' - '${{CF_REPO_NAME}}/deployment/helm/values.yaml:/opt/cloudharness/resources/allvalues.yaml' environment: - - APP_URL=https://workflows.${{DOMAIN}}/api + - APP_URL=https://samples.${{DOMAIN}}/api + - USERNAME=sample@testuser.com + - PASSWORD=test commands: - st --pre-run cloudharness_test.apitest_init run api/openapi.yaml --base-url - https://workflows.${{DOMAIN}}/api -c all + https://samples.${{DOMAIN}}/api -c all --skip-deprecated-operations --exclude-operation-id=submit_sync + --exclude-operation-id=submit_sync_with_results --exclude-operation-id=error + --hypothesis-suppress-health-check=too_slow --hypothesis-deadline=180000 + --request-timeout=180000 --hypothesis-max-examples=2 --show-trace --exclude-checks=ignored_auth + - pytest -v test/api hooks: on_fail: exec: diff --git a/docs/applications/databases.md b/docs/applications/databases.md index 96498f6cd..e803888bd 100644 --- a/docs/applications/databases.md +++ b/docs/applications/databases.md @@ -84,6 +84,8 @@ harness postgres: image: postgres:13 initialdb: cloudharness + operator: false + instances: 1 ports: - name: http port: 5432 @@ -91,6 +93,17 @@ harness `initialdb` is the default database used +`operator`: When set to `true`, uses the [CloudNative-PG operator](https://github.com/cloudnative-pg/cloudnative-pg) instead of a plain Kubernetes Deployment. This provides advanced features like automated failover, backup management, and cluster management. **Requires the CNPG operator to be pre-installed in the cluster.** + +To install the CNPG operator: +```bash +helm repo add cloudnative-pg https://cloudnative-pg.github.io/charts +helm repo update +helm install cnpg cloudnative-pg/cloudnative-pg +``` + +`instances`: Number of PostgreSQL instances (replicas) managed by the CNPG operator. Only used when `operator: true`. Default is 1. + #### Neo4j diff --git a/docs/model/DatabaseConfig.md b/docs/model/DatabaseConfig.md index c6b3bf210..d22244860 100644 --- a/docs/model/DatabaseConfig.md +++ b/docs/model/DatabaseConfig.md @@ -9,6 +9,9 @@ Name | Type | Description | Notes **image** | **str** | | [optional] **name** | **str** | | [optional] **ports** | [**List[PortConfig]**](PortConfig.md) | | [optional] +**operator** | **bool** | Use the CloudNative-PG operator instead of a plain Deployment (postgres only) | [optional] +**instances** | **int** | Number of PostgreSQL instances managed by the CNPG operator (only used when operator is true) | [optional] +**initialdb** | **str** | Initial database name (postgres only) | [optional] ## Example diff --git a/libraries/models/api/openapi.yaml b/libraries/models/api/openapi.yaml index 52b013faf..89d258a35 100644 --- a/libraries/models/api/openapi.yaml +++ b/libraries/models/api/openapi.yaml @@ -950,6 +950,16 @@ components: type: array items: $ref: '#/components/schemas/PortConfig' + operator: + description: 'Use the CloudNative-PG operator instead of a plain Deployment (postgres only)' + type: boolean + instances: + description: 'Number of PostgreSQL instances managed by the CNPG operator (only used when operator is true)' + type: integer + minimum: 1 + initialdb: + description: 'Initial database name (postgres only)' + type: string additionalProperties: true NetworkConfig: title: Root Type for NetworkConfig diff --git a/libraries/models/cloudharness_model/models/database_config.py b/libraries/models/cloudharness_model/models/database_config.py index a2a914c56..6b71a4564 100644 --- a/libraries/models/cloudharness_model/models/database_config.py +++ b/libraries/models/cloudharness_model/models/database_config.py @@ -34,8 +34,11 @@ class DatabaseConfig(CloudHarnessBaseModel): image: Optional[StrictStr] = None name: Optional[StrictStr] = None ports: Optional[List[PortConfig]] = None + operator: Optional[StrictBool] = Field(default=None, description="Use the CloudNative-PG operator instead of a plain Deployment (postgres only)") + instances: Optional[Annotated[int, Field(strict=True, ge=1)]] = Field(default=None, description="Number of PostgreSQL instances managed by the CNPG operator (only used when operator is true)") + initialdb: Optional[StrictStr] = Field(default=None, description="Initial database name (postgres only)") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["image", "name", "ports"] + __properties: ClassVar[List[str]] = ["image", "name", "ports", "operator", "instances", "initialdb"] def to_dict(self) -> Dict[str, Any]: """Return the dictionary representation of the model using alias. @@ -83,7 +86,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "image": obj.get("image"), "name": obj.get("name"), - "ports": [PortConfig.from_dict(_item) for _item in obj["ports"]] if obj.get("ports") is not None else None + "ports": [PortConfig.from_dict(_item) for _item in obj["ports"]] if obj.get("ports") is not None else None, + "operator": obj.get("operator"), + "instances": obj.get("instances"), + "initialdb": obj.get("initialdb") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/libraries/models/cloudharness_model/models/user.py b/libraries/models/cloudharness_model/models/user.py index 1382348ca..bfc2a10fc 100644 --- a/libraries/models/cloudharness_model/models/user.py +++ b/libraries/models/cloudharness_model/models/user.py @@ -13,24 +13,26 @@ from __future__ import annotations +import pprint +import re # noqa: F401 +import json from typing import Optional, Set from typing_extensions import Self from cloudharness_model.base_model import CloudHarnessBaseModel -from pydantic import Field, StrictStr, StrictBool, StrictInt, StrictFloat -from typing import ClassVar, List, Dict, Any, Optional, Annotated - +from pydantic import BaseModel, Field, field_validator, StrictStr, StrictBool, StrictInt, StrictFloat +from typing import ClassVar, List, Dict, Any, Union, Optional, Annotated +import importlib from cloudharness_model.models.organization import Organization from cloudharness_model.models.user_credential import UserCredential from cloudharness_model.models.user_group import UserGroup - class User(CloudHarnessBaseModel): """ User - """ # noqa: E501 + """ # noqa: E501 access: Optional[Dict[str, Any]] = None attributes: Optional[Dict[str, Any]] = None client_roles: Optional[Dict[str, Any]] = Field(default=None, alias="clientRoles") @@ -146,3 +148,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj.additional_properties[_key] = obj.get(_key) return _obj + + diff --git a/libraries/models/docs/DatabaseConfig.md b/libraries/models/docs/DatabaseConfig.md index c6b3bf210..d22244860 100644 --- a/libraries/models/docs/DatabaseConfig.md +++ b/libraries/models/docs/DatabaseConfig.md @@ -9,6 +9,9 @@ Name | Type | Description | Notes **image** | **str** | | [optional] **name** | **str** | | [optional] **ports** | [**List[PortConfig]**](PortConfig.md) | | [optional] +**operator** | **bool** | Use the CloudNative-PG operator instead of a plain Deployment (postgres only) | [optional] +**instances** | **int** | Number of PostgreSQL instances managed by the CNPG operator (only used when operator is true) | [optional] +**initialdb** | **str** | Initial database name (postgres only) | [optional] ## Example From e75071b23950ddcd13279b71eda05e54976568ef Mon Sep 17 00:00:00 2001 From: Filippo Ledda <46561561+filippomc@users.noreply.github.com> Date: Thu, 19 Mar 2026 11:34:10 +0100 Subject: [PATCH 2/8] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docs/applications/databases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/applications/databases.md b/docs/applications/databases.md index e803888bd..1e0e1ffc6 100644 --- a/docs/applications/databases.md +++ b/docs/applications/databases.md @@ -93,7 +93,7 @@ harness `initialdb` is the default database used -`operator`: When set to `true`, uses the [CloudNative-PG operator](https://github.com/cloudnative-pg/cloudnative-pg) instead of a plain Kubernetes Deployment. This provides advanced features like automated failover, backup management, and cluster management. **Requires the CNPG operator to be pre-installed in the cluster.** +`operator`: When set to `true`, uses the [CloudNative-PG operator](https://github.com/cloudnative-pg/cloudnative-pg) instead of a plain Kubernetes Deployment. This provides advanced features like automated failover and cluster management. **Backups are not configured by default by this chart; you must define CNPG backup resources (for example, `Backup` and/or `ScheduledBackup` objects) or use another backup mechanism separately.** **Requires the CNPG operator to be pre-installed in the cluster.** To install the CNPG operator: ```bash From d2ad88a24836d625156738492d38df96d47079fe Mon Sep 17 00:00:00 2001 From: Filippo Ledda <46561561+filippomc@users.noreply.github.com> Date: Thu, 19 Mar 2026 14:06:01 +0100 Subject: [PATCH 3/8] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../helm/templates/auto-network-policies.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment-configuration/helm/templates/auto-network-policies.yaml b/deployment-configuration/helm/templates/auto-network-policies.yaml index 06e80d761..c3594b0b2 100644 --- a/deployment-configuration/helm/templates/auto-network-policies.yaml +++ b/deployment-configuration/helm/templates/auto-network-policies.yaml @@ -118,7 +118,7 @@ spec: - port: 53 protocol: TCP {{- if and (eq .app.harness.database.type "postgres") .app.harness.database.postgres.operator }} - # Allow access to Kubernetes API server for CNPG operator pods + # Allow access to Kubernetes API server for CNPG cluster instance (database) pods - to: - ipBlock: cidr: 0.0.0.0/0 From 8622f9cc9717fbc82feed7ba3b4b661e7e8614f3 Mon Sep 17 00:00:00 2001 From: Filippo Ledda <46561561+filippomc@users.noreply.github.com> Date: Thu, 19 Mar 2026 16:59:22 +0100 Subject: [PATCH 4/8] CH-256 support database image replacement on operator Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../helm/templates/auto-database-postgres-operator.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deployment-configuration/helm/templates/auto-database-postgres-operator.yaml b/deployment-configuration/helm/templates/auto-database-postgres-operator.yaml index 6cf972134..25d380b0c 100644 --- a/deployment-configuration/helm/templates/auto-database-postgres-operator.yaml +++ b/deployment-configuration/helm/templates/auto-database-postgres-operator.yaml @@ -60,6 +60,8 @@ spec: {{- if .app.harness.database.image_ref }} imageName: {{ index (index .app "task-images") .app.harness.database.image_ref | default ("Image ref not found!" | quote) }} + {{- else if .app.harness.database.postgres.image }} + imageName: {{ .app.harness.database.postgres.image | quote }} {{- end }} --- apiVersion: v1 From 73e756f54eb157b3f85e7e378ce989b5789e768d Mon Sep 17 00:00:00 2001 From: Filippo Ledda Date: Thu, 19 Mar 2026 17:02:45 +0100 Subject: [PATCH 5/8] CH-256 remove default postgres image --- deployment-configuration/value-template.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment-configuration/value-template.yaml b/deployment-configuration/value-template.yaml index b28db4ce3..a7df95db7 100644 --- a/deployment-configuration/value-template.yaml +++ b/deployment-configuration/value-template.yaml @@ -95,7 +95,7 @@ harness: port: 27017 # -- settings for postgers database (for type==postgres) postgres: - image: postgres:13 + image: initialdb: cloudharness # -- Use the CloudNative-PG operator instead of a plain Deployment. Requires the CNPG operator to be installed in the cluster. operator: false From bab3bcaff79a0718b658732538fa1f10ea6e2a18 Mon Sep 17 00:00:00 2001 From: Filippo Ledda Date: Thu, 19 Mar 2026 17:36:03 +0100 Subject: [PATCH 6/8] CH-256 test fix --- .../applications/myapp/deploy/values-withpostgres.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/deployment-cli-tools/tests/resources/applications/myapp/deploy/values-withpostgres.yaml b/tools/deployment-cli-tools/tests/resources/applications/myapp/deploy/values-withpostgres.yaml index 4b260dbf7..d808f7351 100644 --- a/tools/deployment-cli-tools/tests/resources/applications/myapp/deploy/values-withpostgres.yaml +++ b/tools/deployment-cli-tools/tests/resources/applications/myapp/deploy/values-withpostgres.yaml @@ -1,2 +1,6 @@ harness: - database: {auto: true, type: postgres} \ No newline at end of file + database: + auto: true + type: postgres + postgres: + image: postgres:17 \ No newline at end of file From aefb84c70f264f7709779b989e873a9af3ebf837 Mon Sep 17 00:00:00 2001 From: Filippo Ledda Date: Thu, 19 Mar 2026 18:39:28 +0100 Subject: [PATCH 7/8] CH-256 Improve network policy with auto-discovery --- .../helm/templates/auto-network-policies.yaml | 23 +++++++++++++++++-- deployment-configuration/value-template.yaml | 3 +++ docs/applications/databases.md | 3 +++ docs/model/DatabaseConfig.md | 1 + libraries/models/api/openapi.yaml | 5 ++++ .../models/database_config.py | 4 +++- libraries/models/docs/DatabaseConfig.md | 1 + 7 files changed, 37 insertions(+), 3 deletions(-) diff --git a/deployment-configuration/helm/templates/auto-network-policies.yaml b/deployment-configuration/helm/templates/auto-network-policies.yaml index c3594b0b2..2416c78bc 100644 --- a/deployment-configuration/helm/templates/auto-network-policies.yaml +++ b/deployment-configuration/helm/templates/auto-network-policies.yaml @@ -118,14 +118,33 @@ spec: - port: 53 protocol: TCP {{- if and (eq .app.harness.database.type "postgres") .app.harness.database.postgres.operator }} - # Allow access to Kubernetes API server for CNPG cluster instance (database) pods + # Allow CNPG pods to reach the Kubernetes API server + {{- $apiCidrs := list }} + {{- $kubeSvc := (lookup "v1" "Service" "default" "kubernetes") }} + {{- $kubeEp := (lookup "v1" "Endpoints" "default" "kubernetes") }} + {{- if and $kubeSvc $kubeSvc.spec $kubeSvc.spec.clusterIP }} + {{- $apiCidrs = append $apiCidrs (printf "%s/32" $kubeSvc.spec.clusterIP) }} + {{- end }} + {{- if and $kubeEp $kubeEp.subsets }} + {{- range $subset := $kubeEp.subsets }} + {{- range $addr := $subset.addresses }} + {{- $apiCidrs = append $apiCidrs (printf "%s/32" $addr.ip) }} + {{- end }} + {{- end }} + {{- end }} + {{- /* Fall back to configured CIDRs when lookup returns nothing (e.g. helm template) */ -}} + {{- if not $apiCidrs }} + {{- $apiCidrs = .app.harness.database.postgres.apiServerCidr }} + {{- end }} + {{- range $cidr := $apiCidrs }} - to: - ipBlock: - cidr: 0.0.0.0/0 + cidr: {{ $cidr }} ports: - port: 443 protocol: TCP {{- end }} + {{- end }} {{- range $ns := $allowedNamespaces }} # Allow traffic to whitelisted namespace - to: diff --git a/deployment-configuration/value-template.yaml b/deployment-configuration/value-template.yaml index a7df95db7..fa34ca0a8 100644 --- a/deployment-configuration/value-template.yaml +++ b/deployment-configuration/value-template.yaml @@ -101,6 +101,9 @@ harness: operator: false # -- Number of PostgreSQL instances managed by the CNPG operator (only used when operator is true) instances: 1 + # -- CIDR(s) allowed for CNPG pods to reach the Kubernetes API server (port 443). + # -- Resolved automatically at deploy time via cluster lookup. Set explicitly only as a fallback for helm-template or air-gapped use. + apiServerCidr: [] ports: - name: http port: 5432 diff --git a/docs/applications/databases.md b/docs/applications/databases.md index 1e0e1ffc6..3704c3f2c 100644 --- a/docs/applications/databases.md +++ b/docs/applications/databases.md @@ -86,6 +86,7 @@ harness initialdb: cloudharness operator: false instances: 1 + apiServerCidr: [] ports: - name: http port: 5432 @@ -104,6 +105,8 @@ helm install cnpg cloudnative-pg/cloudnative-pg `instances`: Number of PostgreSQL instances (replicas) managed by the CNPG operator. Only used when `operator: true`. Default is 1. +`apiServerCidr`: List of CIDRs allowed for CNPG database pods to reach the Kubernetes API server on port 443. **Resolved automatically at deploy time** by looking up the `kubernetes` Service and Endpoints in the `default` namespace. The explicit list is only used as a fallback when lookup returns nothing (e.g. `helm template` dry-run). Leave empty (`[]`) for auto-detection; set explicitly only for air-gapped or restricted environments. + #### Neo4j diff --git a/docs/model/DatabaseConfig.md b/docs/model/DatabaseConfig.md index d22244860..4857965e7 100644 --- a/docs/model/DatabaseConfig.md +++ b/docs/model/DatabaseConfig.md @@ -11,6 +11,7 @@ Name | Type | Description | Notes **ports** | [**List[PortConfig]**](PortConfig.md) | | [optional] **operator** | **bool** | Use the CloudNative-PG operator instead of a plain Deployment (postgres only) | [optional] **instances** | **int** | Number of PostgreSQL instances managed by the CNPG operator (only used when operator is true) | [optional] +**api_server_cidr** | **List[str]** | CIDR(s) allowed for CNPG pods to reach the Kubernetes API server (port 443). Override with your cluster API-server or service CIDR. | [optional] **initialdb** | **str** | Initial database name (postgres only) | [optional] ## Example diff --git a/libraries/models/api/openapi.yaml b/libraries/models/api/openapi.yaml index 89d258a35..b9e7f8bc4 100644 --- a/libraries/models/api/openapi.yaml +++ b/libraries/models/api/openapi.yaml @@ -957,6 +957,11 @@ components: description: 'Number of PostgreSQL instances managed by the CNPG operator (only used when operator is true)' type: integer minimum: 1 + apiServerCidr: + description: 'CIDR(s) allowed for CNPG pods to reach the Kubernetes API server (port 443). Override with your cluster API-server or service CIDR.' + type: array + items: + type: string initialdb: description: 'Initial database name (postgres only)' type: string diff --git a/libraries/models/cloudharness_model/models/database_config.py b/libraries/models/cloudharness_model/models/database_config.py index 6b71a4564..79a62bbdf 100644 --- a/libraries/models/cloudharness_model/models/database_config.py +++ b/libraries/models/cloudharness_model/models/database_config.py @@ -36,9 +36,10 @@ class DatabaseConfig(CloudHarnessBaseModel): ports: Optional[List[PortConfig]] = None operator: Optional[StrictBool] = Field(default=None, description="Use the CloudNative-PG operator instead of a plain Deployment (postgres only)") instances: Optional[Annotated[int, Field(strict=True, ge=1)]] = Field(default=None, description="Number of PostgreSQL instances managed by the CNPG operator (only used when operator is true)") + api_server_cidr: Optional[List[StrictStr]] = Field(default=None, description="CIDR(s) allowed for CNPG pods to reach the Kubernetes API server (port 443). Override with your cluster API-server or service CIDR.", alias="apiServerCidr") initialdb: Optional[StrictStr] = Field(default=None, description="Initial database name (postgres only)") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["image", "name", "ports", "operator", "instances", "initialdb"] + __properties: ClassVar[List[str]] = ["image", "name", "ports", "operator", "instances", "apiServerCidr", "initialdb"] def to_dict(self) -> Dict[str, Any]: """Return the dictionary representation of the model using alias. @@ -89,6 +90,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "ports": [PortConfig.from_dict(_item) for _item in obj["ports"]] if obj.get("ports") is not None else None, "operator": obj.get("operator"), "instances": obj.get("instances"), + "apiServerCidr": obj.get("apiServerCidr"), "initialdb": obj.get("initialdb") }) # store additional fields in additional_properties diff --git a/libraries/models/docs/DatabaseConfig.md b/libraries/models/docs/DatabaseConfig.md index d22244860..4857965e7 100644 --- a/libraries/models/docs/DatabaseConfig.md +++ b/libraries/models/docs/DatabaseConfig.md @@ -11,6 +11,7 @@ Name | Type | Description | Notes **ports** | [**List[PortConfig]**](PortConfig.md) | | [optional] **operator** | **bool** | Use the CloudNative-PG operator instead of a plain Deployment (postgres only) | [optional] **instances** | **int** | Number of PostgreSQL instances managed by the CNPG operator (only used when operator is true) | [optional] +**api_server_cidr** | **List[str]** | CIDR(s) allowed for CNPG pods to reach the Kubernetes API server (port 443). Override with your cluster API-server or service CIDR. | [optional] **initialdb** | **str** | Initial database name (postgres only) | [optional] ## Example From 9f095818bcad770a9a359e500f9561bf12362212 Mon Sep 17 00:00:00 2001 From: Filippo Ledda Date: Fri, 20 Mar 2026 15:18:00 +0100 Subject: [PATCH 8/8] Fix template variable access issue "deploy_utils.database_network_policy" (dict "root" .root "app" .app)>: error calling include: template: mnp/templates/auto-network-policies.yaml:125:46: executing "deploy_utils.database_network_policy" at <$kubeSvc.spec.clusterIP>: nil pointer evaluating interface {}.clusterIP --- .../helm/templates/auto-network-policies.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/deployment-configuration/helm/templates/auto-network-policies.yaml b/deployment-configuration/helm/templates/auto-network-policies.yaml index 2416c78bc..63f5dc4c3 100644 --- a/deployment-configuration/helm/templates/auto-network-policies.yaml +++ b/deployment-configuration/helm/templates/auto-network-policies.yaml @@ -122,8 +122,12 @@ spec: {{- $apiCidrs := list }} {{- $kubeSvc := (lookup "v1" "Service" "default" "kubernetes") }} {{- $kubeEp := (lookup "v1" "Endpoints" "default" "kubernetes") }} - {{- if and $kubeSvc $kubeSvc.spec $kubeSvc.spec.clusterIP }} - {{- $apiCidrs = append $apiCidrs (printf "%s/32" $kubeSvc.spec.clusterIP) }} + {{- if $kubeSvc }} + {{- if $kubeSvc.spec }} + {{- if $kubeSvc.spec.clusterIP }} + {{- $apiCidrs = append $apiCidrs (printf "%s/32" $kubeSvc.spec.clusterIP) }} + {{- end }} + {{- end }} {{- end }} {{- if and $kubeEp $kubeEp.subsets }} {{- range $subset := $kubeEp.subsets }}