From 62112e8df085b4868bb934f64c0debccee3d1545 Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Tue, 7 Nov 2023 14:47:23 +0000 Subject: [PATCH] Utilize bjw-s's `common` Helm library. (#13) Reviewed-on: https://kolaente.dev/vikunja/helm-chart/pulls/13 Reviewed-by: konrad Co-authored-by: perfectra1n Co-committed-by: perfectra1n --- .gitignore | 1 + Chart.lock | 9 +- Chart.yaml | 11 +- README.md | 188 +++++-------- templates/NOTES.txt | 0 templates/_helpers.tpl | 102 ------- templates/api.yaml | 68 +++++ templates/api/deployment.yaml | 126 --------- templates/api/hpa.yaml | 32 --- templates/api/ingress.yaml | 41 --- templates/api/pdb.yaml | 18 -- templates/api/pvc.yaml | 10 - templates/api/service.yaml | 18 -- templates/frontend.yaml | 29 ++ templates/frontend/deployment.yaml | 107 -------- templates/frontend/hpa.yaml | 32 --- templates/frontend/ingress.yaml | 41 --- templates/frontend/pdb.yaml | 18 -- templates/frontend/service.yaml | 18 -- templates/raw.yaml | 5 - templates/secret.yaml | 9 - templates/serviceaccount.yaml | 15 -- templates/typesense.yaml | 39 +++ values.yaml | 409 +++++++++-------------------- 24 files changed, 348 insertions(+), 998 deletions(-) delete mode 100644 templates/NOTES.txt delete mode 100644 templates/_helpers.tpl create mode 100644 templates/api.yaml delete mode 100644 templates/api/deployment.yaml delete mode 100644 templates/api/hpa.yaml delete mode 100644 templates/api/ingress.yaml delete mode 100644 templates/api/pdb.yaml delete mode 100644 templates/api/pvc.yaml delete mode 100644 templates/api/service.yaml create mode 100644 templates/frontend.yaml delete mode 100644 templates/frontend/deployment.yaml delete mode 100644 templates/frontend/hpa.yaml delete mode 100644 templates/frontend/ingress.yaml delete mode 100644 templates/frontend/pdb.yaml delete mode 100644 templates/frontend/service.yaml delete mode 100644 templates/raw.yaml delete mode 100644 templates/secret.yaml delete mode 100644 templates/serviceaccount.yaml create mode 100644 templates/typesense.yaml diff --git a/.gitignore b/.gitignore index f899a70..67f5729 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ charts/*.tgz *.tgz +output.yaml diff --git a/Chart.lock b/Chart.lock index 6c998d4..12fec3b 100644 --- a/Chart.lock +++ b/Chart.lock @@ -1,9 +1,12 @@ dependencies: - name: redis repository: https://charts.bitnami.com/bitnami - version: 17.5.1 + version: 17.11.6 - name: postgresql repository: https://charts.bitnami.com/bitnami version: 12.1.9 -digest: sha256:32d64f09a27c0f9ae04893871166a0eaed21f1575219aa1d5f8cf0cdd076492b -generated: "2023-01-27T08:31:13.211732638+02:00" +- name: common + repository: https://bjw-s.github.io/helm-charts + version: 1.5.1 +digest: sha256:efadd6fed4908e6062d0d227177d5d650e5fe5b9c94f1cc99feb33ce3a1d0916 +generated: "2023-10-05T14:21:22.588364801-07:00" diff --git a/Chart.yaml b/Chart.yaml index 0ff268c..61329e1 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -15,19 +15,24 @@ appVersion: 0.21.0 kubeVersion: ">= 1.19" dependencies: - name: redis - version: 17.5.1 repository: https://charts.bitnami.com/bitnami - condition: redisEnabled + version: 17.11.6 + condition: redis.enabled - name: postgresql version: 12.1.9 repository: https://charts.bitnami.com/bitnami - condition: postgresqlEnabled + condition: postgresql.enabled +- name: common + repository: https://bjw-s.github.io/helm-charts + version: 1.5.1 keywords: - vikunja - todo - to-do - task - tack-tracker +- project-management +- self-hosted maintainers: - name: Vikunja url: https://vikunja.io diff --git a/README.md b/README.md index 8a7a0c9..8e8ebc0 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ Vikunja Helm Chart === -Customizable deployment of frontend and api. -Deploys bitnami's PostgreSQL and Redis as subcharts if you want. +This Helm Chart deploys both the Vikunja [frontend](https://hub.docker.com/r/vikunja/frontend) and Vikunja [api](https://hub.docker.com/r/vikunja/api) containers, in addition to other Kubernetes resources so that you'll have a fully functioning Vikunja deployment quickly. Also, you can deploy Bitnami's [PostgreSQL](https://github.com/bitnami/charts/tree/main/bitnami/postgresql) and [Redis](https://github.com/bitnami/charts/tree/main/bitnami/redis) as subcharts if you want, as Vikunja can utilize them as its database and caching mechanism (respectively). ## Requirements @@ -11,133 +10,80 @@ Deploys bitnami's PostgreSQL and Redis as subcharts if you want. ## Quickstart -Define ingress settings according to your controller (for both API and Frontend) to access the application. -You can set all Vikunja API options as yaml under `api.config`: https://vikunja.io/docs/config-options +The majority of default values defined in `values.yaml` should be compatible for your deployment. Additionally, if you utilize an Ingress for both the API and Frontend, you will be able to access the frontend out of the box. However, it won't have any default credentials. So, you'll need to create an account using the registration button. -See [values.yaml](./values.yaml#L140) for examples. - -## Advanced features - -### Replicas - -Both Frontend and API can be configured to have replicas including autoscaling. -When replicating the API, make sure to set up the redis cache as well -by setting `api.config.keyvalue.type` to `redis`, -configuring the redis subchart (see [values.yaml](./values.yaml#L280)) -and the connection to Vikunja: -https://vikunja.io/docs/config-options/#redis - -### Raw resources - -Sometimes you have to deploy some cloud-specific resources that are not a part of the application chart itself. -You have to either create an extra chart for that, or manage them with other tools (kustomize, plain manifests etc.). -That is painful. We have a solution. If you want to create anything that is not present in the chart, *just add it in raw*! - -Let's say, you are hosted in [GKE](https://cloud.google.com/kubernetes-engine) -and want to use Google-managed TLS certificates. -In order to do that, you have to create a ManagedCertificate resource: - -```yaml -frontend: - enabled: true - annotations: - kubernetes.io/ingress.class: gce - networking.gke.io/managed-certificates: gmc-example-com - hosts: - - host: example.com - paths: - - path: / - pathType: Prefix - -raw: -- apiVersion: networking.gke.io/v1 - kind: ManagedCertificate - metadata: - name: gmc-example-com - spec: - domains: - - example.com -``` - -Or, let's say, you have decided to use Google SQL database instead of self-hosted, and placed credentials in Google Secret Manager. -You plan to use [ExternalSecrets](https://external-secrets.io/v0.7.2/) to store the credentials. -These can be easily integrated as well. - -```yaml -# Disable embedded database -postgresqlEnabled: false - -api: - config: - database: - # Use PostgreSQL database anyway - type: postgres - envFrom: - # Bind env variables from the secret - - name: VIKUNJA_DATABASE_USER - valueFrom: - secretKeyRef: - name: postgresql-credentials - key: username - - name: VIKUNJA_DATABASE_PASSWORD - valueFrom: - secretKeyRef: - name: postgresql-credentials - key: password - - name: VIKUNJA_DATABASE_HOST - valueFrom: - secretKeyRef: - name: postgresql-credentials - key: hostname - - name: VIKUNJA_DATABASE_DATABASE - valueFrom: - secretKeyRef: - name: postgresql-credentials - key: database - -raw: -- apiVersion: external-secrets.io/v1beta1 - kind: SecretStore - metadata: - name: gcpsm - spec: - refreshInterval: 300 - provider: - gcpsm: - projectID: my-google-project-id - -- apiVersion: external-secrets.io/v1beta1 - kind: ExternalSecret - metadata: - name: postgresql-credentials - spec: - secretStoreRef: - kind: SecretStore - name: gcpsm - target: - deletionPolicy: Delete - refreshInterval: 5m - dataFrom: - - extract: - key: cloud-sql-credentials -``` - -Enjoy! +That should be it! ### Use an existing file volume claim -In the `values.yaml` file, you can configure whether to create the Persistent Volume Claim or use an existing one: +In the `values.yaml` file, you can either define your own existing Persistent Volume Claim (PVC) or have the chart create one on your behalf. + +To have the chart use your pre-existing PVC: ```yaml - # Specifies whether a PVC should be created - create: true - # The name of the PVC to use. - # If not set and create is true, a name is generated using the fullname template - name: "" +api: + persistence: + data: + enabled: true + existingClaim: ``` -This is helpful when migrating from a different k8s chart and to re-use the existing volume -or if you need more control over how the volume is created. +To have the chart create one on your behalf: + +```yaml +# You can find the default values +api: + enabled: true + persistence: + data: + enabled: true + accessMode: ReadWriteOnce + size: 10Gi + storageClass: storage-class +``` + +### Modifying Deployed Resources + +Often times, modifications need to be made to a Helm chart to allow it to operate in your Kubernetes cluster. By utilizing bjw-s's `common` library, there are quite a few options that can be easily modified. + +Anything you see [here](https://github.com/bjw-s/helm-charts/blob/a081de53024d8328d1ae9ff7e4f6bc500b0f3a29/charts/library/common/values.yaml), including the top-level keys, can be added and subtracted from this chart's `values.yaml`, underneath the `api`, `frontend`, and (optionally) `typesense` key. + +For example, if you wished to create a `serviceAccount` as can be seen [here](https://github.com/bjw-s/helm-charts/blob/a081de53024d8328d1ae9ff7e4f6bc500b0f3a29/charts/library/common/values.yaml#L85-L87) for the `api` pod: + +```yaml +api: + serviceAccount: + create: true +``` + +Then, (for some reason), if you wished to deploy the `frontend` as a `DaemonSet` ([as can be seen here](https://github.com/bjw-s/helm-charts/blob/a081de53024d8328d1ae9ff7e4f6bc500b0f3a29/charts/library/common/values.yaml#L12-L17)), you could do the following: + +```yaml +frontend: + controller: + type: daemonset +``` + +### Another Example of Modifying `config.yml` (Enabling Registration) + +You can disable registration (if you do not with to allow others to register on your Vikunja), by providing the following values in your `values.yaml`: + +```yaml +api: + configMaps: + config: + enabled: true + data: + config.yml: + service: + enableregistration: false +``` + +If you need to create another user, you could opt to execute the following command on the `api` container: + +```bash +./vikunja user create --email --user --password +``` ## Publishing diff --git a/templates/NOTES.txt b/templates/NOTES.txt deleted file mode 100644 index e69de29..0000000 diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl deleted file mode 100644 index dcd995f..0000000 --- a/templates/_helpers.tpl +++ /dev/null @@ -1,102 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "vikunja.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 "vikunja.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 "vikunja.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "vikunja.labels" -}} -helm.sh/chart: {{ include "vikunja.chart" . }} -{{ include "vikunja.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "vikunja.selectorLabels" -}} -app.kubernetes.io/name: {{ include "vikunja.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- with .Values.extraLabels }} -{{- toYaml . | nindent 0 }} -{{- end }} -{{- end }} - -{{/* -Selector labels for API -*/}} -{{- define "vikunja.apiSelectorLabels" -}} -{{ include "vikunja.selectorLabels" . }} -app.kubernetes.io/component: api -{{- end }} - -{{/* -Selector labels for frontend -*/}} -{{- define "vikunja.frontendSelectorLabels" -}} -{{ include "vikunja.selectorLabels" . }} -app.kubernetes.io/component: frontend -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "vikunja.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "vikunja.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} - -{{/* -API fullname -*/}} -{{- define "vikunja.apiFullname" -}} -{{- include "vikunja.fullname" . | printf "%s-api" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Frontend fullname -*/}} -{{- define "vikunja.frontendFullname" -}} -{{- include "vikunja.fullname" . | printf "%s-frontend" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create the name of the PVC to use -*/}} -{{- define "vikunja.pvcName" -}} -{{- default (include "vikunja.fullname" .) .Values.api.persistence.name }} -{{- end }} \ No newline at end of file diff --git a/templates/api.yaml b/templates/api.yaml new file mode 100644 index 0000000..2c30d63 --- /dev/null +++ b/templates/api.yaml @@ -0,0 +1,68 @@ +{{- define "vikunja.api.hardcodedValues" -}} +global: + nameOverride: api + +service: + main: + enabled: true + primary: true + type: ClusterIP + ports: + http: + enabled: true + primary: true + port: 3456 + protocol: HTTP + +persistence: + config: + enabled: true + type: configMap + name: "{{ .Release.Name }}-api-config" + mountPath: /etc/vikunja/config.yml + subPath: config.yml + +probes: + liveness: &probes + enabled: true + custom: true + spec: + httpGet: + path: /api/v1/info + port: http + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + readiness: *probes + startup: + enabled: false + + +env: +{{ if .Values.redis.enabled }} + VIKUNJA_REDIS_ENABLED: "true" +{{ end }} +{{ if .Values.typesense.enabled }} + VIKUNJA_TYPESENSE_ENABLED: "true" +{{ end }} +{{ if and .Values.frontend.ingress.enabled .Values.api.configMaps.config.enabled}} + # The configuration for Vikunja's api. + # https://vikunja.io/docs/config-options/ + VIKUNJA_SERVICE_FRONTENDURL: "http://{{ index .Values.frontend.ingress.main.hosts 0 "host" }}{{ index .Values.frontend.ingress.main.hosts 0 "path" }}" +{{ end }} + +# Logic to decide what the api URL should be +{{ if .Values.frontend.ingress.enabled }} + VIKUNJA_FRONTEND_URL: "http://{{ index .Values.frontend.ingress.main.hosts 0 "host" }}{{ index .Values.frontend.ingress.main.hosts 0 "path" }}" +{{ end }} +{{ end }} + + + +{{ if .Values.api.enabled }} +{{- $ctx := deepCopy . -}} +{{- $_ := get .Values "api" | mergeOverwrite $ctx.Values -}} +{{- $_ = include "vikunja.api.hardcodedValues" . | fromYaml | merge $ctx.Values -}} +{{- include "bjw-s.common.loader.all" $ctx }} +{{ end }} \ No newline at end of file diff --git a/templates/api/deployment.yaml b/templates/api/deployment.yaml deleted file mode 100644 index 2892bdf..0000000 --- a/templates/api/deployment.yaml +++ /dev/null @@ -1,126 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "vikunja.apiFullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} -spec: - {{- if not .Values.api.autoscaling.enabled }} - replicas: {{ .Values.api.replicaCount }} - {{- end }} - {{- with .Values.api.extraDeploymentSpec }} - {{- toYaml . | nindent 2 }} - {{- end }} - selector: - matchLabels: - {{- include "vikunja.apiSelectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - checksum/config: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} - {{- with .Values.api.podAnnotations }} - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "vikunja.apiSelectorLabels" . | nindent 8 }} - spec: - {{- with .Values.api.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "vikunja.serviceAccountName" . }} - {{- with .Values.api.podSecurityContext }} - securityContext: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.api.initContainers }} - initContainers: - {{- toYaml . | nindent 8 }} - {{- end }} - containers: - {{- with .Values.api.sidecarContainers }} - {{- toYaml . | nindent 8 }} - {{- end }} - - name: api - {{- with .Values.api.securityContext }} - securityContext: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- $image := required ".image.repository is not set" .Values.api.image.repository }} - {{- $tag := default .Chart.AppVersion .Values.api.image.tag | toString }} - image: {{ printf "%s:%s" $image $tag | quote }} - imagePullPolicy: {{ .Values.api.image.pullPolicy }} - ports: - - name: http - containerPort: {{ (.Values.api.config.service.interface | split ":")._1 | int }} - protocol: TCP - {{- with .Values.api.env }} - env: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.api.envFrom }} - envFrom: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.api.livenessProbe }} - livenessProbe: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- with .Values.api.readinessProbe }} - readinessProbe: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- with .Values.api.startupProbe }} - startupProbe: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- with .Values.api.resources }} - resources: - {{- toYaml . | nindent 10 }} - {{- end }} - volumeMounts: - - name: tmp - mountPath: /tmp - - name: api-config - subPath: api-config.yaml - mountPath: /etc/vikunja/config.yaml - {{- if .Values.api.persistence.enabled }} - - name: storage - subPath: files - mountPath: {{ quote .Values.api.config.files.basepath }} - {{- if eq .Values.api.config.database.type "sqlite" }} - - name: storage - subPath: sqlite - mountPath: {{ dir .Values.api.config.database.path | quote }} - {{- end }} - {{- end }} - {{- with .Values.api.extraVolumeMounts }} - {{- toYaml . | nindent 8 }} - {{- end }} - volumes: - - name: tmp - emptyDir: {} - - name: api-config - secret: - secretName: {{ include "vikunja.fullname" . }} - defaultMode: 0644 - {{- if .Values.api.persistence.enabled }} - - name: storage - persistentVolumeClaim: - claimName: {{ include "vikunja.pvcName" . }} - {{- end }} - {{- with .Values.api.extraVolumes }} - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.api.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.api.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.api.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/templates/api/hpa.yaml b/templates/api/hpa.yaml deleted file mode 100644 index b778e94..0000000 --- a/templates/api/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.api.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "vikunja.apiFullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "vikunja.apiFullname" . }} - minReplicas: {{ int .Values.api.autoscaling.minReplicas }} - maxReplicas: {{ int .Values.api.autoscaling.maxReplicas }} - metrics: - {{- if .Values.api.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ int .Values.api.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.api.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ int .Values.api.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/templates/api/ingress.yaml b/templates/api/ingress.yaml deleted file mode 100644 index 0e6b6c0..0000000 --- a/templates/api/ingress.yaml +++ /dev/null @@ -1,41 +0,0 @@ -{{- if .Values.api.ingress.enabled }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ include "vikunja.apiFullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} - {{- with .Values.api.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- with .Values.api.ingress.className }} - ingressClassName: {{ . }} - {{- end }} - {{- if .Values.api.ingress.tls }} - tls: - {{- range .Values.api.ingress.tls }} - - secretName: {{ quote .secretName }} - hosts: - {{- toYaml .hosts | nindent 8 }} - {{- end }} - {{- end }} - rules: - {{- range .Values.api.ingress.hosts }} - - host: {{ quote .host }} - http: - paths: - {{- range .paths }} - - path: {{ quote .path }} - {{- with .pathType }} - pathType: {{ . }} - {{- end }} - backend: - service: - name: {{ include "vikunja.apiFullname" $ }} - port: - name: http - {{- end }} - {{- end }} -{{- end }} diff --git a/templates/api/pdb.yaml b/templates/api/pdb.yaml deleted file mode 100644 index d5a2e11..0000000 --- a/templates/api/pdb.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.api.pdb.enabled }} -apiVersion: policy/v1 -kind: PodDisruptionBudget -metadata: - name: {{ include "vikunja.apiFullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} -spec: - {{- with .Values.api.pdb.maxUnavailable }} - maxUnavailable: {{ . }} - {{- end }} - {{- with .Values.api.pdb.minAvailable }} - minAvailable: {{ . }} - {{- end }} - selector: - matchLabels: - {{- include "vikunja.apiSelectorLabels" . | nindent 6 }} -{{- end }} diff --git a/templates/api/pvc.yaml b/templates/api/pvc.yaml deleted file mode 100644 index 649f602..0000000 --- a/templates/api/pvc.yaml +++ /dev/null @@ -1,10 +0,0 @@ -{{- if and .Values.api.persistence.enabled .Values.api.persistence.create }} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ include "vikunja.pvcName" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} -spec: - {{- toYaml .Values.api.persistence.spec | nindent 2 }} -{{- end }} diff --git a/templates/api/service.yaml b/templates/api/service.yaml deleted file mode 100644 index c9c9aa6..0000000 --- a/templates/api/service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "vikunja.apiFullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} -spec: - type: {{ .Values.api.service.type }} - ports: - - port: {{ int .Values.api.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "vikunja.apiSelectorLabels" . | nindent 4 }} - {{- with .Values.api.service.extraSpec }} - {{- toYaml . | nindent 2 }} - {{- end }} diff --git a/templates/frontend.yaml b/templates/frontend.yaml new file mode 100644 index 0000000..d2b140a --- /dev/null +++ b/templates/frontend.yaml @@ -0,0 +1,29 @@ +{{- define "vikunja.frontend.hardcodedValues" -}} +global: + nameOverride: frontend + +service: + main: + enabled: true + primary: true + type: ClusterIP + ports: + http: + enabled: true + primary: true + port: 80 + protocol: HTTP + +env: + {{- if .Values.api.ingress.main.enabled }} + VIKUNJA_API_URL: "http://{{ index .Values.api.ingress.main.hosts 0 "host" }}{{ index .Values.api.ingress.main.hosts 0 "path" }}" + {{ end }} + +{{ end }} + +{{ if .Values.frontend.enabled }} +{{- $ctx := deepCopy . -}} +{{- $_ := get .Values "frontend" | mergeOverwrite $ctx.Values -}} +{{- $_ = include "vikunja.frontend.hardcodedValues" . | fromYaml | merge $ctx.Values -}} +{{- include "bjw-s.common.loader.all" $ctx }} +{{ end }} \ No newline at end of file diff --git a/templates/frontend/deployment.yaml b/templates/frontend/deployment.yaml deleted file mode 100644 index a1cbffb..0000000 --- a/templates/frontend/deployment.yaml +++ /dev/null @@ -1,107 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "vikunja.frontendFullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} -spec: - {{- if not .Values.frontend.autoscaling.enabled }} - replicas: {{ .Values.frontend.replicaCount }} - {{- end }} - {{- with .Values.frontend.extraDeploymentSpec }} - {{- toYaml . | nindent 2 }} - {{- end }} - selector: - matchLabels: - {{- include "vikunja.frontendSelectorLabels" . | nindent 6 }} - template: - metadata: - {{- with .Values.frontend.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "vikunja.frontendSelectorLabels" . | nindent 8 }} - spec: - {{- with .Values.frontend.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - serviceAccountName: {{ include "vikunja.serviceAccountName" . }} - {{- with .Values.frontend.podSecurityContext }} - securityContext: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.frontend.initContainers }} - initContainers: - {{- toYaml . | nindent 8 }} - {{- end }} - containers: - {{- with .Values.frontend.sidecarContainers }} - {{- toYaml . | nindent 8 }} - {{- end }} - - name: frontend - {{- with .Values.frontend.securityContext }} - securityContext: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- $image := required ".image.repository is not set" .Values.frontend.image.repository }} - {{- $tag := default .Chart.AppVersion .Values.frontend.image.tag | toString }} - image: {{ printf "%s:%s" $image $tag | quote }} - imagePullPolicy: {{ .Values.frontend.image.pullPolicy }} - ports: - - name: http - containerPort: 8080 - protocol: TCP - env: - - name: VIKUNJA_API_URL - value: {{ quote .Values.frontend.apiUrl }} - - name: VIKUNJA_HTTP_PORT - value: "8080" - {{- with .Values.frontend.env }} - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.frontend.envFrom }} - envFrom: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.frontend.livenessProbe }} - livenessProbe: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- with .Values.frontend.readinessProbe }} - readinessProbe: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- with .Values.frontend.startupProbe }} - startupProbe: - {{- toYaml . | nindent 10 }} - {{- end }} - {{- with .Values.frontend.resources }} - resources: - {{- toYaml . | nindent 10 }} - {{- end }} - volumeMounts: - - name: tmp - mountPath: /tmp - {{- with .Values.frontend.extraVolumeMounts }} - {{- toYaml . | nindent 8 }} - {{- end }} - volumes: - - name: tmp - emptyDir: {} - {{- with .Values.frontend.extraVolumes }} - {{- toYaml . | nindent 6 }} - {{- end }} - {{- with .Values.frontend.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.frontend.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.frontend.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} diff --git a/templates/frontend/hpa.yaml b/templates/frontend/hpa.yaml deleted file mode 100644 index 9264d45..0000000 --- a/templates/frontend/hpa.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.frontend.autoscaling.enabled }} -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: {{ include "vikunja.frontendFullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: {{ include "vikunja.frontendFullname" . }} - minReplicas: {{ int .Values.frontend.autoscaling.minReplicas }} - maxReplicas: {{ int .Values.frontend.autoscaling.maxReplicas }} - metrics: - {{- if .Values.frontend.autoscaling.targetCPUUtilizationPercentage }} - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: {{ int .Values.frontend.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.frontend.autoscaling.targetMemoryUtilizationPercentage }} - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: {{ int .Values.frontend.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} diff --git a/templates/frontend/ingress.yaml b/templates/frontend/ingress.yaml deleted file mode 100644 index b824ff5..0000000 --- a/templates/frontend/ingress.yaml +++ /dev/null @@ -1,41 +0,0 @@ -{{- if .Values.frontend.ingress.enabled }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: {{ include "vikunja.frontendFullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} - {{- with .Values.frontend.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- with .Values.frontend.ingress.className }} - ingressClassName: {{ . }} - {{- end }} - {{- if .Values.frontend.ingress.tls }} - tls: - {{- range .Values.frontend.ingress.tls }} - - secretName: {{ quote .secretName }} - hosts: - {{- toYaml .hosts | nindent 8 }} - {{- end }} - {{- end }} - rules: - {{- range .Values.frontend.ingress.hosts }} - - host: {{ quote .host }} - http: - paths: - {{- range .paths }} - - path: {{ quote .path }} - {{- with .pathType }} - pathType: {{ . }} - {{- end }} - backend: - service: - name: {{ include "vikunja.frontendFullname" $ }} - port: - name: http - {{- end }} - {{- end }} -{{- end }} diff --git a/templates/frontend/pdb.yaml b/templates/frontend/pdb.yaml deleted file mode 100644 index c81810f..0000000 --- a/templates/frontend/pdb.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if .Values.frontend.pdb.enabled }} -apiVersion: policy/v1 -kind: PodDisruptionBudget -metadata: - name: {{ include "vikunja.frontendFullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} -spec: - {{- with .Values.frontend.pdb.maxUnavailable }} - maxUnavailable: {{ . }} - {{- end }} - {{- with .Values.frontend.pdb.minAvailable }} - minAvailable: {{ . }} - {{- end }} - selector: - matchLabels: - {{- include "vikunja.frontendSelectorLabels" . | nindent 6 }} -{{- end }} diff --git a/templates/frontend/service.yaml b/templates/frontend/service.yaml deleted file mode 100644 index 34dc798..0000000 --- a/templates/frontend/service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ include "vikunja.frontendFullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} -spec: - type: {{ .Values.frontend.service.type }} - ports: - - port: {{ int .Values.frontend.service.port }} - targetPort: http - protocol: TCP - name: http - selector: - {{- include "vikunja.frontendSelectorLabels" . | nindent 4 }} - {{- with .Values.frontend.service.extraSpec }} - {{- toYaml . | nindent 2 }} - {{- end }} diff --git a/templates/raw.yaml b/templates/raw.yaml deleted file mode 100644 index 7a022d6..0000000 --- a/templates/raw.yaml +++ /dev/null @@ -1,5 +0,0 @@ -{{- range .Values.raw }} -{{- $manifest := include "vikunja.labels" $ | fromYaml | dict "labels" | dict "metadata" | mergeOverwrite . }} -{{- toYaml $manifest }} ---- -{{- end }} diff --git a/templates/secret.yaml b/templates/secret.yaml deleted file mode 100644 index 5ffee56..0000000 --- a/templates/secret.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ include "vikunja.fullname" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} -type: Opaque -data: - api-config.yaml: {{ toYaml .Values.api.config | b64enc }} diff --git a/templates/serviceaccount.yaml b/templates/serviceaccount.yaml deleted file mode 100644 index 3cfbcdd..0000000 --- a/templates/serviceaccount.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if .Values.serviceAccount.create -}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "vikunja.serviceAccountName" . }} - labels: - {{- include "vikunja.labels" . | nindent 4 }} - {{- with .Values.serviceAccount.labels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.serviceAccount.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -{{- end }} diff --git a/templates/typesense.yaml b/templates/typesense.yaml new file mode 100644 index 0000000..25a115a --- /dev/null +++ b/templates/typesense.yaml @@ -0,0 +1,39 @@ +{{- define "vikunja.typesense.hardcodedValues" -}} +global: + nameOverride: typesense + +service: + main: + enabled: true + primary: true + type: ClusterIP + ports: + http: + enabled: true + primary: true + port: 8108 + protocol: HTTP + +probes: + liveness: &probes + enabled: true + custom: true + spec: + httpGet: + path: /health + port: http + initialDelaySeconds: 0 + periodSeconds: 10 + timeoutSeconds: 1 + failureThreshold: 3 + readiness: *probes + startup: + enabled: false +{{- end }} + +{{ if .Values.typesense.enabled }} +{{- $ctx := deepCopy . -}} +{{- $_ := get .Values "typesense" | mergeOverwrite $ctx.Values -}} +{{- $_ = include "vikunja.typesense.hardcodedValues" . | fromYaml | merge $ctx.Values -}} +{{- include "bjw-s.common.loader.all" $ctx }} +{{ end }} \ No newline at end of file diff --git a/values.yaml b/values.yaml index a2a4e67..3e410b8 100644 --- a/values.yaml +++ b/values.yaml @@ -1,289 +1,140 @@ -# ┐ ┬o┬┌ ┬ ┐┌┐┐ ┬┬─┐ -# │┌┘│├┴┐│ ││││┌ ││─┤ -# └┘ ┘┘ ┘┘─┘┘└┘└─┘┘ ┘ +## This chart relies on the common library chart from bjw-s +## You can find it and the values you can provide and modify, at https://github.com/bjw-s/helm-charts/tree/a081de53024d8328d1ae9ff7e4f6bc500b0f3a29/charts/library/common +## Here's the link to the values.yaml file: https://github.com/bjw-s/helm-charts/blob/a081de53024d8328d1ae9ff7e4f6bc500b0f3a29/charts/library/common/values.yaml +## Refer there for more detail about the supported values. +## Any values that you find in the above `values.yaml` can be provided to this chart and are then rendered. -nameOverride: "" -fullnameOverride: "" - -serviceAccount: - # Specifies whether a service account should be created - create: true - # Annotations to add to the service account - annotations: {} - # Extra labels - extraLabels: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - -# Extra labels that will be added to all resources -extraLabels: {} - -# ┬─┐┬─┐┌─┐┌┐┐┌┐┐┬─┐┌┐┐┬─┐ -# ├─ │┬┘│ ││││ │ ├─ ││││ │ -# ┘ ┘└┘┘─┘┘└┘ ┘ ┴─┘┘└┘┘─┘ - -frontend: - # Public API URL that client's browser will reach - apiUrl: "" - - image: - repository: vikunja/frontend - pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "" - - podSecurityContext: {} - # fsGroup: 1000 - - securityContext: - allowPrivilegeEscalation: false - runAsUser: 101 # nginx - capabilities: - drop: - - ALL - add: - - NET_BIND_SERVICE - - - service: - type: ClusterIP - port: 80 - # If you want to set other fields, like externalName, externalTrafficPolicy, etc. - extraSpec: {} - - ingress: - enabled: false - className: "" - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - - 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 - - replicaCount: 1 - - autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - - initContainers: [] - - sidecarContainers: [] - - # Extra keys to set in deployment.spec. - # Useful if you want to set minReadySeconds, progressDeadlineSeconds, strategy - extraDeploymentSpec: {} - - pdb: - enabled: false - # maxUnavailable: 50% - minAvailable: 50% - - imagePullSecrets: [] - - podAnnotations: {} - - nodeSelector: {} - - tolerations: [] - - affinity: {} - - extraVolumes: [] - - extraVolumeMounts: [] - - livenessProbe: {} - # httpGet: - # path: /ready - # port: http - readinessProbe: {} - # httpGet: - # path: /ready - # port: http - startupProbe: {} - # httpGet: - # path: / - # port: http - - env: {} - - envFrom: {} - -# ┬─┐┬─┐o -# │─┤│─┘│ -# ┘ ┘┘ ┘ +image: + tag: 0.21.0 +###################### +# VIKUNJA COMPONENTS # +###################### +# You can find the default values that this `values.yaml` overrides, in the comment at the top of this file. api: - # Everything under this key is loaded into a native Vikunja yaml config: https://vikunja.io/docs/config-options/ - config: - database: - type: sqlite - path: /sqlite/vikunja.db - files: - basepath: /files - - persistence: - enabled: false - # Specifies whether a PVC should be created - create: true - # The name of the PVC to use. - # If not set and create is true, a name is generated using the fullname template - name: "" - spec: {} - # accessModes: ["ReadWriteOnce"] - # resources: - # requests: - # storage: 1Gi - # storageClassName: openebs-hostpath - + enabled: true image: repository: vikunja/api + tag: 0.21.0 pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. - tag: "" - - securityContext: - capabilities: - add: [CAP_CHOWN] - # readOnlyRootFilesystem: true - # runAsNonRoot: true - # runAsUser: 1000 - - service: - type: ClusterIP - port: 80 - # If you want to set other fields, like externalName, externalTrafficPolicy, etc. - extraSpec: {} - + persistence: + # This is your Vikunja data will live, you can either let + # the chart create a new PVC for you or provide an existing one. + data: + enabled: true + # existingClaim: # your-claim + accessMode: ReadWriteOnce + size: 10Gi + # storageClass: storage-class ingress: + main: + enabled: true + annotations: + # proxy-body-size is set to 0 to remove the body limit on file uploads + nginx.ingress.kubernetes.io/proxy-body-size: "0" + hosts: + - host: vikunja.local + paths: + - path: "/api/v1" + tls: [] + configMaps: + # The configuration for Vikunja's api. + # https://vikunja.io/docs/config-options/ + config: + enabled: true + data: + config.yml: | + # Vikunja needs to know the frontend URL for password reset emails. + # So you might need to provide its value, if you're not using an ingress. + # service: + # frontendUrl: http://vikunja.local + + typesense: + # Typesense will only work if it is enabled below (typesense.enabled). + url: "{{ printf "%s-typesense" .Release.Name }}:8108" + apiKey: "{{ .Values.typesense.env.TYPESENSE_API_KEY }}" + redis: + # Redis will only work if it is enabled below (redis.enabled). + host: "{{ printf "%s-redis-master" .Release.Name }}:6379" + db: "{{ .Release.Name }}" + env: + # To utilize a secret in the environment variables, you can do something like the following: https://github.com/bjw-s/helm-charts/blob/a081de53024d8328d1ae9ff7e4f6bc500b0f3a29/charts/library/common/values.yaml#L141-L145 + # You could also use MySQL or SQLite, but we recommend PostgreSQL. + # https://vikunja.io/docs/config-options/#type + VIKUNJA_DATABASE_TYPE: "postgres" + VIKUNJA_DATABASE_USER: "{{ .Values.postgresql.global.postgresql.auth.username }}" + VIKUNJA_DATABASE_PASSWORD: "{{ .Values.postgresql.global.postgresql.auth.password }}" + VIKUNJA_DATABASE_NAME: "{{ .Values.postgresql.global.postgresql.auth.database }}" + +frontend: + enabled: true + # You can add any of the top-level keys in the common chart's `values.yaml` to override them here. + # For example, this values.yaml file overrides the image values, located here: + # https://github.com/bjw-s/helm-charts/blob/a081de53024d8328d1ae9ff7e4f6bc500b0f3a29/charts/library/common/values.yaml#L63-L69 + image: + repository: vikunja/frontend + tag: 0.21.0 + pullPolicy: IfNotPresent + # You can use either a `service` or an `ingress` to interact with Vikunja's frontend. + # `Ingress` is the recommended option, but you can still set the `service` to + # `LoadBalancer` or another service type. + # https://github.com/bjw-s/helm-charts/blob/a081de53024d8328d1ae9ff7e4f6bc500b0f3a29/charts/library/common/values.yaml#L294-L354 + service: + main: + type: ClusterIP + + # https://github.com/bjw-s/helm-charts/blob/a081de53024d8328d1ae9ff7e4f6bc500b0f3a29/charts/library/common/values.yaml#L393-L436 + ingress: + main: + enabled: true + annotations: + # proxy-body-size is set to 0 to remove the body limit on file uploads + nginx.ingress.kubernetes.io/proxy-body-size: "0" + hosts: + # This is just an example. You should change this to your own domain. + - host: vikunja.local + paths: + - path: "/" + tls: [] + # If you've used the "built-in" ingress in the api section, you don't need to specify VIKUNJA_API_URL as an environment variable here. + # If you've used something else, you'll need to provide the URL to the API here. + # env: + # VIKUNJA_API_URL: http://vikunja.local/api + +########################## +# END VIKUNJA COMPONENTS # +########################## + +# Optional Dependencies +postgresql: + enabled: true + global: + postgresql: + auth: + username: vikunja + database: vikunja + password: vikunja + +redis: + enabled: false + architecture: standalone + auth: enabled: false - className: "" - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: chart-example.local - paths: - - path: / - pathType: ImplementationSpecific - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - 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 +typesense: + enabled: true + env: + TYPESENSE_DATA_DIR: /data + TYPESENSE_API_KEY: typesense + persistence: + data: + # Enabling typesense persistence is recommended to avoid slow reindexing + enabled: true + accessMode: ReadWriteOnce + size: 1Gi + # storageClass: storage-class - replicaCount: 1 - - autoscaling: - enabled: false - minReplicas: 1 - maxReplicas: 100 - targetCPUUtilizationPercentage: 80 - # targetMemoryUtilizationPercentage: 80 - - initContainers: [] - - sidecarContainers: [] - - # Extra keys to set in deployment.spec. - # Useful if you want to set minReadySeconds, progressDeadlineSeconds, strategy - extraDeploymentSpec: {} - - pdb: - enabled: false - # maxUnavailable: 50% - minAvailable: 50% - - imagePullSecrets: [] - - podAnnotations: {} - - podSecurityContext: {} - # fsGroup: 1000 - - nodeSelector: {} - - tolerations: [] - - affinity: {} - - extraVolumes: [] - - extraVolumeMounts: [] - - livenessProbe: {} - # httpGet: - # path: /ready - # port: http - readinessProbe: {} - # httpGet: - # path: /ready - # port: http - startupProbe: {} - # httpGet: - # path: / - # port: http - - env: {} - - envFrom: {} - -# ┬─┐┌─┐┐─┐┌┐┐┌─┐┬─┐┬─┐┐─┐┐─┐┬ -# │─┘│ │└─┐ │ │ ┬│┬┘├─ └─┐│ ││ -# ┘ ┘─┘──┘ ┘ ┘─┘┘└┘┴─┘──┘└─\┘─┘ - -postgresqlEnabled: false -# Please refer to PostgreSQL subchart for a full list of possible values -# https://github.com/bitnami/charts/tree/main/bitnami/postgresql/#parameters -postgresql: {} - -# ┬─┐┬─┐┬─┐o┐─┐ -# │┬┘├─ │ ││└─┐ -# ┘└┘┴─┘┘─┘┘──┘ - -redisEnabled: false -# Please refer to Redis subchart for a full list of possible values -# https://github.com/bitnami/charts/tree/main/bitnami/redis/#parameters -redis: {} - -# ┬─┐┬─┐┐ ┬ -# │┬┘│─┤│││ -# ┘└┘┘ ┘└┴┘ - -# You can create custom resources from the plaintext definition -raw: [] + image: + repository: docker.io/typesense/typesense + tag: 0.25.1 + pullPolicy: IfNotPresent