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
35 changes: 15 additions & 20 deletions .github/workflows/helm-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,35 @@ permissions:

jobs:
chart-test:
name: Lint & Install (kind)
name: Lint & Validate
runs-on: ubuntu-latest

permissions:
contents: read

env:
KUBECONFORM_VERSION: v0.6.7
KUBERNETES_VERSION: "1.31.0"

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Helm
uses: azure/setup-helm@v4
with:
version: "v3.16.4"

- name: Set up chart-testing (ct)
uses: helm/chart-testing-action@v2

- name: Run chart linting
run: ct lint --chart-dirs deploy/helm --all
- name: Helm lint
run: helm lint deploy/helm/ledger

- name: Create kind cluster
uses: helm/kind-action@v1
with:
cluster_name: fincore-test

- name: Run chart-testing (install)
run: ct install --chart-dirs deploy/helm --all --debug
- name: Install kubeconform
run: |
curl -sSL "https://github.com/yannh/kubeconform/releases/download/${KUBECONFORM_VERSION}/kubeconform-linux-amd64.tar.gz" \
| tar -xz kubeconform
sudo mv kubeconform /usr/local/bin/

- name: Helm template render check
- name: Helm template and validate manifests
run: |
helm template fincore-test deploy/helm/fincore-engine \
--set global.image.tag=ci \
--debug \
> /dev/null
helm template ledger deploy/helm/ledger --set image.tag=test \
| kubeconform -strict -summary -kubernetes-version "$KUBERNETES_VERSION"
6 changes: 6 additions & 0 deletions deploy/helm/ledger/.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/ledger/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: v2
name: ledger
description: FinCore ledger service, a double-entry accounting core
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
14 changes: 14 additions & 0 deletions deploy/helm/ledger/templates/NOTES.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
The ledger service has been deployed as release {{ .Release.Name }}.

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

Probe a pod locally with port-forward:
kubectl --namespace {{ .Release.Namespace }} port-forward svc/{{ include "ledger.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 }}" and "{{ .Values.secretKeys.keycloakClientSecret }}" before running against a real database.
{{- end }}
35 changes: 35 additions & 0 deletions deploy/helm/ledger/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{{- define "ledger.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

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

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

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

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

{{- define "ledger.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
{{- default (include "ledger.fullname" .) .Values.serviceAccount.name -}}
{{- else -}}
{{- default "default" .Values.serviceAccount.name -}}
{{- end -}}
{{- end -}}
13 changes: 13 additions & 0 deletions deploy/helm/ledger/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "ledger.fullname" . }}
labels:
{{- include "ledger.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 }}
FINCORE_LEDGER_CLEANUP_ENABLED: {{ .Values.config.cleanupEnabled | quote }}
SPRING_DATASOURCE_URL: {{ .Values.config.datasourceUrl | quote }}
SPRING_DATASOURCE_USERNAME: {{ .Values.config.datasourceUsername | quote }}
75 changes: 75 additions & 0 deletions deploy/helm/ledger/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "ledger.fullname" . }}
labels:
{{- include "ledger.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "ledger.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "ledger.labels" . | nindent 8 }}
spec:
serviceAccountName: {{ include "ledger.serviceAccountName" . }}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: ledger
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 "ledger.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 }}
{{- 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/ledger/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 "ledger.fullname" . }}
labels:
{{- include "ledger.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "ledger.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/ledger/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "ledger.fullname" . }}
labels:
{{- include "ledger.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
selector:
{{- include "ledger.selectorLabels" . | nindent 4 }}
8 changes: 8 additions & 0 deletions deploy/helm/ledger/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 "ledger.serviceAccountName" . }}
labels:
{{- include "ledger.labels" . | nindent 4 }}
{{- end }}
80 changes: 80 additions & 0 deletions deploy/helm/ledger/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
replicaCount: 1

nameOverride: ""
fullnameOverride: ""

image:
repository: ghcr.io/tiana-code/fincore-ledger
# 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
# (the prod profile moves actuator to 9090 and would break the 8080 probes).
config:
springProfilesActive: ""
keycloakIssuerUri: ""
otlpTracingEndpoint: ""
cleanupEnabled: "false"
datasourceUrl: ""
datasourceUsername: ledger

# 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

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
Loading