From a8569c8e8336f462bb135b82420f4051b629d1b3 Mon Sep 17 00:00:00 2001 From: akshatgoyal Date: Thu, 25 Jun 2026 15:09:04 +0530 Subject: [PATCH 1/3] #useservice-specific-secret --- CHANGELOG.md | 8 + ci/run-tests.sh | 1 + ci/test-chart/Chart.lock | 6 +- ci/test-chart/ci-values/services-secrets.yaml | 34 +++++ ci/test-chart/templates/services-secrets.yaml | 11 ++ src/common/Chart.yaml | 2 +- src/common/templates/_services.tpl | 138 ++++++++++++++---- 7 files changed, 170 insertions(+), 30 deletions(-) create mode 100644 ci/test-chart/ci-values/services-secrets.yaml create mode 100644 ci/test-chart/templates/services-secrets.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index a68413c..5f338d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [1.9.0] - 2026-06-25 + +### Added +- **Generic global service secrets**: Added `harnesscommon.services.renderServiceSecretsEnv` and `harnesscommon.services.generateServiceExternalSecrets`, which iterate over every entry under `global.services.` and render secrets (Kubernetes secrets + External Secrets Operator) as environment variables / `ExternalSecret` CRDs. Env var names are auto-derived from the declared secret keys, so any service can opt in by listing its secrets in `values.yaml`. Each service entry supports an optional `enabled` flag and a `ctxIdentifier` (ESO secret name prefix, defaults to the service key). + +### Removed +- `harnesscommon.services.rhsEnv` has been removed in favor of `harnesscommon.services.renderServiceSecretsEnv`. The only consumer (Resource Hierarchy Service) now uses the generic helper. + ## [1.8.0] - 2026-06-22 ### Added diff --git a/ci/run-tests.sh b/ci/run-tests.sh index 71b81b0..fe178ac 100755 --- a/ci/run-tests.sh +++ b/ci/run-tests.sh @@ -31,6 +31,7 @@ run_scenario "Gateway API (policies)" "${VALUES_DIR}/gateway-policies.yaml" run_scenario "Gateway API (headers)" "${VALUES_DIR}/gateway-headers.yaml" run_scenario "Gateway API (migration)" "${VALUES_DIR}/gateway-migration.yaml" run_scenario "Gateway API (per-route overrides)" "${VALUES_DIR}/gateway-per-route-override.yaml" +run_scenario "Service Secrets (generic)" "${VALUES_DIR}/services-secrets.yaml" echo "All template scenarios passed." echo "" diff --git a/ci/test-chart/Chart.lock b/ci/test-chart/Chart.lock index bb3b9b6..705af38 100644 --- a/ci/test-chart/Chart.lock +++ b/ci/test-chart/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: harness-common repository: file://../../src/common - version: 1.7.2 -digest: sha256:0ed6cadfefa49ca3a981733b86861bd32d129c9d8111838dfba28ebb6f48a930 -generated: "2026-05-18T10:51:34.093756-06:00" + version: 1.9.0 +digest: sha256:69be3b9b72b96db7a8c010c545eefe3e05288183e6def9b248d6f3f78dcf6241 +generated: "2026-06-25T15:06:48.267649+05:30" diff --git a/ci/test-chart/ci-values/services-secrets.yaml b/ci/test-chart/ci-values/services-secrets.yaml new file mode 100644 index 0000000..cfed809 --- /dev/null +++ b/ci/test-chart/ci-values/services-secrets.yaml @@ -0,0 +1,34 @@ +global: + services: + resourceHierarchy: + ctxIdentifier: resource-hierarchy-service + secrets: + kubernetesSecrets: [] + secretManagement: + externalSecretsOperator: + - secretStore: + name: my-store + kind: ClusterSecretStore + remoteKeys: + RESOURCE_HIERARCHY_SERVICE_SECRET: + name: rhs/secret + property: token + pipeline: + secrets: + kubernetesSecrets: + - secretName: pipeline-k8s-secret + keys: + PIPELINE_SERVICE_SECRET: pipeline-secret-key + secretManagement: + externalSecretsOperator: [] + disabledService: + enabled: false + secrets: + secretManagement: + externalSecretsOperator: + - secretStore: + name: my-store + kind: ClusterSecretStore + remoteKeys: + SHOULD_NOT_RENDER: + name: nope/secret diff --git a/ci/test-chart/templates/services-secrets.yaml b/ci/test-chart/templates/services-secrets.yaml new file mode 100644 index 0000000..25034c1 --- /dev/null +++ b/ci/test-chart/templates/services-secrets.yaml @@ -0,0 +1,11 @@ +{{- if and .Values.global .Values.global.services }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: services-env-test +data: + env: | +{{ include "harnesscommon.services.renderServiceSecretsEnv" (dict "ctx" $) | indent 4 }} +--- +{{- include "harnesscommon.services.generateServiceExternalSecrets" (dict "ctx" $) }} +{{- end }} diff --git a/src/common/Chart.yaml b/src/common/Chart.yaml index b3bcbb1..d08e4fe 100644 --- a/src/common/Chart.yaml +++ b/src/common/Chart.yaml @@ -15,7 +15,7 @@ type: library # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.8.0 +version: 1.9.0 # This is the version number of the application being deployed. This version number should be diff --git a/src/common/templates/_services.tpl b/src/common/templates/_services.tpl index 9a520bc..027dcc0 100644 --- a/src/common/templates/_services.tpl +++ b/src/common/templates/_services.tpl @@ -1,37 +1,123 @@ {{/* -Generate K8S Env Spec for Resource Hierarchy Service Secret +Resolve the ESO Secret Context Identifier for a global service entry. + +Uses the explicit `ctxIdentifier` field on the service entry when present, +otherwise falls back to the service key from `global.services`. USAGE: -{{- include "harnesscommon.services.rhsEnv" (dict "ctx" $ "variableName" "RESOURCE_HIERARCHY_SERVICE_SECRET") | indent 12 }} +{{- include "harnesscommon.services.esoSecretCtxIdentifier" (dict "ctx" $ "serviceKey" "resourceHierarchy" "serviceCtx" $serviceCtx) }} +*/}} +{{- define "harnesscommon.services.esoSecretCtxIdentifier" }} + {{- $ := .ctx }} + {{- $ctxIdentifier := default .serviceKey (dig "ctxIdentifier" "" .serviceCtx) }} + {{- include "harnesscommon.secrets.globalESOSecretCtxIdentifier" (dict "ctx" $ "ctxIdentifier" $ctxIdentifier) | trim }} +{{- end }} -PARAMETERS: -REQUIRED: -1. ctx - Helm context ($) +{{/* +Collect the unique secret keys declared for a service secrets context. -OPTIONAL: -1. variableName - Override the environment variable name (default: "RESOURCE_HIERARCHY_SERVICE_SECRET") +Inspects both `kubernetesSecrets[].keys` and +`secretManagement.externalSecretsOperator[].remoteKeys`. -EXAMPLE: -env: - {{- include "harnesscommon.services.rhsEnv" (dict "ctx" $) | indent 12 }} +USAGE: +{{- include "harnesscommon.services.secretKeys" (dict "secretsCtx" $serviceSecretsCtx) }} */}} -{{- define "harnesscommon.services.rhsEnv" }} +{{- define "harnesscommon.services.secretKeys" }} + {{- $secretKeys := list }} + {{- $secretsCtx := .secretsCtx }} + {{- range (dig "kubernetesSecrets" (list) $secretsCtx) }} + {{- range $key, $value := (dig "keys" (dict) .) }} + {{- $secretKeys = append $secretKeys $key }} + {{- end }} + {{- end }} + {{- range (dig "secretManagement" "externalSecretsOperator" (list) $secretsCtx) }} + {{- range $key, $value := (dig "remoteKeys" (dict) .) }} + {{- $secretKeys = append $secretKeys $key }} + {{- end }} + {{- end }} + {{- $secretKeys | uniq | join "," }} +{{- end }} + +{{/* +Generic: Render K8S Env Spec for all secrets declared by services under +`.Values.global.services`. + +For every enabled service entry, env vars are auto-derived from the declared +secret keys (Kubernetes secrets + ESO remoteKeys) and rendered using the +standard secret precedence (ESO > External K8S Secret > Default). + +Each service entry may optionally declare: + - enabled (default: true) whether to render the service secrets + - ctxIdentifier (default: ) prefix used for the ESO secret name + +VALUES SHAPE: +global: + services: + resourceHierarchy: + ctxIdentifier: resource-hierarchy-service + secrets: + kubernetesSecrets: [] + secretManagement: + externalSecretsOperator: [] + +USAGE: +{{- include "harnesscommon.services.renderServiceSecretsEnv" (dict "ctx" $) | indent 12 }} +*/}} +{{- define "harnesscommon.services.renderServiceSecretsEnv" }} {{- $ := .ctx }} - {{- $variableName := default "RESOURCE_HIERARCHY_SERVICE_SECRET" .variableName }} - {{- $globalServicesCtx := $.Values.global.services }} - {{- $rhsCtx := $globalServicesCtx.resourceHierarchy }} - - {{- if and $globalServicesCtx $rhsCtx }} - {{- $enabled := dig "enabled" true $rhsCtx }} - {{- if $enabled }} - {{- $globalESOSecretIdentifier := include "harnesscommon.secrets.globalESOSecretCtxIdentifier" (dict "ctx" $ "ctxIdentifier" "resource-hierarchy-service") }} - {{- include "harnesscommon.secrets.manageEnv" (dict - "ctx" $ - "variableName" "RESOURCE_HIERARCHY_SERVICE_SECRET" - "overrideEnvName" $variableName - "extKubernetesSecretCtxs" (list $rhsCtx.secrets.kubernetesSecrets) - "esoSecretCtxs" (list (dict "secretCtxIdentifier" $globalESOSecretIdentifier "secretCtx" $rhsCtx.secrets.secretManagement.externalSecretsOperator)) - ) }} + {{- $globalServicesCtx := dict }} + {{- if and $.Values.global $.Values.global.services }} + {{- $globalServicesCtx = $.Values.global.services }} + {{- end }} + {{- range $serviceKey, $serviceCtx := $globalServicesCtx }} + {{- if $serviceCtx }} + {{- $enabled := dig "enabled" true $serviceCtx }} + {{- $serviceSecretsCtx := dig "secrets" (dict) $serviceCtx }} + {{- if and $enabled $serviceSecretsCtx }} + {{- $globalESOSecretIdentifier := include "harnesscommon.services.esoSecretCtxIdentifier" (dict "ctx" $ "serviceKey" $serviceKey "serviceCtx" $serviceCtx) }} + {{- $extKubernetesSecretsCtx := dig "kubernetesSecrets" (list) $serviceSecretsCtx }} + {{- $esoSecretsCtx := dig "secretManagement" "externalSecretsOperator" (list) $serviceSecretsCtx }} + {{- $secretKeysStr := include "harnesscommon.services.secretKeys" (dict "secretsCtx" $serviceSecretsCtx) | trim }} + {{- if $secretKeysStr }} + {{- range $variableName := (splitList "," $secretKeysStr) }} + {{- include "harnesscommon.secrets.manageEnv" (dict + "ctx" $ + "variableName" $variableName + "extKubernetesSecretCtxs" (list $extKubernetesSecretsCtx) + "esoSecretCtxs" (list (dict "secretCtxIdentifier" $globalESOSecretIdentifier "secretCtx" $esoSecretsCtx)) + ) }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} + +{{/* +Generic: Generate ESO ExternalSecret CRDs for all services declared under +`.Values.global.services`. + +For every enabled service entry with valid ESO secrets, an ExternalSecret is +generated using the service's ESO secret context identifier as the name prefix. + +USAGE: +{{- include "harnesscommon.services.generateServiceExternalSecrets" (dict "ctx" $) }} +*/}} +{{- define "harnesscommon.services.generateServiceExternalSecrets" }} + {{- $ := .ctx }} + {{- $globalServicesCtx := dict }} + {{- if and $.Values.global $.Values.global.services }} + {{- $globalServicesCtx = $.Values.global.services }} + {{- end }} + {{- range $serviceKey, $serviceCtx := $globalServicesCtx }} + {{- if $serviceCtx }} + {{- $enabled := dig "enabled" true $serviceCtx }} + {{- $serviceSecretsCtx := dig "secrets" (dict) $serviceCtx }} + {{- if and $enabled (eq (include "harnesscommon.secrets.hasESOSecrets" (dict "secretsCtx" $serviceSecretsCtx)) "true") }} + {{- $globalESOSecretIdentifier := include "harnesscommon.services.esoSecretCtxIdentifier" (dict "ctx" $ "serviceKey" $serviceKey "serviceCtx" $serviceCtx) }} + {{- include "harnesscommon.secrets.generateExternalSecret" (dict "secretsCtx" $serviceSecretsCtx "secretNamePrefix" $globalESOSecretIdentifier) }} + {{- print "\n---" }} + {{- end }} {{- end }} {{- end }} {{- end }} From 61c1ef15b1e401a4d783abecf2896a6bddad0c61 Mon Sep 17 00:00:00 2001 From: akshatgoyal Date: Thu, 25 Jun 2026 15:43:12 +0530 Subject: [PATCH 2/3] #review-comments --- CHANGELOG.md | 5 +- ci/test-chart/ci-values/services-secrets.yaml | 4 ++ src/common/Chart.yaml | 2 +- src/common/templates/_services.tpl | 72 +++++++++++++++---- 4 files changed, 68 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f338d8..e5eca4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ # Changelog -## [1.9.0] - 2026-06-25 +## [1.8.1] - 2026-06-25 ### Added -- **Generic global service secrets**: Added `harnesscommon.services.renderServiceSecretsEnv` and `harnesscommon.services.generateServiceExternalSecrets`, which iterate over every entry under `global.services.` and render secrets (Kubernetes secrets + External Secrets Operator) as environment variables / `ExternalSecret` CRDs. Env var names are auto-derived from the declared secret keys, so any service can opt in by listing its secrets in `values.yaml`. Each service entry supports an optional `enabled` flag and a `ctxIdentifier` (ESO secret name prefix, defaults to the service key). +- **Generic global service secrets**: Added `harnesscommon.services.renderServiceSecretsEnv` and `harnesscommon.services.generateServiceExternalSecrets`, which render secrets (Kubernetes secrets + External Secrets Operator) declared under `global.services.` as environment variables / `ExternalSecret` CRDs. Env var names are auto-derived from the declared secret keys, so any service can opt in by listing its secrets in `values.yaml`. Each service entry supports an optional `enabled` flag and a `ctxIdentifier` (ESO secret name prefix, defaults to the service key). +- **Dependency filtering**: Both helpers are scoped by a chart-level `serviceSecretDependencies` list (or an explicit `services` argument). A workload only receives the credentials of the services it declares as dependencies; with no dependencies declared, nothing is rendered. This prevents global service credentials from leaking into every workload and avoids duplicate `ExternalSecret` resources across charts in a shared namespace. Resolved via `harnesscommon.services.dependencies`. ### Removed - `harnesscommon.services.rhsEnv` has been removed in favor of `harnesscommon.services.renderServiceSecretsEnv`. The only consumer (Resource Hierarchy Service) now uses the generic helper. diff --git a/ci/test-chart/ci-values/services-secrets.yaml b/ci/test-chart/ci-values/services-secrets.yaml index cfed809..de29b8c 100644 --- a/ci/test-chart/ci-values/services-secrets.yaml +++ b/ci/test-chart/ci-values/services-secrets.yaml @@ -1,3 +1,7 @@ +# Only resourceHierarchy is a declared dependency: pipeline (a defined but +# non-dependency service) must NOT be rendered, proving the filter works. +serviceSecretDependencies: + - resourceHierarchy global: services: resourceHierarchy: diff --git a/src/common/Chart.yaml b/src/common/Chart.yaml index d08e4fe..6e98d30 100644 --- a/src/common/Chart.yaml +++ b/src/common/Chart.yaml @@ -15,7 +15,7 @@ type: library # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.9.0 +version: 1.8.1 # This is the version number of the application being deployed. This version number should be diff --git a/src/common/templates/_services.tpl b/src/common/templates/_services.tpl index 027dcc0..2e84b53 100644 --- a/src/common/templates/_services.tpl +++ b/src/common/templates/_services.tpl @@ -39,18 +39,47 @@ USAGE: {{- end }} {{/* -Generic: Render K8S Env Spec for all secrets declared by services under -`.Values.global.services`. +Resolve the list of global service keys a chart depends on. -For every enabled service entry, env vars are auto-derived from the declared -secret keys (Kubernetes secrets + ESO remoteKeys) and rendered using the -standard secret precedence (ESO > External K8S Secret > Default). +The dependency list is sourced (in precedence order) from: + 1. an explicit `services` argument (list), when provided + 2. `.Values.serviceSecretDependencies` (list) -Each service entry may optionally declare: +Returns a comma-joined string of service keys (empty when no dependencies are +declared). This is the filter that ensures a workload only receives the +credentials of the services it actually depends on. + +USAGE: +{{- include "harnesscommon.services.dependencies" (dict "ctx" $) }} +*/}} +{{- define "harnesscommon.services.dependencies" }} + {{- $ := .ctx }} + {{- $dependencies := .services }} + {{- if not $dependencies }} + {{- $dependencies = ($.Values.serviceSecretDependencies | default (list)) }} + {{- end }} + {{- $dependencies | join "," }} +{{- end }} + +{{/* +Generic: Render K8S Env Spec for the secrets of the services a chart depends on. + +For every dependency declared via `.Values.serviceSecretDependencies` (or the +optional `services` argument), env vars are auto-derived from that service's +declared secret keys (Kubernetes secrets + ESO remoteKeys) and rendered using +the standard secret precedence (ESO > External K8S Secret > Default). + +Services NOT listed as a dependency are skipped, so a workload never receives +credentials it does not depend on. When no dependencies are declared, nothing +is rendered. + +Each service entry under `global.services` may optionally declare: - enabled (default: true) whether to render the service secrets - ctxIdentifier (default: ) prefix used for the ESO secret name VALUES SHAPE: +serviceSecretDependencies: + - resourceHierarchy global: services: resourceHierarchy: @@ -62,6 +91,7 @@ global: USAGE: {{- include "harnesscommon.services.renderServiceSecretsEnv" (dict "ctx" $) | indent 12 }} +{{- include "harnesscommon.services.renderServiceSecretsEnv" (dict "ctx" $ "services" (list "resourceHierarchy")) | indent 12 }} */}} {{- define "harnesscommon.services.renderServiceSecretsEnv" }} {{- $ := .ctx }} @@ -69,8 +99,13 @@ USAGE: {{- if and $.Values.global $.Values.global.services }} {{- $globalServicesCtx = $.Values.global.services }} {{- end }} + {{- $dependenciesStr := include "harnesscommon.services.dependencies" (dict "ctx" $ "services" .services) | trim }} + {{- $dependencies := list }} + {{- if $dependenciesStr }} + {{- $dependencies = splitList "," $dependenciesStr }} + {{- end }} {{- range $serviceKey, $serviceCtx := $globalServicesCtx }} - {{- if $serviceCtx }} + {{- if and $serviceCtx (has $serviceKey $dependencies) }} {{- $enabled := dig "enabled" true $serviceCtx }} {{- $serviceSecretsCtx := dig "secrets" (dict) $serviceCtx }} {{- if and $enabled $serviceSecretsCtx }} @@ -94,14 +129,22 @@ USAGE: {{- end }} {{/* -Generic: Generate ESO ExternalSecret CRDs for all services declared under -`.Values.global.services`. +Generic: Generate ESO ExternalSecret CRDs for the services a chart is responsible +for materializing. + +Like the env helper, the set of services is filtered by +`.Values.serviceSecretDependencies` (or the optional `services` argument), so a +chart only emits the ExternalSecret CRDs it needs. This prevents multiple charts +in a shared namespace from emitting duplicate ExternalSecret resources with the +same name. -For every enabled service entry with valid ESO secrets, an ExternalSecret is -generated using the service's ESO secret context identifier as the name prefix. +For every filtered, enabled service entry with valid ESO secrets, an +ExternalSecret is generated using the service's ESO secret context identifier as +the name prefix. USAGE: {{- include "harnesscommon.services.generateServiceExternalSecrets" (dict "ctx" $) }} +{{- include "harnesscommon.services.generateServiceExternalSecrets" (dict "ctx" $ "services" (list "resourceHierarchy")) }} */}} {{- define "harnesscommon.services.generateServiceExternalSecrets" }} {{- $ := .ctx }} @@ -109,8 +152,13 @@ USAGE: {{- if and $.Values.global $.Values.global.services }} {{- $globalServicesCtx = $.Values.global.services }} {{- end }} + {{- $dependenciesStr := include "harnesscommon.services.dependencies" (dict "ctx" $ "services" .services) | trim }} + {{- $dependencies := list }} + {{- if $dependenciesStr }} + {{- $dependencies = splitList "," $dependenciesStr }} + {{- end }} {{- range $serviceKey, $serviceCtx := $globalServicesCtx }} - {{- if $serviceCtx }} + {{- if and $serviceCtx (has $serviceKey $dependencies) }} {{- $enabled := dig "enabled" true $serviceCtx }} {{- $serviceSecretsCtx := dig "secrets" (dict) $serviceCtx }} {{- if and $enabled (eq (include "harnesscommon.secrets.hasESOSecrets" (dict "secretsCtx" $serviceSecretsCtx)) "true") }} From 6cb8b03971fae81872c6568b3306447cfd6267a3 Mon Sep 17 00:00:00 2001 From: akshatgoyal Date: Fri, 26 Jun 2026 09:25:43 +0530 Subject: [PATCH 3/3] #fix --- CHANGELOG.md | 1 + ci/test-chart/Chart.lock | 6 +++--- src/common/templates/_services.tpl | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5eca4d..a906a6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added - **Generic global service secrets**: Added `harnesscommon.services.renderServiceSecretsEnv` and `harnesscommon.services.generateServiceExternalSecrets`, which render secrets (Kubernetes secrets + External Secrets Operator) declared under `global.services.` as environment variables / `ExternalSecret` CRDs. Env var names are auto-derived from the declared secret keys, so any service can opt in by listing its secrets in `values.yaml`. Each service entry supports an optional `enabled` flag and a `ctxIdentifier` (ESO secret name prefix, defaults to the service key). - **Dependency filtering**: Both helpers are scoped by a chart-level `serviceSecretDependencies` list (or an explicit `services` argument). A workload only receives the credentials of the services it declares as dependencies; with no dependencies declared, nothing is rendered. This prevents global service credentials from leaking into every workload and avoids duplicate `ExternalSecret` resources across charts in a shared namespace. Resolved via `harnesscommon.services.dependencies`. +- **RFC-1123 safe ESO names**: `harnesscommon.services.esoSecretCtxIdentifier` now kebab-cases the resolved identifier, so a camelCase service key (e.g. `resourceHierarchy`) yields a valid lowercase `ExternalSecret` name (`resource-hierarchy-ext-secret-0`) even when no `ctxIdentifier` is set. ### Removed - `harnesscommon.services.rhsEnv` has been removed in favor of `harnesscommon.services.renderServiceSecretsEnv`. The only consumer (Resource Hierarchy Service) now uses the generic helper. diff --git a/ci/test-chart/Chart.lock b/ci/test-chart/Chart.lock index 705af38..f1b1fa7 100644 --- a/ci/test-chart/Chart.lock +++ b/ci/test-chart/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: harness-common repository: file://../../src/common - version: 1.9.0 -digest: sha256:69be3b9b72b96db7a8c010c545eefe3e05288183e6def9b248d6f3f78dcf6241 -generated: "2026-06-25T15:06:48.267649+05:30" + version: 1.8.1 +digest: sha256:89dc9f243c922edca78a670defa3d355f8cbd4cf9ade1f03a45f308bd649ff5c +generated: "2026-06-25T15:42:54.138257+05:30" diff --git a/src/common/templates/_services.tpl b/src/common/templates/_services.tpl index 2e84b53..cf6b4a1 100644 --- a/src/common/templates/_services.tpl +++ b/src/common/templates/_services.tpl @@ -10,6 +10,8 @@ USAGE: {{- define "harnesscommon.services.esoSecretCtxIdentifier" }} {{- $ := .ctx }} {{- $ctxIdentifier := default .serviceKey (dig "ctxIdentifier" "" .serviceCtx) }} + {{- /* Normalize to a valid lowercase RFC-1123 name (e.g. camelCase service keys like "resourceHierarchy" -> "resource-hierarchy"). */}} + {{- $ctxIdentifier = $ctxIdentifier | kebabcase }} {{- include "harnesscommon.secrets.globalESOSecretCtxIdentifier" (dict "ctx" $ "ctxIdentifier" $ctxIdentifier) | trim }} {{- end }}