diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1df7900825f..4caa1dee417 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -265,8 +265,6 @@ All PR titles should start with Upper case and have no dot at the end. and [base-builder](https://github.com/temporalio/docker-builds/blob/main/docker/base-images/base-builder.Dockerfile)~~ **Note:** The docker-builds repository is now deprecated and will be archived. - - ## License MIT License, please see [LICENSE](LICENSE) for details. diff --git a/common/config/config_template_embedded.yaml b/common/config/config_template_embedded.yaml index dbb4b33e2ec..68c66ec0a96 100644 --- a/common/config/config_template_embedded.yaml +++ b/common/config/config_template_embedded.yaml @@ -1,163 +1,162 @@ # enable-template -# TODO: Remove this file after temporalio/docker-builds repository is archived log: stdout: true - level: {{ default .Env.LOG_LEVEL "info" }} + level: {{ default "info" (env "LOG_LEVEL") }} persistence: - numHistoryShards: {{ default .Env.NUM_HISTORY_SHARDS "4" }} + numHistoryShards: {{ default "4" (env "NUM_HISTORY_SHARDS") }} defaultStore: default - {{- $es := default .Env.ENABLE_ES "false" | lower -}} + {{- $es := default "false" (env "ENABLE_ES") | lower -}} {{- if eq $es "true" }} visibilityStore: es-visibility {{- else }} visibilityStore: visibility {{- end }} datastores: - {{- $db := default .Env.DB "cassandra" | lower -}} + {{- $db := default "cassandra" (env "DB") | lower -}} {{- if eq $db "cassandra" }} default: cassandra: - hosts: "{{ default .Env.CASSANDRA_SEEDS "" }}" - keyspace: "{{ default .Env.KEYSPACE "temporal" }}" - user: "{{ default .Env.CASSANDRA_USER "" }}" - password: "{{ default .Env.CASSANDRA_PASSWORD "" }}" - {{- if .Env.CASSANDRA_ALLOWED_AUTHENTICATORS }} - allowedAuthenticators: {{ range split .Env.CASSANDRA_ALLOWED_AUTHENTICATORS "," }} + hosts: "{{ default "" (env "CASSANDRA_SEEDS") }}" + keyspace: "{{ default "temporal" (env "KEYSPACE") }}" + user: "{{ default "" (env "CASSANDRA_USER") }}" + password: "{{ default "" (env "CASSANDRA_PASSWORD") }}" + {{- if env "CASSANDRA_ALLOWED_AUTHENTICATORS" }} + allowedAuthenticators: {{ range split (env "CASSANDRA_ALLOWED_AUTHENTICATORS") "," }} - {{trim .}} {{- end }} {{- end }} - port: {{ default .Env.CASSANDRA_PORT "9042" }} - maxConns: {{ default .Env.CASSANDRA_MAX_CONNS "20" }} + port: {{ default "9042" (env "CASSANDRA_PORT") }} + maxConns: {{ default "20" (env "CASSANDRA_MAX_CONNS") }} tls: - enabled: {{ default .Env.CASSANDRA_TLS_ENABLED "false" }} - caFile: {{ default .Env.CASSANDRA_CA "" }} - certFile: {{ default .Env.CASSANDRA_CERT "" }} - keyFile: {{ default .Env.CASSANDRA_CERT_KEY "" }} - caData: {{ default .Env.CASSANDRA_CA_DATA "" }} - certData: {{ default .Env.CASSANDRA_CERT_DATA "" }} - keyData: {{ default .Env.CASSANDRA_CERT_KEY_DATA "" }} - enableHostVerification: {{ default .Env.CASSANDRA_HOST_VERIFICATION "false" }} - serverName: {{ default .Env.CASSANDRA_HOST_NAME "" }} - {{- if .Env.CASSANDRA_ADDRESS_TRANSLATOR }} + enabled: {{ default "false" (env "CASSANDRA_TLS_ENABLED") }} + caFile: {{ default "" (env "CASSANDRA_CA") }} + certFile: {{ default "" (env "CASSANDRA_CERT") }} + keyFile: {{ default "" (env "CASSANDRA_CERT_KEY") }} + caData: {{ default "" (env "CASSANDRA_CA_DATA") }} + certData: {{ default "" (env "CASSANDRA_CERT_DATA") }} + keyData: {{ default "" (env "CASSANDRA_CERT_KEY_DATA") }} + enableHostVerification: {{ default "false" (env "CASSANDRA_HOST_VERIFICATION") }} + serverName: {{ default "" (env "CASSANDRA_HOST_NAME") }} + {{- if env "CASSANDRA_ADDRESS_TRANSLATOR" }} addressTranslator: - translator: {{ default .Env.CASSANDRA_ADDRESS_TRANSLATOR "" }} - {{- if .Env.CASSANDRA_ADDRESS_TRANSLATOR_OPTIONS }} + translator: {{ default "" (env "CASSANDRA_ADDRESS_TRANSLATOR") }} + {{- if env "CASSANDRA_ADDRESS_TRANSLATOR_OPTIONS" }} options: - advertised-hostname: {{ default .Env.CASSANDRA_ADDRESS_TRANSLATOR_OPTIONS "" }} + advertised-hostname: {{ default "" (env "CASSANDRA_ADDRESS_TRANSLATOR_OPTIONS") }} {{- end }} {{- end }} {{- else if eq $db "mysql8" }} default: sql: pluginName: "{{ $db }}" - databaseName: "{{ default .Env.DBNAME "temporal" }}" - connectAddr: "{{ default .Env.MYSQL_SEEDS "" }}:{{ default .Env.DB_PORT "3306" }}" + databaseName: "{{ default "temporal" (env "DBNAME") }}" + connectAddr: "{{ default "" (env "MYSQL_SEEDS") }}:{{ default "3306" (env "DB_PORT") }}" connectProtocol: "tcp" - user: "{{ default .Env.MYSQL_USER "" }}" - password: "{{ default .Env.MYSQL_PWD "" }}" - {{- if .Env.MYSQL_TX_ISOLATION_COMPAT }} + user: "{{ default "" (env "MYSQL_USER") }}" + password: "{{ default "" (env "MYSQL_PWD") }}" + {{- if env "MYSQL_TX_ISOLATION_COMPAT" }} connectAttributes: tx_isolation: "'READ-COMMITTED'" {{- end }} - maxConns: {{ default .Env.SQL_MAX_CONNS "20" }} - maxIdleConns: {{ default .Env.SQL_MAX_IDLE_CONNS "20" }} - maxConnLifetime: {{ default .Env.SQL_MAX_CONN_TIME "1h" }} + maxConns: {{ default "20" (env "SQL_MAX_CONNS") }} + maxIdleConns: {{ default "20" (env "SQL_MAX_IDLE_CONNS") }} + maxConnLifetime: {{ default "1h" (env "SQL_MAX_CONN_TIME") }} tls: - enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} - caFile: {{ default .Env.SQL_CA "" }} - certFile: {{ default .Env.SQL_CERT "" }} - keyFile: {{ default .Env.SQL_CERT_KEY "" }} - enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} - serverName: {{ default .Env.SQL_HOST_NAME "" }} + enabled: {{ default "false" (env "SQL_TLS_ENABLED") }} + caFile: {{ default "" (env "SQL_CA") }} + certFile: {{ default "" (env "SQL_CERT") }} + keyFile: {{ default "" (env "SQL_CERT_KEY") }} + enableHostVerification: {{ default "false" (env "SQL_HOST_VERIFICATION") }} + serverName: {{ default "" (env "SQL_HOST_NAME") }} visibility: sql: - {{ $visibility_seeds_default := default .Env.MYSQL_SEEDS "" }} - {{ $visibility_seeds := default .Env.VISIBILITY_MYSQL_SEEDS $visibility_seeds_default }} - {{ $visibility_port_default := default .Env.DB_PORT "3306" }} - {{ $visibility_port := default .Env.VISIBILITY_DB_PORT $visibility_port_default }} - {{ $visibility_user_default := default .Env.MYSQL_USER "" }} - {{ $visibility_user := default .Env.VISIBILITY_MYSQL_USER $visibility_user_default }} - {{ $visibility_pwd_default := default .Env.MYSQL_PWD "" }} - {{ $visibility_pwd := default .Env.VISIBILITY_MYSQL_PWD $visibility_pwd_default }} + {{ $visibility_seeds_default := default "" (env "MYSQL_SEEDS") }} + {{ $visibility_seeds := default $visibility_seeds_default (env "VISIBILITY_MYSQL_SEEDS") }} + {{ $visibility_port_default := default "3306" (env "DB_PORT") }} + {{ $visibility_port := default $visibility_port_default (env "VISIBILITY_DB_PORT") }} + {{ $visibility_user_default := default "" (env "MYSQL_USER") }} + {{ $visibility_user := default $visibility_user_default (env "VISIBILITY_MYSQL_USER") }} + {{ $visibility_pwd_default := default "" (env "MYSQL_PWD") }} + {{ $visibility_pwd := default $visibility_pwd_default (env "VISIBILITY_MYSQL_PWD") }} pluginName: "{{ $db }}" - databaseName: "{{ default .Env.VISIBILITY_DBNAME "temporal_visibility" }}" + databaseName: "{{ default "temporal_visibility" (env "VISIBILITY_DBNAME") }}" connectAddr: "{{ $visibility_seeds }}:{{ $visibility_port }}" connectProtocol: "tcp" user: "{{ $visibility_user }}" password: "{{ $visibility_pwd }}" - {{- if .Env.MYSQL_TX_ISOLATION_COMPAT }} + {{- if env "MYSQL_TX_ISOLATION_COMPAT" }} connectAttributes: tx_isolation: "'READ-COMMITTED'" {{- end }} - maxConns: {{ default .Env.SQL_VIS_MAX_CONNS "10" }} - maxIdleConns: {{ default .Env.SQL_VIS_MAX_IDLE_CONNS "10" }} - maxConnLifetime: {{ default .Env.SQL_VIS_MAX_CONN_TIME "1h" }} + maxConns: {{ default "10" (env "SQL_VIS_MAX_CONNS") }} + maxIdleConns: {{ default "10" (env "SQL_VIS_MAX_IDLE_CONNS") }} + maxConnLifetime: {{ default "1h" (env "SQL_VIS_MAX_CONN_TIME") }} tls: - enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} - caFile: {{ default .Env.SQL_CA "" }} - certFile: {{ default .Env.SQL_CERT "" }} - keyFile: {{ default .Env.SQL_CERT_KEY "" }} - enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} - serverName: {{ default .Env.SQL_HOST_NAME "" }} + enabled: {{ default "false" (env "SQL_TLS_ENABLED") }} + caFile: {{ default "" (env "SQL_CA") }} + certFile: {{ default "" (env "SQL_CERT") }} + keyFile: {{ default "" (env "SQL_CERT_KEY") }} + enableHostVerification: {{ default "false" (env "SQL_HOST_VERIFICATION") }} + serverName: {{ default "" (env "SQL_HOST_NAME") }} {{- else if eq $db "postgres12" "postgres12_pgx" }} default: sql: pluginName: "{{ $db }}" - databaseName: "{{ default .Env.DBNAME "temporal" }}" - connectAddr: "{{ default .Env.POSTGRES_SEEDS "" }}:{{ default .Env.DB_PORT "5432" }}" + databaseName: "{{ default "temporal" (env "DBNAME") }}" + connectAddr: "{{ default "" (env "POSTGRES_SEEDS") }}:{{ default "5432" (env "DB_PORT") }}" connectProtocol: "tcp" - user: "{{ default .Env.POSTGRES_USER "" }}" - password: "{{ default .Env.POSTGRES_PWD "" }}" - maxConns: {{ default .Env.SQL_MAX_CONNS "20" }} - maxIdleConns: {{ default .Env.SQL_MAX_IDLE_CONNS "20" }} - maxConnLifetime: {{ default .Env.SQL_MAX_CONN_TIME "1h" }} + user: "{{ default "" (env "POSTGRES_USER") }}" + password: "{{ default "" (env "POSTGRES_PWD") }}" + maxConns: {{ default "20" (env "SQL_MAX_CONNS") }} + maxIdleConns: {{ default "20" (env "SQL_MAX_IDLE_CONNS") }} + maxConnLifetime: {{ default "1h" (env "SQL_MAX_CONN_TIME") }} tls: - enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} - caFile: {{ default .Env.SQL_CA "" }} - certFile: {{ default .Env.SQL_CERT "" }} - keyFile: {{ default .Env.SQL_CERT_KEY "" }} - enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} - serverName: {{ default .Env.SQL_HOST_NAME "" }} + enabled: {{ default "false" (env "SQL_TLS_ENABLED") }} + caFile: {{ default "" (env "SQL_CA") }} + certFile: {{ default "" (env "SQL_CERT") }} + keyFile: {{ default "" (env "SQL_CERT_KEY") }} + enableHostVerification: {{ default "false" (env "SQL_HOST_VERIFICATION") }} + serverName: {{ default "" (env "SQL_HOST_NAME") }} visibility: sql: - {{ $visibility_seeds_default := default .Env.POSTGRES_SEEDS "" }} - {{ $visibility_seeds := default .Env.VISIBILITY_POSTGRES_SEEDS $visibility_seeds_default }} - {{ $visibility_port_default := default .Env.DB_PORT "5432" }} - {{ $visibility_port := default .Env.VISIBILITY_DB_PORT $visibility_port_default }} - {{ $visibility_user_default := default .Env.POSTGRES_USER "" }} - {{ $visibility_user := default .Env.VISIBILITY_POSTGRES_USER $visibility_user_default }} - {{ $visibility_pwd_default := default .Env.POSTGRES_PWD "" }} - {{ $visibility_pwd := default .Env.VISIBILITY_POSTGRES_PWD $visibility_pwd_default }} + {{ $visibility_seeds_default := default "" (env "POSTGRES_SEEDS") }} + {{ $visibility_seeds := default $visibility_seeds_default (env "VISIBILITY_POSTGRES_SEEDS") }} + {{ $visibility_port_default := default "5432" (env "DB_PORT") }} + {{ $visibility_port := default $visibility_port_default (env "VISIBILITY_DB_PORT") }} + {{ $visibility_user_default := default "" (env "POSTGRES_USER") }} + {{ $visibility_user := default $visibility_user_default (env "VISIBILITY_POSTGRES_USER") }} + {{ $visibility_pwd_default := default "" (env "POSTGRES_PWD") }} + {{ $visibility_pwd := default $visibility_pwd_default (env "VISIBILITY_POSTGRES_PWD") }} pluginName: "{{ $db }}" - databaseName: "{{ default .Env.VISIBILITY_DBNAME "temporal_visibility" }}" + databaseName: "{{ default "temporal_visibility" (env "VISIBILITY_DBNAME") }}" connectAddr: "{{ $visibility_seeds }}:{{ $visibility_port }}" connectProtocol: "tcp" user: "{{ $visibility_user }}" password: "{{ $visibility_pwd }}" - maxConns: {{ default .Env.SQL_VIS_MAX_CONNS "10" }} - maxIdleConns: {{ default .Env.SQL_VIS_MAX_IDLE_CONNS "10" }} - maxConnLifetime: {{ default .Env.SQL_VIS_MAX_CONN_TIME "1h" }} + maxConns: {{ default "10" (env "SQL_VIS_MAX_CONNS") }} + maxIdleConns: {{ default "10" (env "SQL_VIS_MAX_IDLE_CONNS") }} + maxConnLifetime: {{ default "1h" (env "SQL_VIS_MAX_CONN_TIME") }} tls: - enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} - caFile: {{ default .Env.SQL_CA "" }} - certFile: {{ default .Env.SQL_CERT "" }} - keyFile: {{ default .Env.SQL_CERT_KEY "" }} - enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} - serverName: {{ default .Env.SQL_HOST_NAME "" }} + enabled: {{ default "false" (env "SQL_TLS_ENABLED") }} + caFile: {{ default "" (env "SQL_CA") }} + certFile: {{ default "" (env "SQL_CERT") }} + keyFile: {{ default "" (env "SQL_CERT_KEY") }} + enableHostVerification: {{ default "false" (env "SQL_HOST_VERIFICATION") }} + serverName: {{ default "" (env "SQL_HOST_NAME") }} {{- end }} {{- if eq $es "true" }} es-visibility: elasticsearch: - version: {{ default .Env.ES_VERSION "" }} + version: {{ default "" (env "ES_VERSION") }} url: - scheme: {{ default .Env.ES_SCHEME "http" }} - host: "{{ default .Env.ES_SEEDS "" }}:{{ default .Env.ES_PORT "9200" }}" - username: "{{ default .Env.ES_USER "" }}" - password: "{{ default .Env.ES_PWD "" }}" + scheme: {{ default "http" (env "ES_SCHEME") }} + host: "{{ default "" (env "ES_SEEDS") }}:{{ default "9200" (env "ES_PORT") }}" + username: "{{ default "" (env "ES_USER") }}" + password: "{{ default "" (env "ES_PWD") }}" indices: - visibility: "{{ default .Env.ES_VIS_INDEX "temporal_visibility_v1_dev" }}" - {{- $es_sec_vis_index := default .Env.ES_SEC_VIS_INDEX "" -}} + visibility: "{{ default "temporal_visibility_v1_dev" (env "ES_VIS_INDEX") }}" + {{- $es_sec_vis_index := default "" (env "ES_SEC_VIS_INDEX") -}} {{- if ne $es_sec_vis_index "" }} secondary_visibility: "{{ $es_sec_vis_index }}" {{- end }} @@ -166,147 +165,147 @@ persistence: global: membership: maxJoinDuration: 30s - broadcastAddress: "{{ default .Env.TEMPORAL_BROADCAST_ADDRESS "" }}" + broadcastAddress: "{{ default "" (env "TEMPORAL_BROADCAST_ADDRESS") }}" pprof: - port: {{ default .Env.PPROF_PORT "0" }} + port: {{ default "0" (env "PPROF_PORT") }} tls: - refreshInterval: {{ default .Env.TEMPORAL_TLS_REFRESH_INTERVAL "0s" }} + refreshInterval: {{ default "0s" (env "TEMPORAL_TLS_REFRESH_INTERVAL") }} expirationChecks: - warningWindow: {{ default .Env.TEMPORAL_TLS_EXPIRATION_CHECKS_WARNING_WINDOW "0s" }} - errorWindow: {{ default .Env.TEMPORAL_TLS_EXPIRATION_CHECKS_ERROR_WINDOW "0s" }} - checkInterval: {{ default .Env.TEMPORAL_TLS_EXPIRATION_CHECKS_CHECK_INTERVAL "0s" }} + warningWindow: {{ default "0s" (env "TEMPORAL_TLS_EXPIRATION_CHECKS_WARNING_WINDOW") }} + errorWindow: {{ default "0s" (env "TEMPORAL_TLS_EXPIRATION_CHECKS_ERROR_WINDOW") }} + checkInterval: {{ default "0s" (env "TEMPORAL_TLS_EXPIRATION_CHECKS_CHECK_INTERVAL") }} internode: # This server section configures the TLS certificate that internal temporal # cluster nodes (history, matching, and internal-frontend) present to other # clients within the Temporal Cluster. server: - requireClientAuth: {{ default .Env.TEMPORAL_TLS_REQUIRE_CLIENT_AUTH "false" }} + requireClientAuth: {{ default "false" (env "TEMPORAL_TLS_REQUIRE_CLIENT_AUTH") }} - certFile: {{ default .Env.TEMPORAL_TLS_SERVER_CERT "" }} - keyFile: {{ default .Env.TEMPORAL_TLS_SERVER_KEY "" }} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT }} + certFile: {{ default "" (env "TEMPORAL_TLS_SERVER_CERT") }} + keyFile: {{ default "" (env "TEMPORAL_TLS_SERVER_KEY") }} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT" }} clientCaFiles: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT") }} {{- end }} - certData: {{ default .Env.TEMPORAL_TLS_SERVER_CERT_DATA "" }} - keyData: {{ default .Env.TEMPORAL_TLS_SERVER_KEY_DATA "" }} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA }} + certData: {{ default "" (env "TEMPORAL_TLS_SERVER_CERT_DATA") }} + keyData: {{ default "" (env "TEMPORAL_TLS_SERVER_KEY_DATA") }} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT_DATA" }} clientCaData: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT_DATA") }} {{- end }} # This client section is used to configure the TLS clients within # the Temporal Cluster that connect to an Internode (history, matching, or # internal-frontend) client: - serverName: {{ default .Env.TEMPORAL_TLS_INTERNODE_SERVER_NAME "" }} - disableHostVerification: {{ default .Env.TEMPORAL_TLS_INTERNODE_DISABLE_HOST_VERIFICATION "false"}} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT }} + serverName: {{ default "" (env "TEMPORAL_TLS_INTERNODE_SERVER_NAME") }} + disableHostVerification: {{ default "false" (env "TEMPORAL_TLS_INTERNODE_DISABLE_HOST_VERIFICATION")}} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT" }} rootCaFiles: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT") }} {{- end }} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA }} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT_DATA" }} rootCaData: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT_DATA") }} {{- end }} frontend: # This server section configures the TLS certificate that the Frontend # server presents to external clients. server: - requireClientAuth: {{ default .Env.TEMPORAL_TLS_REQUIRE_CLIENT_AUTH "false" }} - certFile: {{ default .Env.TEMPORAL_TLS_FRONTEND_CERT "" }} - keyFile: {{ default .Env.TEMPORAL_TLS_FRONTEND_KEY "" }} - {{- if .Env.TEMPORAL_TLS_CLIENT1_CA_CERT }} + requireClientAuth: {{ default "false" (env "TEMPORAL_TLS_REQUIRE_CLIENT_AUTH") }} + certFile: {{ default "" (env "TEMPORAL_TLS_FRONTEND_CERT") }} + keyFile: {{ default "" (env "TEMPORAL_TLS_FRONTEND_KEY") }} + {{- if env "TEMPORAL_TLS_CLIENT1_CA_CERT" }} clientCaFiles: - - {{ default .Env.TEMPORAL_TLS_CLIENT1_CA_CERT "" }} - - {{ default .Env.TEMPORAL_TLS_CLIENT2_CA_CERT "" }} + - {{ default "" (env "TEMPORAL_TLS_CLIENT1_CA_CERT") }} + - {{ default "" (env "TEMPORAL_TLS_CLIENT2_CA_CERT") }} {{- end }} - certData: {{ default .Env.TEMPORAL_TLS_FRONTEND_CERT_DATA "" }} - keyData: {{ default .Env.TEMPORAL_TLS_FRONTEND_KEY_DATA "" }} - {{- if .Env.TEMPORAL_TLS_CLIENT1_CA_CERT_DATA }} + certData: {{ default "" (env "TEMPORAL_TLS_FRONTEND_CERT_DATA") }} + keyData: {{ default "" (env "TEMPORAL_TLS_FRONTEND_KEY_DATA") }} + {{- if env "TEMPORAL_TLS_CLIENT1_CA_CERT_DATA" }} clientCaData: - - {{ default .Env.TEMPORAL_TLS_CLIENT1_CA_CERT_DATA "" }} - - {{ default .Env.TEMPORAL_TLS_CLIENT2_CA_CERT_DATA "" }} + - {{ default "" (env "TEMPORAL_TLS_CLIENT1_CA_CERT_DATA") }} + - {{ default "" (env "TEMPORAL_TLS_CLIENT2_CA_CERT_DATA") }} {{- end }} # This client section is used to configure the TLS clients within # the Temporal Cluster (specifically the Worker role) that connect to the Frontend service client: - serverName: {{ default .Env.TEMPORAL_TLS_FRONTEND_SERVER_NAME "" }} - disableHostVerification: {{ default .Env.TEMPORAL_TLS_FRONTEND_DISABLE_HOST_VERIFICATION "false"}} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT }} + serverName: {{ default "" (env "TEMPORAL_TLS_FRONTEND_SERVER_NAME") }} + disableHostVerification: {{ default "false" (env "TEMPORAL_TLS_FRONTEND_DISABLE_HOST_VERIFICATION")}} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT" }} rootCaFiles: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT") }} {{- end }} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA }} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT_DATA" }} rootCaData: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT_DATA") }} {{- end }} - {{- if .Env.STATSD_ENDPOINT }} + {{- if env "STATSD_ENDPOINT" }} metrics: statsd: - hostPort: {{ .Env.STATSD_ENDPOINT }} + hostPort: {{ env "STATSD_ENDPOINT" }} prefix: "temporal" - {{- else if .Env.PROMETHEUS_ENDPOINT }} + {{- else if env "PROMETHEUS_ENDPOINT" }} metrics: prometheus: - timerType: {{ default .Env.PROMETHEUS_TIMER_TYPE "histogram" }} - listenAddress: "{{ .Env.PROMETHEUS_ENDPOINT }}" + timerType: {{ default "histogram" (env "PROMETHEUS_TIMER_TYPE") }} + listenAddress: "{{ env "PROMETHEUS_ENDPOINT" }}" {{- end }} authorization: jwtKeyProvider: keySourceURIs: - {{- if .Env.TEMPORAL_JWT_KEY_SOURCE1 }} - - {{ default .Env.TEMPORAL_JWT_KEY_SOURCE1 "" }} + {{- if env "TEMPORAL_JWT_KEY_SOURCE1" }} + - {{ default "" (env "TEMPORAL_JWT_KEY_SOURCE1") }} {{- end }} - {{- if .Env.TEMPORAL_JWT_KEY_SOURCE2 }} - - {{ default .Env.TEMPORAL_JWT_KEY_SOURCE2 "" }} + {{- if env "TEMPORAL_JWT_KEY_SOURCE2" }} + - {{ default "" (env "TEMPORAL_JWT_KEY_SOURCE2") }} {{- end }} - refreshInterval: {{ default .Env.TEMPORAL_JWT_KEY_REFRESH "1m" }} - permissionsClaimName: {{ default .Env.TEMPORAL_JWT_PERMISSIONS_CLAIM "permissions" }} - permissionsRegex: {{ default .Env.TEMPORAL_JWT_PERMISSIONS_REGEX "" }} - authorizer: {{ default .Env.TEMPORAL_AUTH_AUTHORIZER "" }} - claimMapper: {{ default .Env.TEMPORAL_AUTH_CLAIM_MAPPER "" }} + refreshInterval: {{ default "1m" (env "TEMPORAL_JWT_KEY_REFRESH") }} + permissionsClaimName: {{ default "permissions" (env "TEMPORAL_JWT_PERMISSIONS_CLAIM") }} + permissionsRegex: {{ default "" (env "TEMPORAL_JWT_PERMISSIONS_REGEX") }} + authorizer: {{ default "" (env "TEMPORAL_AUTH_AUTHORIZER") }} + claimMapper: {{ default "" (env "TEMPORAL_AUTH_CLAIM_MAPPER") }} -{{- $temporalGrpcPort := default .Env.FRONTEND_GRPC_PORT "7233" }} -{{- $temporalHTTPPort := default .Env.FRONTEND_HTTP_PORT "7243" }} -{{- $temporalInternalHTTPPort := default .Env.INTERNAL_FRONTEND_HTTP_PORT "7246" }} +{{- $temporalGrpcPort := default "7233" (env "FRONTEND_GRPC_PORT") }} +{{- $temporalHTTPPort := default "7243" (env "FRONTEND_HTTP_PORT") }} +{{- $temporalInternalHTTPPort := default "7246" (env "INTERNAL_FRONTEND_HTTP_PORT") }} services: frontend: rpc: grpcPort: {{ $temporalGrpcPort }} - membershipPort: {{ default .Env.FRONTEND_MEMBERSHIP_PORT "6933" }} - bindOnIP: "{{ default .Env.BIND_ON_IP "127.0.0.1" }}" + membershipPort: {{ default "6933" (env "FRONTEND_MEMBERSHIP_PORT") }} + bindOnIP: "{{ default "127.0.0.1" (env "BIND_ON_IP") }}" httpPort: {{ $temporalHTTPPort }} - {{- if .Env.USE_INTERNAL_FRONTEND }} + {{- if env "USE_INTERNAL_FRONTEND" }} internal-frontend: rpc: - grpcPort: {{ default .Env.INTERNAL_FRONTEND_GRPC_PORT "7236" }} - membershipPort: {{ default .Env.INTERNAL_FRONTEND_MEMBERSHIP_PORT "6936" }} - bindOnIP: "{{ default .Env.BIND_ON_IP "127.0.0.1" }}" + grpcPort: {{ default "7236" (env "INTERNAL_FRONTEND_GRPC_PORT") }} + membershipPort: {{ default "6936" (env "INTERNAL_FRONTEND_MEMBERSHIP_PORT") }} + bindOnIP: "{{ default "127.0.0.1" (env "BIND_ON_IP") }}" httpPort: {{ $temporalInternalHTTPPort }} {{- end }} matching: rpc: - grpcPort: {{ default .Env.MATCHING_GRPC_PORT "7235" }} - membershipPort: {{ default .Env.MATCHING_MEMBERSHIP_PORT "6935" }} - bindOnIP: "{{ default .Env.BIND_ON_IP "127.0.0.1" }}" + grpcPort: {{ default "7235" (env "MATCHING_GRPC_PORT") }} + membershipPort: {{ default "6935" (env "MATCHING_MEMBERSHIP_PORT") }} + bindOnIP: "{{ default "127.0.0.1" (env "BIND_ON_IP") }}" history: rpc: - grpcPort: {{ default .Env.HISTORY_GRPC_PORT "7234" }} - membershipPort: {{ default .Env.HISTORY_MEMBERSHIP_PORT "6934" }} - bindOnIP: "{{ default .Env.BIND_ON_IP "127.0.0.1" }}" + grpcPort: {{ default "7234" (env "HISTORY_GRPC_PORT") }} + membershipPort: {{ default "6934" (env "HISTORY_MEMBERSHIP_PORT") }} + bindOnIP: "{{ default "127.0.0.1" (env "BIND_ON_IP") }}" worker: rpc: - grpcPort: {{ default .Env.WORKER_GRPC_PORT "7239" }} - membershipPort: {{ default .Env.WORKER_MEMBERSHIP_PORT "6939" }} - bindOnIP: "{{ default .Env.BIND_ON_IP "127.0.0.1" }}" + grpcPort: {{ default "7239" (env "WORKER_GRPC_PORT") }} + membershipPort: {{ default "6939" (env "WORKER_MEMBERSHIP_PORT") }} + bindOnIP: "{{ default "127.0.0.1" (env "BIND_ON_IP") }}" clusterMetadata: enableGlobalNamespace: false @@ -349,15 +348,15 @@ namespaceDefaults: state: "disabled" URI: "file:///tmp/temporal_vis_archival/development" -{{- if or (.Env.USE_INTERNAL_FRONTEND) (and (not .Env.TEMPORAL_AUTH_AUTHORIZER) (not .Env.TEMPORAL_AUTH_CLAIM_MAPPER)) }} +{{- if or (env "USE_INTERNAL_FRONTEND") (and (not (env "TEMPORAL_AUTH_AUTHORIZER")) (not (env "TEMPORAL_AUTH_CLAIM_MAPPER"))) }} {{/* publicClient is not needed with internal frontend, or if not using authorizer + claim mapper */}} {{- else }} -{{ $publicIp := default .Env.BIND_ON_IP "127.0.0.1" -}} +{{ $publicIp := default "127.0.0.1" (env "BIND_ON_IP") -}} {{- $defaultPublicHostPost := (print $publicIp ":" $temporalGrpcPort) -}} publicClient: - hostPort: "{{ default .Env.PUBLIC_FRONTEND_ADDRESS $defaultPublicHostPost }}" + hostPort: "{{ default $defaultPublicHostPost (env "PUBLIC_FRONTEND_ADDRESS") }}" {{- end }} dynamicConfigClient: - filepath: "{{ default .Env.DYNAMIC_CONFIG_FILE_PATH "/etc/temporal/config/dynamicconfig/docker.yaml" }}" + filepath: "{{ default "/etc/temporal/config/dynamicconfig/docker.yaml" (env "DYNAMIC_CONFIG_FILE_PATH") }}" pollInterval: "60s" diff --git a/common/config/config_test.go b/common/config/config_test.go index be4fba752d2..1ed42ebfda6 100644 --- a/common/config/config_test.go +++ b/common/config/config_test.go @@ -2,6 +2,7 @@ package config import ( "os" + "strings" "testing" "github.com/stretchr/testify/require" @@ -13,17 +14,31 @@ func TestToString(t *testing.T) { require.NotEmpty(t, cfg.String()) } -func TestEmbeddedTemplateOnlyDiffersFromDockerByComment(t *testing.T) { - embeddedContent, err := os.ReadFile("config_template_embedded.yaml") +func TestEmbeddedTemplateConsistentWithDockerTemplate(t *testing.T) { + embeddedBytes, err := os.ReadFile("config_template_embedded.yaml") require.NoError(t, err) - dockerContent, err := os.ReadFile("../../docker/config_template.yaml") + embeddedFiltered := skipComments(embeddedBytes, 3) + dockerBytes, err := os.ReadFile("../../docker/config_template.yaml") require.NoError(t, err) + dockerFiltered := skipComments(dockerBytes, 3) + require.Equal(t, embeddedFiltered, dockerFiltered, "embedded template does not match docker template") - dockerWithComment := "# enable-template\n" + string(dockerContent) +} + +func skipComments(fb []byte, first int) string { + lines := strings.Split(string(fb), "\n") + i := 0 + var filtered []string + for i < first && i < len(lines) { - require.Equal(t, dockerWithComment, string(embeddedContent), - "Embedded template (config_template_embedded.yaml) must only differ from docker template "+ - "(docker/config_template.yaml) by the '# enable-template' comment at the top. "+ - "This comment is required for the config loader to detect and process the template.") + if strings.HasPrefix(strings.TrimSpace(lines[i]), "#") { + i++ + continue + } + filtered = append(filtered, strings.TrimSpace(lines[i])) + i++ + } + filtered = append(filtered, lines[i:]...) + return strings.Join(filtered, "\n") } diff --git a/common/config/loader.go b/common/config/loader.go index bc5eae90149..9085d60340a 100644 --- a/common/config/loader.go +++ b/common/config/loader.go @@ -64,7 +64,6 @@ type loadOptions struct { zone string configFilePath string useEmbeddedOnly bool - envMap map[string]string } type loadOption func(*loadOptions) @@ -117,31 +116,19 @@ func WithEmbedded() loadOption { } } -// WithEnvMap provides a custom environment variable map for template rendering. -// If not provided, the loader will use os.Environ() to populate environment variables. -func WithEnvMap(envMap map[string]string) loadOption { - return func(o *loadOptions) { - if envMap != nil { - o.envMap = envMap - } - } -} - // Load loads and validates the Temporal server configuration. // It supports multiple loading strategies based on the provided options: // - Embedded template with environment variables (WithEmbedded) // - Single config file (WithConfigFile) // - Legacy hierarchical config directory (WithConfigDir, WithEnv, WithZone) // -// Configuration files can be templated using Go template syntax with dockerize-compatible +// Configuration files can be templated using Go template syntax with sprig-compatible // functions. To enable templating, add "# enable-template" comment in the first 1KB of the file. // // Returns the loaded configuration or an error if loading or validation fails. func Load(opts ...loadOption) (*Config, error) { cfg := &Config{} - options := &loadOptions{ - envMap: loadEnvMap(), - } + options := &loadOptions{} for _, opt := range opts { opt(options) @@ -154,13 +141,10 @@ func Load(opts ...loadOption) (*Config, error) { } func (opts *loadOptions) load(config any) error { - if opts.envMap == nil { - opts.envMap = loadEnvMap() - } if opts.useEmbeddedOnly { stdlog.Println("Loading configuration from environment variables only") - return loadAndUnmarshalContent(embeddedConfigTemplate, "config_template_embedded.yaml", opts.envMap, config) + return loadAndUnmarshalContent(embeddedConfigTemplate, "config_template_embedded.yaml", config) } if opts.configFilePath != "" { @@ -168,7 +152,7 @@ func (opts *loadOptions) load(config any) error { if err != nil { return err } - return loadAndUnmarshalContent(content, filepath.Base(opts.configFilePath), opts.envMap, config) + return loadAndUnmarshalContent(content, filepath.Base(opts.configFilePath), config) } return opts.loadLegacy(config) @@ -215,7 +199,7 @@ func (opts *loadOptions) loadLegacy(config any) error { return err } - processedData, err := processConfigFile(data, filepath.Base(f), opts.envMap) + processedData, err := processConfigFile(data, filepath.Base(f)) if err != nil { return err } @@ -240,7 +224,7 @@ func readConfigFile(path string) ([]byte, error) { } // processConfigFile processes a config file, rendering it as a template if enabled -func processConfigFile(data []byte, filename string, envMap map[string]string) ([]byte, error) { +func processConfigFile(data []byte, filename string) ([]byte, error) { // If the config file contains "enable-template" in a comment within the first 1KB, then // we will treat the file as a template and render it. templating, err := checkTemplatingEnabled(data) @@ -253,74 +237,13 @@ func processConfigFile(data []byte, filename string, envMap map[string]string) ( } stdlog.Printf("Processing config file as template; filename=%v\n", filename) - return renderTemplate(data, filename, envMap) -} - -// templateContext mimics dockerize's Context struct to support .Env.VAR_NAME syntax. -// In dockerize, .Env is a method that returns the environment map, allowing dot-based access. -type templateContext struct { - envMap map[string]string -} - -// Env returns the environment variable map, matching dockerize's Context.Env() method. -// This allows templates to use .Env.VAR_NAME syntax for environment variable access. -func (c *templateContext) Env() map[string]string { - return c.envMap -} - -// defaultValue implements dockerize-compatible default handling. -// This properly handles nil values from missing map keys when using .Env.VAR syntax. -// Args order: value first, default second (e.g., {{ default .Env.VAR "fallback" }}) -func defaultValue(args ...any) (string, error) { - if len(args) == 0 { - return "", errors.New("default called with no values") - } - - if len(args) > 0 { - if args[0] != nil { - val, ok := args[0].(string) - if !ok { - return "", errors.New("first argument is not a string") - } - return val, nil - } - } - - if len(args) > 1 { - if args[1] == nil { - return "", errors.New("default called with nil default value") - } - - val, ok := args[1].(string) - if !ok { - return "", errors.New("default is not a string value, hint: surround it w/ double quotes") - } - - return val, nil - } - - return "", errors.New("default called with no default value") -} - -// renderTemplate renders a config file as a Go template with environment variables. -// It uses dockerize-compatible template functions and supports .Env.VAR syntax. -func renderTemplate(data []byte, filename string, envMap map[string]string) ([]byte, error) { - templateFuncs := sprig.FuncMap() - // Override sprig's default with dockerize's implementation that properly handles - // nil values from missing environment variables - templateFuncs["default"] = defaultValue - - // Create a context with Env() method that returns the environment map - // Templates access environment variables using .Env.VAR_NAME syntax - ctx := &templateContext{envMap: envMap} - - tpl, err := template.New(filename).Funcs(templateFuncs).Parse(string(data)) + tpl, err := template.New(filename).Funcs(sprig.FuncMap()).Parse(string(data)) if err != nil { return nil, err } var rendered bytes.Buffer - err = tpl.Execute(&rendered, ctx) + err = tpl.Execute(&rendered, nil) if err != nil { return nil, err } @@ -328,8 +251,8 @@ func renderTemplate(data []byte, filename string, envMap map[string]string) ([]b return rendered.Bytes(), nil } -func loadAndUnmarshalContent(content []byte, filename string, envMap map[string]string, config any) error { - processed, err := processConfigFile(content, filename, envMap) +func loadAndUnmarshalContent(content []byte, filename string, config any) error { + processed, err := processConfigFile(content, filename) if err != nil { return fmt.Errorf("failed to process config file %s: %w", filename, err) } diff --git a/common/config/loader_test.go b/common/config/loader_test.go index 23a237aee93..ec0fc1c8033 100644 --- a/common/config/loader_test.go +++ b/common/config/loader_test.go @@ -12,82 +12,6 @@ import ( const fileMode = os.FileMode(0644) -func TestRenderTemplateWithEnvVars(t *testing.T) { - templateContent := []byte(`# enable-template -log: - level: {{ default .Env.LOG_LEVEL "info" }} -persistence: - numHistoryShards: {{ default .Env.NUM_HISTORY_SHARDS "4" }}`) - - testCases := []struct { - name string - envMap map[string]string - expectedLogLevel string - expectedNumShards string - }{ - { - name: "with environment variables set", - envMap: map[string]string{ - "LOG_LEVEL": "debug", - "NUM_HISTORY_SHARDS": "8", - }, - expectedLogLevel: "debug", - expectedNumShards: "8", - }, - { - name: "with no environment variables - uses defaults", - envMap: map[string]string{}, - expectedLogLevel: "info", - expectedNumShards: "4", - }, - { - name: "with partial environment variables", - envMap: map[string]string{ - "LOG_LEVEL": "warn", - }, - expectedLogLevel: "warn", - expectedNumShards: "4", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - rendered, err := renderTemplate(templateContent, "test.yaml", tc.envMap) - require.NoError(t, err) - - renderedStr := string(rendered) - require.Contains(t, renderedStr, "level: "+tc.expectedLogLevel) - require.Contains(t, renderedStr, "numHistoryShards: "+tc.expectedNumShards) - }) - } -} - -func TestProcessConfigFile(t *testing.T) { - content := []byte(`log: - level: info`) - - envMap := map[string]string{"LOG_LEVEL": "debug"} - processed, err := processConfigFile(content, "test.yaml", envMap) - require.NoError(t, err) - require.Equal(t, content, processed) -} - -func TestLoadWithEmbeddedTemplate(t *testing.T) { - envMap := map[string]string{ - "DB": "postgres12", - "POSTGRES_SEEDS": "localhost", - } - - cfg, err := Load(WithEmbedded(), WithEnvMap(envMap)) - require.NoError(t, err) - - // Verify embedded template loaded with defaults - require.Equal(t, "info", cfg.Log.Level) - require.Equal(t, int32(4), cfg.Persistence.NumHistoryShards) - require.NotNil(t, cfg.Services["frontend"]) - require.Equal(t, 7233, cfg.Services["frontend"].RPC.GRPCPort) -} - func TestLoad(t *testing.T) { const staticConfig = `log: level: warn @@ -110,9 +34,9 @@ services: const templateConfig = `# enable-template log: - level: {{ default .Env.LOG_LEVEL "info" }} + level: {{ default "info" (env "LOG_LEVEL") }} persistence: - numHistoryShards: {{ default .Env.NUM_HISTORY_SHARDS "4" }} + numHistoryShards: {{ default "4" (env "NUM_HISTORY_SHARDS") }} defaultStore: default datastores: default: @@ -124,7 +48,7 @@ persistence: services: frontend: rpc: - grpcPort: {{ default .Env.FRONTEND_GRPC_PORT "7233" }} + grpcPort: {{ default "7233" (env "FRONTEND_GRPC_PORT") }} bindOnIP: "127.0.0.1" ` @@ -156,37 +80,6 @@ services: require.Equal(t, 9233, cfg.Services["frontend"].RPC.GRPCPort) }, }, - { - name: "template config with custom env vars", - configContent: templateConfig, - loadOptions: func(configPath string) []loadOption { - envMap := map[string]string{ - "LOG_LEVEL": "debug", - "NUM_HISTORY_SHARDS": "8", - "FRONTEND_GRPC_PORT": "8233", - } - return []loadOption{WithConfigDir(filepath.Dir(configPath)), WithEnvMap(envMap)} - }, - expectError: false, - validateConfig: func(t *testing.T, cfg *Config) { - require.Equal(t, "debug", cfg.Log.Level) - require.Equal(t, int32(8), cfg.Persistence.NumHistoryShards) - require.Equal(t, 8233, cfg.Services["frontend"].RPC.GRPCPort) - }, - }, - { - name: "template config uses defaults when env vars not set", - configContent: templateConfig, - loadOptions: func(configPath string) []loadOption { - return []loadOption{WithConfigDir(filepath.Dir(configPath))} - }, - expectError: false, - validateConfig: func(t *testing.T, cfg *Config) { - require.Equal(t, "info", cfg.Log.Level) - require.Equal(t, int32(4), cfg.Persistence.NumHistoryShards) - require.Equal(t, 7233, cfg.Services["frontend"].RPC.GRPCPort) - }, - }, { name: "template config with file path uses system env vars", configContent: templateConfig, diff --git a/common/config/template_coverage_test.go b/common/config/template_coverage_test.go index b8b6e379441..d912156bec0 100644 --- a/common/config/template_coverage_test.go +++ b/common/config/template_coverage_test.go @@ -1,227 +1 @@ package config - -import ( - "reflect" - "strings" - "testing" - - "github.com/stretchr/testify/require" - "gopkg.in/yaml.v3" -) - -func TestEmbeddedTemplateCoversAllConfigFields(t *testing.T) { - envMap := make(map[string]string) - - rendered, err := processConfigFile(embeddedConfigTemplate, "config_template_embedded.yaml", envMap) - require.NoError(t, err) - - var templateData map[string]any - err = yaml.Unmarshal(rendered, &templateData) - require.NoError(t, err) - - // Recursively validate all fields in the Config struct and its nested structs - validateStructFields(t, reflect.TypeOf(Config{}), templateData, "") -} - -// validateStructFields recursively validates that all required fields in a struct type -// are present in the corresponding YAML template data -func validateStructFields(t *testing.T, structType reflect.Type, templateData map[string]any, path string) { - t.Helper() - - for i := 0; i < structType.NumField(); i++ { - field := structType.Field(i) - yamlTag := field.Tag.Get("yaml") - - // Skip fields without yaml tags or explicitly excluded - if yamlTag == "" || yamlTag == "-" { - continue - } - - yamlFieldName := strings.Split(yamlTag, ",")[0] - fieldPath := yamlFieldName - if path != "" { - fieldPath = path + "." + yamlFieldName - } - - validateTag := field.Tag.Get("validate") - isRequired := strings.Contains(validateTag, "nonzero") - - fieldData, exists := templateData[yamlFieldName] - - if isRequired && !exists { - t.Errorf("REQUIRED field '%s' (yaml:'%s') is missing from embedded template at path '%s'", - field.Name, yamlFieldName, fieldPath) - } else if !exists { - t.Logf("Optional field '%s' (yaml:'%s') not in embedded template at path '%s' (this is OK)", - field.Name, yamlFieldName, fieldPath) - continue - } - - // Recursively validate nested structs - fieldType := field.Type - // Dereference pointers - if fieldType.Kind() == reflect.Ptr { - fieldType = fieldType.Elem() - } - - switch fieldType.Kind() { - case reflect.Struct: - // Only recurse if we have nested map data - if nestedMap, ok := fieldData.(map[string]any); ok { - validateStructFields(t, fieldType, nestedMap, fieldPath) - } - case reflect.Map: - // For maps like Services, validate the value type if it's a struct - if fieldType.Elem().Kind() == reflect.Struct { - if mapData, ok := fieldData.(map[string]any); ok { - // Validate each entry in the map - for key, value := range mapData { - if nestedMap, ok := value.(map[string]any); ok { - mapPath := fieldPath + "." + key - validateStructFields(t, fieldType.Elem(), nestedMap, mapPath) - } - } - } - } - default: - // Other types (primitives, slices, etc.) don't require recursive validation - } - } -} - -func TestEmbeddedTemplateHasDefaults(t *testing.T) { - t.Run("cassandra_with_required_env", func(t *testing.T) { - cassandraEnv := map[string]string{ - "CASSANDRA_SEEDS": "localhost", - } - rendered, err := processConfigFile(embeddedConfigTemplate, "config_template_embedded.yaml", cassandraEnv) - require.NoError(t, err) - - var cfg Config - err = yaml.Unmarshal(rendered, &cfg) - require.NoError(t, err) - - validate := newValidator() - err = validate.Validate(&cfg) - require.NoError(t, err, "Cassandra config with required env vars should be valid") - - // Verify cassandra hosts were set - require.NotEmpty(t, cfg.Persistence.DataStores["default"].Cassandra.Hosts, "cassandra hosts should be set from CASSANDRA_SEEDS") - }) - - t.Run("postgres_with_required_env", func(t *testing.T) { - postgresEnv := map[string]string{ - "DB": "postgres12", - "POSTGRES_SEEDS": "localhost", - } - rendered, err := processConfigFile(embeddedConfigTemplate, "config_template_embedded.yaml", postgresEnv) - require.NoError(t, err) - - var cfg Config - err = yaml.Unmarshal(rendered, &cfg) - require.NoError(t, err) - - validate := newValidator() - err = validate.Validate(&cfg) - require.NoError(t, err, "Postgres config with required env vars should be valid") - - // Verify specific critical defaults - require.NotEmpty(t, cfg.Log.Level, "log.level should have a default") - require.NotZero(t, cfg.Persistence.NumHistoryShards, "persistence.numHistoryShards should have a default") - require.NotEmpty(t, cfg.Persistence.DefaultStore, "persistence.defaultStore should have a default") - require.NotEmpty(t, cfg.Services, "services should have defaults") - require.Contains(t, cfg.Services, "frontend", "frontend service should be defined") - require.Contains(t, cfg.Services, "history", "history service should be defined") - require.Contains(t, cfg.Services, "matching", "matching service should be defined") - require.Contains(t, cfg.Services, "worker", "worker service should be defined") - }) - - t.Run("mysql_with_required_env", func(t *testing.T) { - // When using mysql with required env vars, config should be valid - mysqlEnv := map[string]string{ - "DB": "mysql8", - "MYSQL_SEEDS": "localhost", - } - rendered, err := processConfigFile(embeddedConfigTemplate, "config_template_embedded.yaml", mysqlEnv) - require.NoError(t, err) - - var cfg Config - err = yaml.Unmarshal(rendered, &cfg) - require.NoError(t, err) - - validate := newValidator() - err = validate.Validate(&cfg) - require.NoError(t, err, "MySQL config with required env vars should be valid") - }) -} - -func TestEmbeddedTemplateMatchesDockerTemplate(t *testing.T) { - // This test is informational - it documents that the embedded template matches docker template - t.Log("Embedded template should match docker/config_template.yaml structure") - t.Log("Both use dockerize-compatible syntax: .Env.VAR_NAME") - t.Log("Embedded template has # enable-template comment at the top for config loader detection") - - // Render both templates with the same env - testEnv := map[string]string{ - "DB": "postgres12", - "POSTGRES_SEEDS": "localhost", - "LOG_LEVEL": "debug", - } - - embeddedRendered, err := processConfigFile(embeddedConfigTemplate, "embedded", testEnv) - require.NoError(t, err) - - // Parse both into generic maps - var embeddedData map[string]any - err = yaml.Unmarshal(embeddedRendered, &embeddedData) - require.NoError(t, err) - - // Verify key sections exist - requiredSections := []string{"log", "persistence", "global", "services", "clusterMetadata", - "dcRedirectionPolicy", "archival", "dynamicConfigClient", "namespaceDefaults"} - - for _, section := range requiredSections { - _, exists := embeddedData[section] - require.True(t, exists, "Embedded template should have '%s' section", section) - } - - // publicClient is conditionally included: - // - Omitted if USE_INTERNAL_FRONTEND is set - // - Omitted if neither TEMPORAL_AUTH_AUTHORIZER nor TEMPORAL_AUTH_CLAIM_MAPPER is set - // With no env vars set, it's omitted (expected behavior) - t.Log("Note: publicClient is conditionally included based on USE_INTERNAL_FRONTEND and auth settings") -} - -func TestConfigToYAML(t *testing.T) { - // Load config from template - testEnv := map[string]string{ - "DB": "postgres12", - "POSTGRES_SEEDS": "localhost", - "LOG_LEVEL": "info", - } - - rendered, err := processConfigFile(embeddedConfigTemplate, "config_template_embedded.yaml", testEnv) - require.NoError(t, err) - - var cfg Config - err = yaml.Unmarshal(rendered, &cfg) - require.NoError(t, err) - - // Marshal config back to YAML - yamlBytes, err := yaml.Marshal(&cfg) - require.NoError(t, err) - require.NotEmpty(t, yamlBytes, "Config should marshal to YAML") - - // Verify it's valid YAML by unmarshaling it again - var cfg2 Config - err = yaml.Unmarshal(yamlBytes, &cfg2) - require.NoError(t, err, "Marshaled YAML should be valid and parseable") - - // Also test the String() method - configString := cfg.String() - require.NotEmpty(t, configString, "Config.String() should produce output") - require.Contains(t, configString, "log:", "Config string should contain log section") - require.Contains(t, configString, "persistence:", "Config string should contain persistence section") - - t.Logf("Config successfully marshaled to %d bytes of YAML", len(yamlBytes)) -} diff --git a/docker/config_template.yaml b/docker/config_template.yaml index d871ed31ed2..62d2df5b170 100644 --- a/docker/config_template.yaml +++ b/docker/config_template.yaml @@ -1,162 +1,162 @@ # TODO: Remove this file after temporalio/docker-builds repository is archived log: stdout: true - level: {{ default .Env.LOG_LEVEL "info" }} + level: {{ default "info" (env "LOG_LEVEL") }} persistence: - numHistoryShards: {{ default .Env.NUM_HISTORY_SHARDS "4" }} + numHistoryShards: {{ default "4" (env "NUM_HISTORY_SHARDS") }} defaultStore: default - {{- $es := default .Env.ENABLE_ES "false" | lower -}} + {{- $es := default "false" (env "ENABLE_ES") | lower -}} {{- if eq $es "true" }} visibilityStore: es-visibility {{- else }} visibilityStore: visibility {{- end }} datastores: - {{- $db := default .Env.DB "cassandra" | lower -}} + {{- $db := default "cassandra" (env "DB") | lower -}} {{- if eq $db "cassandra" }} default: cassandra: - hosts: "{{ default .Env.CASSANDRA_SEEDS "" }}" - keyspace: "{{ default .Env.KEYSPACE "temporal" }}" - user: "{{ default .Env.CASSANDRA_USER "" }}" - password: "{{ default .Env.CASSANDRA_PASSWORD "" }}" - {{- if .Env.CASSANDRA_ALLOWED_AUTHENTICATORS }} - allowedAuthenticators: {{ range split .Env.CASSANDRA_ALLOWED_AUTHENTICATORS "," }} + hosts: "{{ default "" (env "CASSANDRA_SEEDS") }}" + keyspace: "{{ default "temporal" (env "KEYSPACE") }}" + user: "{{ default "" (env "CASSANDRA_USER") }}" + password: "{{ default "" (env "CASSANDRA_PASSWORD") }}" + {{- if env "CASSANDRA_ALLOWED_AUTHENTICATORS" }} + allowedAuthenticators: {{ range split (env "CASSANDRA_ALLOWED_AUTHENTICATORS") "," }} - {{trim .}} {{- end }} {{- end }} - port: {{ default .Env.CASSANDRA_PORT "9042" }} - maxConns: {{ default .Env.CASSANDRA_MAX_CONNS "20" }} + port: {{ default "9042" (env "CASSANDRA_PORT") }} + maxConns: {{ default "20" (env "CASSANDRA_MAX_CONNS") }} tls: - enabled: {{ default .Env.CASSANDRA_TLS_ENABLED "false" }} - caFile: {{ default .Env.CASSANDRA_CA "" }} - certFile: {{ default .Env.CASSANDRA_CERT "" }} - keyFile: {{ default .Env.CASSANDRA_CERT_KEY "" }} - caData: {{ default .Env.CASSANDRA_CA_DATA "" }} - certData: {{ default .Env.CASSANDRA_CERT_DATA "" }} - keyData: {{ default .Env.CASSANDRA_CERT_KEY_DATA "" }} - enableHostVerification: {{ default .Env.CASSANDRA_HOST_VERIFICATION "false" }} - serverName: {{ default .Env.CASSANDRA_HOST_NAME "" }} - {{- if .Env.CASSANDRA_ADDRESS_TRANSLATOR }} + enabled: {{ default "false" (env "CASSANDRA_TLS_ENABLED") }} + caFile: {{ default "" (env "CASSANDRA_CA") }} + certFile: {{ default "" (env "CASSANDRA_CERT") }} + keyFile: {{ default "" (env "CASSANDRA_CERT_KEY") }} + caData: {{ default "" (env "CASSANDRA_CA_DATA") }} + certData: {{ default "" (env "CASSANDRA_CERT_DATA") }} + keyData: {{ default "" (env "CASSANDRA_CERT_KEY_DATA") }} + enableHostVerification: {{ default "false" (env "CASSANDRA_HOST_VERIFICATION") }} + serverName: {{ default "" (env "CASSANDRA_HOST_NAME") }} + {{- if env "CASSANDRA_ADDRESS_TRANSLATOR" }} addressTranslator: - translator: {{ default .Env.CASSANDRA_ADDRESS_TRANSLATOR "" }} - {{- if .Env.CASSANDRA_ADDRESS_TRANSLATOR_OPTIONS }} + translator: {{ default "" (env "CASSANDRA_ADDRESS_TRANSLATOR") }} + {{- if env "CASSANDRA_ADDRESS_TRANSLATOR_OPTIONS" }} options: - advertised-hostname: {{ default .Env.CASSANDRA_ADDRESS_TRANSLATOR_OPTIONS "" }} + advertised-hostname: {{ default "" (env "CASSANDRA_ADDRESS_TRANSLATOR_OPTIONS") }} {{- end }} {{- end }} {{- else if eq $db "mysql8" }} default: sql: pluginName: "{{ $db }}" - databaseName: "{{ default .Env.DBNAME "temporal" }}" - connectAddr: "{{ default .Env.MYSQL_SEEDS "" }}:{{ default .Env.DB_PORT "3306" }}" + databaseName: "{{ default "temporal" (env "DBNAME") }}" + connectAddr: "{{ default "" (env "MYSQL_SEEDS") }}:{{ default "3306" (env "DB_PORT") }}" connectProtocol: "tcp" - user: "{{ default .Env.MYSQL_USER "" }}" - password: "{{ default .Env.MYSQL_PWD "" }}" - {{- if .Env.MYSQL_TX_ISOLATION_COMPAT }} + user: "{{ default "" (env "MYSQL_USER") }}" + password: "{{ default "" (env "MYSQL_PWD") }}" + {{- if env "MYSQL_TX_ISOLATION_COMPAT" }} connectAttributes: tx_isolation: "'READ-COMMITTED'" {{- end }} - maxConns: {{ default .Env.SQL_MAX_CONNS "20" }} - maxIdleConns: {{ default .Env.SQL_MAX_IDLE_CONNS "20" }} - maxConnLifetime: {{ default .Env.SQL_MAX_CONN_TIME "1h" }} + maxConns: {{ default "20" (env "SQL_MAX_CONNS") }} + maxIdleConns: {{ default "20" (env "SQL_MAX_IDLE_CONNS") }} + maxConnLifetime: {{ default "1h" (env "SQL_MAX_CONN_TIME") }} tls: - enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} - caFile: {{ default .Env.SQL_CA "" }} - certFile: {{ default .Env.SQL_CERT "" }} - keyFile: {{ default .Env.SQL_CERT_KEY "" }} - enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} - serverName: {{ default .Env.SQL_HOST_NAME "" }} + enabled: {{ default "false" (env "SQL_TLS_ENABLED") }} + caFile: {{ default "" (env "SQL_CA") }} + certFile: {{ default "" (env "SQL_CERT") }} + keyFile: {{ default "" (env "SQL_CERT_KEY") }} + enableHostVerification: {{ default "false" (env "SQL_HOST_VERIFICATION") }} + serverName: {{ default "" (env "SQL_HOST_NAME") }} visibility: sql: - {{ $visibility_seeds_default := default .Env.MYSQL_SEEDS "" }} - {{ $visibility_seeds := default .Env.VISIBILITY_MYSQL_SEEDS $visibility_seeds_default }} - {{ $visibility_port_default := default .Env.DB_PORT "3306" }} - {{ $visibility_port := default .Env.VISIBILITY_DB_PORT $visibility_port_default }} - {{ $visibility_user_default := default .Env.MYSQL_USER "" }} - {{ $visibility_user := default .Env.VISIBILITY_MYSQL_USER $visibility_user_default }} - {{ $visibility_pwd_default := default .Env.MYSQL_PWD "" }} - {{ $visibility_pwd := default .Env.VISIBILITY_MYSQL_PWD $visibility_pwd_default }} + {{ $visibility_seeds_default := default "" (env "MYSQL_SEEDS") }} + {{ $visibility_seeds := default $visibility_seeds_default (env "VISIBILITY_MYSQL_SEEDS") }} + {{ $visibility_port_default := default "3306" (env "DB_PORT") }} + {{ $visibility_port := default $visibility_port_default (env "VISIBILITY_DB_PORT") }} + {{ $visibility_user_default := default "" (env "MYSQL_USER") }} + {{ $visibility_user := default $visibility_user_default (env "VISIBILITY_MYSQL_USER") }} + {{ $visibility_pwd_default := default "" (env "MYSQL_PWD") }} + {{ $visibility_pwd := default $visibility_pwd_default (env "VISIBILITY_MYSQL_PWD") }} pluginName: "{{ $db }}" - databaseName: "{{ default .Env.VISIBILITY_DBNAME "temporal_visibility" }}" + databaseName: "{{ default "temporal_visibility" (env "VISIBILITY_DBNAME") }}" connectAddr: "{{ $visibility_seeds }}:{{ $visibility_port }}" connectProtocol: "tcp" user: "{{ $visibility_user }}" password: "{{ $visibility_pwd }}" - {{- if .Env.MYSQL_TX_ISOLATION_COMPAT }} + {{- if env "MYSQL_TX_ISOLATION_COMPAT" }} connectAttributes: tx_isolation: "'READ-COMMITTED'" {{- end }} - maxConns: {{ default .Env.SQL_VIS_MAX_CONNS "10" }} - maxIdleConns: {{ default .Env.SQL_VIS_MAX_IDLE_CONNS "10" }} - maxConnLifetime: {{ default .Env.SQL_VIS_MAX_CONN_TIME "1h" }} + maxConns: {{ default "10" (env "SQL_VIS_MAX_CONNS") }} + maxIdleConns: {{ default "10" (env "SQL_VIS_MAX_IDLE_CONNS") }} + maxConnLifetime: {{ default "1h" (env "SQL_VIS_MAX_CONN_TIME") }} tls: - enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} - caFile: {{ default .Env.SQL_CA "" }} - certFile: {{ default .Env.SQL_CERT "" }} - keyFile: {{ default .Env.SQL_CERT_KEY "" }} - enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} - serverName: {{ default .Env.SQL_HOST_NAME "" }} + enabled: {{ default "false" (env "SQL_TLS_ENABLED") }} + caFile: {{ default "" (env "SQL_CA") }} + certFile: {{ default "" (env "SQL_CERT") }} + keyFile: {{ default "" (env "SQL_CERT_KEY") }} + enableHostVerification: {{ default "false" (env "SQL_HOST_VERIFICATION") }} + serverName: {{ default "" (env "SQL_HOST_NAME") }} {{- else if eq $db "postgres12" "postgres12_pgx" }} default: sql: pluginName: "{{ $db }}" - databaseName: "{{ default .Env.DBNAME "temporal" }}" - connectAddr: "{{ default .Env.POSTGRES_SEEDS "" }}:{{ default .Env.DB_PORT "5432" }}" + databaseName: "{{ default "temporal" (env "DBNAME") }}" + connectAddr: "{{ default "" (env "POSTGRES_SEEDS") }}:{{ default "5432" (env "DB_PORT") }}" connectProtocol: "tcp" - user: "{{ default .Env.POSTGRES_USER "" }}" - password: "{{ default .Env.POSTGRES_PWD "" }}" - maxConns: {{ default .Env.SQL_MAX_CONNS "20" }} - maxIdleConns: {{ default .Env.SQL_MAX_IDLE_CONNS "20" }} - maxConnLifetime: {{ default .Env.SQL_MAX_CONN_TIME "1h" }} + user: "{{ default "" (env "POSTGRES_USER") }}" + password: "{{ default "" (env "POSTGRES_PWD") }}" + maxConns: {{ default "20" (env "SQL_MAX_CONNS") }} + maxIdleConns: {{ default "20" (env "SQL_MAX_IDLE_CONNS") }} + maxConnLifetime: {{ default "1h" (env "SQL_MAX_CONN_TIME") }} tls: - enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} - caFile: {{ default .Env.SQL_CA "" }} - certFile: {{ default .Env.SQL_CERT "" }} - keyFile: {{ default .Env.SQL_CERT_KEY "" }} - enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} - serverName: {{ default .Env.SQL_HOST_NAME "" }} + enabled: {{ default "false" (env "SQL_TLS_ENABLED") }} + caFile: {{ default "" (env "SQL_CA") }} + certFile: {{ default "" (env "SQL_CERT") }} + keyFile: {{ default "" (env "SQL_CERT_KEY") }} + enableHostVerification: {{ default "false" (env "SQL_HOST_VERIFICATION") }} + serverName: {{ default "" (env "SQL_HOST_NAME") }} visibility: sql: - {{ $visibility_seeds_default := default .Env.POSTGRES_SEEDS "" }} - {{ $visibility_seeds := default .Env.VISIBILITY_POSTGRES_SEEDS $visibility_seeds_default }} - {{ $visibility_port_default := default .Env.DB_PORT "5432" }} - {{ $visibility_port := default .Env.VISIBILITY_DB_PORT $visibility_port_default }} - {{ $visibility_user_default := default .Env.POSTGRES_USER "" }} - {{ $visibility_user := default .Env.VISIBILITY_POSTGRES_USER $visibility_user_default }} - {{ $visibility_pwd_default := default .Env.POSTGRES_PWD "" }} - {{ $visibility_pwd := default .Env.VISIBILITY_POSTGRES_PWD $visibility_pwd_default }} + {{ $visibility_seeds_default := default "" (env "POSTGRES_SEEDS") }} + {{ $visibility_seeds := default $visibility_seeds_default (env "VISIBILITY_POSTGRES_SEEDS") }} + {{ $visibility_port_default := default "5432" (env "DB_PORT") }} + {{ $visibility_port := default $visibility_port_default (env "VISIBILITY_DB_PORT") }} + {{ $visibility_user_default := default "" (env "POSTGRES_USER") }} + {{ $visibility_user := default $visibility_user_default (env "VISIBILITY_POSTGRES_USER") }} + {{ $visibility_pwd_default := default "" (env "POSTGRES_PWD") }} + {{ $visibility_pwd := default $visibility_pwd_default (env "VISIBILITY_POSTGRES_PWD") }} pluginName: "{{ $db }}" - databaseName: "{{ default .Env.VISIBILITY_DBNAME "temporal_visibility" }}" + databaseName: "{{ default "temporal_visibility" (env "VISIBILITY_DBNAME") }}" connectAddr: "{{ $visibility_seeds }}:{{ $visibility_port }}" connectProtocol: "tcp" user: "{{ $visibility_user }}" password: "{{ $visibility_pwd }}" - maxConns: {{ default .Env.SQL_VIS_MAX_CONNS "10" }} - maxIdleConns: {{ default .Env.SQL_VIS_MAX_IDLE_CONNS "10" }} - maxConnLifetime: {{ default .Env.SQL_VIS_MAX_CONN_TIME "1h" }} + maxConns: {{ default "10" (env "SQL_VIS_MAX_CONNS") }} + maxIdleConns: {{ default "10" (env "SQL_VIS_MAX_IDLE_CONNS") }} + maxConnLifetime: {{ default "1h" (env "SQL_VIS_MAX_CONN_TIME") }} tls: - enabled: {{ default .Env.SQL_TLS_ENABLED "false" }} - caFile: {{ default .Env.SQL_CA "" }} - certFile: {{ default .Env.SQL_CERT "" }} - keyFile: {{ default .Env.SQL_CERT_KEY "" }} - enableHostVerification: {{ default .Env.SQL_HOST_VERIFICATION "false" }} - serverName: {{ default .Env.SQL_HOST_NAME "" }} + enabled: {{ default "false" (env "SQL_TLS_ENABLED") }} + caFile: {{ default "" (env "SQL_CA") }} + certFile: {{ default "" (env "SQL_CERT") }} + keyFile: {{ default "" (env "SQL_CERT_KEY") }} + enableHostVerification: {{ default "false" (env "SQL_HOST_VERIFICATION") }} + serverName: {{ default "" (env "SQL_HOST_NAME") }} {{- end }} {{- if eq $es "true" }} es-visibility: elasticsearch: - version: {{ default .Env.ES_VERSION "" }} + version: {{ default "" (env "ES_VERSION") }} url: - scheme: {{ default .Env.ES_SCHEME "http" }} - host: "{{ default .Env.ES_SEEDS "" }}:{{ default .Env.ES_PORT "9200" }}" - username: "{{ default .Env.ES_USER "" }}" - password: "{{ default .Env.ES_PWD "" }}" + scheme: {{ default "http" (env "ES_SCHEME") }} + host: "{{ default "" (env "ES_SEEDS") }}:{{ default "9200" (env "ES_PORT") }}" + username: "{{ default "" (env "ES_USER") }}" + password: "{{ default "" (env "ES_PWD") }}" indices: - visibility: "{{ default .Env.ES_VIS_INDEX "temporal_visibility_v1_dev" }}" - {{- $es_sec_vis_index := default .Env.ES_SEC_VIS_INDEX "" -}} + visibility: "{{ default "temporal_visibility_v1_dev" (env "ES_VIS_INDEX") }}" + {{- $es_sec_vis_index := default "" (env "ES_SEC_VIS_INDEX") -}} {{- if ne $es_sec_vis_index "" }} secondary_visibility: "{{ $es_sec_vis_index }}" {{- end }} @@ -165,147 +165,147 @@ persistence: global: membership: maxJoinDuration: 30s - broadcastAddress: "{{ default .Env.TEMPORAL_BROADCAST_ADDRESS "" }}" + broadcastAddress: "{{ default "" (env "TEMPORAL_BROADCAST_ADDRESS") }}" pprof: - port: {{ default .Env.PPROF_PORT "0" }} + port: {{ default "0" (env "PPROF_PORT") }} tls: - refreshInterval: {{ default .Env.TEMPORAL_TLS_REFRESH_INTERVAL "0s" }} + refreshInterval: {{ default "0s" (env "TEMPORAL_TLS_REFRESH_INTERVAL") }} expirationChecks: - warningWindow: {{ default .Env.TEMPORAL_TLS_EXPIRATION_CHECKS_WARNING_WINDOW "0s" }} - errorWindow: {{ default .Env.TEMPORAL_TLS_EXPIRATION_CHECKS_ERROR_WINDOW "0s" }} - checkInterval: {{ default .Env.TEMPORAL_TLS_EXPIRATION_CHECKS_CHECK_INTERVAL "0s" }} + warningWindow: {{ default "0s" (env "TEMPORAL_TLS_EXPIRATION_CHECKS_WARNING_WINDOW") }} + errorWindow: {{ default "0s" (env "TEMPORAL_TLS_EXPIRATION_CHECKS_ERROR_WINDOW") }} + checkInterval: {{ default "0s" (env "TEMPORAL_TLS_EXPIRATION_CHECKS_CHECK_INTERVAL") }} internode: # This server section configures the TLS certificate that internal temporal # cluster nodes (history, matching, and internal-frontend) present to other # clients within the Temporal Cluster. server: - requireClientAuth: {{ default .Env.TEMPORAL_TLS_REQUIRE_CLIENT_AUTH "false" }} + requireClientAuth: {{ default "false" (env "TEMPORAL_TLS_REQUIRE_CLIENT_AUTH") }} - certFile: {{ default .Env.TEMPORAL_TLS_SERVER_CERT "" }} - keyFile: {{ default .Env.TEMPORAL_TLS_SERVER_KEY "" }} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT }} + certFile: {{ default "" (env "TEMPORAL_TLS_SERVER_CERT") }} + keyFile: {{ default "" (env "TEMPORAL_TLS_SERVER_KEY") }} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT" }} clientCaFiles: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT") }} {{- end }} - certData: {{ default .Env.TEMPORAL_TLS_SERVER_CERT_DATA "" }} - keyData: {{ default .Env.TEMPORAL_TLS_SERVER_KEY_DATA "" }} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA }} + certData: {{ default "" (env "TEMPORAL_TLS_SERVER_CERT_DATA") }} + keyData: {{ default "" (env "TEMPORAL_TLS_SERVER_KEY_DATA") }} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT_DATA" }} clientCaData: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT_DATA") }} {{- end }} # This client section is used to configure the TLS clients within # the Temporal Cluster that connect to an Internode (history, matching, or # internal-frontend) client: - serverName: {{ default .Env.TEMPORAL_TLS_INTERNODE_SERVER_NAME "" }} - disableHostVerification: {{ default .Env.TEMPORAL_TLS_INTERNODE_DISABLE_HOST_VERIFICATION "false"}} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT }} + serverName: {{ default "" (env "TEMPORAL_TLS_INTERNODE_SERVER_NAME") }} + disableHostVerification: {{ default "false" (env "TEMPORAL_TLS_INTERNODE_DISABLE_HOST_VERIFICATION")}} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT" }} rootCaFiles: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT") }} {{- end }} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA }} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT_DATA" }} rootCaData: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT_DATA") }} {{- end }} frontend: # This server section configures the TLS certificate that the Frontend # server presents to external clients. server: - requireClientAuth: {{ default .Env.TEMPORAL_TLS_REQUIRE_CLIENT_AUTH "false" }} - certFile: {{ default .Env.TEMPORAL_TLS_FRONTEND_CERT "" }} - keyFile: {{ default .Env.TEMPORAL_TLS_FRONTEND_KEY "" }} - {{- if .Env.TEMPORAL_TLS_CLIENT1_CA_CERT }} + requireClientAuth: {{ default "false" (env "TEMPORAL_TLS_REQUIRE_CLIENT_AUTH") }} + certFile: {{ default "" (env "TEMPORAL_TLS_FRONTEND_CERT") }} + keyFile: {{ default "" (env "TEMPORAL_TLS_FRONTEND_KEY") }} + {{- if env "TEMPORAL_TLS_CLIENT1_CA_CERT" }} clientCaFiles: - - {{ default .Env.TEMPORAL_TLS_CLIENT1_CA_CERT "" }} - - {{ default .Env.TEMPORAL_TLS_CLIENT2_CA_CERT "" }} + - {{ default "" (env "TEMPORAL_TLS_CLIENT1_CA_CERT") }} + - {{ default "" (env "TEMPORAL_TLS_CLIENT2_CA_CERT") }} {{- end }} - certData: {{ default .Env.TEMPORAL_TLS_FRONTEND_CERT_DATA "" }} - keyData: {{ default .Env.TEMPORAL_TLS_FRONTEND_KEY_DATA "" }} - {{- if .Env.TEMPORAL_TLS_CLIENT1_CA_CERT_DATA }} + certData: {{ default "" (env "TEMPORAL_TLS_FRONTEND_CERT_DATA") }} + keyData: {{ default "" (env "TEMPORAL_TLS_FRONTEND_KEY_DATA") }} + {{- if env "TEMPORAL_TLS_CLIENT1_CA_CERT_DATA" }} clientCaData: - - {{ default .Env.TEMPORAL_TLS_CLIENT1_CA_CERT_DATA "" }} - - {{ default .Env.TEMPORAL_TLS_CLIENT2_CA_CERT_DATA "" }} + - {{ default "" (env "TEMPORAL_TLS_CLIENT1_CA_CERT_DATA") }} + - {{ default "" (env "TEMPORAL_TLS_CLIENT2_CA_CERT_DATA") }} {{- end }} # This client section is used to configure the TLS clients within # the Temporal Cluster (specifically the Worker role) that connect to the Frontend service client: - serverName: {{ default .Env.TEMPORAL_TLS_FRONTEND_SERVER_NAME "" }} - disableHostVerification: {{ default .Env.TEMPORAL_TLS_FRONTEND_DISABLE_HOST_VERIFICATION "false"}} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT }} + serverName: {{ default "" (env "TEMPORAL_TLS_FRONTEND_SERVER_NAME") }} + disableHostVerification: {{ default "false" (env "TEMPORAL_TLS_FRONTEND_DISABLE_HOST_VERIFICATION")}} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT" }} rootCaFiles: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT") }} {{- end }} - {{- if .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA }} + {{- if env "TEMPORAL_TLS_SERVER_CA_CERT_DATA" }} rootCaData: - - {{ default .Env.TEMPORAL_TLS_SERVER_CA_CERT_DATA "" }} + - {{ default "" (env "TEMPORAL_TLS_SERVER_CA_CERT_DATA") }} {{- end }} - {{- if .Env.STATSD_ENDPOINT }} + {{- if env "STATSD_ENDPOINT" }} metrics: statsd: - hostPort: {{ .Env.STATSD_ENDPOINT }} + hostPort: {{ env "STATSD_ENDPOINT" }} prefix: "temporal" - {{- else if .Env.PROMETHEUS_ENDPOINT }} + {{- else if env "PROMETHEUS_ENDPOINT" }} metrics: prometheus: - timerType: {{ default .Env.PROMETHEUS_TIMER_TYPE "histogram" }} - listenAddress: "{{ .Env.PROMETHEUS_ENDPOINT }}" + timerType: {{ default "histogram" (env "PROMETHEUS_TIMER_TYPE") }} + listenAddress: "{{ env "PROMETHEUS_ENDPOINT" }}" {{- end }} authorization: jwtKeyProvider: keySourceURIs: - {{- if .Env.TEMPORAL_JWT_KEY_SOURCE1 }} - - {{ default .Env.TEMPORAL_JWT_KEY_SOURCE1 "" }} + {{- if env "TEMPORAL_JWT_KEY_SOURCE1" }} + - {{ default "" (env "TEMPORAL_JWT_KEY_SOURCE1") }} {{- end }} - {{- if .Env.TEMPORAL_JWT_KEY_SOURCE2 }} - - {{ default .Env.TEMPORAL_JWT_KEY_SOURCE2 "" }} + {{- if env "TEMPORAL_JWT_KEY_SOURCE2" }} + - {{ default "" (env "TEMPORAL_JWT_KEY_SOURCE2") }} {{- end }} - refreshInterval: {{ default .Env.TEMPORAL_JWT_KEY_REFRESH "1m" }} - permissionsClaimName: {{ default .Env.TEMPORAL_JWT_PERMISSIONS_CLAIM "permissions" }} - permissionsRegex: {{ default .Env.TEMPORAL_JWT_PERMISSIONS_REGEX "" }} - authorizer: {{ default .Env.TEMPORAL_AUTH_AUTHORIZER "" }} - claimMapper: {{ default .Env.TEMPORAL_AUTH_CLAIM_MAPPER "" }} + refreshInterval: {{ default "1m" (env "TEMPORAL_JWT_KEY_REFRESH") }} + permissionsClaimName: {{ default "permissions" (env "TEMPORAL_JWT_PERMISSIONS_CLAIM") }} + permissionsRegex: {{ default "" (env "TEMPORAL_JWT_PERMISSIONS_REGEX") }} + authorizer: {{ default "" (env "TEMPORAL_AUTH_AUTHORIZER") }} + claimMapper: {{ default "" (env "TEMPORAL_AUTH_CLAIM_MAPPER") }} -{{- $temporalGrpcPort := default .Env.FRONTEND_GRPC_PORT "7233" }} -{{- $temporalHTTPPort := default .Env.FRONTEND_HTTP_PORT "7243" }} -{{- $temporalInternalHTTPPort := default .Env.INTERNAL_FRONTEND_HTTP_PORT "7246" }} +{{- $temporalGrpcPort := default "7233" (env "FRONTEND_GRPC_PORT") }} +{{- $temporalHTTPPort := default "7243" (env "FRONTEND_HTTP_PORT") }} +{{- $temporalInternalHTTPPort := default "7246" (env "INTERNAL_FRONTEND_HTTP_PORT") }} services: frontend: rpc: grpcPort: {{ $temporalGrpcPort }} - membershipPort: {{ default .Env.FRONTEND_MEMBERSHIP_PORT "6933" }} - bindOnIP: "{{ default .Env.BIND_ON_IP "127.0.0.1" }}" + membershipPort: {{ default "6933" (env "FRONTEND_MEMBERSHIP_PORT") }} + bindOnIP: "{{ default "127.0.0.1" (env "BIND_ON_IP") }}" httpPort: {{ $temporalHTTPPort }} - {{- if .Env.USE_INTERNAL_FRONTEND }} + {{- if env "USE_INTERNAL_FRONTEND" }} internal-frontend: rpc: - grpcPort: {{ default .Env.INTERNAL_FRONTEND_GRPC_PORT "7236" }} - membershipPort: {{ default .Env.INTERNAL_FRONTEND_MEMBERSHIP_PORT "6936" }} - bindOnIP: "{{ default .Env.BIND_ON_IP "127.0.0.1" }}" + grpcPort: {{ default "7236" (env "INTERNAL_FRONTEND_GRPC_PORT") }} + membershipPort: {{ default "6936" (env "INTERNAL_FRONTEND_MEMBERSHIP_PORT") }} + bindOnIP: "{{ default "127.0.0.1" (env "BIND_ON_IP") }}" httpPort: {{ $temporalInternalHTTPPort }} {{- end }} matching: rpc: - grpcPort: {{ default .Env.MATCHING_GRPC_PORT "7235" }} - membershipPort: {{ default .Env.MATCHING_MEMBERSHIP_PORT "6935" }} - bindOnIP: "{{ default .Env.BIND_ON_IP "127.0.0.1" }}" + grpcPort: {{ default "7235" (env "MATCHING_GRPC_PORT") }} + membershipPort: {{ default "6935" (env "MATCHING_MEMBERSHIP_PORT") }} + bindOnIP: "{{ default "127.0.0.1" (env "BIND_ON_IP") }}" history: rpc: - grpcPort: {{ default .Env.HISTORY_GRPC_PORT "7234" }} - membershipPort: {{ default .Env.HISTORY_MEMBERSHIP_PORT "6934" }} - bindOnIP: "{{ default .Env.BIND_ON_IP "127.0.0.1" }}" + grpcPort: {{ default "7234" (env "HISTORY_GRPC_PORT") }} + membershipPort: {{ default "6934" (env "HISTORY_MEMBERSHIP_PORT") }} + bindOnIP: "{{ default "127.0.0.1" (env "BIND_ON_IP") }}" worker: rpc: - grpcPort: {{ default .Env.WORKER_GRPC_PORT "7239" }} - membershipPort: {{ default .Env.WORKER_MEMBERSHIP_PORT "6939" }} - bindOnIP: "{{ default .Env.BIND_ON_IP "127.0.0.1" }}" + grpcPort: {{ default "7239" (env "WORKER_GRPC_PORT") }} + membershipPort: {{ default "6939" (env "WORKER_MEMBERSHIP_PORT") }} + bindOnIP: "{{ default "127.0.0.1" (env "BIND_ON_IP") }}" clusterMetadata: enableGlobalNamespace: false @@ -348,15 +348,15 @@ namespaceDefaults: state: "disabled" URI: "file:///tmp/temporal_vis_archival/development" -{{- if or (.Env.USE_INTERNAL_FRONTEND) (and (not .Env.TEMPORAL_AUTH_AUTHORIZER) (not .Env.TEMPORAL_AUTH_CLAIM_MAPPER)) }} +{{- if or (env "USE_INTERNAL_FRONTEND") (and (not (env "TEMPORAL_AUTH_AUTHORIZER")) (not (env "TEMPORAL_AUTH_CLAIM_MAPPER"))) }} {{/* publicClient is not needed with internal frontend, or if not using authorizer + claim mapper */}} {{- else }} -{{ $publicIp := default .Env.BIND_ON_IP "127.0.0.1" -}} +{{ $publicIp := default "127.0.0.1" (env "BIND_ON_IP") -}} {{- $defaultPublicHostPost := (print $publicIp ":" $temporalGrpcPort) -}} publicClient: - hostPort: "{{ default .Env.PUBLIC_FRONTEND_ADDRESS $defaultPublicHostPost }}" + hostPort: "{{ default $defaultPublicHostPost (env "PUBLIC_FRONTEND_ADDRESS") }}" {{- end }} dynamicConfigClient: - filepath: "{{ default .Env.DYNAMIC_CONFIG_FILE_PATH "/etc/temporal/config/dynamicconfig/docker.yaml" }}" + filepath: "{{ default "/etc/temporal/config/dynamicconfig/docker.yaml" (env "DYNAMIC_CONFIG_FILE_PATH") }}" pollInterval: "60s"