From 4433de2427b0ba234f1bd88d5ef58785ceffcf7b Mon Sep 17 00:00:00 2001 From: Gaurav Rawat Date: Thu, 2 Jul 2026 12:54:07 +0530 Subject: [PATCH 1/2] feat(helm): add Hypersense backend and ETL support with shared ConfigMap and Secret --- helm-charts/templates/_helpers.tpl | 32 ++++ helm-charts/templates/deployment.yaml | 14 ++ .../hypersense-backend-deployment.yaml | 153 +++++++++++++++++ .../templates/hypersense-backend-service.yaml | 19 +++ helm-charts/templates/hypersense-config.yaml | 19 +++ .../templates/hypersense-etl-deployment.yaml | 161 ++++++++++++++++++ .../templates/hypersense-etl-service.yaml | 19 +++ helm-charts/templates/hypersense-secret.yaml | 19 +++ helm-charts/values-hypersense.yaml | 116 +++++++++++++ helm-charts/values-local.yaml | 124 ++++++++++++++ helm-charts/values.yaml | 115 +++++++++++++ 11 files changed, 791 insertions(+) create mode 100644 helm-charts/templates/hypersense-backend-deployment.yaml create mode 100644 helm-charts/templates/hypersense-backend-service.yaml create mode 100644 helm-charts/templates/hypersense-config.yaml create mode 100644 helm-charts/templates/hypersense-etl-deployment.yaml create mode 100644 helm-charts/templates/hypersense-etl-service.yaml create mode 100644 helm-charts/templates/hypersense-secret.yaml create mode 100644 helm-charts/values-hypersense.yaml create mode 100644 helm-charts/values-local.yaml diff --git a/helm-charts/templates/_helpers.tpl b/helm-charts/templates/_helpers.tpl index e49c6603..23f250fa 100644 --- a/helm-charts/templates/_helpers.tpl +++ b/helm-charts/templates/_helpers.tpl @@ -209,3 +209,35 @@ Define the MySQL hostname {{- .Values.mysql.hostname | default (printf "%s-mysql" .Release.Name) }} {{- end }} {{- end }} + +{{/* +Create the name for the Hypersense Backend +*/}} +{{- define "decision-engine.hypersenseBackendName" -}} +{{- printf "%s-hypersense-backend" (include "decision-engine.fullname" .) }} +{{- end }} + +{{/* +Create the name for the Hypersense ETL +*/}} +{{- define "decision-engine.hypersenseEtlName" -}} +{{- printf "%s-hypersense-etl" (include "decision-engine.fullname" .) }} +{{- end }} + +{{/* +Name of the shared Hypersense ConfigMap (DB/Redis connection coordinates). +Mirrors hypersense-main's configMapName: referenced by backend + etl via configMapKeyRef. +Override hypersenseShared.configMapName to point at a pre-existing (external) ConfigMap. +*/}} +{{- define "decision-engine.hypersenseConfigMapName" -}} +{{- .Values.hypersenseShared.configMapName | default (printf "%s-hypersense-config" (include "decision-engine.fullname" .)) }} +{{- end }} + +{{/* +Name of the shared Hypersense Secret (DB password). +Mirrors hypersense-main's secretsName: referenced by backend + etl via secretKeyRef. +Override hypersenseShared.secretName to point at a pre-existing (external) Secret. +*/}} +{{- define "decision-engine.hypersenseSecretName" -}} +{{- .Values.hypersenseShared.secretName | default (printf "%s-hypersense-secret" (include "decision-engine.fullname" .)) }} +{{- end }} diff --git a/helm-charts/templates/deployment.yaml b/helm-charts/templates/deployment.yaml index af877e43..b06fed2b 100644 --- a/helm-charts/templates/deployment.yaml +++ b/helm-charts/templates/deployment.yaml @@ -68,6 +68,20 @@ spec: env: - name: GROOVY_RUNNER_HOST value: "{{ include "decision-engine.groovyRunnerName" . }}:{{ .Values.groovyRunner.service.port }}" + {{- if .Values.decisionEngine.usePostgreSQL }} + - name: DECISION_ENGINE__PG_DATABASE__PG_HOST + value: {{ include "decision-engine.postgresqlHost" . | quote }} + - name: DECISION_ENGINE__PG_DATABASE__PG_USERNAME + value: {{ .Values.postgresql.auth.username | quote }} + - name: DECISION_ENGINE__PG_DATABASE__PG_PASSWORD + value: {{ .Values.postgresql.auth.password | quote }} + - name: DECISION_ENGINE__PG_DATABASE__PG_DBNAME + value: {{ .Values.postgresql.auth.database | quote }} + {{- end }} + - name: DECISION_ENGINE__SERVER__HOST + value: "0.0.0.0" + - name: DECISION_ENGINE__REDIS__HOST + value: {{ include "decision-engine.redisHost" . | quote }} - name: DECISION_ENGINE__ANALYTICS__ENABLED value: {{ ternary "true" "false" .Values.analytics.enabled | quote }} - name: DECISION_ENGINE__ANALYTICS__KAFKA__BROKERS diff --git a/helm-charts/templates/hypersense-backend-deployment.yaml b/helm-charts/templates/hypersense-backend-deployment.yaml new file mode 100644 index 00000000..64ab5a65 --- /dev/null +++ b/helm-charts/templates/hypersense-backend-deployment.yaml @@ -0,0 +1,153 @@ +{{- if .Values.hypersenseBackend.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "decision-engine.hypersenseBackendName" . }} + labels: + {{- include "decision-engine.labels" . | nindent 4 }} + app.kubernetes.io/component: {{ .Values.hypersenseBackend.metadata.labels.component }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "decision-engine.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: {{ .Values.hypersenseBackend.metadata.labels.component }} + template: + metadata: + labels: + {{- include "decision-engine.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: {{ .Values.hypersenseBackend.metadata.labels.component }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "decision-engine.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.initContainers.enabled }} + initContainers: + {{- if .Values.decisionEngine.usePostgreSQL }} + - name: wait-for-postgresql + image: "{{ .Values.initContainers.busybox.repository }}:{{ .Values.initContainers.busybox.tag }}" + imagePullPolicy: {{ .Values.initContainers.busybox.pullPolicy }} + command: ['sh', '-c', 'until nc -z {{ include "decision-engine.postgresqlHost" . }} 5432; do echo waiting for postgresql; sleep 2; done;'] + {{- end }} + {{- if .Values.decisionEngine.useRedis }} + - name: wait-for-redis + image: "{{ .Values.initContainers.busybox.repository }}:{{ .Values.initContainers.busybox.tag }}" + imagePullPolicy: {{ .Values.initContainers.busybox.pullPolicy }} + command: ['sh', '-c', 'until nc -z {{ include "decision-engine.redisHost" . }} 6379; do echo waiting for redis; sleep 2; done;'] + {{- end }} + {{- end }} + containers: + - name: hypersense-backend + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.hypersenseBackend.image.repository }}:{{ .Values.hypersenseBackend.image.tag }}" + imagePullPolicy: {{ .Values.hypersenseBackend.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.hypersenseBackend.service.port }} + protocol: TCP + env: + # ── Connection coordinates: from the shared Hypersense ConfigMap ── + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + key: DB_HOST + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + key: DB_PORT + - name: DB_USER + valueFrom: + configMapKeyRef: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + key: DB_USER + - name: DB_NAME + valueFrom: + configMapKeyRef: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + key: DB_NAME + - name: REDIS_URL + valueFrom: + configMapKeyRef: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + key: REDIS_URL + # ── DB password: from the shared Hypersense Secret ── + - name: DB_PASSWD + valueFrom: + secretKeyRef: + name: {{ include "decision-engine.hypersenseSecretName" . }} + key: DB_PASSWD + # ── Application config: direct values ── + - name: RUNNING_ENV + value: {{ .Values.hypersenseBackend.env.runningEnv | quote }} + - name: MODE + value: {{ .Values.hypersenseBackend.env.mode | quote }} + - name: DB_SCHEMA + value: {{ .Values.hypersenseBackend.env.dbSchema | quote }} + - name: DB_SCHEMA_RE + value: {{ .Values.hypersenseBackend.env.dbSchemaRe | quote }} + - name: DB_SCHEMA_AUTH + value: {{ .Values.hypersenseBackend.env.dbSchemaAuth | quote }} + - name: KAFKA_BOOTSTRAP_SERVERS + value: {{ .Values.hypersenseBackend.env.kafkaBootstrapServers | quote }} + - name: KAFKA_TOPIC + value: {{ .Values.hypersenseBackend.env.kafkaTopic | quote }} + - name: KAFKA_GROUP_ID + value: {{ .Values.hypersenseBackend.env.kafkaGroupId | quote }} + - name: AWS_REGION + value: {{ .Values.hypersenseBackend.env.awsRegion | quote }} + - name: S3_BUCKET + value: {{ .Values.hypersenseBackend.env.s3Bucket | quote }} + - name: AI_BACKEND_HOST + value: {{ .Values.hypersenseBackend.env.aiBackendHost | quote }} + - name: HYPER_SWITCH_BASE_URL + value: {{ .Values.hypersenseBackend.env.hyperSwitchBaseUrl | quote }} + {{- if .Values.hypersenseBackend.migration.runOnStartup }} + - name: RUN_RDS_MIGRATIONS + value: "TRUE" + {{- end }} + {{- range $name, $value := .Values.hypersenseBackend.extraEnvVars }} + - name: {{ $name }} + {{- if and (kindIs "map" $value) $value.valueFrom }} + valueFrom: + {{- toYaml $value.valueFrom | nindent 16 }} + {{- else }} + value: {{ $value | quote }} + {{- end }} + {{- end }} + livenessProbe: + httpGet: + path: {{ .Values.hypersenseBackend.healthcheck.path }} + port: http + initialDelaySeconds: {{ .Values.hypersenseBackend.healthcheck.initialDelaySeconds }} + periodSeconds: {{ .Values.hypersenseBackend.healthcheck.periodSeconds }} + timeoutSeconds: {{ .Values.hypersenseBackend.healthcheck.timeoutSeconds }} + failureThreshold: {{ .Values.hypersenseBackend.healthcheck.failureThreshold }} + readinessProbe: + httpGet: + path: {{ .Values.hypersenseBackend.healthcheck.path }} + port: http + initialDelaySeconds: {{ .Values.hypersenseBackend.healthcheck.initialDelaySeconds }} + periodSeconds: {{ .Values.hypersenseBackend.healthcheck.periodSeconds }} + timeoutSeconds: {{ .Values.hypersenseBackend.healthcheck.timeoutSeconds }} + resources: + {{- toYaml .Values.hypersenseBackend.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/helm-charts/templates/hypersense-backend-service.yaml b/helm-charts/templates/hypersense-backend-service.yaml new file mode 100644 index 00000000..7d08ffc3 --- /dev/null +++ b/helm-charts/templates/hypersense-backend-service.yaml @@ -0,0 +1,19 @@ +{{- if .Values.hypersenseBackend.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "decision-engine.hypersenseBackendName" . }} + labels: + {{- include "decision-engine.labels" . | nindent 4 }} + app.kubernetes.io/component: {{ .Values.hypersenseBackend.metadata.labels.component }} +spec: + type: ClusterIP + ports: + - name: http + port: 80 + targetPort: {{ .Values.hypersenseBackend.service.port }} + protocol: TCP + selector: + {{- include "decision-engine.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: {{ .Values.hypersenseBackend.metadata.labels.component }} +{{- end }} diff --git a/helm-charts/templates/hypersense-config.yaml b/helm-charts/templates/hypersense-config.yaml new file mode 100644 index 00000000..016393a1 --- /dev/null +++ b/helm-charts/templates/hypersense-config.yaml @@ -0,0 +1,19 @@ +{{- if and (or .Values.hypersenseBackend.enabled .Values.hypersenseEtl.enabled) .Values.hypersenseShared.create -}} +# Shared connection coordinates for the Hypersense backend + etl services. +# Mirrors the external ConfigMap referenced by the hypersense-main chart; the +# deployments consume these keys via configMapKeyRef. Set hypersenseShared.create +# to false and point hypersenseShared.configMapName at your own ConfigMap to use +# an externally-managed one instead (e.g. pointing DB_HOST at RDS). +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + labels: + {{- include "decision-engine.labels" . | nindent 4 }} +data: + DB_HOST: {{ include "decision-engine.postgresqlHost" . | quote }} + DB_PORT: "5432" + DB_USER: {{ .Values.postgresql.auth.username | quote }} + DB_NAME: {{ .Values.hypersenseShared.dbName | quote }} + REDIS_URL: {{ printf "redis://%s:6379" (include "decision-engine.redisHost" .) | quote }} +{{- end }} diff --git a/helm-charts/templates/hypersense-etl-deployment.yaml b/helm-charts/templates/hypersense-etl-deployment.yaml new file mode 100644 index 00000000..0cc4a8d3 --- /dev/null +++ b/helm-charts/templates/hypersense-etl-deployment.yaml @@ -0,0 +1,161 @@ +{{- if .Values.hypersenseEtl.enabled -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "decision-engine.hypersenseEtlName" . }} + labels: + {{- include "decision-engine.labels" . | nindent 4 }} + app.kubernetes.io/component: {{ .Values.hypersenseEtl.metadata.labels.component }} +spec: + replicas: 1 + selector: + matchLabels: + {{- include "decision-engine.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: {{ .Values.hypersenseEtl.metadata.labels.component }} + template: + metadata: + labels: + {{- include "decision-engine.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: {{ .Values.hypersenseEtl.metadata.labels.component }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "decision-engine.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + {{- if .Values.initContainers.enabled }} + initContainers: + {{- if .Values.decisionEngine.usePostgreSQL }} + - name: wait-for-postgresql + image: "{{ .Values.initContainers.busybox.repository }}:{{ .Values.initContainers.busybox.tag }}" + imagePullPolicy: {{ .Values.initContainers.busybox.pullPolicy }} + command: ['sh', '-c', 'until nc -z {{ include "decision-engine.postgresqlHost" . }} 5432; do echo waiting for postgresql; sleep 2; done;'] + {{- end }} + {{- if .Values.decisionEngine.useRedis }} + - name: wait-for-redis + image: "{{ .Values.initContainers.busybox.repository }}:{{ .Values.initContainers.busybox.tag }}" + imagePullPolicy: {{ .Values.initContainers.busybox.pullPolicy }} + command: ['sh', '-c', 'until nc -z {{ include "decision-engine.redisHost" . }} 6379; do echo waiting for redis; sleep 2; done;'] + {{- end }} + {{- end }} + containers: + - name: hypersense-etl + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.hypersenseEtl.image.repository }}:{{ .Values.hypersenseEtl.image.tag }}" + imagePullPolicy: {{ .Values.hypersenseEtl.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.hypersenseEtl.service.port }} + protocol: TCP + env: + # ── Connection coordinates: from the shared Hypersense ConfigMap ── + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + key: DB_HOST + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + key: DB_PORT + - name: DB_USER + valueFrom: + configMapKeyRef: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + key: DB_USER + - name: DB_NAME + valueFrom: + configMapKeyRef: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + key: DB_NAME + - name: REDIS_URL + valueFrom: + configMapKeyRef: + name: {{ include "decision-engine.hypersenseConfigMapName" . }} + key: REDIS_URL + # ── DB password: from the shared Hypersense Secret ── + - name: DB_PASSWD + valueFrom: + secretKeyRef: + name: {{ include "decision-engine.hypersenseSecretName" . }} + key: DB_PASSWD + # ── Application config: direct values ── + - name: RUNNING_ENV + value: {{ .Values.hypersenseEtl.env.runningEnv | quote }} + - name: MODE + value: {{ .Values.hypersenseEtl.env.mode | quote }} + - name: DB_SCHEMA + value: {{ .Values.hypersenseEtl.env.dbSchema | quote }} + - name: DB_SCHEMA_RE + value: {{ .Values.hypersenseEtl.env.dbSchemaRe | quote }} + - name: DB_SCHEMA_AUTH + value: {{ .Values.hypersenseEtl.env.dbSchemaAuth | quote }} + - name: KAFKA_BOOTSTRAP_SERVERS + value: {{ .Values.hypersenseEtl.env.kafkaBootstrapServers | quote }} + - name: KAFKA_TOPIC + value: {{ .Values.hypersenseEtl.env.kafkaTopic | quote }} + - name: KAFKA_GROUP_ID + value: {{ .Values.hypersenseEtl.env.kafkaGroupId | quote }} + - name: AWS_REGION + value: {{ .Values.hypersenseEtl.env.awsRegion | quote }} + - name: S3_BUCKET + value: {{ .Values.hypersenseEtl.env.s3Bucket | quote }} + - name: CH_HOST + value: {{ .Values.hypersenseEtl.env.clickhouseHost | default .Values.analytics.clickhouse.host | quote }} + - name: CH_PORT + value: {{ .Values.hypersenseEtl.env.clickhousePort | quote }} + - name: CH_USER + value: {{ .Values.hypersenseEtl.env.clickhouseUser | quote }} + - name: CH_NAME + value: {{ .Values.hypersenseEtl.env.clickhouseName | quote }} + - name: AI_BACKEND_HOST + value: {{ .Values.hypersenseEtl.env.aiBackendHost | quote }} + - name: HYPER_SWITCH_BASE_URL + value: {{ .Values.hypersenseEtl.env.hyperSwitchBaseUrl | quote }} + {{- if .Values.hypersenseEtl.migration.runOnStartup }} + - name: RUN_RDS_MIGRATIONS + value: "TRUE" + {{- end }} + {{- range $name, $value := .Values.hypersenseEtl.extraEnvVars }} + - name: {{ $name }} + {{- if and (kindIs "map" $value) $value.valueFrom }} + valueFrom: + {{- toYaml $value.valueFrom | nindent 16 }} + {{- else }} + value: {{ $value | quote }} + {{- end }} + {{- end }} + livenessProbe: + httpGet: + path: {{ .Values.hypersenseEtl.healthcheck.path }} + port: http + initialDelaySeconds: {{ .Values.hypersenseEtl.healthcheck.initialDelaySeconds }} + periodSeconds: {{ .Values.hypersenseEtl.healthcheck.periodSeconds }} + timeoutSeconds: {{ .Values.hypersenseEtl.healthcheck.timeoutSeconds }} + failureThreshold: {{ .Values.hypersenseEtl.healthcheck.failureThreshold }} + readinessProbe: + httpGet: + path: {{ .Values.hypersenseEtl.healthcheck.path }} + port: http + initialDelaySeconds: {{ .Values.hypersenseEtl.healthcheck.initialDelaySeconds }} + periodSeconds: {{ .Values.hypersenseEtl.healthcheck.periodSeconds }} + timeoutSeconds: {{ .Values.hypersenseEtl.healthcheck.timeoutSeconds }} + resources: + {{- toYaml .Values.hypersenseEtl.resources | nindent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/helm-charts/templates/hypersense-etl-service.yaml b/helm-charts/templates/hypersense-etl-service.yaml new file mode 100644 index 00000000..32457f23 --- /dev/null +++ b/helm-charts/templates/hypersense-etl-service.yaml @@ -0,0 +1,19 @@ +{{- if .Values.hypersenseEtl.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "decision-engine.hypersenseEtlName" . }} + labels: + {{- include "decision-engine.labels" . | nindent 4 }} + app.kubernetes.io/component: {{ .Values.hypersenseEtl.metadata.labels.component }} +spec: + type: ClusterIP + ports: + - name: http + port: 80 + targetPort: {{ .Values.hypersenseEtl.service.port }} + protocol: TCP + selector: + {{- include "decision-engine.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: {{ .Values.hypersenseEtl.metadata.labels.component }} +{{- end }} diff --git a/helm-charts/templates/hypersense-secret.yaml b/helm-charts/templates/hypersense-secret.yaml new file mode 100644 index 00000000..9c8d262d --- /dev/null +++ b/helm-charts/templates/hypersense-secret.yaml @@ -0,0 +1,19 @@ +{{- if and (or .Values.hypersenseBackend.enabled .Values.hypersenseEtl.enabled) .Values.hypersenseShared.create -}} +# Shared secret for the Hypersense backend + etl services (DB password). +# Mirrors the external Secret referenced by the hypersense-main chart; the +# deployments consume DB_PASSWD via secretKeyRef. Set hypersenseShared.create to +# false and point hypersenseShared.secretName at your own Secret to use an +# externally-managed one instead. +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "decision-engine.hypersenseSecretName" . }} + labels: + {{- include "decision-engine.labels" . | nindent 4 }} +type: Opaque +stringData: + # The hypersense app reads DB_PASSWD with is_encoded=True and base64-decodes it + # itself (Configs/AppConfigs.py, when RUNNING_ENV=LOCAL or IS_EC2=TRUE), so the + # value delivered to the container must be base64-encoded. Do NOT remove b64enc. + DB_PASSWD: {{ .Values.postgresql.auth.password | b64enc | quote }} +{{- end }} diff --git a/helm-charts/values-hypersense.yaml b/helm-charts/values-hypersense.yaml new file mode 100644 index 00000000..fa43a4a1 --- /dev/null +++ b/helm-charts/values-hypersense.yaml @@ -0,0 +1,116 @@ +# ============================================================================= +# Deployed setup — all services use their remote registry images. +# Covers: decision-engine, groovy-runner, hypersense-backend, hypersense-etl. +# +# Hypersense images live in a PRIVATE ECR registry; you must have been granted +# pull access by Juspay before using this file. +# +# PREREQUISITES +# 1. Create the ECR image-pull secret from the credentials Juspay provided: +# +# kubectl create secret docker-registry hypersense-ecr \ +# --docker-server=701342709052.dkr.ecr.eu-central-1.amazonaws.com \ +# --docker-username=AWS \ +# --docker-password="" \ +# --namespace decision-engine +# +# INSTALL +# helm install de helm-charts/ -f helm-charts/values-hypersense.yaml \ +# --namespace decision-engine --create-namespace +# +# The migration job (dbMigration.enabled: true) downloads and compiles Diesel +# to run schema migrations on first install. It can be disabled after the first +# successful install by adding --set dbMigration.enabled=false on upgrades. +# ============================================================================= + +# Pull secret for private ECR images (hypersense-backend, hypersense-etl). +# Decision Engine and Groovy Runner are on public GHCR and don't need it, +# but Kubernetes applies imagePullSecrets to all containers in the pod spec. +imagePullSecrets: + - name: hypersense-ecr + +# Decision Engine — remote GHCR image, always pull latest +image: + repository: ghcr.io/juspay/decision-engine/postgres + version: "v1.4" + pullPolicy: Always + +# Groovy Runner — remote GHCR image, always pull latest +groovyRunner: + enabled: true + image: + repository: ghcr.io/juspay/decision-engine/groovy-runner + version: "v1.4" + pullPolicy: Always + +# PostgreSQL — persistent storage for deployed environment +postgresql: + enabled: true + auth: + username: "db_user" + password: "db_pass" + database: "decision_engine_db" + primary: + persistence: + enabled: true + size: 8Gi + +# Redis — persistent storage for deployed environment +redis: + enabled: true + auth: + enabled: false + master: + persistence: + enabled: true + size: 8Gi + replica: + replicaCount: 1 + persistence: + enabled: true + size: 8Gi + +# Run the DE schema migration job on install/upgrade +dbMigration: + enabled: true + postgresql: + enabled: true + +# Shared config + secret for the Hypersense services (backend + etl). +# +# Default below: the chart renders the ConfigMap + Secret from the in-cluster +# PostgreSQL/Redis values — deployed setup works out of the box. +# +# To use EXTERNAL (pre-created) resources instead — e.g. DB_HOST pointing at an +# RDS instance managed outside the chart — flip create to false and name them: +# +# hypersenseShared: +# create: false +# configMapName: hypersense-config # you create this ConfigMap first +# secretName: hypersense-secret # you create this Secret first +# +# Required ConfigMap keys: DB_HOST, DB_PORT, DB_USER, DB_NAME, REDIS_URL +# Required Secret key: DB_PASSWD +hypersenseShared: + create: true + dbName: "hypersense_db" + +# Hypersense Backend — remote ECR image, always pull latest +hypersenseBackend: + enabled: true + image: + repository: 701342709052.dkr.ecr.eu-central-1.amazonaws.com/hypersense/backend + tag: "hypersense-backend-sandbox-latest" + pullPolicy: Always + migration: + runOnStartup: true + +# Hypersense ETL — remote ECR image, always pull latest +hypersenseEtl: + enabled: true + image: + repository: 701342709052.dkr.ecr.eu-central-1.amazonaws.com/hypersense/backend + tag: "hypersense-etl-sandbox-latest" + pullPolicy: Always + migration: + runOnStartup: true diff --git a/helm-charts/values-local.yaml b/helm-charts/values-local.yaml new file mode 100644 index 00000000..94f8e72c --- /dev/null +++ b/helm-charts/values-local.yaml @@ -0,0 +1,124 @@ +# ============================================================================= +# Local development setup — uses locally built images for hypersense services. +# Decision Engine and Groovy Runner use cached GHCR images (pulled once). +# +# PREREQUISITES +# Build hypersense images and load them into your local cluster: +# docker build -t hypersense-backend:local +# docker build -t hypersense-etl:local +# +# If using minikube: +# minikube image load hypersense-backend:local +# minikube image load hypersense-etl:local +# +# If using kind: +# kind load docker-image hypersense-backend:local +# kind load docker-image hypersense-etl:local +# +# INSTALL +# helm install de helm-charts/ -f helm-charts/values-local.yaml \ +# --namespace decision-engine --create-namespace +# +# NOTE: DE database migrations are skipped (dbMigration.enabled: false) because +# the migration job requires downloading and compiling Rust source which is too +# slow for local iteration. Run DE migrations manually before first deploy: +# DATABASE_URL="postgres://db_user:db_pass@localhost:5432/decision_engine_db" \ +# diesel migration run --migration-dir migrations_pg +# ============================================================================= + +initContainers: + enabled: true + busybox: + repository: busybox + tag: "1.28" + pullPolicy: IfNotPresent + +# Decision Engine — cached GHCR image; pulled once, reused locally +image: + repository: ghcr.io/juspay/decision-engine/postgres + version: "v1.4" + pullPolicy: IfNotPresent + +# Groovy Runner — cached GHCR image +groovyRunner: + enabled: true + image: + repository: ghcr.io/juspay/decision-engine/groovy-runner + version: "v1.4" + pullPolicy: IfNotPresent + +# PostgreSQL — ephemeral (no PVC); hypersense_db is created via initdb.scripts in values.yaml +postgresql: + enabled: true + auth: + username: "db_user" + password: "db_pass" + database: "decision_engine_db" + primary: + persistence: + enabled: false + +# Redis — ephemeral (no PVC), single master, no replicas +redis: + enabled: true + auth: + enabled: false + master: + persistence: + enabled: false + replica: + replicaCount: 0 + +# Skip the migration job — it compiles diesel_cli from source and takes 30+ min +dbMigration: + enabled: false + +# Hypersense Backend — locally built image, never pulled from registry +hypersenseBackend: + enabled: true + image: + repository: hypersense-backend + tag: "local" + pullPolicy: Never + env: + runningEnv: "LOCAL" + mode: "DEV" + dbSchema: "hs_v1" + dbSchemaRe: "rule_engine" + dbSchemaAuth: "auth_v1" + awsRegion: "ap-south-1" + kafkaBootstrapServers: "" + kafkaTopic: "hypersense-etl-topic" + kafkaGroupId: "hypersense-etl-group" + s3Bucket: "hypersense-sbx-reports" + aiBackendHost: "" + hyperSwitchBaseUrl: "" + migration: + runOnStartup: true + +# Hypersense ETL — locally built image, never pulled from registry +hypersenseEtl: + enabled: true + image: + repository: hypersense-etl + tag: "local" + pullPolicy: Never + env: + runningEnv: "LOCAL" + mode: "DEV" + dbSchema: "hs_v1" + dbSchemaRe: "rule_engine" + dbSchemaAuth: "auth_v1" + awsRegion: "ap-south-1" + kafkaBootstrapServers: "" + kafkaTopic: "hypersense-etl-topic" + kafkaGroupId: "hypersense-etl-group" + s3Bucket: "hypersense-sbx-reports" + clickhouseHost: "" + clickhousePort: 8123 + clickhouseUser: "default" + clickhouseName: "default" + aiBackendHost: "" + hyperSwitchBaseUrl: "" + migration: + runOnStartup: true diff --git a/helm-charts/values.yaml b/helm-charts/values.yaml index c602411b..af25e4fb 100644 --- a/helm-charts/values.yaml +++ b/helm-charts/values.yaml @@ -174,6 +174,11 @@ postgresql: persistence: enabled: true size: 8Gi + initdb: + scripts: + create_hypersense_db.sql: | + CREATE DATABASE hypersense_db; + GRANT ALL PRIVILEGES ON DATABASE hypersense_db TO db_user; # Redis configuration redis: @@ -264,6 +269,116 @@ extraEnvVars: {} # name: app-config # key: config.json +# Shared config + secret for the Hypersense services (backend + etl). +# Modelled on the hypersense-main chart: connection coordinates live in a +# ConfigMap and the DB password in a Secret, both referenced by the deployments +# via configMapKeyRef / secretKeyRef. +hypersenseShared: + # true → the chart renders the ConfigMap + Secret from the values below + # (works out of the box for the local + in-cluster deployed setups). + # false → use pre-existing (external) resources; you must create them first + # and set configMapName / secretName to their names. Lets you point + # DB_HOST at an external DB (e.g. RDS) without the chart knowing. + create: true + # Names to reference. Empty => chart-generated "-hypersense-config" + # and "-hypersense-secret". + configMapName: "" + secretName: "" + # Hypersense database name (shared by backend + etl; distinct from decision_engine_db) + dbName: "hypersense_db" + +# Hypersense Backend configuration +hypersenseBackend: + enabled: false + image: + repository: "701342709052.dkr.ecr.eu-central-1.amazonaws.com/hypersense/backend" + tag: "hypersense-backend-sandbox-latest" + pullPolicy: "Always" + service: + port: 8081 + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "1Gi" + healthcheck: + path: "/healthcheck" + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + migration: + runOnStartup: false + env: + runningEnv: "LOCAL" + mode: "DEV" + # dbName / DB connection now come from hypersenseShared via the ConfigMap + dbSchema: "hs_v1" + dbSchemaRe: "rule_engine" + dbSchemaAuth: "auth_v1" + awsRegion: "ap-south-1" + kafkaBootstrapServers: "" + kafkaTopic: "hypersense-etl-topic" + kafkaGroupId: "hypersense-etl-group" + s3Bucket: "hypersense-sbx-reports" + aiBackendHost: "" + hyperSwitchBaseUrl: "https://integ.hyperswitch.io/api" + extraEnvVars: {} + metadata: + labels: + component: hypersense-backend + +# Hypersense ETL configuration +hypersenseEtl: + enabled: false + image: + repository: "701342709052.dkr.ecr.eu-central-1.amazonaws.com/hypersense/backend" + tag: "hypersense-etl-sandbox-latest" + pullPolicy: "Always" + service: + port: 8081 + resources: {} + healthcheck: + path: "/healthcheck" + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 5 + env: + runningEnv: "LOCAL" + mode: "DEV" + # dbName / DB connection now come from hypersenseShared via the ConfigMap + dbSchema: "hs_v1" + dbSchemaRe: "rule_engine" + dbSchemaAuth: "auth_v1" + awsRegion: "ap-south-1" + kafkaBootstrapServers: "" + kafkaTopic: "hypersense-etl-topic" + kafkaGroupId: "hypersense-etl-group" + s3Bucket: "hypersense-sbx-reports" + # ClickHouse — leave empty to fall back to analytics.clickhouse.host + clickhouseHost: "" + clickhousePort: 8123 + clickhouseUser: "default" + clickhouseName: "default" + aiBackendHost: "" + hyperSwitchBaseUrl: "https://integ.hyperswitch.io/api" + resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "1Gi" + migration: + runOnStartup: false + extraEnvVars: {} + metadata: + labels: + component: hypersense-etl + # Istio configuration (optional) istio: enabled: false From 0ac527a241d3b2ee793801adf1a2740046b133da Mon Sep 17 00:00:00 2001 From: Gaurav Rawat Date: Fri, 3 Jul 2026 17:16:51 +0530 Subject: [PATCH 2/2] feat(helm): update deployment and values for Hypersense integration; remove local values --- helm-charts/templates/deployment.yaml | 4 + helm-charts/values-hypersense.yaml | 116 ------------------------ helm-charts/values-local.yaml | 124 -------------------------- helm-charts/values.yaml | 23 +++-- 4 files changed, 19 insertions(+), 248 deletions(-) delete mode 100644 helm-charts/values-hypersense.yaml delete mode 100644 helm-charts/values-local.yaml diff --git a/helm-charts/templates/deployment.yaml b/helm-charts/templates/deployment.yaml index b06fed2b..f4a3d777 100644 --- a/helm-charts/templates/deployment.yaml +++ b/helm-charts/templates/deployment.yaml @@ -84,6 +84,10 @@ spec: value: {{ include "decision-engine.redisHost" . | quote }} - name: DECISION_ENGINE__ANALYTICS__ENABLED value: {{ ternary "true" "false" .Values.analytics.enabled | quote }} + - name: DECISION_ENGINE__ANALYTICS__KAFKA__ENABLED + value: {{ ternary "true" "false" .Values.analytics.enabled | quote }} + - name: DECISION_ENGINE__ANALYTICS__CLICKHOUSE__ENABLED + value: {{ ternary "true" "false" .Values.analytics.enabled | quote }} - name: DECISION_ENGINE__ANALYTICS__KAFKA__BROKERS value: {{ .Values.analytics.kafka.brokers | quote }} - name: DECISION_ENGINE__ANALYTICS__KAFKA__API_TOPIC diff --git a/helm-charts/values-hypersense.yaml b/helm-charts/values-hypersense.yaml deleted file mode 100644 index fa43a4a1..00000000 --- a/helm-charts/values-hypersense.yaml +++ /dev/null @@ -1,116 +0,0 @@ -# ============================================================================= -# Deployed setup — all services use their remote registry images. -# Covers: decision-engine, groovy-runner, hypersense-backend, hypersense-etl. -# -# Hypersense images live in a PRIVATE ECR registry; you must have been granted -# pull access by Juspay before using this file. -# -# PREREQUISITES -# 1. Create the ECR image-pull secret from the credentials Juspay provided: -# -# kubectl create secret docker-registry hypersense-ecr \ -# --docker-server=701342709052.dkr.ecr.eu-central-1.amazonaws.com \ -# --docker-username=AWS \ -# --docker-password="" \ -# --namespace decision-engine -# -# INSTALL -# helm install de helm-charts/ -f helm-charts/values-hypersense.yaml \ -# --namespace decision-engine --create-namespace -# -# The migration job (dbMigration.enabled: true) downloads and compiles Diesel -# to run schema migrations on first install. It can be disabled after the first -# successful install by adding --set dbMigration.enabled=false on upgrades. -# ============================================================================= - -# Pull secret for private ECR images (hypersense-backend, hypersense-etl). -# Decision Engine and Groovy Runner are on public GHCR and don't need it, -# but Kubernetes applies imagePullSecrets to all containers in the pod spec. -imagePullSecrets: - - name: hypersense-ecr - -# Decision Engine — remote GHCR image, always pull latest -image: - repository: ghcr.io/juspay/decision-engine/postgres - version: "v1.4" - pullPolicy: Always - -# Groovy Runner — remote GHCR image, always pull latest -groovyRunner: - enabled: true - image: - repository: ghcr.io/juspay/decision-engine/groovy-runner - version: "v1.4" - pullPolicy: Always - -# PostgreSQL — persistent storage for deployed environment -postgresql: - enabled: true - auth: - username: "db_user" - password: "db_pass" - database: "decision_engine_db" - primary: - persistence: - enabled: true - size: 8Gi - -# Redis — persistent storage for deployed environment -redis: - enabled: true - auth: - enabled: false - master: - persistence: - enabled: true - size: 8Gi - replica: - replicaCount: 1 - persistence: - enabled: true - size: 8Gi - -# Run the DE schema migration job on install/upgrade -dbMigration: - enabled: true - postgresql: - enabled: true - -# Shared config + secret for the Hypersense services (backend + etl). -# -# Default below: the chart renders the ConfigMap + Secret from the in-cluster -# PostgreSQL/Redis values — deployed setup works out of the box. -# -# To use EXTERNAL (pre-created) resources instead — e.g. DB_HOST pointing at an -# RDS instance managed outside the chart — flip create to false and name them: -# -# hypersenseShared: -# create: false -# configMapName: hypersense-config # you create this ConfigMap first -# secretName: hypersense-secret # you create this Secret first -# -# Required ConfigMap keys: DB_HOST, DB_PORT, DB_USER, DB_NAME, REDIS_URL -# Required Secret key: DB_PASSWD -hypersenseShared: - create: true - dbName: "hypersense_db" - -# Hypersense Backend — remote ECR image, always pull latest -hypersenseBackend: - enabled: true - image: - repository: 701342709052.dkr.ecr.eu-central-1.amazonaws.com/hypersense/backend - tag: "hypersense-backend-sandbox-latest" - pullPolicy: Always - migration: - runOnStartup: true - -# Hypersense ETL — remote ECR image, always pull latest -hypersenseEtl: - enabled: true - image: - repository: 701342709052.dkr.ecr.eu-central-1.amazonaws.com/hypersense/backend - tag: "hypersense-etl-sandbox-latest" - pullPolicy: Always - migration: - runOnStartup: true diff --git a/helm-charts/values-local.yaml b/helm-charts/values-local.yaml deleted file mode 100644 index 94f8e72c..00000000 --- a/helm-charts/values-local.yaml +++ /dev/null @@ -1,124 +0,0 @@ -# ============================================================================= -# Local development setup — uses locally built images for hypersense services. -# Decision Engine and Groovy Runner use cached GHCR images (pulled once). -# -# PREREQUISITES -# Build hypersense images and load them into your local cluster: -# docker build -t hypersense-backend:local -# docker build -t hypersense-etl:local -# -# If using minikube: -# minikube image load hypersense-backend:local -# minikube image load hypersense-etl:local -# -# If using kind: -# kind load docker-image hypersense-backend:local -# kind load docker-image hypersense-etl:local -# -# INSTALL -# helm install de helm-charts/ -f helm-charts/values-local.yaml \ -# --namespace decision-engine --create-namespace -# -# NOTE: DE database migrations are skipped (dbMigration.enabled: false) because -# the migration job requires downloading and compiling Rust source which is too -# slow for local iteration. Run DE migrations manually before first deploy: -# DATABASE_URL="postgres://db_user:db_pass@localhost:5432/decision_engine_db" \ -# diesel migration run --migration-dir migrations_pg -# ============================================================================= - -initContainers: - enabled: true - busybox: - repository: busybox - tag: "1.28" - pullPolicy: IfNotPresent - -# Decision Engine — cached GHCR image; pulled once, reused locally -image: - repository: ghcr.io/juspay/decision-engine/postgres - version: "v1.4" - pullPolicy: IfNotPresent - -# Groovy Runner — cached GHCR image -groovyRunner: - enabled: true - image: - repository: ghcr.io/juspay/decision-engine/groovy-runner - version: "v1.4" - pullPolicy: IfNotPresent - -# PostgreSQL — ephemeral (no PVC); hypersense_db is created via initdb.scripts in values.yaml -postgresql: - enabled: true - auth: - username: "db_user" - password: "db_pass" - database: "decision_engine_db" - primary: - persistence: - enabled: false - -# Redis — ephemeral (no PVC), single master, no replicas -redis: - enabled: true - auth: - enabled: false - master: - persistence: - enabled: false - replica: - replicaCount: 0 - -# Skip the migration job — it compiles diesel_cli from source and takes 30+ min -dbMigration: - enabled: false - -# Hypersense Backend — locally built image, never pulled from registry -hypersenseBackend: - enabled: true - image: - repository: hypersense-backend - tag: "local" - pullPolicy: Never - env: - runningEnv: "LOCAL" - mode: "DEV" - dbSchema: "hs_v1" - dbSchemaRe: "rule_engine" - dbSchemaAuth: "auth_v1" - awsRegion: "ap-south-1" - kafkaBootstrapServers: "" - kafkaTopic: "hypersense-etl-topic" - kafkaGroupId: "hypersense-etl-group" - s3Bucket: "hypersense-sbx-reports" - aiBackendHost: "" - hyperSwitchBaseUrl: "" - migration: - runOnStartup: true - -# Hypersense ETL — locally built image, never pulled from registry -hypersenseEtl: - enabled: true - image: - repository: hypersense-etl - tag: "local" - pullPolicy: Never - env: - runningEnv: "LOCAL" - mode: "DEV" - dbSchema: "hs_v1" - dbSchemaRe: "rule_engine" - dbSchemaAuth: "auth_v1" - awsRegion: "ap-south-1" - kafkaBootstrapServers: "" - kafkaTopic: "hypersense-etl-topic" - kafkaGroupId: "hypersense-etl-group" - s3Bucket: "hypersense-sbx-reports" - clickhouseHost: "" - clickhousePort: 8123 - clickhouseUser: "default" - clickhouseName: "default" - aiBackendHost: "" - hyperSwitchBaseUrl: "" - migration: - runOnStartup: true diff --git a/helm-charts/values.yaml b/helm-charts/values.yaml index af25e4fb..dbdaeee7 100644 --- a/helm-charts/values.yaml +++ b/helm-charts/values.yaml @@ -7,7 +7,8 @@ image: pullPolicy: Always version: "v1.4" -# Configure these if your images are in a private registry +# Only needed if you enable Hypersense with images in a private registry. +# Decision Engine + Groovy Runner are public (GHCR) and need no pull secret. imagePullSecrets: # - name: regcred nameOverride: "" @@ -31,7 +32,7 @@ initContainers: # Set to false to disable all init containers enabled: true busybox: - repository: public.ecr.aws/docker/library/busybox + repository: docker.io/library/busybox tag: "1.28" pullPolicy: IfNotPresent @@ -287,12 +288,16 @@ hypersenseShared: # Hypersense database name (shared by backend + etl; distinct from decision_engine_db) dbName: "hypersense_db" -# Hypersense Backend configuration +# Hypersense Backend — OFF by default (proprietary Juspay add-on). +# The image source is deployment-specific (a private registry you were granted +# access to, or an image Juspay provides) — it is intentionally left blank. +# To enable: set image.repository/tag to a registry you can pull from, uncomment +# imagePullSecrets above if it is private, then flip enabled: true. hypersenseBackend: enabled: false image: - repository: "701342709052.dkr.ecr.eu-central-1.amazonaws.com/hypersense/backend" - tag: "hypersense-backend-sandbox-latest" + repository: "" # e.g. 701342709052.dkr.ecr.eu-central-1.amazonaws.com/hypersense/backend + tag: "" # e.g. hypersense-backend-sandbox-latest pullPolicy: "Always" service: port: 8081 @@ -330,12 +335,14 @@ hypersenseBackend: labels: component: hypersense-backend -# Hypersense ETL configuration +# Hypersense ETL — OFF by default (proprietary Juspay add-on). See hypersenseBackend +# above for how to enable. Set the image to a registry you can pull from, then flip +# enabled: true. hypersenseEtl: enabled: false image: - repository: "701342709052.dkr.ecr.eu-central-1.amazonaws.com/hypersense/backend" - tag: "hypersense-etl-sandbox-latest" + repository: "" # e.g. 701342709052.dkr.ecr.eu-central-1.amazonaws.com/hypersense/backend + tag: "" # e.g. hypersense-etl-sandbox-latest pullPolicy: "Always" service: port: 8081