From cc37fb0dc509a39292a8246a89e0b5a52f6c1a16 Mon Sep 17 00:00:00 2001 From: WrenIX Date: Fri, 20 Oct 2023 17:38:50 +0200 Subject: [PATCH] feat(forgejo-runner): init helm-chart #1 --- forgejo-runner/.helmignore | 23 +++ forgejo-runner/Chart.yaml | 7 + forgejo-runner/README.md | 52 +++++++ forgejo-runner/templates/_helpers.tpl | 62 ++++++++ forgejo-runner/templates/deployment.yaml | 90 ++++++++++++ forgejo-runner/templates/hpa.yaml | 32 +++++ forgejo-runner/templates/jobs.yaml | 142 +++++++++++++++++++ forgejo-runner/templates/serviceaccount.yaml | 13 ++ forgejo-runner/values.yaml | 103 ++++++++++++++ 9 files changed, 524 insertions(+) create mode 100644 forgejo-runner/.helmignore create mode 100644 forgejo-runner/Chart.yaml create mode 100644 forgejo-runner/README.md create mode 100644 forgejo-runner/templates/_helpers.tpl create mode 100644 forgejo-runner/templates/deployment.yaml create mode 100644 forgejo-runner/templates/hpa.yaml create mode 100644 forgejo-runner/templates/jobs.yaml create mode 100644 forgejo-runner/templates/serviceaccount.yaml create mode 100644 forgejo-runner/values.yaml diff --git a/forgejo-runner/.helmignore b/forgejo-runner/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/forgejo-runner/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/forgejo-runner/Chart.yaml b/forgejo-runner/Chart.yaml new file mode 100644 index 0000000..7c794f7 --- /dev/null +++ b/forgejo-runner/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: forgejo-runner +description: Deploy runner for an forgejo instance (default codeberg.org) +type: application +version: 0.1.0 + +appVersion: "3.0.1" diff --git a/forgejo-runner/README.md b/forgejo-runner/README.md new file mode 100644 index 0000000..f392779 --- /dev/null +++ b/forgejo-runner/README.md @@ -0,0 +1,52 @@ +# forgejo-runner + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 3.0.1](https://img.shields.io/badge/AppVersion-3.0.1-informational?style=flat-square) + +Deploy runner for an forgejo instance (default codeberg.org) + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| dind.image.pullPolicy | string | `"IfNotPresent"` | | +| dind.image.registry | string | `"docker.io"` | | +| dind.image.repository | string | `"library/docker"` | | +| dind.image.tag | string | `"24.0.6-dind-rootless"` | | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | | +| image.registry | string | `"code.forgejo.org"` | | +| image.repository | string | `"forgejo/runner"` | | +| image.tag | string | `""` | | +| imagePullSecrets | list | `[]` | | +| kubectl.image.pullPolicy | string | `"IfNotPresent"` | | +| kubectl.image.registry | string | `"docker.io"` | | +| kubectl.image.repository | string | `"bitnami/kubectl"` | | +| kubectl.image.tag | string | `"1.27.7"` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| podAnnotations | object | `{}` | | +| podLabels | object | `{}` | | +| podSecurityContext | object | `{}` | | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| runner.config.create | bool | `true` | | +| runner.config.existingSecret | string | `""` | use existingSecret instatt | +| runner.config.instance | string | `"https://codeberg.org"` | | +| runner.config.name | string | `nil` | | +| runner.config.token | string | `nil` | | +| securityContext.privileged | bool | `true` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.automount | bool | `true` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | +| volumeMounts | list | `[]` | | +| volumes | list | `[]` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.11.2](https://github.com/norwoodj/helm-docs/releases/v1.11.2) diff --git a/forgejo-runner/templates/_helpers.tpl b/forgejo-runner/templates/_helpers.tpl new file mode 100644 index 0000000..7af352b --- /dev/null +++ b/forgejo-runner/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "forgejo-runner.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "forgejo-runner.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "forgejo-runner.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "forgejo-runner.labels" -}} +helm.sh/chart: {{ include "forgejo-runner.chart" . }} +{{ include "forgejo-runner.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "forgejo-runner.selectorLabels" -}} +app.kubernetes.io/name: {{ include "forgejo-runner.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "forgejo-runner.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "forgejo-runner.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/forgejo-runner/templates/deployment.yaml b/forgejo-runner/templates/deployment.yaml new file mode 100644 index 0000000..e9555e5 --- /dev/null +++ b/forgejo-runner/templates/deployment.yaml @@ -0,0 +1,90 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "forgejo-runner.fullname" . }} + labels: + {{- include "forgejo-runner.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "forgejo-runner.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "forgejo-runner.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "forgejo-runner.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: runner + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: [ "/bin//forgejo-runner", "daemon" ] + resources: + {{- toYaml .Values.resources | nindent 12 }} + env: + - name: DOCKER_HOST + value: tcp://127.0.0.1:2376 + - name: DOCKER_CERT_PATH + value: /certs/client + - name: DOCKER_TLS_VERIFY + value: "1" + volumeMounts: + - name: docker-certs + mountPath: /certs + - name: runner-data + mountPath: /data + - name: dind + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.dind.image.registry }}/{{ .Values.dind.image.repository }}:{{ .Values.dind.image.tag }}" + imagePullPolicy: {{ .Values.dind.image.pullPolicy }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + env: + - name: DOCKER_TLS_CERTDIR + value: /certs + volumeMounts: + - name: docker-certs + mountPath: /certs + {{- with .Values.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: docker-certs + emptyDir: {} + - name: runner-data + secret: + secretName: {{ .Values.runner.config.existingSecret | default (print ( include "forgejo-runner.fullname" . ) "-config") | quote }} + {{- with .Values.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/forgejo-runner/templates/hpa.yaml b/forgejo-runner/templates/hpa.yaml new file mode 100644 index 0000000..c221811 --- /dev/null +++ b/forgejo-runner/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "forgejo-runner.fullname" . }} + labels: + {{- include "forgejo-runner.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "forgejo-runner.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/forgejo-runner/templates/jobs.yaml b/forgejo-runner/templates/jobs.yaml new file mode 100644 index 0000000..934dc85 --- /dev/null +++ b/forgejo-runner/templates/jobs.yaml @@ -0,0 +1,142 @@ +{{ if and .Values.runner.config.create (not .Values.runner.config.existingSecret ) }} +{{ $name := (print ( include "forgejo-runner.fullname" . ) "-config-generate") }} +{{ $secretName := (print ( include "forgejo-runner.fullname" . ) "-config") }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ $name }} + labels: + app.kubernetes.io/component: config-generate-job + {{- include "forgejo-runner.labels" . | nindent 4 }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ $name }} + labels: + app.kubernetes.io/component: config-generate-job + {{- include "forgejo-runner.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - secrets + resourceNames: + - {{ $secretName }} + verbs: + - get + - update + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ $name }} + labels: + app.kubernetes.io/component: config-generate-job + {{- include "forgejo-runner.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ $name }} +subjects: + - kind: ServiceAccount + name: {{ $name }} + namespace: {{ .Release.Namespace }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + annotations: + helm.sh/resource-policy: keep +type: Opaque +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $name }} + labels: + app.kubernetes.io/component: config-generate-job + {{- include "forgejo-runner.labels" . | nindent 4 }} + annotations: + config-hash: {{ toYaml .Values.runner.config | sha256sum }} +stringData: + CONFIG_NAME: {{ .Values.runner.config.name | quote }} + CONFIG_INSTANCE: {{ .Values.runner.config.instance | quote }} + CONFIG_TOKEN: {{ .Values.runner.config.token | quote }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ $name }} + labels: + {{- include "forgejo-runner.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": "post-install,post-upgrade" + "helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded" +spec: + template: + metadata: + annotations: + config-hash: {{ toYaml .Values.runner.config | sha256sum }} + spec: + restartPolicy: "Never" + serviceAccount: {{ $name }} + containers: + - name: upload-config + image: "{{ .Values.kubectl.image.registry }}/{{ .Values.kubectl.image.repository }}:{{ .Values.kubectl.image.tag }}" + command: + - sh + - -c + - | + # check if key already exists + key=$(kubectl get secret {{ $secretName }} -o jsonpath="{.data['.runner']}" 2> /dev/null) + [ $? -ne 0 ] && echo "Failed to get existing secret" && exit 1 + [ -n "$key" ] && echo "Config already created, exiting." && exit 0 + # wait for config + while [ ! -f /data/.runner ]; do + echo "Waiting for config.." + sleep 5; + done + # update secret + kubectl patch secret {{ $secretName }} -p "{\"data\":{\".runner\":\"$(base64 /data/.runner | tr -d '\n')\"}}" + [ $? -ne 0 ] && echo "Failed to update secret." && exit 1 + echo "Config successfully created." + volumeMounts: + - mountPath: /data/ + name: data + readOnly: true + - name: generate-config + image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + command: + - sh + - -c + - | + if [[ -s /current/.runner ]]; then + echo "runner-config exists already"; + cp /current/.runner /data/.runner; + exit 0; + fi + cd /data; + /bin/forgejo-runner register --no-interactive --token "${CONFIG_TOKEN}" --name "${CONFIG_NAME}" --instance "${CONFIG_INSTANCE}" 2>&1 | tee /tmp/reg.log; + cat /tmp/reg.log | grep 'Runner registered successfully'; + envFrom: + - secretRef: + name: {{ $name }} + volumeMounts: + - mountPath: /data/ + name: data + - name: runner-data + mountPath: /current + volumes: + - name: data + emptyDir: {} + - name: runner-data + secret: + secretName: {{ $secretName }} + parallelism: 1 + completions: 1 + backoffLimit: 1 +{{ end }} diff --git a/forgejo-runner/templates/serviceaccount.yaml b/forgejo-runner/templates/serviceaccount.yaml new file mode 100644 index 0000000..94e1159 --- /dev/null +++ b/forgejo-runner/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "forgejo-runner.serviceAccountName" . }} + labels: + {{- include "forgejo-runner.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/forgejo-runner/values.yaml b/forgejo-runner/values.yaml new file mode 100644 index 0000000..951f8ee --- /dev/null +++ b/forgejo-runner/values.yaml @@ -0,0 +1,103 @@ +# Default values for forgejo-runner. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + registry: code.forgejo.org + repository: forgejo/runner + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +runner: + config: + # -- create a secret by run: forgejo-runner register --no-interactive --token {TOKEN} --name runner --instance https://next.forgejo.org + create: true + # -- use existingSecret instatt + existingSecret: "" + instance: https://codeberg.org + name: + token: + +dind: + image: + registry: docker.io + repository: library/docker + pullPolicy: IfNotPresent + tag: 24.0.6-dind-rootless +kubectl: + image: + registry: docker.io + repository: bitnami/kubectl + pullPolicy: IfNotPresent + tag: 1.27.7 + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: + privileged: true + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {}