From ecaf232ed9450c50f50ed65bb0992066c4dd8763 Mon Sep 17 00:00:00 2001 From: Jacek N Date: Tue, 3 Mar 2026 12:38:46 +0000 Subject: [PATCH 1/2] Improve friendbot helm chart The changes should be backwards compatible * add support for pre-existing secret * move non-sensitive config from a Secret to a ConfigMap * add support for otel config options * add support for using rpc_url * add support for using fund_contract_addresses * add support for adding Deployment annotations * add support for non-standard deployment strategy * add support for setting ingressClassName --- charts/friendbot/Chart.yaml | 2 +- charts/friendbot/templates/_helpers.tpl | 9 +++++ .../friendbot/templates/friendbot-config.yaml | 38 +++++++++++++++++++ .../templates/friendbot-deployment.yaml | 25 ++++++++++-- .../templates/friendbot-ingress.yaml | 3 ++ .../friendbot/templates/friendbot-secret.yaml | 26 ++++++------- charts/friendbot/values.yaml | 36 +++++++++++++++--- 7 files changed, 115 insertions(+), 24 deletions(-) create mode 100644 charts/friendbot/templates/friendbot-config.yaml diff --git a/charts/friendbot/Chart.yaml b/charts/friendbot/Chart.yaml index 5e87c1d..2845cf9 100644 --- a/charts/friendbot/Chart.yaml +++ b/charts/friendbot/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: friendbot description: This chart will deploy friendbot to your private network -version: 0.0.3 +version: 0.0.4 appVersion: "bbdf3132" maintainers: - name: Stellar Development Foundation diff --git a/charts/friendbot/templates/_helpers.tpl b/charts/friendbot/templates/_helpers.tpl index a33db05..ff95a85 100644 --- a/charts/friendbot/templates/_helpers.tpl +++ b/charts/friendbot/templates/_helpers.tpl @@ -22,3 +22,12 @@ {{- define "common.friendbotImage" -}} {{ .Values.global.image.friendbot.registry }}/{{ .Values.global.image.friendbot.repository }}:{{ .Values.global.image.friendbot.tag | default .Chart.AppVersion }} {{- end -}} + +{{- define "friendbot.secretName" -}} +{{- $friendbotSecret := get .Values.friendbot "secret" | default dict -}} +{{- if (get $friendbotSecret "existingSecret") -}} +{{- get $friendbotSecret "existingSecret" -}} +{{- else -}} +{{- printf "%s-secret" (include "common.fullname" .) -}} +{{- end -}} +{{- end -}} diff --git a/charts/friendbot/templates/friendbot-config.yaml b/charts/friendbot/templates/friendbot-config.yaml new file mode 100644 index 0000000..d526cb4 --- /dev/null +++ b/charts/friendbot/templates/friendbot-config.yaml @@ -0,0 +1,38 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "common.fullname" . }}-config + {{- if .Release.Namespace }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app: {{ template "common.fullname" . }} + chart: {{ template "common.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: + friendbot.conf: | + {{- $config := .Values.friendbot.configmap | default dict }} + {{- $horizonUrl := coalesce .Values.friendbot.configmap.horizon_url .Values.global.horizonUrl (printf "%s-horizon-ingest" .Release.Name) }} + port = {{ .Values.friendbot.configmap.port | default 8000 }} + network_passphrase = {{ .Values.global.networkPassphrase | quote }} + {{- if .Values.friendbot.configmap.rpc_url }} + rpc_url = {{ .Values.friendbot.configmap.rpc_url | quote }} + {{- else }} + horizon_url = {{ $horizonUrl | quote }} + {{- end }} + starting_balance = {{ .Values.friendbot.configmap.starting_balance | default 10000 | quote }} + num_minions = {{ .Values.friendbot.configmap.num_minions | default 1000 }} + base_fee = {{ .Values.friendbot.configmap.base_fee | default 100000 }} + minion_batch_size = {{ .Values.friendbot.configmap.minion_batch_size | default 50 }} + submit_tx_retries_allowed = {{ .Values.friendbot.configmap.submit_tx_retries_allowed | default .Values.friendbot.configmap.tx | default 5 }} + {{- if hasKey $config "otel_enabled" }} + otel_enabled = {{ .Values.friendbot.configmap.otel_enabled }} + {{- end }} + {{- if .Values.friendbot.configmap.otel_enabled }} + otel_endpoint = {{ required "Set friendbot.configmap.otel_endpoint when friendbot.configmap.otel_enabled=true" .Values.friendbot.configmap.otel_endpoint | quote }} + {{- end }} + {{- if hasKey $config "fund_contract_addresses" }} + fund_contract_addresses = {{ .Values.friendbot.configmap.fund_contract_addresses }} + {{- end }} diff --git a/charts/friendbot/templates/friendbot-deployment.yaml b/charts/friendbot/templates/friendbot-deployment.yaml index 8724caf..e0ab0c7 100644 --- a/charts/friendbot/templates/friendbot-deployment.yaml +++ b/charts/friendbot/templates/friendbot-deployment.yaml @@ -13,13 +13,23 @@ metadata: chart: {{ template "common.chart" . }} release: {{ .Release.Name }} heritage: {{ .Release.Service }} + {{- if (.Values.friendbot.deployment).deploymentAnnotations }} + annotations: + {{- range $key, $value := .Values.friendbot.deployment.deploymentAnnotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} spec: replicas: {{ .Values.friendbot.deployment.container.replicaCount }} selector: matchLabels: app: {{ template "common.fullname" . }} strategy: + {{- if .Values.friendbot.deployment.strategy }} + {{- toYaml .Values.friendbot.deployment.strategy | nindent 4 }} + {{- else }} type: RollingUpdate + {{- end }} template: metadata: labels: @@ -50,6 +60,9 @@ spec: {{- end }} {{- end }} imagePullPolicy: {{ .Values.global.image.friendbot.pullPolicy }} + ports: + - containerPort: {{ .Values.friendbot.service.targetport | default 8004 }} + protocol: TCP startupProbe: tcpSocket: port: {{ .Values.friendbot.deployment.container.startupProbe.tcpSocketPort }} @@ -58,10 +71,16 @@ spec: periodSeconds: {{ .Values.friendbot.deployment.container.startupProbe.periodSeconds }} timeoutSeconds: {{ .Values.friendbot.deployment.container.startupProbe.timeoutSeconds }} volumeMounts: - - name: config-volume + - name: friendbot-secret + mountPath: /secret + readOnly: true + - name: friendbot-conf mountPath: /config readOnly: true volumes: - - name: config-volume + - name: friendbot-secret secret: - secretName: {{ template "common.fullname" . }}-vol + secretName: {{ include "friendbot.secretName" . }} + - name: friendbot-conf + configMap: + name: {{ template "common.fullname" . }}-config \ No newline at end of file diff --git a/charts/friendbot/templates/friendbot-ingress.yaml b/charts/friendbot/templates/friendbot-ingress.yaml index fea0ee1..259826f 100644 --- a/charts/friendbot/templates/friendbot-ingress.yaml +++ b/charts/friendbot/templates/friendbot-ingress.yaml @@ -13,6 +13,9 @@ metadata: {{- end }} {{- end }} spec: + {{- if .Values.friendbot.ingress.ingressClassName }} + ingressClassName: {{ .Values.friendbot.ingress.ingressClassName }} + {{- end }} tls: - secretName: {{ template "common.fullname" . }}-cert hosts: diff --git a/charts/friendbot/templates/friendbot-secret.yaml b/charts/friendbot/templates/friendbot-secret.yaml index 4d02e8d..0214dc1 100644 --- a/charts/friendbot/templates/friendbot-secret.yaml +++ b/charts/friendbot/templates/friendbot-secret.yaml @@ -1,8 +1,15 @@ +{{- $friendbotSecret := get .Values.friendbot "secret" | default dict }} +{{- $friendbotConfig := get .Values.friendbot "configmap" | default dict }} +{{- $friendbotAccountSeed := coalesce (get $friendbotSecret "friendbotAccountSeed") (get $friendbotConfig "friendbotAccountSeed") "" }} +{{- if and (get $friendbotSecret "existingSecret") (get $friendbotSecret "friendbotAccountSeed") }} +{{- fail "Set either friendbot.secret.existingSecret or friendbot.secret.friendbotAccountSeed, but not both" }} +{{- end }} +{{- if not (get $friendbotSecret "existingSecret") }} --- apiVersion: v1 kind: Secret metadata: - name: {{ template "common.fullname" . }}-vol + name: {{ include "friendbot.secretName" . }} {{- if .Release.Namespace }} namespace: {{ .Release.Namespace }} {{- end }} @@ -12,17 +19,6 @@ metadata: release: {{ .Release.Name }} heritage: {{ .Release.Service }} stringData: - friendbot.conf: | - port = {{ .Values.friendbot.configmap.port | default 8000 }} - friendbot_secret = {{ .Values.friendbot.configmap.friendbotAccountSeed | quote }} - network_passphrase = {{ .Values.global.networkPassphrase | quote }} - starting_balance = {{ .Values.friendbot.configmap.starting_balance | default 10000 | quote }} - num_minions = {{ .Values.friendbot.configmap.num_minions | default 1000 }} - base_fee = {{ .Values.friendbot.configmap.base_fee | default 100000 }} - minion_batch_size = {{ .Values.friendbot.configmap.minion_batch_size | default 50 }} - submit_tx_retries_allowed = {{ .Values.friendbot.configmap.submit_tx_retries_allowed | default .Values.friendbot.configmap.tx | default 5 }} - {{- if (.Values.global).horizonUrl }} - horizon_url = {{ .Values.global.horizonUrl | quote }} - {{- else }} - horizon_url = {{ .Release.Name }}-horizon-ingest - {{- end }} + secret.conf: | + friendbot_secret = {{ required "Set friendbot.secret.existingSecret or set friendbot.secret.friendbotAccountSeed (legacy fallback: friendbot.configmap.friendbotAccountSeed)" $friendbotAccountSeed | quote }} +{{- end }} diff --git a/charts/friendbot/values.yaml b/charts/friendbot/values.yaml index a277389..06b5bd5 100644 --- a/charts/friendbot/values.yaml +++ b/charts/friendbot/values.yaml @@ -21,10 +21,19 @@ friendbot: # serviceAccountName: default deployment: + # deploymentAnnotations: + # reloader.stakater.com/auto: "true" + strategy: + type: RollingUpdate + # rollingUpdate: + # maxUnavailable: 0 + # maxSurge: 1 container: cliArgs: - --conf - /config/friendbot.conf + - --secret + - /secret/secret.conf replicaCount: 1 startupProbe: tcpSocketPort: 8004 @@ -44,18 +53,35 @@ friendbot: targetport: 8004 ingress: - # port: 80 - #annotations: - # kubernetes.io/ingress.class: "public" - # cert-manager.io/cluster-issuer: "default" host: "friendbot.example.com" + # ingressClassName: "" + # port: 80 + # annotations: + # cert-manager.io/cluster-issuer: "default" + + secret: + ## Friendbot requires account seed to be configured. This can be provided using two mutually exclusive ways: + ## 1. Using the friendbotAccountSeed value. The chart will create secret with the required content + ## If not set, chart falls back to legacy friendbot.configmap.friendbotAccountSeed + ## 2. Using the existingSecret value. The chart will mount the secret in the Deployment. + ## Required format for existingSecret: + ## - Secret must contain a key named `secret.conf` + ## - That key is mounted as /secret/secret.conf (used by container args) + ## - secret.conf content must use: friendbot_secret = "" + # friendbotAccountSeed: "XXXXXXX" + # existingSecret: "" configmap: port: 8000 - # friendbotAccountSeed: "XXXXXXX" # this comes from stellar-network parent chart + # friendbotAccountSeed: "XXXXXXX" # legacy fallback; prefer friendbot.secret.friendbotAccountSeed + # otel_enabled: false + # otel_endpoint: "http://otel-collector:4318" + # rpc_url: "https://soroban-rpc.example.com" + # horizon_url: "https://horizon-testnet.stellar.org" # starting_balance: 10000 # num_minions: 1000 # base_fee: 10000 # minion_batch_size: 50 # submit_tx_retries_allowed: 5 + # fund_contract_addresses: true From c5d14c94824d62c22e8b48fff9fb72a728ebfca0 Mon Sep 17 00:00:00 2001 From: Jacek N Date: Tue, 3 Mar 2026 16:40:29 +0000 Subject: [PATCH 2/2] Standarize port handling --- .../friendbot/templates/friendbot-config.yaml | 2 +- .../templates/friendbot-deployment.yaml | 17 +++++++++-------- .../friendbot/templates/friendbot-ingress.yaml | 2 +- .../friendbot/templates/friendbot-service.yaml | 4 ++-- charts/friendbot/values.yaml | 9 ++------- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/charts/friendbot/templates/friendbot-config.yaml b/charts/friendbot/templates/friendbot-config.yaml index d526cb4..c60275e 100644 --- a/charts/friendbot/templates/friendbot-config.yaml +++ b/charts/friendbot/templates/friendbot-config.yaml @@ -24,7 +24,7 @@ data: {{- end }} starting_balance = {{ .Values.friendbot.configmap.starting_balance | default 10000 | quote }} num_minions = {{ .Values.friendbot.configmap.num_minions | default 1000 }} - base_fee = {{ .Values.friendbot.configmap.base_fee | default 100000 }} + base_fee = {{ .Values.friendbot.configmap.base_fee | default 100000 | int64 }} minion_batch_size = {{ .Values.friendbot.configmap.minion_batch_size | default 50 }} submit_tx_retries_allowed = {{ .Values.friendbot.configmap.submit_tx_retries_allowed | default .Values.friendbot.configmap.tx | default 5 }} {{- if hasKey $config "otel_enabled" }} diff --git a/charts/friendbot/templates/friendbot-deployment.yaml b/charts/friendbot/templates/friendbot-deployment.yaml index e0ab0c7..be984c3 100644 --- a/charts/friendbot/templates/friendbot-deployment.yaml +++ b/charts/friendbot/templates/friendbot-deployment.yaml @@ -61,15 +61,16 @@ spec: {{- end }} imagePullPolicy: {{ .Values.global.image.friendbot.pullPolicy }} ports: - - containerPort: {{ .Values.friendbot.service.targetport | default 8004 }} + - containerPort: {{ .Values.friendbot.configmap.port | default 8000 }} protocol: TCP + {{- with .Values.friendbot.deployment.container.startupProbe }} + {{- $startupProbe := deepCopy . }} + {{- if and (hasKey $startupProbe "tcpSocket") (kindIs "map" $startupProbe.tcpSocket) (not (hasKey $startupProbe.tcpSocket "port")) }} + {{- $_ := set $startupProbe.tcpSocket "port" ($.Values.friendbot.configmap.port | default 8000) }} + {{- end }} startupProbe: - tcpSocket: - port: {{ .Values.friendbot.deployment.container.startupProbe.tcpSocketPort }} - initialDelaySeconds: {{ .Values.friendbot.deployment.container.startupProbe.initialDelaySeconds }} - failureThreshold: {{ .Values.friendbot.deployment.container.startupProbe.failureThreshold }} - periodSeconds: {{ .Values.friendbot.deployment.container.startupProbe.periodSeconds }} - timeoutSeconds: {{ .Values.friendbot.deployment.container.startupProbe.timeoutSeconds }} + {{- toYaml $startupProbe | nindent 10 }} + {{- end }} volumeMounts: - name: friendbot-secret mountPath: /secret @@ -83,4 +84,4 @@ spec: secretName: {{ include "friendbot.secretName" . }} - name: friendbot-conf configMap: - name: {{ template "common.fullname" . }}-config \ No newline at end of file + name: {{ template "common.fullname" . }}-config diff --git a/charts/friendbot/templates/friendbot-ingress.yaml b/charts/friendbot/templates/friendbot-ingress.yaml index 259826f..c0688f9 100644 --- a/charts/friendbot/templates/friendbot-ingress.yaml +++ b/charts/friendbot/templates/friendbot-ingress.yaml @@ -30,4 +30,4 @@ spec: service: name: {{ template "common.fullname" . }} port: - number: {{ .Values.friendbot.ingress.port | default 80 }} + number: {{ .Values.friendbot.configmap.port | default 8000 }} diff --git a/charts/friendbot/templates/friendbot-service.yaml b/charts/friendbot/templates/friendbot-service.yaml index 6fddc48..b91899a 100644 --- a/charts/friendbot/templates/friendbot-service.yaml +++ b/charts/friendbot/templates/friendbot-service.yaml @@ -15,7 +15,7 @@ spec: type: ClusterIP ports: - protocol: TCP - port: {{ .Values.friendbot.service.port | default 80 }} - targetPort: {{ .Values.friendbot.service.targetport | default 8004 }} + port: {{ .Values.friendbot.configmap.port | default 8000 }} + targetPort: {{ .Values.friendbot.configmap.port | default 8000 }} selector: app: {{ template "common.fullname" . }} diff --git a/charts/friendbot/values.yaml b/charts/friendbot/values.yaml index 06b5bd5..9f6c16d 100644 --- a/charts/friendbot/values.yaml +++ b/charts/friendbot/values.yaml @@ -36,7 +36,7 @@ friendbot: - /secret/secret.conf replicaCount: 1 startupProbe: - tcpSocketPort: 8004 + tcpSocket: {} initialDelaySeconds: 60 failureThreshold: 60 periodSeconds: 10 @@ -48,14 +48,9 @@ friendbot: # environment: "dev" # mylabel1: "myvalue1" - service: - port: 80 - targetport: 8004 - ingress: host: "friendbot.example.com" # ingressClassName: "" - # port: 80 # annotations: # cert-manager.io/cluster-issuer: "default" @@ -72,7 +67,7 @@ friendbot: # existingSecret: "" configmap: - port: 8000 + port: 8000 # friendbotAccountSeed: "XXXXXXX" # legacy fallback; prefer friendbot.secret.friendbotAccountSeed # otel_enabled: false # otel_endpoint: "http://otel-collector:4318"