From 6eab226ceb32ac8dfbf8219cbd7293e777dc1ff7 Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Mon, 14 Jul 2025 15:55:05 -0600 Subject: [PATCH 1/6] Hawkbit: Fix mountPaths Dockerfile removed WORKDIR before 0.5.0, so this helm chart has been broken for a while --- charts/hawkbit/templates/deployment.yaml | 2 +- charts/hawkbit/values.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/charts/hawkbit/templates/deployment.yaml b/charts/hawkbit/templates/deployment.yaml index 614581af..d994dca1 100644 --- a/charts/hawkbit/templates/deployment.yaml +++ b/charts/hawkbit/templates/deployment.yaml @@ -34,7 +34,7 @@ spec: image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} env: - - name: SPRING_PROFILES_ACTIVE + - name: PROFILES value: "{{ .Values.spring.profiles }}" - name: "SPRING_DATASOURCE_URL" {{- if .Values.env.springDatasourceUrl }} diff --git a/charts/hawkbit/values.yaml b/charts/hawkbit/values.yaml index 44a4c17b..b88bd0a6 100644 --- a/charts/hawkbit/values.yaml +++ b/charts/hawkbit/values.yaml @@ -78,7 +78,7 @@ routes: fileStorage: enabled: true pvcSize: "1Gi" - mountPath: "/var/lib/hawkbit-storage" + mountPath: "/artifactrepo" # env vars for configuration env: @@ -119,7 +119,7 @@ extraVolumes: [] extraVolumeMounts: [] configMap: - mountPath: "/opt/hawkbit/config" + mountPath: "/config" spring: profiles: "mysql" From a19a1fb3535bc16ddcdadb7b8e18d19407dd0a81 Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Thu, 26 Jun 2025 11:49:40 -0600 Subject: [PATCH 2/6] Hawkbit: refactor whitespace Update indentation to confrom with yaml norms Remove commented code in values.yaml --- charts/hawkbit/templates/deployment.yaml | 12 ++++++------ charts/hawkbit/templates/pvc.yaml | 10 +++++----- charts/hawkbit/values.yaml | 13 ------------- 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/charts/hawkbit/templates/deployment.yaml b/charts/hawkbit/templates/deployment.yaml index d994dca1..0f71c6ef 100644 --- a/charts/hawkbit/templates/deployment.yaml +++ b/charts/hawkbit/templates/deployment.yaml @@ -113,13 +113,13 @@ spec: {{- end }} {{- end }} volumes: - - name: configmap - configMap: - name: {{ include "hawkbit.fullname" . }} + - name: configmap + configMap: + name: {{ include "hawkbit.fullname" . }} {{- if .Values.fileStorage.enabled }} - - name: storage - persistentVolumeClaim: - claimName: {{ include "hawkbit.fullname" . }}-data + - name: storage + persistentVolumeClaim: + claimName: {{ include "hawkbit.fullname" . }}-data {{- end}} {{- if .Values.extraVolumes }} {{ toYaml .Values.extraVolumes | nindent 6 }} diff --git a/charts/hawkbit/templates/pvc.yaml b/charts/hawkbit/templates/pvc.yaml index 4be6f9ef..0ce880b9 100644 --- a/charts/hawkbit/templates/pvc.yaml +++ b/charts/hawkbit/templates/pvc.yaml @@ -11,9 +11,9 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: {{ .Values.fileStorage.pvcSize }} + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.fileStorage.pvcSize }} {{- end }} diff --git a/charts/hawkbit/values.yaml b/charts/hawkbit/values.yaml index b88bd0a6..e60cf55d 100644 --- a/charts/hawkbit/values.yaml +++ b/charts/hawkbit/values.yaml @@ -129,19 +129,6 @@ config: server: useForwardHeaders: true hawkbit: - ## Configuration for the device management federation - ## ref: https://www.eclipse.org/hawkbit/apis/dmf_api/ - ## These configuration will become available once https://github.com/eclipse/hawkbit/pull/890 is merged - # dmf: - # hono: - # enabled: false - # tenant-list-uri: "http://[DEVICE_REGISTRY_HOST]:8080/admin/tenants" - # device-list-uri: "http://[DEVICE_REGISTRY_HOST]:8080/admin/$$tenantId/devices" - # credentials-list-uri: "http://[DEVICE_REGISTRY_HOST]:8080/v1/credentials/$$tenantId/$$deviceId" - # authentication-method: "oidc" - # username: "[KEYCLOAK_HAWKBIT_USERNAME]" - # oidc-token-uri: "http://[KEYCLOAK_HOST]:8080/auth/realms/master/protocol/openid-connect/token" - # oidc-client-id: "[KEYCLOAK_DEVICE_REGISTRY_CLIENT_ID]" spring: cloud: stream: From ad084742eb6aac8ce68d3426c3ffba47bff06d8f Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Thu, 26 Jun 2025 15:03:36 -0600 Subject: [PATCH 3/6] Hawkbit chart: update to latest hawkbit version Update hawkbit to 0.9.0 update dependant charts to lateset versions --- charts/hawkbit/Chart.yaml | 6 +++--- charts/hawkbit/values.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/charts/hawkbit/Chart.yaml b/charts/hawkbit/Chart.yaml index f2bfa03f..e3e82fbc 100644 --- a/charts/hawkbit/Chart.yaml +++ b/charts/hawkbit/Chart.yaml @@ -11,7 +11,7 @@ --- apiVersion: v2 version: 1.7.0 -appVersion: "0.5.0-mysql" +appVersion: "0.9.0" description: | Eclipse hawkBit™ is a domain independent back-end framework for rolling out software updates to constrained edge devices as well as more powerful controllers and gateways connected to @@ -33,10 +33,10 @@ maintainers: email: ctron@dentrassi.de dependencies: - name: mysql - version: ^9.x + version: ^13.x repository: "oci://registry-1.docker.io/bitnamicharts" condition: mysql.enabled - name: rabbitmq - version: ^10.x + version: ^16.x repository: "oci://registry-1.docker.io/bitnamicharts" condition: rabbitmq.enabled diff --git a/charts/hawkbit/values.yaml b/charts/hawkbit/values.yaml index e60cf55d..eb4b60ce 100644 --- a/charts/hawkbit/values.yaml +++ b/charts/hawkbit/values.yaml @@ -15,7 +15,7 @@ image: repository: "hawkbit/hawkbit-update-server" - tag: 0.5.0-mysql + tag: '0.9.0' pullPolicy: IfNotPresent replicaCount: 1 From 868a7494db3f2e55131b23d86a85adf92d971aa4 Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Thu, 26 Jun 2025 15:03:09 -0600 Subject: [PATCH 4/6] Hawkbit: Make the chart compatible with k8s secrets Give existingSecrets examples Add existingSecrets for the hawkbit passwords Integrate mysql and rabbitmq secrets from the subcharts Move internal secrets out of SPRING_APPLICATION_JSON, and into individual environment variables --- charts/hawkbit/templates/_helpers.tpl | 11 +++++++ charts/hawkbit/templates/deployment.yaml | 31 ++++++++++++------- charts/hawkbit/templates/secrets.yaml | 23 ++++++-------- .../templates/tests/test-connection.yaml | 2 +- charts/hawkbit/values.yaml | 31 +++++++------------ 5 files changed, 53 insertions(+), 45 deletions(-) diff --git a/charts/hawkbit/templates/_helpers.tpl b/charts/hawkbit/templates/_helpers.tpl index a097f0e4..fe91a7f4 100644 --- a/charts/hawkbit/templates/_helpers.tpl +++ b/charts/hawkbit/templates/_helpers.tpl @@ -54,3 +54,14 @@ Return the appropriate apiVersion for ingress. {{- print "networking.k8s.io/v1beta1" -}} {{- end -}} {{- end -}} + +{{/* +Return the secret with the Hawkbit credentials. +*/}} +{{- define "hawkbit.secretName" -}} + {{- if .Values.auth.existingSecret -}} + {{ print (tpl .Values.auth.existingSecret $) -}} + {{- else -}} + {{ printf "%s" (include "hawkbit.fullname" .) -}} + {{- end -}} +{{- end -}} diff --git a/charts/hawkbit/templates/deployment.yaml b/charts/hawkbit/templates/deployment.yaml index 0f71c6ef..c3edc610 100644 --- a/charts/hawkbit/templates/deployment.yaml +++ b/charts/hawkbit/templates/deployment.yaml @@ -36,26 +36,35 @@ spec: env: - name: PROFILES value: "{{ .Values.spring.profiles }}" + - name: SPRING_DATASOURCE_USERNAME + value: "{{ .Values.mysql.auth.username }}" + - name: SPRING_DATASOURCE_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mysql.secretName" .Subcharts.mysql }} + key: mysql-password - name: "SPRING_DATASOURCE_URL" - {{- if .Values.env.springDatasourceUrl }} + {{- if and .Values.env .Values.env.springDatasourceUrl }} value: "{{ .Values.env.springDatasourceUrl }}" {{- else }} - value: "jdbc:mariadb://{{ if .Values.mysql.enabled }}{{ .Release.Name }}-mysql{{ else }}{{ .Values.env.springDatasourceHost }}{{ end }}:3306/{{ .Values.env.springDatasourceDb }}" + value: "jdbc:mariadb://{{ .Release.Name }}-mysql:3306/{{ .Values.mysql.auth.database }}" {{- end }} - - name: "SPRING_APPLICATION_JSON" - valueFrom: - secretKeyRef: - name: {{ include "hawkbit.fullname" . }} - key: "SPRING_APPLICATION_JSON" - name: "SPRING_RABBITMQ_HOST" - value: "{{ if .Values.rabbitmq.enabled }}{{ .Release.Name }}-rabbitmq{{ else }}{{ .Values.env.springRabbitmqHost }}{{ end }}" + value: "{{ .Release.Name }}-rabbitmq" - name: "SPRING_RABBITMQ_USERNAME" - value: "{{ .Values.env.springRabbitmqUsername }}" + value: "{{ .Values.rabbitmq.auth.username }}" - name: "SPRING_RABBITMQ_PASSWORD" valueFrom: secretKeyRef: - name: "{{ template "hawkbit.fullname" . }}-rabbitmq-pass" - key: "rabbitmq-pass" + name: {{ include "rabbitmq.secretPasswordName" .Subcharts.rabbitmq }} + key: rabbitmq-password + - name: SPRING_SECURITY_USER_NAME + value: "{{ .Values.auth.username }}" + - name: SPRING_SECURITY_USER_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "hawkbit.secretName" . }} + key: hawkbit-password {{- if .Values.fileStorage.enabled }} - name: "org.eclipse.hawkbit.repository.file.path" value: {{ .Values.fileStorage.mountPath }} diff --git a/charts/hawkbit/templates/secrets.yaml b/charts/hawkbit/templates/secrets.yaml index 2def1c4a..9533fe60 100644 --- a/charts/hawkbit/templates/secrets.yaml +++ b/charts/hawkbit/templates/secrets.yaml @@ -1,3 +1,4 @@ +{{- if not .Values.auth.existingSecret }} apiVersion: v1 kind: Secret metadata: @@ -6,17 +7,11 @@ metadata: {{ include "hawkbit.labels" . | indent 4 }} type: Opaque data: - SPRING_APPLICATION_JSON: {{ .Values.config.secrets | toJson | b64enc }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ template "hawkbit.fullname" . }}-rabbitmq-pass - labels: - app.kubernetes.io/name: {{ include "hawkbit.name" . }} - helm.sh/chart: {{ include "hawkbit.chart" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} -type: Opaque -data: - rabbitmq-pass: {{ .Values.env.springRabbitmqPassword | b64enc | quote }} +{{- if .Values.config.secrets }} + hawkbit-dmf-password: {{ .Values.config.secrets.hawkbit.dmf.hono.password | b64enc | quote }} + hawkbit-password: {{ .Values.config.secrets.spring.securinty.user.password | b64enc | quote }} +{{- else }} + hawkbit-dmf-password: {{ .Values.auth.dmfPassword | b64enc | quote }} + hawkbit-password: {{ .Values.auth.password | b64enc | quote }} +{{- end }} +{{- end }} diff --git a/charts/hawkbit/templates/tests/test-connection.yaml b/charts/hawkbit/templates/tests/test-connection.yaml index 1cc847ab..aa38fa89 100644 --- a/charts/hawkbit/templates/tests/test-connection.yaml +++ b/charts/hawkbit/templates/tests/test-connection.yaml @@ -16,7 +16,7 @@ spec: command: ['curl'] args: [ "-X", "GET", - "-u", "{{ .Values.config.application.spring.security.user.name }}:{{ trimPrefix "{noop}" .Values.config.secrets.spring.security.user.password }}", + "-u", "{{ .Values.auth.username }}:{{ trimPrefix "{noop}" .Values.auth.password }}", "http://{{ include "hawkbit.fullname" . }}:{{ .Values.service.port }}/rest/v1/userinfo" ] restartPolicy: Never diff --git a/charts/hawkbit/values.yaml b/charts/hawkbit/values.yaml index eb4b60ce..eb31d298 100644 --- a/charts/hawkbit/values.yaml +++ b/charts/hawkbit/values.yaml @@ -18,6 +18,14 @@ image: tag: '0.9.0' pullPolicy: IfNotPresent +# auth configuration +auth: + # if set, the secret will be used to set the hawkbit user password + existingSecret: "" + username: "admin" + password: "{noop}admin" + dmfPassword: "[KEYCLOAK_HAWKBIT_USER_PASSWORD]" + replicaCount: 1 ## podDisruptionBudget configuration @@ -82,8 +90,6 @@ fileStorage: # env vars for configuration env: - springDatasourceHost: "hawkbit-mysql" - springDatasourceDb: "hawkbit" # if springDatasourceUrl is set override default mysql db url springDatasourceUrl: "" springRabbitmqHost: "hawkbit-rabbitmq" @@ -141,23 +147,6 @@ config: destination: "device-registry.device-updated" device-deleted: destination: "device-registry.device-deleted" - security: - user: - name: admin - secrets: - hawkbit: - dmf: - hono: - password: "[KEYCLOAK_HAWKBIT_USER_PASSWORD]" - spring: - security: - user: - # the "{noop}" prefix is needed! - password: "{noop}admin" - datasource: - username: hawkbit - password: hawkbit - ## dependency charts config ## ref: https://github.com/bitnami/charts/blob/master/bitnami/mysql/values.yaml @@ -170,6 +159,8 @@ mysql: enabled: true architecture: standalone auth: + # The secret has to contain the keys mysql-root-password, mysql-replication-password and mysql-password + existingSecret: "" username: hawkbit password: hawkbit database: hawkbit @@ -184,6 +175,8 @@ rabbitmq: volumePermissions: enabled: true auth: + existingPasswordSecret: "" + existingSecretPasswordKey: rabbitmq-password username: hawkbit password: hawkbit metrics: From 3201fae05aa3c7c4befe50ff9aca861739e13e5f Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Thu, 26 Jun 2025 15:03:21 -0600 Subject: [PATCH 5/6] Hawkbit: Make extraEnv work with valueFrom Secrets and configMaps can now be used rather than just key value pairs, but maintain backward compatiblity with the old way --- charts/hawkbit/templates/deployment.yaml | 8 ++++++++ charts/hawkbit/values.yaml | 13 +++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/charts/hawkbit/templates/deployment.yaml b/charts/hawkbit/templates/deployment.yaml index c3edc610..a30aaffc 100644 --- a/charts/hawkbit/templates/deployment.yaml +++ b/charts/hawkbit/templates/deployment.yaml @@ -69,10 +69,18 @@ spec: - name: "org.eclipse.hawkbit.repository.file.path" value: {{ .Values.fileStorage.mountPath }} {{- end }} + {{- if .Values.extraEnv }} + {{- if kindIs "slice" .Values.extraEnv }} + {{- toYaml .Values.extraEnv | nindent 12 }} + {{- else if kindIs "map" .Values.extraEnv }} {{- range $key, $value := .Values.extraEnv }} - name: "{{ $key }}" value: "{{ $value }}" {{- end }} + {{- else }} + # .Values.extraEnv of type {{kindOf .Values.extraEnv}} is ignored + {{- end }} + {{- end }} ports: - name: http containerPort: 8080 diff --git a/charts/hawkbit/values.yaml b/charts/hawkbit/values.yaml index eb31d298..a1f8fa40 100644 --- a/charts/hawkbit/values.yaml +++ b/charts/hawkbit/values.yaml @@ -88,17 +88,10 @@ fileStorage: pvcSize: "1Gi" mountPath: "/artifactrepo" -# env vars for configuration -env: - # if springDatasourceUrl is set override default mysql db url - springDatasourceUrl: "" - springRabbitmqHost: "hawkbit-rabbitmq" - springRabbitmqUsername: "hawkbit" - springRabbitmqPassword: "hawkbit" - # optional env vars -extraEnv: {} - # JAVA_TOOL_OPTIONS: "-Xms1024m -Xmx1024m" +extraEnv: [] +# - name: JAVA_TOOL_OPTIONS: +# value: "-Xms1024m -Xmx1024m" resources: {} # We usually recommend not to specify default resources and to leave this as a conscious From 1828c7ed74d17607f965e992bd431054909a51e5 Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Mon, 14 Jul 2025 10:39:06 -0600 Subject: [PATCH 6/6] Hawkbit: include an initContainer to intialize the database This is optional in the docker compose version, but in kubernetes, the addition of an init container make the startup more stable by ensuring the databases are up and updated before running the main hawkbit container. --- charts/hawkbit/templates/deployment.yaml | 24 ++++++++++++++++++++++++ charts/hawkbit/values.yaml | 1 + 2 files changed, 25 insertions(+) diff --git a/charts/hawkbit/templates/deployment.yaml b/charts/hawkbit/templates/deployment.yaml index a30aaffc..5223dd3a 100644 --- a/charts/hawkbit/templates/deployment.yaml +++ b/charts/hawkbit/templates/deployment.yaml @@ -25,6 +25,28 @@ spec: {{- toYaml . | nindent 8 }} {{- end }} spec: + initContainers: + - name: hawkbit-init + image: "{{ .Values.image.initContainer }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: HAWKBIT_DB_MODE + value: "migrate" + - name: "SPRING_DATASOURCE_URL" + {{- if and .Values.env .Values.env.springDatasourceUrl }} + value: "{{ .Values.env.springDatasourceUrl }}" + {{- else }} + value: "jdbc:mariadb://{{ .Release.Name }}-mysql:3306/{{ .Values.mysql.auth.database }}" + {{- end }} + - name: SPRING_DATASOURCE_USERNAME + value: "{{ .Values.mysql.auth.username }}" + - name: SPRING_DATASOURCE_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "mysql.secretName" .Subcharts.mysql }} + key: mysql-password + - name: AND_THEN + value: "true" {{- with .Values.image.pullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} @@ -36,6 +58,8 @@ spec: env: - name: PROFILES value: "{{ .Values.spring.profiles }}" + - name: SPRING_FLYWAY_ENABLED + value: "false" - name: SPRING_DATASOURCE_USERNAME value: "{{ .Values.mysql.auth.username }}" - name: SPRING_DATASOURCE_PASSWORD diff --git a/charts/hawkbit/values.yaml b/charts/hawkbit/values.yaml index a1f8fa40..51b7a530 100644 --- a/charts/hawkbit/values.yaml +++ b/charts/hawkbit/values.yaml @@ -17,6 +17,7 @@ image: repository: "hawkbit/hawkbit-update-server" tag: '0.9.0' pullPolicy: IfNotPresent + initContainer: "hawkbit/hawkbit-repository-jpa-init" # auth configuration auth: