From cdb2128ed4dc52ab99b7afb5b7be2f36a2d69dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Gonz=C3=A1lez?= Date: Thu, 22 Jan 2026 11:31:09 +0100 Subject: [PATCH 1/7] feat: add support for secondary visibility store (dual visibility) Add support for secondaryVisibilityStore configuration to enable dual visibility feature in Temporal server. This allows writing to two visibility stores simultaneously for migration scenarios. Changes: - Add secondaryVisibilityStore support in temporal.persistence.filterConfig - Include secondaryVisibility in temporal.persistence.eachStore iteration - Add TEMPORAL_SECONDARY_VISIBILITY_STORE_PASSWORD env var to server pods - Automatically process secondary visibility store in schema jobs This implementation adapts PR #803 to the V1 chart architecture, leveraging the centralized helper functions introduced in V1 to avoid code duplication. Resolves: #803 --- charts/temporal/templates/_helpers.tpl | 7 +++++++ charts/temporal/templates/server-deployment.yaml | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/charts/temporal/templates/_helpers.tpl b/charts/temporal/templates/_helpers.tpl index 41fe651c..649a8856 100644 --- a/charts/temporal/templates/_helpers.tpl +++ b/charts/temporal/templates/_helpers.tpl @@ -140,6 +140,7 @@ app.kubernetes.io/part-of: {{ $global.Chart.Name }} {{- $config := deepCopy . -}} {{- $defaultStore := $config.defaultStore -}} {{- $visibilityStore := $config.visibilityStore -}} +{{- $secondaryVisibilityStore := $config.secondaryVisibilityStore | default "" -}} {{- $patchedDatastores := dict -}} {{- range $name, $ds := $config.datastores -}} {{- $dsCopy := deepCopy $ds -}} @@ -151,6 +152,8 @@ app.kubernetes.io/part-of: {{ $global.Chart.Name }} {{- $_ := set $storeConfig "password" "__ENV_TEMPORAL_DEFAULT_STORE_PASSWORD__" -}} {{- else if eq $name $visibilityStore -}} {{- $_ := set $storeConfig "password" "__ENV_TEMPORAL_VISIBILITY_STORE_PASSWORD__" -}} + {{- else if and $secondaryVisibilityStore (eq $name $secondaryVisibilityStore) -}} + {{- $_ := set $storeConfig "password" "__ENV_TEMPORAL_SECONDARY_VISIBILITY_STORE_PASSWORD__" -}} {{- else -}} {{- $_ := unset $storeConfig "password" -}} {{- end -}} @@ -168,6 +171,10 @@ app.kubernetes.io/part-of: {{ $global.Chart.Name }} {{- $stores := dict -}} {{- $_ := set $stores "default" (include "temporal.persistence.getStoreByType" (list $ "default") | fromYaml) -}} {{- $_ := set $stores "visibility" (include "temporal.persistence.getStoreByType" (list $ "visibility") | fromYaml) -}} +{{- if .Values.server.config.persistence.secondaryVisibilityStore -}} +{{- $secondaryVisibilityStoreName := .Values.server.config.persistence.secondaryVisibilityStore -}} +{{- $_ := set $stores "secondaryVisibility" (include "temporal.persistence.getStore" (list $ $secondaryVisibilityStoreName) | fromYaml) -}} +{{- end -}} {{- $stores | toYaml -}} {{- end -}} diff --git a/charts/temporal/templates/server-deployment.yaml b/charts/temporal/templates/server-deployment.yaml index 7af5c076..70ddd6eb 100644 --- a/charts/temporal/templates/server-deployment.yaml +++ b/charts/temporal/templates/server-deployment.yaml @@ -1,6 +1,10 @@ {{- if $.Values.server.enabled }} {{- $defaultStore := include "temporal.persistence.getStoreByType" (list $ "default") | fromYaml -}} {{- $visibilityStore := include "temporal.persistence.getStoreByType" (list $ "visibility") | fromYaml -}} +{{- $secondaryVisibilityStore := dict -}} +{{- if $.Values.server.config.persistence.secondaryVisibilityStore -}} +{{- $secondaryVisibilityStore = include "temporal.persistence.getStore" (list $ $.Values.server.config.persistence.secondaryVisibilityStore) | fromYaml -}} +{{- end -}} {{- range $service := (list "frontend" "internal-frontend" "history" "matching" "worker") }} {{- $serviceValues := index $.Values.server $service }} {{- if or (not (hasKey $serviceValues "enabled")) $serviceValues.enabled }} @@ -66,7 +70,15 @@ spec: {{- include "temporal.password-env" (list $ $defaultStore) | nindent 14 }} - name: TEMPORAL_VISIBILITY_STORE_PASSWORD {{- include "temporal.password-env" (list $ $visibilityStore) | nindent 14 }} +<<<<<<< HEAD {{- if (index $.Values.server "internal-frontend").enabled }} +======= + {{- if $.Values.server.config.persistence.secondaryVisibilityStore }} + - name: TEMPORAL_SECONDARY_VISIBILITY_STORE_PASSWORD + {{- include "temporal.password-env" (list $ $secondaryVisibilityStore) | nindent 14 }} + {{- end }} + {{- if and (hasKey $.Values.server "internalFrontend") $.Values.server.internalFrontend.enabled }} +>>>>>>> d02b74b (feat: add support for secondary visibility store (dual visibility)) - name: USE_INTERNAL_FRONTEND value: "1" {{- end }} From a8fab0cb57685a3e670c3f03afd27163561b91f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Gonz=C3=A1lez?= Date: Thu, 22 Jan 2026 11:35:43 +0100 Subject: [PATCH 2/7] test: add unit tests for secondary visibility store Add helm-unittest tests to verify: - ConfigMap contains secondaryVisibilityStore configuration - Secondary visibility password uses correct env var placeholder - Environment variable is injected when secondaryVisibilityStore is configured - Environment variable is not injected when secondaryVisibilityStore is absent --- .../temporal/tests/server_configmap_test.yaml | 56 ++++++++++++++++++ .../tests/server_deployment_test.yaml | 59 ++++++++++++++++++- 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/charts/temporal/tests/server_configmap_test.yaml b/charts/temporal/tests/server_configmap_test.yaml index 38fa524c..6810e223 100644 --- a/charts/temporal/tests/server_configmap_test.yaml +++ b/charts/temporal/tests/server_configmap_test.yaml @@ -134,3 +134,59 @@ tests: - matchRegex: path: data['config_template.yaml'] pattern: 'password: \{\{ env "TEMPORAL_VISIBILITY_STORE_PASSWORD" \| quote \}\}' + - it: handles secondary visibility store for dual visibility + set: + server: + enabled: true + config: + persistence: + defaultStore: default + visibilityStore: visibility + secondaryVisibilityStore: secondary-visibility + numHistoryShards: 512 + datastores: + default: + sql: + pluginName: mysql8 + driverName: mysql8 + databaseName: temporal + connectAddr: "mysql.example.com:3306" + user: temporal_user + password: "secret" + visibility: + elasticsearch: + version: v8 + url: + scheme: https + host: "elasticsearch.example.com:9200" + username: elastic + password: "secret" + indices: + visibility: temporal_visibility_v1 + secondary-visibility: + elasticsearch: + version: v8 + url: + scheme: https + host: "elasticsearch.example.com:9200" + username: elastic + password: "secret2" + indices: + visibility: temporal_visibility_v1_secondary + template: templates/server-configmap.yaml + documentSelector: + path: metadata.name + value: RELEASE-NAME-temporal-config + asserts: + - matchRegex: + path: data['config_template.yaml'] + pattern: 'secondaryVisibilityStore: secondary-visibility' + - matchRegex: + path: data['config_template.yaml'] + pattern: 'secondary-visibility:' + - matchRegex: + path: data['config_template.yaml'] + pattern: 'password: \{\{ env "TEMPORAL_SECONDARY_VISIBILITY_STORE_PASSWORD" \| quote \}\}' + - matchRegex: + path: data['config_template.yaml'] + pattern: 'visibility: temporal_visibility_v1_secondary' diff --git a/charts/temporal/tests/server_deployment_test.yaml b/charts/temporal/tests/server_deployment_test.yaml index 4ed9400f..bf909e36 100644 --- a/charts/temporal/tests/server_deployment_test.yaml +++ b/charts/temporal/tests/server_deployment_test.yaml @@ -295,6 +295,7 @@ tests: - equal: path: spec.template.spec.containers[0].readinessProbe.tcpSocket.port value: rpc + - it: additional environment variables are set on all services template: templates/server-deployment.yaml documentSelector: @@ -315,6 +316,62 @@ tests: - equal: path: spec.template.spec.containers[0].envFrom[0].secretRef.name value: secret-env - - equal: + - equal: path: spec.template.spec.containers[0].envFrom[1].configMapRef.name value: configmap-env + + - it: injects secondary visibility store password env var when configured + template: templates/server-deployment.yaml + set: + server: + config: + persistence: + defaultStore: default + visibilityStore: visibility + secondaryVisibilityStore: secondary-visibility + datastores: + default: + sql: + password: "secret" + visibility: + elasticsearch: + password: "secret" + secondary-visibility: + elasticsearch: + password: "secret2" + documentSelector: + path: metadata.name + value: RELEASE-NAME-temporal-frontend + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: TEMPORAL_SECONDARY_VISIBILITY_STORE_PASSWORD + valueFrom: + secretKeyRef: + name: RELEASE-NAME-secondary-visibility-store + key: password + + - it: does not inject secondary visibility env var when not configured + template: templates/server-deployment.yaml + set: + server: + config: + persistence: + defaultStore: default + visibilityStore: visibility + datastores: + default: + sql: + password: "secret" + visibility: + elasticsearch: + password: "secret" + documentSelector: + path: metadata.name + value: RELEASE-NAME-temporal-frontend + asserts: + - notContains: + path: spec.template.spec.containers[0].env + content: + name: TEMPORAL_SECONDARY_VISIBILITY_STORE_PASSWORD From 2c730f7ffffb54950d0a7118989cb49bf55a19c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Gonz=C3=A1lez?= Date: Fri, 23 Jan 2026 09:23:19 +0100 Subject: [PATCH 3/7] refactor: simplify secondaryVisibilityStore condition check Remove redundant check for in the conditional. When is empty, eq comparison will be false, making the extra 'and' check unnecessary. --- charts/temporal/templates/_helpers.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/temporal/templates/_helpers.tpl b/charts/temporal/templates/_helpers.tpl index 649a8856..e1a02af4 100644 --- a/charts/temporal/templates/_helpers.tpl +++ b/charts/temporal/templates/_helpers.tpl @@ -152,7 +152,7 @@ app.kubernetes.io/part-of: {{ $global.Chart.Name }} {{- $_ := set $storeConfig "password" "__ENV_TEMPORAL_DEFAULT_STORE_PASSWORD__" -}} {{- else if eq $name $visibilityStore -}} {{- $_ := set $storeConfig "password" "__ENV_TEMPORAL_VISIBILITY_STORE_PASSWORD__" -}} - {{- else if and $secondaryVisibilityStore (eq $name $secondaryVisibilityStore) -}} + {{- else if eq $name $secondaryVisibilityStore -}} {{- $_ := set $storeConfig "password" "__ENV_TEMPORAL_SECONDARY_VISIBILITY_STORE_PASSWORD__" -}} {{- else -}} {{- $_ := unset $storeConfig "password" -}} From b222fc986f1d079e2c4e5383b6302cbf98a9f9df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Gonz=C3=A1lez?= Date: Fri, 23 Jan 2026 09:32:13 +0100 Subject: [PATCH 4/7] refactor: handle unconfigured stores in getStoreByType Make getStoreByType return an empty dict when the store isn't configured, removing the need for special-case logic in eachStore. This treats secondaryVisibility consistently with other stores. This change: - Adds a check in getStoreByType to return empty dict if storeName is nil - Simplifies eachStore to use getStoreByType for all stores including secondary - Makes secondary visibility less of an exceptional case --- charts/temporal/templates/_helpers.tpl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/charts/temporal/templates/_helpers.tpl b/charts/temporal/templates/_helpers.tpl index e1a02af4..7774cbc9 100644 --- a/charts/temporal/templates/_helpers.tpl +++ b/charts/temporal/templates/_helpers.tpl @@ -171,9 +171,9 @@ app.kubernetes.io/part-of: {{ $global.Chart.Name }} {{- $stores := dict -}} {{- $_ := set $stores "default" (include "temporal.persistence.getStoreByType" (list $ "default") | fromYaml) -}} {{- $_ := set $stores "visibility" (include "temporal.persistence.getStoreByType" (list $ "visibility") | fromYaml) -}} -{{- if .Values.server.config.persistence.secondaryVisibilityStore -}} -{{- $secondaryVisibilityStoreName := .Values.server.config.persistence.secondaryVisibilityStore -}} -{{- $_ := set $stores "secondaryVisibility" (include "temporal.persistence.getStore" (list $ $secondaryVisibilityStoreName) | fromYaml) -}} +{{- $secondaryVisibility := include "temporal.persistence.getStoreByType" (list $ "secondaryVisibility") | fromYaml -}} +{{- if $secondaryVisibility -}} +{{- $_ := set $stores "secondaryVisibility" $secondaryVisibility -}} {{- end -}} {{- $stores | toYaml -}} {{- end -}} @@ -221,7 +221,11 @@ app.kubernetes.io/part-of: {{ $global.Chart.Name }} {{- $root := index . 0 -}} {{- $type := index . 1 -}} {{- $storeName := get $root.Values.server.config.persistence (printf "%sStore" $type) -}} +{{- if $storeName -}} {{- include "temporal.persistence.getStore" (list $root $storeName) -}} +{{- else -}} +{{- dict | toYaml -}} +{{- end -}} {{- end -}} {{- define "temporal.persistence.schema" -}} From da2298d320f406eaea69aa64b081f792dd110573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Gonz=C3=A1lez?= Date: Fri, 23 Jan 2026 11:28:46 +0100 Subject: [PATCH 5/7] fix: resolve merge conflict in server-deployment.yaml Remove unresolved conflict markers --- charts/temporal/templates/server-deployment.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/charts/temporal/templates/server-deployment.yaml b/charts/temporal/templates/server-deployment.yaml index 70ddd6eb..b1b95d6c 100644 --- a/charts/temporal/templates/server-deployment.yaml +++ b/charts/temporal/templates/server-deployment.yaml @@ -70,15 +70,11 @@ spec: {{- include "temporal.password-env" (list $ $defaultStore) | nindent 14 }} - name: TEMPORAL_VISIBILITY_STORE_PASSWORD {{- include "temporal.password-env" (list $ $visibilityStore) | nindent 14 }} -<<<<<<< HEAD - {{- if (index $.Values.server "internal-frontend").enabled }} -======= {{- if $.Values.server.config.persistence.secondaryVisibilityStore }} - name: TEMPORAL_SECONDARY_VISIBILITY_STORE_PASSWORD {{- include "temporal.password-env" (list $ $secondaryVisibilityStore) | nindent 14 }} {{- end }} - {{- if and (hasKey $.Values.server "internalFrontend") $.Values.server.internalFrontend.enabled }} ->>>>>>> d02b74b (feat: add support for secondary visibility store (dual visibility)) + {{- if (index $.Values.server "internal-frontend").enabled }} - name: USE_INTERNAL_FRONTEND value: "1" {{- end }} From f06ab887d297db19be64f08f299c3a3320ae3d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Gonz=C3=A1lez?= Date: Tue, 27 Jan 2026 17:29:50 +0100 Subject: [PATCH 6/7] refactor: simplify secondaryVisibilityStore handling in server-deployment Use getStoreByType for secondaryVisibility to be consistent with default and visibility stores. This removes special-case logic and makes the code cleaner by: - Using getStoreByType which returns empty dict when not configured - Checking $secondaryVisibilityStore variable instead of .Values path --- charts/temporal/templates/server-deployment.yaml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/charts/temporal/templates/server-deployment.yaml b/charts/temporal/templates/server-deployment.yaml index b1b95d6c..30ab593e 100644 --- a/charts/temporal/templates/server-deployment.yaml +++ b/charts/temporal/templates/server-deployment.yaml @@ -1,10 +1,7 @@ {{- if $.Values.server.enabled }} {{- $defaultStore := include "temporal.persistence.getStoreByType" (list $ "default") | fromYaml -}} {{- $visibilityStore := include "temporal.persistence.getStoreByType" (list $ "visibility") | fromYaml -}} -{{- $secondaryVisibilityStore := dict -}} -{{- if $.Values.server.config.persistence.secondaryVisibilityStore -}} -{{- $secondaryVisibilityStore = include "temporal.persistence.getStore" (list $ $.Values.server.config.persistence.secondaryVisibilityStore) | fromYaml -}} -{{- end -}} +{{- $secondaryVisibilityStore := include "temporal.persistence.getStoreByType" (list $ "secondaryVisibility") | fromYaml -}} {{- range $service := (list "frontend" "internal-frontend" "history" "matching" "worker") }} {{- $serviceValues := index $.Values.server $service }} {{- if or (not (hasKey $serviceValues "enabled")) $serviceValues.enabled }} @@ -70,7 +67,7 @@ spec: {{- include "temporal.password-env" (list $ $defaultStore) | nindent 14 }} - name: TEMPORAL_VISIBILITY_STORE_PASSWORD {{- include "temporal.password-env" (list $ $visibilityStore) | nindent 14 }} - {{- if $.Values.server.config.persistence.secondaryVisibilityStore }} + {{- if $secondaryVisibilityStore }} - name: TEMPORAL_SECONDARY_VISIBILITY_STORE_PASSWORD {{- include "temporal.password-env" (list $ $secondaryVisibilityStore) | nindent 14 }} {{- end }} From 046312ff544ae2d74b22a838f528f319b15fec4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20Gonz=C3=A1lez?= Date: Wed, 4 Feb 2026 09:10:38 +0100 Subject: [PATCH 7/7] fix: correct secret name in secondary visibility test The secret name should include 'temporal-' prefix to match the template output. --- charts/temporal/tests/server_deployment_test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/temporal/tests/server_deployment_test.yaml b/charts/temporal/tests/server_deployment_test.yaml index bf909e36..0ccc4a8e 100644 --- a/charts/temporal/tests/server_deployment_test.yaml +++ b/charts/temporal/tests/server_deployment_test.yaml @@ -349,7 +349,7 @@ tests: name: TEMPORAL_SECONDARY_VISIBILITY_STORE_PASSWORD valueFrom: secretKeyRef: - name: RELEASE-NAME-secondary-visibility-store + name: RELEASE-NAME-temporal-secondary-visibility-store key: password - it: does not inject secondary visibility env var when not configured