Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/helm-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ jobs:
permissions:
contents: read

strategy:
matrix:
chart: [ledger, payments]

env:
KUBECONFORM_VERSION: v0.6.7
KUBERNETES_VERSION: "1.31.0"
Expand All @@ -39,7 +43,7 @@ jobs:
version: "v3.16.4"

- name: Helm lint
run: helm lint deploy/helm/ledger
run: helm lint deploy/helm/${{ matrix.chart }}

- name: Install kubeconform
run: |
Expand All @@ -49,5 +53,5 @@ jobs:

- name: Helm template and validate manifests
run: |
helm template ledger deploy/helm/ledger --set image.tag=test \
helm template ${{ matrix.chart }} deploy/helm/${{ matrix.chart }} --set image.tag=test \
| kubeconform -strict -summary -kubernetes-version "$KUBERNETES_VERSION"
6 changes: 6 additions & 0 deletions deploy/helm/payments/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.DS_Store
.git/
.gitignore
*.tmp
*.bak
*.swp
11 changes: 11 additions & 0 deletions deploy/helm/payments/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: v2
name: payments
description: FinCore payments service, payment orchestration with idempotency and an outbox
type: application
version: 0.1.0
appVersion: "0.1.0"
home: https://github.com/tiana-code/fincore-engine
sources:
- https://github.com/tiana-code/fincore-engine
maintainers:
- name: FinCore Engine Authors
22 changes: 22 additions & 0 deletions deploy/helm/payments/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
The payments service has been deployed as release {{ .Release.Name }}.

Service (ClusterIP) reachable in-cluster at:
{{ include "payments.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.port }}

Probe a pod locally with port-forward:
kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "payments.fullname" . }} {{ .Values.service.port }}:{{ .Values.service.port }}
curl http://localhost:{{ .Values.service.port }}/actuator/health/readiness

{{- if not .Values.existingSecret }}

WARNING: existingSecret is empty. Set existingSecret to a Secret holding keys
"{{ .Values.secretKeys.datasourcePassword }}", "{{ .Values.secretKeys.keycloakClientSecret }}" and "{{ .Values.secretKeys.webhookHmacSecret }}" before running against a real database.
{{- end }}

{{- if eq .Values.config.sandboxBankEnabled "false" }}

WARNING: config.sandboxBankEnabled is false and no real bank provider ships with
the open-source service. PaymentOrchestrator requires a bank provider bean, so
the pod will fail to start unless you supply one. Keep the sandbox on or provide
a real provider.
{{- end }}
35 changes: 35 additions & 0 deletions deploy/helm/payments/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{{- define "payments.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "payments.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name (include "payments.name" .) | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}

{{- define "payments.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{- define "payments.selectorLabels" -}}
app.kubernetes.io/name: {{ include "payments.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}

{{- define "payments.labels" -}}
helm.sh/chart: {{ include "payments.chart" . }}
{{ include "payments.selectorLabels" . }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}

{{- define "payments.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{- default (include "payments.fullname" .) .Values.serviceAccount.name -}}
{{- else -}}
{{- default "default" .Values.serviceAccount.name -}}
{{- end -}}
{{- end -}}
16 changes: 16 additions & 0 deletions deploy/helm/payments/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "payments.fullname" . }}
labels:
{{- include "payments.labels" . | nindent 4 }}
data:
SPRING_PROFILES_ACTIVE: {{ .Values.config.springProfilesActive | quote }}
KEYCLOAK_ISSUER_URI: {{ .Values.config.keycloakIssuerUri | quote }}
OTLP_TRACING_ENDPOINT: {{ .Values.config.otlpTracingEndpoint | quote }}
SPRING_DATASOURCE_URL: {{ .Values.config.datasourceUrl | quote }}
SPRING_DATASOURCE_USERNAME: {{ .Values.config.datasourceUsername | quote }}
FINCORE_PAYMENTS_BANK_SANDBOX_ENABLED: {{ .Values.config.sandboxBankEnabled | quote }}
FINCORE_PAYMENTS_DISPATCHER_ENABLED: {{ .Values.config.dispatcherEnabled | quote }}
FINCORE_PAYMENTS_RETRY_ENABLED: {{ .Values.config.retryEnabled | quote }}
FINCORE_EVENTBUS_BOOTSTRAP_SERVERS: {{ .Values.config.eventbusBootstrapServers | quote }}
80 changes: 80 additions & 0 deletions deploy/helm/payments/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "payments.fullname" . }}
labels:
{{- include "payments.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "payments.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "payments.labels" . | nindent 8 }}
spec:
serviceAccountName: {{ include "payments.serviceAccountName" . }}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: payments
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
envFrom:
- configMapRef:
name: {{ include "payments.fullname" . }}
{{- if .Values.existingSecret }}
env:
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.existingSecret }}
key: {{ .Values.secretKeys.datasourcePassword }}
- name: KEYCLOAK_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: {{ .Values.existingSecret }}
key: {{ .Values.secretKeys.keycloakClientSecret }}
- name: FINCORE_PAYMENTS_WEBHOOK_HMAC_SECRET
valueFrom:
secretKeyRef:
name: {{ .Values.existingSecret }}
key: {{ .Values.secretKeys.webhookHmacSecret }}
{{- end }}
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: http
initialDelaySeconds: {{ .Values.probes.liveness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.liveness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.liveness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.liveness.failureThreshold }}
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: http
initialDelaySeconds: {{ .Values.probes.readiness.initialDelaySeconds }}
periodSeconds: {{ .Values.probes.readiness.periodSeconds }}
timeoutSeconds: {{ .Values.probes.readiness.timeoutSeconds }}
failureThreshold: {{ .Values.probes.readiness.failureThreshold }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
22 changes: 22 additions & 0 deletions deploy/helm/payments/templates/hpa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "payments.fullname" . }}
labels:
{{- include "payments.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "payments.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
15 changes: 15 additions & 0 deletions deploy/helm/payments/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "payments.fullname" . }}
labels:
{{- include "payments.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
selector:
{{- include "payments.selectorLabels" . | nindent 4 }}
8 changes: 8 additions & 0 deletions deploy/helm/payments/templates/serviceaccount.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "payments.serviceAccountName" . }}
labels:
{{- include "payments.labels" . | nindent 4 }}
{{- end }}
90 changes: 90 additions & 0 deletions deploy/helm/payments/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
replicaCount: 1

nameOverride: ""
fullnameOverride: ""

image:
repository: ghcr.io/tiana-code/fincore-payments
# Defaults to the chart appVersion when empty.
tag: ""
pullPolicy: IfNotPresent

imagePullSecrets: []

serviceAccount:
create: true
name: ""

service:
type: ClusterIP
port: 8080

resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi

autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 70

# Non-secret environment surfaced through the ConfigMap. Probes assume the
# actuator stays on the main 8080 port, so leave springProfilesActive empty
# (a prod profile that moves actuator to 9090 would break the 8080 probes).
#
# sandboxBankEnabled defaults true: the sandbox is the only bank provider
# shipped in the open-source service, and PaymentOrchestrator requires a
# provider to start. Supply a real provider and flip this off in private
# deployments. The dispatcher and retry schedulers default off; enable the
# dispatcher only alongside eventbusBootstrapServers.
config:
springProfilesActive: ""
keycloakIssuerUri: ""
otlpTracingEndpoint: ""
datasourceUrl: ""
datasourceUsername: payments
sandboxBankEnabled: "true"
dispatcherEnabled: "false"
retryEnabled: "false"
eventbusBootstrapServers: ""

# Name of a pre-existing Kubernetes Secret holding the credentials. The chart
# never contains secret values; it only references them. Leave empty to render
# without secret-backed env (for example during template validation).
existingSecret: ""
secretKeys:
datasourcePassword: datasource-password
keycloakClientSecret: keycloak-client-secret
webhookHmacSecret: webhook-hmac-secret

podSecurityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
seccompProfile:
type: RuntimeDefault

securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL

probes:
liveness:
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
readiness:
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 6
35 changes: 35 additions & 0 deletions services/payments/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
server:
port: 8080
shutdown: graceful
spring:
application:
name: payments
lifecycle:
timeout-per-shutdown-phase: 30s
jpa:
hibernate:
ddl-auto: none
Expand All @@ -11,3 +16,33 @@ spring:
resourceserver:
jwt:
issuer-uri: ${KEYCLOAK_ISSUER_URI}
management:
endpoint:
health:
probes:
enabled: true
show-components: always
show-details: never
group:
liveness:
include: livenessState
readiness:
include: readinessState,db
endpoints:
web:
exposure:
include: health,info,prometheus
metrics:
distribution:
percentiles-histogram:
http.server.requests: true
tracing:
sampling:
probability: 0.1
otlp:
tracing:
endpoint: ${OTLP_TRACING_ENDPOINT:http://localhost:4318/v1/traces}
logging:
structured:
format:
console: logstash
Loading