diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ddd3fe9..57d5783 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,7 +5,7 @@ stages: - test - build -test: +test:go: stage: test image: golang:alpine variables: @@ -26,6 +26,13 @@ test: coverage_format: cobertura path: coverage.xml +test:helm: + stage: test + image: chainguard/helm:latest + script: + - helm lint ./deploy + - helm template ./deploy --values deploy/values.test.yaml + build:httpserver: stage: build variables: diff --git a/deploy/Chart.yaml b/deploy/Chart.yaml new file mode 100644 index 0000000..3654f54 --- /dev/null +++ b/deploy/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v2 +name: yggdrasil +description: A Helm chart for Kubernetes +version: 0.0.0 diff --git a/deploy/templates/NOTES.txt b/deploy/templates/NOTES.txt new file mode 100644 index 0000000..571fe88 --- /dev/null +++ b/deploy/templates/NOTES.txt @@ -0,0 +1,3 @@ +{{- if .Values.ingress.enabled }} +URL: https://{{ .Values.ingress.host }} +{{- end }} diff --git a/deploy/templates/_helpers.tpl b/deploy/templates/_helpers.tpl new file mode 100644 index 0000000..86678f3 --- /dev/null +++ b/deploy/templates/_helpers.tpl @@ -0,0 +1,5 @@ +{{- define "imagePullSecret" }} +{{- with .Values.imageCredentials }} +{{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"email\":\"%s\",\"auth\":\"%s\"}}}" .registry .username .password .email (printf "%s:%s" .username .password | b64enc) | b64enc }} +{{- end }} +{{- end }} diff --git a/deploy/templates/config.yaml b/deploy/templates/config.yaml new file mode 100644 index 0000000..f8f27fa --- /dev/null +++ b/deploy/templates/config.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Release.Name }} +data: + APP_ENV: "production" + APP_PORT: {{ .Values.config.port | quote }} + DATABASE_URL_FILE: "/etc/yggdrasil/secrets/database_url.txt" diff --git a/deploy/templates/deployment.yaml b/deploy/templates/deployment.yaml new file mode 100644 index 0000000..1ecbc91 --- /dev/null +++ b/deploy/templates/deployment.yaml @@ -0,0 +1,62 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Release.Name }} + labels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "backend-api" +spec: + replicas: {{ .Values.replicas }} + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "backend-api" + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/config.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/secrets.yaml") . | sha256sum }} + labels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "backend-api" + spec: + automountServiceAccountToken: false + imagePullSecrets: + - name: {{ .Release.Name }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: Always + ports: + - name: {{ .Values.service.port.name }} + containerPort: {{ .Values.config.port }} + protocol: TCP +# livenessProbe: +# httpGet: +# path: /livez +# port: {{ .Values.service.port.name }} +# readinessProbe: +# httpGet: +# path: /readyz +# port: {{ .Values.service.port.name }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + envFrom: + - configMapRef: + name: {{ .Release.Name }} + volumeMounts: + - mountPath: /etc/yggdrasil/secrets + name: secrets + readOnly: true + volumes: + - name: secrets + secret: + secretName: {{ .Release.Name }} diff --git a/deploy/templates/image-pull-secret.yaml b/deploy/templates/image-pull-secret.yaml new file mode 100644 index 0000000..b656f73 --- /dev/null +++ b/deploy/templates/image-pull-secret.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }} + annotations: + "helm.sh/hook": pre-install + "helm.sh/hook-weight": "-99" +type: kubernetes.io/dockerconfigjson +data: + .dockerconfigjson: {{ template "imagePullSecret" . }} diff --git a/deploy/templates/ingress.yaml b/deploy/templates/ingress.yaml new file mode 100644 index 0000000..cb2c3b5 --- /dev/null +++ b/deploy/templates/ingress.yaml @@ -0,0 +1,28 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }} + annotations: + {{- if .Values.ingress.annotations }} + {{- toYaml .Values.ingress.annotations | nindent 8 }} + {{- end }} +spec: + ingressClassName: {{ .Values.ingress.className }} + tls: + - hosts: + - {{ .Values.ingress.host | quote }} + secretName: {{ .Release.Name }}-ingress-tls + + rules: + - host: {{ .Values.ingress.host | quote }} + http: + paths: + - path: {{ .Values.ingress.path }} + pathType: {{ .Values.ingress.pathType }} + backend: + service: + name: {{ .Release.Name }} + port: + name: {{ .Values.service.port.name }} +{{- end -}} diff --git a/deploy/templates/poddisruptionbudget.yaml b/deploy/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000..2125ddf --- /dev/null +++ b/deploy/templates/poddisruptionbudget.yaml @@ -0,0 +1,11 @@ +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ .Release.Name }} +spec: + minAvailable: 1 + selector: + matchLabels: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: "backend-api" diff --git a/deploy/templates/secrets.yaml b/deploy/templates/secrets.yaml new file mode 100644 index 0000000..16e1409 --- /dev/null +++ b/deploy/templates/secrets.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }} +stringData: + database_url.txt: | + {{ .Values.config.database.url }} diff --git a/deploy/templates/service.yaml b/deploy/templates/service.yaml new file mode 100644 index 0000000..83f2df6 --- /dev/null +++ b/deploy/templates/service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Release.Name }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port.number }} + targetPort: {{ .Values.service.port.number }} + protocol: TCP + name: {{ .Values.service.port.name }} + selector: + app.kubernetes.io/name: {{ .Chart.Name }} + app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/deploy/values.staging.yaml b/deploy/values.staging.yaml new file mode 100644 index 0000000..2709c46 --- /dev/null +++ b/deploy/values.staging.yaml @@ -0,0 +1,8 @@ +ingress: + enabled: true + host: staging.yggdrasil.vmdevel.cz + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + cert-manager.io/issuer: letsencrypt-prod + +replicas: 2 diff --git a/deploy/values.test.yaml b/deploy/values.test.yaml new file mode 100644 index 0000000..b88b000 --- /dev/null +++ b/deploy/values.test.yaml @@ -0,0 +1,12 @@ +ingress: + enabled: true + host: yggdrasil.example.com + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + cert-manager.io/issuer: letsencrypt-prod + +replicas: 2 + +config: + database: + url: postgres://user:pass@127.0.0.1:5432/db?sslmode=disable diff --git a/deploy/values.yaml b/deploy/values.yaml new file mode 100644 index 0000000..60e0dc8 --- /dev/null +++ b/deploy/values.yaml @@ -0,0 +1,38 @@ +replicas: 1 + +image: + repository: registry.mareshq.com/hq/yggdrasil/httpserver + tag: latest + +imageCredentials: + registry: registry.mareshq.com + email: nobody@mareshq.com + username: someone + password: sillyness + +ingress: + enabled: false + host: example.com + className: nginx + path: / + pathType: Prefix + annotations: {} + +service: + type: ClusterIP + port: + name: http + number: 80 + +resources: + limits: + cpu: 250m + memory: 512Mi + requests: + cpu: 100m + memory: 128Mi + +config: + port: 8080 + database: + url: