diff --git a/README.md b/README.md index 5f3c491..29efd7c 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ helm upgrade --install squirrelbot deploy/helm/squirrelbot \ --set secrets.sessionSecret=AT_LEAST_32_RANDOM_CHARACTERS ``` -Set `postgres.enabled=true` and `postgres.auth.password` to start a bundled Postgres StatefulSet. That database is for a single cluster and a small server. Use an external Postgres for anything you need to restore. +Set `postgres.bundled=true` and `postgres.auth.password` to start a bundled Postgres StatefulSet. That database is for a single cluster and a small server. Use an external Postgres for anything you need to restore. `postgres.sslMode` sets the libpq mode on `DATABASE_URL` when the chart writes that URL. The default is `disable`. An `sslmode` already present in `secrets.databaseUrl` is left as written. `make image` builds `squirrelbot:0.1.0` from the repository root. Override the tag with `make image IMAGE=squirrelbot:dev`. Set `imagePullSecrets` when the registry is private. diff --git a/deploy/helm/squirrelbot/templates/_helpers.tpl b/deploy/helm/squirrelbot/templates/_helpers.tpl index 91848e1..d5449fc 100644 --- a/deploy/helm/squirrelbot/templates/_helpers.tpl +++ b/deploy/helm/squirrelbot/templates/_helpers.tpl @@ -23,7 +23,37 @@ {{- end }} {{- end }} +{{- define "squirrelbot.host" -}} +{{- $parsed := urlParse (required "publicUrl is required" .Values.publicUrl) -}} +{{- required "publicUrl must include a host" $parsed.hostname -}} +{{- end }} + {{- define "squirrelbot.image" -}} {{- $tag := .Values.image.tag | default .Chart.AppVersion }} {{- printf "%s:%s" .Values.image.repository $tag }} {{- end }} + +{{- define "squirrelbot.sslMode" -}} +{{- $mode := .Values.postgres.sslMode | default "disable" -}} +{{- $allowed := list "disable" "allow" "prefer" "require" "verify-ca" "verify-full" -}} +{{- if not (has $mode $allowed) -}} +{{- fail "postgres.sslMode must be disable, allow, prefer, require, verify-ca, or verify-full" -}} +{{- end -}} +{{- $mode -}} +{{- end }} + +{{- define "squirrelbot.databaseUrl" -}} +{{- $mode := include "squirrelbot.sslMode" . -}} +{{- if .Values.postgres.bundled -}} +{{- printf "postgres://%s:%s@%s-postgres:5432/%s?sslmode=%s" .Values.postgres.auth.username (.Values.postgres.auth.password | urlquery) (include "squirrelbot.fullname" .) .Values.postgres.auth.database $mode -}} +{{- else -}} +{{- $raw := required "secrets.databaseUrl is required when postgres.bundled is false" .Values.secrets.databaseUrl -}} +{{- if contains "sslmode=" $raw -}} +{{- $raw -}} +{{- else if contains "?" $raw -}} +{{- printf "%s&sslmode=%s" $raw $mode -}} +{{- else -}} +{{- printf "%s?sslmode=%s" $raw $mode -}} +{{- end -}} +{{- end -}} +{{- end }} diff --git a/deploy/helm/squirrelbot/templates/deployment.yaml b/deploy/helm/squirrelbot/templates/deployment.yaml index 8d27cfd..5641cc6 100644 --- a/deploy/helm/squirrelbot/templates/deployment.yaml +++ b/deploy/helm/squirrelbot/templates/deployment.yaml @@ -34,7 +34,7 @@ spec: containers: - name: squirrelbot image: {{ include "squirrelbot.image" . | quote }} - imagePullPolicy: {{ .Values.image.pullPolicy }} + imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }} ports: - name: http containerPort: 8080 diff --git a/deploy/helm/squirrelbot/templates/ingress.yaml b/deploy/helm/squirrelbot/templates/ingress.yaml index f94ed91..05b93d2 100644 --- a/deploy/helm/squirrelbot/templates/ingress.yaml +++ b/deploy/helm/squirrelbot/templates/ingress.yaml @@ -6,7 +6,15 @@ metadata: labels: app.kubernetes.io/name: {{ include "squirrelbot.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} - {{- with .Values.ingress.annotations }} + {{- $annotations := dict }} + {{- if .Values.ingress.tls }} + {{- $_ := set $annotations "traefik.ingress.kubernetes.io/router.tls" "true" }} + {{- end }} + {{- if and .Values.ingress.tls .Values.ingress.certResolver }} + {{- $_ := set $annotations "traefik.ingress.kubernetes.io/router.tls.certresolver" .Values.ingress.certResolver }} + {{- end }} + {{- $annotations = merge $annotations (.Values.ingress.annotations | default dict) }} + {{- with $annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} @@ -17,11 +25,13 @@ spec: {{- if .Values.ingress.tls }} tls: - hosts: - - {{ required "ingress.host is required" .Values.ingress.host }} - secretName: {{ required "ingress.tlsSecretName is required" .Values.ingress.tlsSecretName }} + - {{ include "squirrelbot.host" . }} + {{- with .Values.ingress.tlsSecretName }} + secretName: {{ . }} + {{- end }} {{- end }} rules: - - host: {{ required "ingress.host is required" .Values.ingress.host }} + - host: {{ include "squirrelbot.host" . }} http: paths: - path: / diff --git a/deploy/helm/squirrelbot/templates/postgres.yaml b/deploy/helm/squirrelbot/templates/postgres.yaml index f5f1519..7caf5ba 100644 --- a/deploy/helm/squirrelbot/templates/postgres.yaml +++ b/deploy/helm/squirrelbot/templates/postgres.yaml @@ -1,6 +1,6 @@ -{{- if .Values.postgres.enabled }} +{{- if .Values.postgres.bundled }} {{- if not .Values.postgres.auth.password }} -{{- fail "postgres.auth.password is required when postgres.enabled is true" }} +{{- fail "postgres.auth.password is required when postgres.bundled is true" }} {{- end }} apiVersion: v1 kind: Service diff --git a/deploy/helm/squirrelbot/templates/secret.yaml b/deploy/helm/squirrelbot/templates/secret.yaml index 6e48b93..738a42a 100644 --- a/deploy/helm/squirrelbot/templates/secret.yaml +++ b/deploy/helm/squirrelbot/templates/secret.yaml @@ -1,6 +1,6 @@ {{- if not .Values.existingSecret }} -{{- if and .Values.postgres.enabled (not .Values.postgres.auth.password) }} -{{- fail "postgres.auth.password is required when postgres.enabled is true" }} +{{- if and .Values.postgres.bundled (not .Values.postgres.auth.password) }} +{{- fail "postgres.auth.password is required when postgres.bundled is true" }} {{- end }} {{- if lt (len .Values.secrets.sessionSecret) 32 }} {{- fail "secrets.sessionSecret must be at least 32 characters" }} @@ -18,9 +18,5 @@ stringData: DISCORD_CLIENT_ID: {{ required "secrets.discordClientId is required" .Values.secrets.discordClientId | quote }} DISCORD_CLIENT_SECRET: {{ required "secrets.discordClientSecret is required" .Values.secrets.discordClientSecret | quote }} SESSION_SECRET: {{ .Values.secrets.sessionSecret | quote }} - {{- if .Values.postgres.enabled }} - DATABASE_URL: {{ printf "postgres://%s:%s@%s-postgres:5432/%s?sslmode=disable" .Values.postgres.auth.username (.Values.postgres.auth.password | urlquery) (include "squirrelbot.fullname" .) .Values.postgres.auth.database | quote }} - {{- else }} - DATABASE_URL: {{ required "secrets.databaseUrl is required when postgres.enabled is false" .Values.secrets.databaseUrl | quote }} - {{- end }} + DATABASE_URL: {{ include "squirrelbot.databaseUrl" . | quote }} {{- end }} diff --git a/deploy/helm/squirrelbot/values.yaml b/deploy/helm/squirrelbot/values.yaml index 6cd8074..279de53 100644 --- a/deploy/helm/squirrelbot/values.yaml +++ b/deploy/helm/squirrelbot/values.yaml @@ -25,13 +25,21 @@ secrets: discordClientSecret: "" sessionSecret: "" +# enabled creates the Ingress. Set it to false to skip the Ingress. +# className is the IngressClass. The default is traefik. +# The host comes from publicUrl. +# annotations are copied onto the Ingress. +# tls asks Traefik to serve HTTPS. certResolver is the ACME resolver +# in Traefik's static config. Traefik stores the certificate in +# tlsSecretName. Clear certResolver to use a certificate that +# already exists in that Secret. ingress: - enabled: false - className: "" - host: "" + enabled: true + className: traefik annotations: {} - tls: false - tlsSecretName: "" + tls: true + certResolver: letsencrypt + tlsSecretName: squirrelbot-tls resources: requests: @@ -40,8 +48,16 @@ resources: limits: memory: 256Mi +# bundled starts a Postgres StatefulSet for this release. +# Leave it false and set secrets.databaseUrl for an external database. +# sslMode is the libpq mode: disable, allow, prefer, require, +# verify-ca, or verify-full. The bundled server does not terminate +# TLS, so leave sslMode at disable for that database. For an external +# database, an sslmode already in secrets.databaseUrl is kept. When +# that URL omits sslmode, the chart adds this value. postgres: - enabled: false + bundled: false + sslMode: disable image: postgres:16-alpine auth: database: squirrelbot