diff --git a/README.md b/README.md index 150d2567..e78ce160 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,6 @@ Applications, developed or curated by [mika](https://github.com/irfanhakim-as), | [grocy](mika/grocy) | Grocy is a web-based self-hosted groceries & household management solution for your home. | ✅ | ✅ | | [kutt](mika/kutt) | Kutt is a modern URL shortener with support for custom domains. Shorten URLs, manage your links and view the click rate statistics. | ✅ | ✅ | | [linkstack](mika/linkstack) | LinkStack is a highly customizable link sharing platform with an intuitive, easy to use user interface. | ✅ | ✅ | -| [mango](mika/mango) | Mango is an easy to use Mastodon bot framework built on top of Django. | ✅ | 🔒 | | [mariadb-agent](mika/mariadb-agent) | Easily create or delete multiple pairs of databases and users in a remote MariaDB instance. | ✅ | ✅ | | [postgres](mika/postgres) | Easy tool to deploy a PostgreSQL instance on Kubernetes. | ✅ | ✅ | | [postgres-agent](mika/postgres-agent) | Easily create or delete a database and user pair in a remote PostgreSQL instance. | ✅ | ✅ | diff --git a/logos/cloudflare.png b/logos/cloudflare.png deleted file mode 100644 index 544f67f2..00000000 Binary files a/logos/cloudflare.png and /dev/null differ diff --git a/logos/cloudflare.svg b/logos/cloudflare.svg new file mode 100644 index 00000000..77b9009b --- /dev/null +++ b/logos/cloudflare.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/logos/grocy.svg b/logos/grocy.svg new file mode 100644 index 00000000..18ba1786 --- /dev/null +++ b/logos/grocy.svg @@ -0,0 +1,10 @@ + + + + +Created by potrace 1.16, written by Peter Selinger 2001-2019 + + + + + \ No newline at end of file diff --git a/logos/kutt.svg b/logos/kutt.svg new file mode 100644 index 00000000..031ea53f --- /dev/null +++ b/logos/kutt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/logos/mariadb.png b/logos/mariadb.png deleted file mode 100644 index 31050fab..00000000 Binary files a/logos/mariadb.png and /dev/null differ diff --git a/logos/mariadb.svg b/logos/mariadb.svg new file mode 100644 index 00000000..ddbe283f --- /dev/null +++ b/logos/mariadb.svg @@ -0,0 +1,15 @@ + + + + + + MDB-VLogo_RGB + + + + + + + + + \ No newline at end of file diff --git a/logos/postgres.png b/logos/postgres.png deleted file mode 100644 index 71d6980c..00000000 Binary files a/logos/postgres.png and /dev/null differ diff --git a/logos/postgres.svg b/logos/postgres.svg new file mode 100644 index 00000000..8666f75c --- /dev/null +++ b/logos/postgres.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mika/clog/Chart.yaml b/mika/clog/Chart.yaml index 267dad4a..60ff79e2 100644 --- a/mika/clog/Chart.yaml +++ b/mika/clog/Chart.yaml @@ -2,11 +2,13 @@ apiVersion: v2 name: clog description: Creative blog, Career blog, Coin blog, you name it. type: application -version: 0.2.3 +version: 0.3.0 appVersion: "0.0.2-stable-r1" keywords: - "clog" - "blog" + - "money" + - "todo" home: "https://github.com/irfanhakim-as/clog" icon: "https://irfanhakim-as.github.io/charts/logos/clog.png" sources: diff --git a/mika/clog/README.md b/mika/clog/README.md index 45e22bd9..c13c47c2 100644 --- a/mika/clog/README.md +++ b/mika/clog/README.md @@ -1,131 +1,225 @@ -# [`clog`](https://github.com/irfanhakim-as/clog) 🔒 +# [Clog](https://github.com/irfanhakim-as/clog) + +> [!WARNING] +> This chart requires access to a private image registry, please request access from the owner of the repository. + +Creative blog, Career blog, Coin blog, you name it. ## Prerequisites +> [!NOTE] +> You may refer to [Orked](https://github.com/irfanhakim-as/orked) for help with setting up a Kubernetes cluster that meets all the following prerequisites. + - Kubernetes 1.19+ - Helm 3.2.0+ +- Longhorn 1.4.1+ + +--- ## Preflight checklist -### Create image pull secret +> [!IMPORTANT] +> The following items are required to be set up prior to installing this chart. + +### Image pull secret + +An image pull secret is required to access the private image registry that hosts the required image. + +1. If you have the necessary credentials, create a named image pull secret (i.e. `ghcr-token-secret`) in the `default` namespace: + + ```sh + kubectl create secret docker-registry ghcr-token-secret --docker-server= --docker-username= --docker-password= --docker-email= -n default + ``` + +2. Copy the image pull secret from the `default` namespace to the destination namespace: + + ```sh + kubectl get secret ghcr-token-secret -n default -o yaml | sed "s/namespace: .*/namespace: /" | kubectl apply -f - + ``` + +3. Add the name of the image pull secret to the `imagePullSecrets` array in your installation's values file: + + ```yaml + imagePullSecrets: + - name: "ghcr-token-secret" + ``` + +### Generate secret key + +A unique, secure secret key is required for each Clog installation. + +1. Generate a secret key using the following command: + + ```sh + python -c 'import random; print("".join([random.choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for i in range(50)]))' + ``` + +2. Set the generated secret key as the value of the `clog.secret` setting in your installation's values file: + + ```yaml + secret: "" + ``` + +--- + +## Recommended configurations + +> [!NOTE] +> The following configuration recommendations might not be the default settings for this chart but are **highly recommended**. Please carefully consider them before configuring your installation. + +**This section does not apply to this chart.** + +--- + +## Application configurations + +> [!NOTE] +> The following configurations are expected or recommended to be set up from within the application after completing the installation. + +**This section does not apply to this chart.** + +--- + +## How to add the chart repo + +1. Add the repo to your local helm client: -Replace `$github-username`, `$github-pass`, `$github-email` and `$namespace` accordingly. + ```sh + helm repo add mika https://irfanhakim-as.github.io/charts + ``` -```sh -kubectl create secret docker-registry ghcr-token-secret --docker-server=https://ghcr.io --docker-username="$github-username" --docker-password="$github-pass" --docker-email="$github-email" -n $namespace -``` +2. Update the repo to retrieve the latest versions of the packages: -### Generate secret key for [`clog.secret`](values.yaml) + ```sh + helm repo update + ``` -```sh -python -c 'import random; print("".join([random.choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for i in range(50)]))' -``` +--- -## How to add repo +## How to install or upgrade a chart release -Add the repo to your local helm client. +1. Get the values file of the Clog chart or an existing installation (release). -```sh -helm repo add mika https://irfanhakim-as.github.io/charts -``` + Get the latest Clog chart values file for a new installation: -Update the repo to retrieve the latest versions of the packages. + ```sh + helm show values mika/clog > values.yaml + ``` -```sh -helm repo update -``` + Alternatively, get the values file of an existing Clog release: -## How to install + ```sh + helm get values ${releaseName} --namespace ${namespace} > values.yaml + ``` -### Create database + Replace `${releaseName}` and `${namespace}` accordingly. -Deploy [`mika/postgres-agent`](../postgres-agent/) with `postgres.mode.create` set to `true`. This step can be skipped if you have an existing PostgreSQL database. +2. Edit your Clog values file with the intended configurations: -### Prepare chart values + ```sh + nano values.yaml + ``` -Copy `values.yaml` from the chart you would like to install. + Pay extra attention to the descriptions and sample values provided in the chart values file. -```sh -cp mika/clog/values.yaml . -``` +3. Install a new release for Clog or upgrade an existing Clog release: -Edit `values.yaml` with the appropriate values. Refer to the [Configurations](#Configurations) section for available options. + ```sh + helm upgrade --install ${releaseName} mika/clog --namespace ${namespace} --create-namespace --values values.yaml --wait + ``` -```sh -nano values.yaml -``` + Replace `${releaseName}` and `${namespace}` accordingly. -### Perform installation +4. Verify that your Clog release has been installed: -Install the desired chart. Replace `$release_name` and `$namespace` accordingly. + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -```sh -helm install $release_name mika/clog --namespace $namespace --create-namespace --values values.yaml --wait -``` + Replace `${namespace}` and `${releaseName}` accordingly. This should return the release information if the release has been installed. -Verify that your chart has been installed. Replace `$namespace` and `$release_name` accordingly. +--- -```sh -helm ls --namespace $namespace | grep "$release_name" -``` +## How to uninstall a chart release -## How to upgrade +> [!CAUTION] +> Uninstalling a release will irreversibly delete all the resources associated with the release, including any persistent data. -After making any necessary changes to the `values.yaml` file, upgrade the desired chart. Replace `$release_name` and `$namespace` accordingly. +1. Uninstall the desired release: -```sh -helm upgrade $release_name mika/clog --namespace $namespace --values values.yaml --wait -``` + ```sh + helm uninstall ${releaseName} --namespace ${namespace} --wait + ``` -## How to uninstall + Replace `${releaseName}` and `${namespace}` accordingly. -Uninstall the desired chart. Replace `$release_name` and `$namespace` accordingly. +2. Verify that the release has been uninstalled: -```sh -helm uninstall $release_name --namespace $namespace --wait -``` + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -### Delete database + Replace `${namespace}` and `${releaseName}` accordingly. This should return nothing if the release has been uninstalled. -Deploy [`mika/postgres-agent`](../postgres-agent/) with `postgres.mode.drop` set to `true`. +--- -## Configurations +## Chart configurations | Key | Type | Default | Description | |-----|------|---------|-------------| -| clog.cloudflared.domain | string | `""` | Registered domain name on Cloudflare used for Clog. Default: `"localhost"`. | -| clog.cloudflared.enabled | bool | `false` | Specifies whether Clog should run using a Cloudflare tunnel. | -| clog.debug | string | `""` | Specifies whether Clog should run in debug mode. Default: `false`. | -| clog.ingress.clusterIssuer | string | `""` | The name of the cluster issuer for Ingress. Default: `"letsencrypt-dns-prod"`. | -| clog.ingress.domain | string | `""` | Registered domain name for Clog. Default: `"localhost"`. | -| clog.ingress.enabled | bool | `false` | Specifies whether Clog should be hosted using an Ingress. | -| clog.name | string | `""` | The name of the Clog service. Default: `"Clog"`. | -| clog.ngrok.enabled | bool | `false` | Specifies whether Clog should run using an Ngrok tunnel. | -| clog.ngrok.token | string | `""` | Ngrok authentication token. | -| clog.persistence.enabled | bool | `false` | Specifies whether Clog should persist its storage. | -| clog.persistence.logs.storage | string | `""` | The amount of persistent storage allocated for Clog logs. Default: `"50Mi"`. | -| clog.persistence.media.storage | string | `""` | The amount of persistent storage allocated for Clog media files. Default: `"100Mi"`. | -| clog.persistence.migrations.storage | string | `""` | The amount of persistent storage allocated for Clog migration files. Default: `"20Mi"`. | -| clog.persistence.static.storage | string | `""` | The amount of persistent storage allocated for Clog static files. Default: `"50Mi"`. | -| clog.persistence.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the Clog storage. Default: `"longhorn"`. | +| clog.cloudflared.enabled | bool | `false` | Specifies whether Cloudflare Tunnel should be enabled for hosting Clog services. | +| clog.debug | string | `""` | Specifies whether Clog should run in debug mode. Default: `"false"`. | +| clog.domain | string | `""` | The ingress domain name that hosts the Clog server. Default: `"localhost"`. | +| clog.name | string | `""` | The full name of the Clog web application. Default: `"Clog"`. | +| clog.ngrok.enabled | bool | `false` | Specifies whether Ngrok should be enabled for hosting Clog services. | +| clog.ngrok.token | string | `""` | The authentication token used to authenticate with Ngrok. | | clog.secret | string | `""` | A 50-character secret key used for secure session management and cryptographic operations within the Clog service. | +| clog.serverAdmin | string | `""` | The email address displayed by Apache for server administration contact. Default: `"admin@example.com"`. | | db.host | string | `""` | The hostname or IP address of the Clog database server. | -| db.name | string | `""` | The name of the database used by Clog. | -| db.password | string | `""` | The password associated with the Clog database's user. | -| db.port | string | `""` | The port number on which the Clog database server is listening. Default: `"5432"`. | -| db.type | string | `""` | The type of the database used by Clog. Default: `"postgresql"`. | +| db.name | string | `""` | The name of the database being used by Clog. | +| db.password | string | `""` | The password associated with the Clog database user. | +| db.port | string | `""` | The port number the Clog database server is listening for connections. Default: `"5432"`. | +| db.type | string | `""` | The database engine or backend being used by Clog. Default: `"postgresql"`. | | db.user | string | `""` | The username or user account for accessing the Clog database. | | image.clog.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the Clog container image. Default: `"IfNotPresent"`. | | image.clog.registry | string | `""` | The registry where the Clog container image is hosted. Default: `"ghcr.io"`. | | image.clog.repository | string | `""` | The name of the repository that contains the Clog container image used. Default: `"irfanhakim-as/clog"`. | -| image.clog.tag | string | `""` | The tag that specifies the version of the Clog container image used. Default: `"Chart appVersion"`. | +| image.clog.tag | string | `""` | The tag that specifies the version of the Clog container image used. Default: `Chart appVersion`. | | image.ngrok.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the Ngrok container image. Default: `"IfNotPresent"`. | | image.ngrok.registry | string | `""` | The registry where the Ngrok container image is hosted. Default: `"docker.io"`. | | image.ngrok.repository | string | `""` | The name of the repository that contains the Ngrok container image used. Default: `"wernight/ngrok"`. | | image.ngrok.tag | string | `""` | The tag that specifies the version of the Ngrok container image used. Default: `"latest"`. | | imagePullSecrets | list | `[]` | Credentials used to securely authenticate and authorise the pulling of container images from private registries. | -| replicaCount | string | `""` | The desired number of running replicas for Clog. Default: `"1"`. | -| resources.clog.limits.cpu | string | `"50m"` | The maximum amount of CPU resources allowed for Clog. | -| resources.clog.limits.memory | string | `"200Mi"` | The maximum amount of memory allowed for Clog. | -| resources.clog.requests.cpu | string | `"10m"` | The minimum amount of CPU resources required by Clog. | -| resources.clog.requests.memory | string | `"100Mi"` | The minimum amount of memory required by Clog. | +| ingress.clusterIssuer | string | `""` | The name of the cluster issuer for Ingress. Default: `"letsencrypt-dns-prod"`. | +| ingress.customAnnotations | list | `[]` | Additional configuration annotations to be added to the Ingress resource. Items: `.prefix`, `.name`, `.value`. | +| ingress.enabled | bool | `false` | Specifies whether Ingress should be enabled for hosting Clog services. | +| ingress.www | bool | `false` | Specifies whether the WWW subdomain should be enabled. | +| replicaCount | string | `""` | The desired number of running replicas for Clog. | +| resources.clog | object | `{}` | Resource requirements and limits for Clog containers. | +| service.nodePort | string | `""` | The optional node port to expose when the service type is NodePort. | +| service.port | string | `""` | The port on which the Clog server should listen for connections. Default: `"80"`. | +| service.type | string | `""` | The type of service used to expose Clog services. Default: `"ClusterIP"`. | +| storage.log.accessMode | string | `""` | The access mode defining how the log storage can be mounted. Default: `"ReadWriteMany"`. | +| storage.log.enabled | bool | `false` | Specifies whether persistent storage should be provisioned for log storage. | +| storage.log.mountPath | string | `""` | The path where the log storage should be mounted on the container. Default: `"/var/log/apache2"`. | +| storage.log.storage | string | `""` | The default amount of persistent storage allocated for the log storage. Default: `"50Mi"`. | +| storage.log.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the log storage. Default: `"longhorn"`. | +| storage.log.subPath | string | `""` | The subpath within the log storage to mount to the container. Leave empty if not required. | +| storage.media.accessMode | string | `""` | The access mode defining how the media storage can be mounted. Default: `"ReadWriteMany"`. | +| storage.media.enabled | bool | `false` | Specifies whether persistent storage should be provisioned for media storage. | +| storage.media.mountPath | string | `""` | The path where the media storage should be mounted on the container. Default: `"/clog/media"`. | +| storage.media.storage | string | `""` | The default amount of persistent storage allocated for the media storage. Default: `"100Mi"`. | +| storage.media.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the media storage. Default: `"longhorn"`. | +| storage.media.subPath | string | `""` | The subpath within the media storage to mount to the container. Leave empty if not required. | +| storage.migration.accessMode | string | `""` | The access mode defining how the migration storage can be mounted. Default: `"ReadWriteMany"`. | +| storage.migration.enabled | bool | `false` | Specifies whether persistent storage should be provisioned for migration storage. | +| storage.migration.mountPath | string | `""` | The path where the migration storage should be mounted on the container. Default: `"/clog/%s/migrations"`. | +| storage.migration.storage | string | `""` | The default amount of persistent storage allocated for the migration storage. Default: `"20Mi"`. | +| storage.migration.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the migration storage. Default: `"longhorn"`. | +| storage.migration.subPath | string | `""` | The subpath within the migration storage to mount to the container. Leave empty if not required. | +| storage.static.accessMode | string | `""` | The access mode defining how the static storage can be mounted. Default: `"ReadWriteMany"`. | +| storage.static.enabled | bool | `false` | Specifies whether persistent storage should be provisioned for static storage. | +| storage.static.mountPath | string | `""` | The path where the static storage should be mounted on the container. Default: `"/static"`. | +| storage.static.storage | string | `""` | The default amount of persistent storage allocated for the static storage. Default: `"50Mi"`. | +| storage.static.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the static storage. Default: `"longhorn"`. | +| storage.static.subPath | string | `""` | The subpath within the static storage to mount to the container. Leave empty if not required. | \ No newline at end of file diff --git a/mika/clog/templates/NOTES.txt b/mika/clog/templates/NOTES.txt index a7bceb78..bfa74965 100644 --- a/mika/clog/templates/NOTES.txt +++ b/mika/clog/templates/NOTES.txt @@ -1,5 +1,46 @@ -Clog is now installed and configured for {{ .Release.Name | toString }}. +{{- $serviceAddress := "" }} +{{- $ingress := .Values.ingress.enabled }} +{{- $domain := .Values.clog.domain | toString }} +{{- $port := .Values.service.port | default "80" | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +{{- $serviceName := printf "%s-clog-svc" .Release.Name | toString }} +Clog has been installed and configured for {{ .Release.Name | toString }} 🎉 -See the values.yaml file of this chart for more configuration options. +{{- if $ingress }} + {{- $serviceAddress = printf "https://%s" $domain | toString }} +{{- else if or (eq $type "ClusterIP") (eq $type "LoadBalancer") (eq $type "NodePort") }} -Please refer to the official documentation for more information on how to use Clog. +Please run the following command(s) to obtain the right address to the service: + + ```sh + {{- if eq $type "ClusterIP" }} + {{- $forwardPort := "8080" | toString }} + {{- $serviceAddress = printf "http://127.0.0.1:%s" $forwardPort | toString }} + export POD_NAME=$(kubectl get pod --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "clog.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} ${POD_NAME} -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + kubectl port-forward --namespace {{ .Release.Namespace }} ${POD_NAME} {{ $forwardPort }}:${CONTAINER_PORT} + {{- else if eq $type "LoadBalancer" }} + {{- $serviceAddress = printf "$(echo http://${SERVICE_IP}:%s)" $port | toString }} + export SERVICE_IP=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} --template "{{"{{- range (index .status.loadBalancer.ingress 0) }}{{ . }}{{- end }}"}}") + {{- else if eq $type "NodePort" }} + {{- $serviceAddress = "$(echo http://${NODE_IP}:${NODE_PORT})" | toString }} + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} -o jsonpath="{.spec.ports[0].nodePort}") + {{- end }} + ``` + +{{- end }} + +Visit the following service(s) at the provided address: + +{{- if $serviceAddress }} + + - Clog: {{ $serviceAddress }} + +{{- else }} + + ⚠️ This chart may have no accessible services available + +{{- end }} + +For more information on how to use and configure Clog, please refer to the official documentation. \ No newline at end of file diff --git a/mika/clog/templates/_helpers.tpl b/mika/clog/templates/_helpers.tpl index 4a18a3d6..1140b352 100644 --- a/mika/clog/templates/_helpers.tpl +++ b/mika/clog/templates/_helpers.tpl @@ -60,37 +60,3 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} - -{{/* -Apache site-config.conf template -*/}} -{{- define "clog.site-config-conf" -}} - - ServerName DOMAIN:443 - UseCanonicalName On - ServerAdmin support@mikahomelab.com - DocumentRoot /clog - WSGIScriptAlias / /clog/clog/wsgi.py - WSGIDaemonProcess DOMAIN python-path=/clog - WSGIProcessGroup DOMAIN - - - - Require all granted - - - - Alias /static /static - - Require all granted - - - Alias /media /clog/media - - Require all granted - - - ErrorLog /var/log/apache2/apache.error.log - CustomLog /var/log/apache2/apache.access.log combined - -{{- end }} diff --git a/mika/clog/templates/configmap.yaml b/mika/clog/templates/configmap.yaml index 796b06a2..0e4bb450 100644 --- a/mika/clog/templates/configmap.yaml +++ b/mika/clog/templates/configmap.yaml @@ -1,16 +1,12 @@ -{{- $name := .Values.clog.name | default "Clog" | toString | quote }} -{{- $debug := .Values.clog.debug | default "false" | toString | quote }} {{- $cloudflared := .Values.clog.cloudflared.enabled }} -{{- $ingress := .Values.clog.ingress.enabled }} +{{- $ingress := .Values.ingress.enabled }} {{- $ngrok := .Values.clog.ngrok.enabled }} -{{- $domain := "" -}} -{{- if $cloudflared }} -{{- $domain = .Values.clog.cloudflared.domain | default "localhost" | toString }} -{{- else if $ingress }} -{{- $domain = .Values.clog.ingress.domain | default "localhost" | toString }} -{{- else }} -{{- $domain = "localhost" }} -{{- end }} +{{- $debug := .Values.clog.debug | default "false" | toString | quote }} +{{- $domain := .Values.clog.domain | default "localhost" | toString }} +{{- $name := .Values.clog.name | default "Clog" | toString | quote }} +{{- $serverAdmin := .Values.clog.serverAdmin | default "admin@example.com" | toString }} +{{- $logMountPath := .Values.storage.log.mountPath | default "/var/log/apache2" | toString }} +--- apiVersion: v1 kind: ConfigMap metadata: @@ -18,9 +14,9 @@ metadata: labels: {{- include "clog.labels" . | nindent 4 }} data: - SITE_NAME: {{ $name }} DEBUG: {{ $debug }} NGROK: {{ $ngrok | toString | quote }} + SITE_NAME: {{ $name }} {{- if or $cloudflared $ingress }} DOMAIN: {{ $domain | quote }} {{- end }} @@ -33,4 +29,4 @@ metadata: {{- include "clog.labels" . | nindent 4 }} data: site-config.conf: |- - {{- include "clog.site-config-conf" . | replace "DOMAIN" $domain | nindent 4 }} + {{- include "clog.site-config-conf" . | toString | replace "DOMAIN" $domain | replace "SERVER_ADMIN" $serverAdmin | replace "LOG_MOUNT_PATH" $logMountPath | nindent 4 }} diff --git a/mika/clog/templates/deployment.yaml b/mika/clog/templates/deployment.yaml index c30bc0c6..d6909e6d 100644 --- a/mika/clog/templates/deployment.yaml +++ b/mika/clog/templates/deployment.yaml @@ -1,4 +1,8 @@ -{{- $replica_count := .Values.replicaCount | default "1" | toString }} +{{- $ngrok := .Values.clog.ngrok.enabled }} +{{- $logPersistence := .Values.storage.log.enabled }} +{{- $mediaPersistence := .Values.storage.media.enabled }} +{{- $migrationPersistence := .Values.storage.migration.enabled }} +{{- $staticPersistence := .Values.storage.static.enabled }} {{- $clog_registry := .Values.image.clog.registry | default "ghcr.io" | toString }} {{- $clog_repository := .Values.image.clog.repository | default "irfanhakim-as/clog" | toString }} {{- $clog_tag := .Values.image.clog.tag | default .Chart.AppVersion | toString }} @@ -7,10 +11,16 @@ {{- $ngrok_repository := .Values.image.ngrok.repository | default "wernight/ngrok" | toString }} {{- $ngrok_tag := .Values.image.ngrok.tag | default "latest" | toString }} {{- $ngrok_pullPolicy := .Values.image.ngrok.pullPolicy | default "IfNotPresent" | toString | quote }} -{{- $cloudflared := .Values.clog.cloudflared.enabled }} -{{- $ingress := .Values.clog.ingress.enabled }} -{{- $ngrok := .Values.clog.ngrok.enabled }} -{{- $persistence := .Values.clog.persistence.enabled }} +{{- $replica_count := .Values.replicaCount | default "1" | toString }} +{{- $logMountPath := .Values.storage.log.mountPath | default "/var/log/apache2" | toString | quote }} +{{- $logSubPath := .Values.storage.log.subPath | toString }} +{{- $mediaMountPath := .Values.storage.media.mountPath | default "/clog/media" | toString | quote }} +{{- $mediaSubPath := .Values.storage.media.subPath | toString }} +{{- $migrationMountPath := .Values.storage.migration.mountPath | default "/clog/%s/migrations" | toString | quote }} +{{- $migrationSubPath := .Values.storage.migration.subPath | toString }} +{{- $staticMountPath := .Values.storage.static.mountPath | default "/static" | toString | quote }} +{{- $staticSubPath := .Values.storage.static.subPath | toString }} +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -55,17 +65,38 @@ spec: mountPath: /etc/apache2/sites-available/000-default.conf subPath: site-config.conf readOnly: true - {{- if $persistence }} - - name: {{ .Release.Name }}-clog-static - mountPath: /static + {{- if $logPersistence }} + - name: {{ .Release.Name }}-clog-log + mountPath: {{ $logMountPath }} + {{- if $logSubPath }} + subPath: {{ $logSubPath | quote }} + {{- end }} + {{- end }} + {{- if $mediaPersistence }} - name: {{ .Release.Name }}-clog-media - mountPath: /clog/media - - name: {{ .Release.Name }}-clog-logs - mountPath: /var/log/apache2 - - name: {{ .Release.Name }}-clog-core-migrations - mountPath: /clog/core/migrations - - name: {{ .Release.Name }}-clog-money-migrations - mountPath: /clog/money/migrations + mountPath: {{ $mediaMountPath }} + {{- if $mediaSubPath }} + subPath: {{ $mediaSubPath | quote }} + {{- end }} + {{- end }} + {{- if $migrationPersistence }} + - name: {{ .Release.Name }}-clog-core-migration + mountPath: {{ printf $migrationMountPath "core" }} + {{- if $migrationSubPath }} + subPath: {{ $migrationSubPath | quote }} + {{- end }} + - name: {{ .Release.Name }}-clog-money-migration + mountPath: {{ printf $migrationMountPath "money" }} + {{- if $migrationSubPath }} + subPath: {{ $migrationSubPath | quote }} + {{- end }} + {{- end }} + {{- if $staticPersistence }} + - name: {{ .Release.Name }}-clog-static + mountPath: {{ $staticMountPath }} + {{- if $staticSubPath }} + subPath: {{ $staticSubPath | quote }} + {{- end }} {{- end }} {{- if $ngrok }} - name: ngrok @@ -92,23 +123,28 @@ spec: - name: {{ .Release.Name }}-clog-site-config configMap: name: {{ .Release.Name }}-clog-site-config - items: - - key: site-config.conf - path: site-config.conf - {{- if $persistence }} - - name: {{ .Release.Name }}-clog-static + {{- if $logPersistence }} + - name: {{ .Release.Name }}-clog-log persistentVolumeClaim: - claimName: {{ .Release.Name }}-clog-static-pvc + claimName: {{ .Release.Name }}-clog-log-pvc + {{- end }} + {{- if $mediaPersistence }} - name: {{ .Release.Name }}-clog-media persistentVolumeClaim: claimName: {{ .Release.Name }}-clog-media-pvc - - name: {{ .Release.Name }}-clog-logs + {{- end }} + {{- if $migrationPersistence }} + - name: {{ .Release.Name }}-clog-core-migration persistentVolumeClaim: - claimName: {{ .Release.Name }}-clog-logs-pvc - - name: {{ .Release.Name }}-clog-core-migrations + claimName: {{ .Release.Name }}-clog-core-migration-pvc + - name: {{ .Release.Name }}-clog-money-migration persistentVolumeClaim: - claimName: {{ .Release.Name }}-clog-core-migrations-pvc - - name: {{ .Release.Name }}-clog-money-migrations + claimName: {{ .Release.Name }}-clog-money-migration-pvc + {{- end }} + {{- if $staticPersistence }} + - name: {{ .Release.Name }}-clog-static persistentVolumeClaim: - claimName: {{ .Release.Name }}-clog-money-migrations-pvc + claimName: {{ .Release.Name }}-clog-static-pvc {{- end }} + securityContext: + fsGroup: 33 diff --git a/mika/clog/templates/ingress.yaml b/mika/clog/templates/ingress.yaml index 8ec71ae0..4875c06f 100644 --- a/mika/clog/templates/ingress.yaml +++ b/mika/clog/templates/ingress.yaml @@ -1,7 +1,11 @@ -{{- $ingress := .Values.clog.ingress.enabled }} -{{- if $ingress }} -{{- $cluster_issuer := .Values.clog.ingress.clusterIssuer | default "letsencrypt-dns-prod" | toString | quote }} -{{- $domain := .Values.clog.ingress.domain | default "localhost" | toString }} +{{- $ingress := .Values.ingress.enabled }} +{{- $www := .Values.ingress.www }} +{{- $clusterIssuer := .Values.ingress.clusterIssuer | default "letsencrypt-dns-prod" | toString | quote }} +{{- $customAnnotations := .Values.ingress.customAnnotations }} +{{- $domain := .Values.clog.domain | toString }} +{{- $wwwDomain := printf "www.%s" $domain | toString | quote }} +{{- if and $ingress $domain }} +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -9,7 +13,7 @@ metadata: labels: {{- include "clog.labels" . | nindent 4 }} annotations: - cert-manager.io/cluster-issuer: {{ $cluster_issuer }} + cert-manager.io/cluster-issuer: {{ $clusterIssuer }} cert-manager.io/private-key-algorithm: "ECDSA" nginx.ingress.kubernetes.io/affinity: "cookie" nginx.ingress.kubernetes.io/affinity-mode: "persistent" @@ -18,21 +22,39 @@ metadata: nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" nginx.ingress.kubernetes.io/session-cookie-name: "route" nginx.org/client-max-body-size: "100m" + {{- range $customAnnotations }} + {{ printf "%s/%s" (.prefix | default "nginx.ingress.kubernetes.io") .name }}: {{ .value | quote }} + {{- end }} spec: ingressClassName: "nginx" rules: - - host: {{ $domain | quote }} - http: - paths: - - backend: - service: - name: {{ .Release.Name }}-clog-svc - port: - number: 80 - path: / - pathType: Prefix + - host: {{ $domain | quote }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }}-clog-svc + port: + name: clog + path: / + pathType: Prefix + {{- if $www }} + - host: {{ $wwwDomain }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }}-clog-svc + port: + name: clog + path: / + pathType: Prefix + {{- end }} tls: - - hosts: - - {{ $domain | quote }} - secretName: {{ .Release.Name }}-clog-tls-cert + - hosts: + - {{ $domain | quote }} + {{- if $www }} + - {{ $wwwDomain }} + {{- end }} + secretName: {{ .Release.Name }}-clog-tls-cert {{- end }} diff --git a/mika/clog/templates/pvc.yaml b/mika/clog/templates/pvc.yaml index e3044e1b..d2ee581c 100644 --- a/mika/clog/templates/pvc.yaml +++ b/mika/clog/templates/pvc.yaml @@ -1,23 +1,36 @@ -{{- $static_storage := .Values.clog.persistence.static.storage | default "50Mi" | toString | quote }} -{{- $media_storage := .Values.clog.persistence.media.storage | default "100Mi" | toString | quote }} -{{- $logs_storage := .Values.clog.persistence.logs.storage | default "50Mi" | toString | quote }} -{{- $migrations_storage := .Values.clog.persistence.migrations.storage | default "20Mi" | toString | quote }} -{{- $storage_class_name := .Values.clog.persistence.storageClassName | default "longhorn" | toString | quote }} -{{- $persistence := .Values.clog.persistence.enabled }} -{{- if $persistence }} +{{- $logPersistence := .Values.storage.log.enabled }} +{{- $logAccessMode := .Values.storage.log.accessMode | default "ReadWriteMany" | toString | quote }} +{{- $logStorage := .Values.storage.log.storage | default "50Mi" | toString | quote }} +{{- $logStorageClassName := .Values.storage.log.storageClassName | default "longhorn" | toString | quote }} +{{- $mediaPersistence := .Values.storage.media.enabled }} +{{- $mediaAccessMode := .Values.storage.media.accessMode | default "ReadWriteMany" | toString | quote }} +{{- $mediaStorage := .Values.storage.media.storage | default "100Mi" | toString | quote }} +{{- $mediaStorageClassName := .Values.storage.media.storageClassName | default "longhorn" | toString | quote }} +{{- $migrationPersistence := .Values.storage.migration.enabled }} +{{- $migrationAccessMode := .Values.storage.migration.accessMode | default "ReadWriteMany" | toString | quote }} +{{- $migrationStorage := .Values.storage.migration.storage | default "20Mi" | toString | quote }} +{{- $migrationStorageClassName := .Values.storage.migration.storageClassName | default "longhorn" | toString | quote }} +{{- $staticPersistence := .Values.storage.static.enabled }} +{{- $staticAccessMode := .Values.storage.static.accessMode | default "ReadWriteMany" | toString | quote }} +{{- $staticStorage := .Values.storage.static.storage | default "50Mi" | toString | quote }} +{{- $staticStorageClassName := .Values.storage.static.storageClassName | default "longhorn" | toString | quote }} +{{- if $logPersistence }} +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ .Release.Name }}-clog-static-pvc + name: {{ .Release.Name }}-clog-log-pvc labels: {{- include "clog.labels" . | nindent 4 }} spec: accessModes: - - ReadWriteMany + - {{ $logAccessMode }} resources: requests: - storage: {{ $static_storage }} - storageClassName: {{ $storage_class_name }} + storage: {{ $logStorage }} + storageClassName: {{ $logStorageClassName }} +{{- end }} +{{- if $mediaPersistence }} --- apiVersion: v1 kind: PersistentVolumeClaim @@ -27,51 +40,55 @@ metadata: {{- include "clog.labels" . | nindent 4 }} spec: accessModes: - - ReadWriteMany + - {{ $mediaAccessMode }} resources: requests: - storage: {{ $media_storage }} - storageClassName: {{ $storage_class_name }} + storage: {{ $mediaStorage }} + storageClassName: {{ $mediaStorageClassName }} +{{- end }} +{{- if $migrationPersistence }} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ .Release.Name }}-clog-logs-pvc + name: {{ .Release.Name }}-clog-core-migration-pvc labels: {{- include "clog.labels" . | nindent 4 }} spec: accessModes: - - ReadWriteMany + - {{ $migrationAccessMode }} resources: requests: - storage: {{ $logs_storage }} - storageClassName: {{ $storage_class_name }} + storage: {{ $migrationStorage }} + storageClassName: {{ $migrationStorageClassName }} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ .Release.Name }}-clog-core-migrations-pvc + name: {{ .Release.Name }}-clog-money-migration-pvc labels: {{- include "clog.labels" . | nindent 4 }} spec: accessModes: - - ReadWriteMany + - {{ $migrationAccessMode }} resources: requests: - storage: {{ $migrations_storage }} - storageClassName: {{ $storage_class_name }} + storage: {{ $migrationStorage }} + storageClassName: {{ $migrationStorageClassName }} +{{- end }} +{{- if $staticPersistence }} --- apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ .Release.Name }}-clog-money-migrations-pvc + name: {{ .Release.Name }}-clog-static-pvc labels: {{- include "clog.labels" . | nindent 4 }} spec: accessModes: - - ReadWriteMany + - {{ $staticAccessMode }} resources: requests: - storage: {{ $migrations_storage }} - storageClassName: {{ $storage_class_name }} + storage: {{ $staticStorage }} + storageClassName: {{ $staticStorageClassName }} {{- end }} diff --git a/mika/clog/templates/secret.yaml b/mika/clog/templates/secret.yaml index 5ea5021d..862b9ea7 100644 --- a/mika/clog/templates/secret.yaml +++ b/mika/clog/templates/secret.yaml @@ -1,3 +1,4 @@ +{{- $ngrok := .Values.clog.ngrok.enabled }} {{- $secret := .Values.clog.secret | toString | b64enc }} {{- $token := .Values.clog.ngrok.token | toString | b64enc }} {{- $db_type := .Values.db.type | default "postgresql" | toString | b64enc }} @@ -6,7 +7,7 @@ {{- $db_password := .Values.db.password | toString | b64enc }} {{- $db_host := .Values.db.host | toString | b64enc }} {{- $db_port := .Values.db.port | default "5432" | toString | b64enc }} -{{- $ngrok := .Values.clog.ngrok.enabled }} +--- apiVersion: v1 kind: Secret metadata: @@ -16,12 +17,12 @@ metadata: type: Opaque data: SECRET_KEY: {{ $secret }} - {{- if $ngrok }} - NGROK_AUTH_TOKEN: {{ $token }} - {{- end }} DB_TYPE: {{ $db_type }} DB_NAME: {{ $db_name }} DB_USER: {{ $db_user }} DB_PASS: {{ $db_password }} DB_HOST: {{ $db_host }} DB_PORT: {{ $db_port }} + {{- if $ngrok }} + NGROK_AUTH_TOKEN: {{ $token }} + {{- end }} diff --git a/mika/clog/templates/service.yaml b/mika/clog/templates/service.yaml index 82be697c..f8cb241b 100644 --- a/mika/clog/templates/service.yaml +++ b/mika/clog/templates/service.yaml @@ -1,3 +1,7 @@ +{{- $nodePort := .Values.service.nodePort | toString }} +{{- $port := .Values.service.port | default "80" | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +--- apiVersion: v1 kind: Service metadata: @@ -5,11 +9,14 @@ metadata: labels: {{- include "clog.labels" . | nindent 4 }} spec: - type: ClusterIP + type: {{ $type }} ports: - - port: 80 + - port: {{ int $port }} targetPort: clog + {{- if and (eq $type "NodePort") $nodePort }} + nodePort: {{ int $nodePort }} + {{- end }} protocol: TCP - name: {{ .Release.Name }}-clog + name: clog selector: {{- include "clog.selectorLabels" . | nindent 4 }} diff --git a/mika/clog/templates/site-config.conf.tpl b/mika/clog/templates/site-config.conf.tpl new file mode 100644 index 00000000..103cea2c --- /dev/null +++ b/mika/clog/templates/site-config.conf.tpl @@ -0,0 +1,33 @@ +{{/* +Apache site-config.conf template +*/}} +{{- define "clog.site-config-conf" -}} + + ServerName DOMAIN:443 + UseCanonicalName On + ServerAdmin SERVER_ADMIN + DocumentRoot /clog + WSGIScriptAlias / /clog/clog/wsgi.py + WSGIDaemonProcess DOMAIN python-path=/clog + WSGIProcessGroup DOMAIN + + + + Require all granted + + + + Alias /static /static + + Require all granted + + + Alias /media /clog/media + + Require all granted + + + ErrorLog LOG_MOUNT_PATH/apache.error.log + CustomLog LOG_MOUNT_PATH/apache.access.log combined + +{{- end }} diff --git a/mika/clog/values.yaml b/mika/clog/values.yaml index f9c16782..0c570734 100644 --- a/mika/clog/values.yaml +++ b/mika/clog/values.yaml @@ -9,6 +9,7 @@ replicaCount: "" # Container images used for Clog. image: # Clog container image configurations. + # Source: https://github.com/irfanhakim-as/clog/pkgs/container/clog clog: # The registry where the Clog container image is hosted. # Default: "ghcr.io" @@ -23,6 +24,7 @@ image: # Default: "IfNotPresent" pullPolicy: "" # Ngrok container image configurations. + # Source: https://hub.docker.com/r/wernight/ngrok ngrok: # The registry where the Ngrok container image is hosted. # Default: "docker.io" @@ -43,104 +45,66 @@ image: # - name: "ghcr-token-secret" imagePullSecrets: [] +# Clog configurations. clog: - # The name of the Clog service. - # Default: "Clog" - # Example: - # name: "Clog" - name: "" # Specifies whether Clog should run in debug mode. - # Default: false + # Default: "false" + # Example: + # debug: "true" + debug: "" + # The ingress domain name that hosts the Clog server. + # Default: "localhost" + # Example: + # domain: "clog.example.com" + domain: "" + # The full name of the Clog web application. + # Default: "Clog" # Example: - # debug: true - debug: "" + # name: "My Blog" + name: "" # A 50-character secret key used for secure session management and cryptographic operations within the Clog service. # Example: # secret: "6&p4%t)-$8a14fmfh92py8j55+us51r6%e52dzy&=a3-6yd4#e" - secret: "" - # Clog storage persistence configurations. - persistence: - # Specifies whether Clog should persist its storage. - # Example: - # enabled: true - enabled: false - # The storage class name used for dynamically provisioning a persistent volume for the Clog storage. - # Default: "longhorn" - # Example: - # storageClassName: "longhorn" - storageClassName: "" - # Clog static files persistence configurations. - static: - # The amount of persistent storage allocated for Clog static files. - # Default: "50Mi" - # Example: - # storage: "1Gi" - storage: "" - # Clog media files persistence configurations. - media: - # The amount of persistent storage allocated for Clog media files. - # Default: "100Mi" - # Example: - # storage: "1Gi" - storage: "" - # Clog logs persistence configurations. - logs: - # The amount of persistent storage allocated for Clog logs. - # Default: "50Mi" - # Example: - # storage: "1Gi" - storage: "" - # Clog migration files persistence configurations. - migrations: - # The amount of persistent storage allocated for Clog migration files. - # Default: "20Mi" - # Example: - # storage: "1Gi" - storage: "" - # Clog Cloudflare configurations. + secret: "" + # The email address displayed by Apache for server administration contact. + # Default: "admin@example.com" + # Example: + # serverAdmin: "foo@example.com" + serverAdmin: "" + # Cloudflare Tunnel configurations. cloudflared: - # Specifies whether Clog should run using a Cloudflare tunnel. - # Example: - # enabled: true - enabled: false - # Registered domain name on Cloudflare used for Clog. - # Default: "localhost" - # Example: - # domain: "clog.example.com" - domain: "" - # Clog Ingress configurations. - ingress: - # Specifies whether Clog should be hosted using an Ingress. + # Specifies whether Cloudflare Tunnel should be enabled for hosting Clog services. # Example: # enabled: true enabled: false - # The name of the cluster issuer for Ingress. - # Default: "letsencrypt-dns-prod" - clusterIssuer: "" - # Registered domain name for Clog. - # Default: "localhost" - # Example: - # domain: "clog.example.com" - domain: "" - # Clog Ngrok configurations. + # Ngrok configurations. ngrok: - # Specifies whether Clog should run using an Ngrok tunnel. + # Specifies whether Ngrok should be enabled for hosting Clog services. # Example: # enabled: true enabled: false - # Ngrok authentication token. + # The authentication token used to authenticate with Ngrok. # Example: # token: "s7Ed4IO23nw1HWRJwumSgcyB7BtcXr4ZYLtziJCDDLIVDv7uq" token: "" # Database configurations. db: - # The type of the database used by Clog. + # The database engine or backend being used by Clog. # Default: "postgresql" # Example: - # type: "postgresql" + # type: "mysql" type: "" - # The name of the database used by Clog. + # The hostname or IP address of the Clog database server. + # Example: + # host: "clog.default.svc.cluster.local" + host: "" + # The port number the Clog database server is listening for connections. + # Default: "5432" + # Example: + # port: "3306" + port: "" + # The name of the database being used by Clog. # Example: # name: "clog" name: "" @@ -148,41 +112,208 @@ db: # Example: # user: "root" user: "" - # The password associated with the Clog database's user. + # The password associated with the Clog database user. # Example: # password: "password" password: "" - # The hostname or IP address of the Clog database server. + +# Ingress configurations. +ingress: + # Specifies whether Ingress should be enabled for hosting Clog services. # Example: - # host: "clog.default.svc.cluster.local" - host: "" - # The port number on which the Clog database server is listening. - # Default: "5432" + # enabled: true + enabled: false + # The name of the cluster issuer for Ingress. + # Default: "letsencrypt-dns-prod" + # Example: + # clusterIssuer: "letsencrypt-http-prod" + clusterIssuer: "" + # Specifies whether the WWW subdomain should be enabled. # Example: - # port: "5432" + # www: true + www: false + # Additional configuration annotations to be added to the Ingress resource. + # Items: `.prefix`, `.name`, `.value` + # Example: + # customAnnotations: + # # The prefix of the annotation. + # # Default: "nginx.ingress.kubernetes.io" + # # Example: + # # prefix: "nginx.org" + # - prefix: "" + # # The name of the annotation. + # # Example: + # # name: "proxy-connect-timeout" + # name: "" + # # The value of the annotation. + # # Example: + # # value: "120" + # value: "" + customAnnotations: [] + +# Service configurations. +service: + # The optional node port to expose when the service type is NodePort. + # Example: + # nodePort: "32000" + nodePort: "" + # The port on which the Clog server should listen for connections. + # Default: "80" + # Example: + # port: "8080" port: "" + # The type of service used to expose Clog services. + # Default: "ClusterIP" + # Example: + # type: "NodePort" + type: "" + +# Storage configurations. +storage: + # Log storage configurations. + log: + # Specifies whether persistent storage should be provisioned for log storage. + # Example: + # enabled: true + enabled: false + # The access mode defining how the log storage can be mounted. + # Default: "ReadWriteMany" + # Example: + # accessMode: "ReadWriteOnce" + accessMode: "" + # The path where the log storage should be mounted on the container. + # Default: "/var/log/apache2" + # Example: + # mountPath: "/log" + mountPath: "" + # The subpath within the log storage to mount to the container. Leave empty if not required. + # Example: + # subPath: "Log" + subPath: "" + # The default amount of persistent storage allocated for the log storage. + # Default: "50Mi" + # Example: + # storage: "10Gi" + storage: "" + # The storage class name used for dynamically provisioning a persistent volume for the log storage. + # Default: "longhorn" + # Example: + # storageClassName: "smb" + storageClassName: "" + # Media storage configurations. + media: + # Specifies whether persistent storage should be provisioned for media storage. + # Example: + # enabled: true + enabled: false + # The access mode defining how the media storage can be mounted. + # Default: "ReadWriteMany" + # Example: + # accessMode: "ReadWriteOnce" + accessMode: "" + # The path where the media storage should be mounted on the container. + # Default: "/clog/media" + # Example: + # mountPath: "/media" + mountPath: "" + # The subpath within the media storage to mount to the container. Leave empty if not required. + # Example: + # subPath: "Media" + subPath: "" + # The default amount of persistent storage allocated for the media storage. + # Default: "100Mi" + # Example: + # storage: "10Gi" + storage: "" + # The storage class name used for dynamically provisioning a persistent volume for the media storage. + # Default: "longhorn" + # Example: + # storageClassName: "smb" + storageClassName: "" + # Migration storage configurations. + migration: + # Specifies whether persistent storage should be provisioned for migration storage. + # Example: + # enabled: true + enabled: false + # The access mode defining how the migration storage can be mounted. + # Default: "ReadWriteMany" + # Example: + # accessMode: "ReadWriteOnce" + accessMode: "" + # The path where the migration storage should be mounted on the container. + # Default: "/clog/%s/migrations" + # Example: + # mountPath: "/migration" + mountPath: "" + # The subpath within the migration storage to mount to the container. Leave empty if not required. + # Example: + # subPath: "Migration" + subPath: "" + # The default amount of persistent storage allocated for the migration storage. + # Default: "20Mi" + # Example: + # storage: "10Gi" + storage: "" + # The storage class name used for dynamically provisioning a persistent volume for the migration storage. + # Default: "longhorn" + # Example: + # storageClassName: "smb" + storageClassName: "" + # Static storage configurations. + static: + # Specifies whether persistent storage should be provisioned for static storage. + # Example: + # enabled: true + enabled: false + # The access mode defining how the static storage can be mounted. + # Default: "ReadWriteMany" + # Example: + # accessMode: "ReadWriteOnce" + accessMode: "" + # The path where the static storage should be mounted on the container. + # Default: "/static" + # Example: + # mountPath: "/static" + mountPath: "" + # The subpath within the static storage to mount to the container. Leave empty if not required. + # Example: + # subPath: "Static" + subPath: "" + # The default amount of persistent storage allocated for the static storage. + # Default: "50Mi" + # Example: + # storage: "10Gi" + storage: "" + # The storage class name used for dynamically provisioning a persistent volume for the static storage. + # Default: "longhorn" + # Example: + # storageClassName: "smb" + storageClassName: "" # Resource requirements and limits for Clog containers. resources: # Clog container resources. - clog: - # The minimum amount of resources required by Clog to run. - requests: - # The minimum amount of CPU resources required by Clog. - # Example: - # cpu: "20m" - cpu: "10m" - # The minimum amount of memory required by Clog. - # Example: - # memory: "250Mi" - memory: "100Mi" - # The maximum amount of resources allowed for Clog. - limits: - # The maximum amount of CPU resources allowed for Clog. - # Example: - # cpu: "50m" - cpu: "50m" - # The maximum amount of memory allowed for Clog. - # Example: - # memory: "450Mi" - memory: "200Mi" + # Example: + # clog: + # # The minimum amount of resources required by Clog to run. + # requests: + # # The minimum amount of CPU resources required by Clog. + # # Example: + # # cpu: "10m" + # cpu: "10m" + # # The minimum amount of memory required by Clog. + # # Example: + # # memory: "10Mi" + # memory: "100Mi" + # # The maximum amount of resources allowed for Clog. + # limits: + # # The maximum amount of CPU resources allowed for Clog. + # # Example: + # # cpu: "250m" + # cpu: "50m" + # # The maximum amount of memory allowed for Clog. + # # Example: + # # memory: "250Mi" + # memory: "200Mi" + clog: {} diff --git a/mika/cloudflareddns/Chart.yaml b/mika/cloudflareddns/Chart.yaml index 61c90521..587d401a 100644 --- a/mika/cloudflareddns/Chart.yaml +++ b/mika/cloudflareddns/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: cloudflareddns description: Access your home network remotely via a custom domain name without a static IP! type: application -version: 0.1.0 +version: 0.1.1 appVersion: "latest" keywords: - "cloudflareddns" @@ -10,7 +10,7 @@ keywords: - "ddns" - "cloudflare-ddns" home: "https://github.com/irfanhakim-as/charts" -icon: "https://irfanhakim-as.github.io/charts/logos/cloudflare.png" +icon: "https://irfanhakim-as.github.io/charts/logos/cloudflare.svg" sources: - "https://github.com/timothymiller/cloudflare-ddns" maintainers: diff --git a/mika/cloudflareddns/README.md b/mika/cloudflareddns/README.md index d1c0b3b0..b751c476 100644 --- a/mika/cloudflareddns/README.md +++ b/mika/cloudflareddns/README.md @@ -1,87 +1,143 @@ -# [`cloudflareddns`](https://github.com/timothymiller/cloudflare-ddns) +# [Cloudflare DDNS](https://github.com/timothymiller/cloudflare-ddns) + +Access your home network remotely via a custom domain name without a static IP! ## Prerequisites +> [!NOTE] +> You may refer to [Orked](https://github.com/irfanhakim-as/orked) for help with setting up a Kubernetes cluster that meets all the following prerequisites. + - Kubernetes 1.19+ - Helm 3.2.0+ -## How to add repo +--- + +## Preflight checklist + +> [!IMPORTANT] +> The following items are required to be set up prior to installing this chart. + +**This section does not apply to this chart.** + +--- + +## Recommended configurations + +> [!NOTE] +> The following configuration recommendations might not be the default settings for this chart but are **highly recommended**. Please carefully consider them before configuring your installation. + +**This section does not apply to this chart.** + +--- + +## Application configurations + +> [!NOTE] +> The following configurations are expected or recommended to be set up from within the application after completing the installation. + +**This section does not apply to this chart.** + +--- + +## How to add the chart repo + +1. Add the repo to your local helm client: + + ```sh + helm repo add mika https://irfanhakim-as.github.io/charts + ``` + +2. Update the repo to retrieve the latest versions of the packages: + + ```sh + helm repo update + ``` + +--- + +## How to install or upgrade a chart release + +1. Get the values file of the Cloudflare DDNS chart or an existing installation (release). + + Get the latest Cloudflare DDNS chart values file for a new installation: + + ```sh + helm show values mika/cloudflareddns > values.yaml + ``` + + Alternatively, get the values file of an existing Cloudflare DDNS release: -Add the repo to your local helm client. + ```sh + helm get values ${releaseName} --namespace ${namespace} > values.yaml + ``` -```sh -helm repo add mika https://irfanhakim-as.github.io/charts -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Update the repo to retrieve the latest versions of the packages. +2. Edit your Cloudflare DDNS values file with the intended configurations: -```sh -helm repo update -``` + ```sh + nano values.yaml + ``` -## How to install + Pay extra attention to the descriptions and sample values provided in the chart values file. -### Prepare chart values +3. Install a new release for Cloudflare DDNS or upgrade an existing Cloudflare DDNS release: -Copy `values.yaml` from the chart you would like to install. + ```sh + helm upgrade --install ${releaseName} mika/cloudflareddns --namespace ${namespace} --create-namespace --values values.yaml --wait + ``` -```sh -cp mika/cloudflareddns/values.yaml . -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Edit `values.yaml` with the appropriate values. Please refer to the [Configurations](#configurations) section below, or the `values.yaml` file itself for details and sample values. +4. Verify that your Cloudflare DDNS release has been installed: -```sh -nano values.yaml -``` + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -### Perform installation + Replace `${namespace}` and `${releaseName}` accordingly. This should return the release information if the release has been installed. -Install the desired chart. Replace `$release_name` and `$namespace` accordingly. +--- -```sh -helm install $release_name mika/cloudflareddns --namespace $namespace --create-namespace --values values.yaml --wait -``` +## How to uninstall a chart release -Verify that your chart has been installed. Replace `$namespace` and `$release_name` accordingly. +> [!CAUTION] +> Uninstalling a release will irreversibly delete all the resources associated with the release, including any persistent data. -```sh -helm ls --namespace $namespace | grep "$release_name" -``` +1. Uninstall the desired release: -## How to upgrade + ```sh + helm uninstall ${releaseName} --namespace ${namespace} --wait + ``` -After making any necessary changes to the `values.yaml` file, upgrade the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${releaseName}` and `${namespace}` accordingly. -```sh -helm upgrade $release_name mika/cloudflareddns --namespace $namespace --values values.yaml --wait -``` +2. Verify that the release has been uninstalled: -## How to uninstall + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -Uninstall the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${namespace}` and `${releaseName}` accordingly. This should return nothing if the release has been uninstalled. -```sh -helm uninstall $release_name --namespace $namespace --wait -``` +--- -## Configurations +## Chart configurations | Key | Type | Default | Description | |-----|------|---------|-------------| -| cloudflareddns.configPath | string | `""` | The path to the cloudflareddns configuration directory. Default: `"/etc/cloudflare-ddns"`. | +| cloudflareddns.configPath | string | `""` | The path to the Cloudflare DDNS configuration directory. Default: `"/etc/cloudflare-ddns"`. | | cloudflareddns.ipv4 | string | `""` | Specify whether to add an A record for each subdomain. Default: `"true"`. | | cloudflareddns.ipv6 | string | `""` | Specify whether to add an AAAA record for each subdomain. Default: `"false"`. | -| cloudflareddns.subdomains | list | `[]` | The list of subdomains to be updated, each with their own hostname and proxied setting. | +| cloudflareddns.purge | string | `""` | Specify whether to purge stale DNS records not defined in the configuration. Default: `"false"`. | +| cloudflareddns.subdomains | list | `[]` | The list of subdomains to be updated for a specified domain (zone). Items: `.hostname`, `.proxied`. | | cloudflareddns.token | string | `""` | The Cloudflare API token used to authenticate with the Cloudflare API. | +| cloudflareddns.ttl | string | `""` | The Time-To-Live (TTL) duration defining how long DNS records are cached in seconds. Default: `"300"`. | | cloudflareddns.zoneID | string | `""` | The ID of the zone that will get the records. | -| image.cloudflareddns.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the cloudflareddns container image. Default: `"IfNotPresent"`. | -| image.cloudflareddns.registry | string | `""` | The registry where the cloudflareddns container image is hosted. Default: `"docker.io"`. | -| image.cloudflareddns.repository | string | `""` | The name of the repository that contains the cloudflareddns container image used. Default: `"timothyjmiller/cloudflare-ddns"`. | -| image.cloudflareddns.tag | string | `""` | The tag that specifies the version of the cloudflareddns container image used. Default: `Chart appVersion`. | +| image.cloudflareddns.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the Cloudflare DDNS container image. Default: `"IfNotPresent"`. | +| image.cloudflareddns.registry | string | `""` | The registry where the Cloudflare DDNS container image is hosted. Default: `"docker.io"`. | +| image.cloudflareddns.repository | string | `""` | The name of the repository that contains the Cloudflare DDNS container image used. Default: `"timothyjmiller/cloudflare-ddns"`. | +| image.cloudflareddns.tag | string | `""` | The tag that specifies the version of the Cloudflare DDNS container image used. Default: `Chart appVersion`. | | imagePullSecrets | list | `[]` | Credentials used to securely authenticate and authorise the pulling of container images from private registries. | -| replicaCount | string | `""` | The desired number of running replicas for cloudflareddns. Default: `"1"`. | -| resources.limits.cpu | string | `"50m"` | The maximum amount of CPU resources allowed for cloudflareddns. | -| resources.limits.memory | string | `"32Mi"` | The maximum amount of memory allowed for cloudflareddns. | -| resources.requests.cpu | string | `"10m"` | The minimum amount of CPU resources required by cloudflareddns. | -| resources.requests.memory | string | `"10Mi"` | The minimum amount of memory required by cloudflareddns. | \ No newline at end of file +| replicaCount | string | `""` | The desired number of running replicas for Cloudflare DDNS. Default: `"1"`. | +| resources.cloudflareddns | object | `{}` | Resource requirements and limits for Cloudflare DDNS containers. | \ No newline at end of file diff --git a/mika/cloudflareddns/templates/NOTES.txt b/mika/cloudflareddns/templates/NOTES.txt index 186b0d10..ad5e052b 100644 --- a/mika/cloudflareddns/templates/NOTES.txt +++ b/mika/cloudflareddns/templates/NOTES.txt @@ -1,5 +1,69 @@ -cloudflareddns is now installed and configured for {{ .Release.Name | toString }}. +{{- $cloudflareIP := "" }} +{{- $ipv4 := .Values.cloudflareddns.ipv4 | default "true" | toString }} +{{- $ipv6 := .Values.cloudflareddns.ipv6 | default "false" | toString }} +{{- $subdomains := .Values.cloudflareddns.subdomains }} +Cloudflare DDNS has been installed and configured for {{ .Release.Name | toString }} 🎉 -See the values.yaml file of this chart for more configuration options. +The following are a list of subdomain(s) you have supplied to be updated: -Please refer to the official documentation for more information on how to use cloudflareddns. +{{- if not $subdomains }} + + ⚠️ No subdomains were supplied for Cloudflare DDNS to monitor and update + +{{- else }} + + {{- range $index, $subdomain := $subdomains }} + {{- $fqdn := "" }} + {{- $ip := "" }} + {{- $hostname := $subdomain.hostname | toString }} + {{- $proxied := $subdomain.proxied | default "false" | toString }} + + {{- if eq $hostname "" }} + {{- $fqdn = "domain" | toString }} + {{- else }} + {{- $fqdn = printf "%s.domain" $hostname | toString }} + {{- end }} + {{- if eq $proxied "true" }} + {{- $cloudflareIP = "true" | toString }} + {{- $ip = "Cloudflare IP" | toString }} + {{- else }} + {{- $ip = printf "IPv4=%s/IPv6=%s" $ipv4 $ipv6 | toString }} + {{- end }} + + {{ printf "%s. %s (%s)" ($index | add1 | toString) $fqdn $ip }} + + {{- end }} + +Expected endpoint(s): + + {{- if or (eq $ipv4 "true") (eq $ipv6 "true") (eq $cloudflareIP "true") }} + {{- if eq $ipv4 "true" }} + + - IPv4: $(dig -4 +short myip.opendns.com @resolver1.opendns.com) + + {{- end }} + {{- if eq $ipv6 "true" }} + + - IPv6: $(dig AAAA +short myip.opendns.com @resolver1.ipv6-sandbox.opendns.com) + + {{- end }} + {{- if eq $cloudflareIP "true" }} + + - Cloudflare IP: Please refer to https://www.cloudflare.com/ips for the full list of IPs + + {{- end }} + +Please run the following command to check if each subdomain is being routed to the right endpoint: + + ```sh + nslookup . + ``` + + {{- else }} + + ⚠️ Subdomains supplied were not configured to be updated according to any endpoint + + {{- end }} +{{- end }} + +For more information on how to use and configure Cloudflare DDNS, please refer to the official documentation. diff --git a/mika/cloudflareddns/templates/config.json.tpl b/mika/cloudflareddns/templates/config.json.tpl index c671325b..1ff5aed7 100644 --- a/mika/cloudflareddns/templates/config.json.tpl +++ b/mika/cloudflareddns/templates/config.json.tpl @@ -13,8 +13,8 @@ Cloudflare-DDNS config.json template {{- $subdomains := .Values.cloudflareddns.subdomains }} {{- range $index, $subdomain := $subdomains }} { - "name": "{{ $subdomain.hostname }}", - "proxied": {{ $subdomain.proxied }} + "name": {{ $subdomain.hostname | quote }}, + "proxied": {{ $subdomain.proxied | default "false" | toString }} }{{ if ne $index (sub (len $subdomains) 1) }},{{ end }} {{- end }} ] @@ -22,7 +22,7 @@ Cloudflare-DDNS config.json template ], "a": ENABLE_IPV4, "aaaa": ENABLE_IPV6, - "purgeUnknownRecords": false, - "ttl": 300 + "purgeUnknownRecords": ENABLE_PURGE, + "ttl": TTL_SECONDS } {{- end }} diff --git a/mika/cloudflareddns/templates/configmap.yaml b/mika/cloudflareddns/templates/configmap.yaml index 9c3205b5..d6c8e6b1 100644 --- a/mika/cloudflareddns/templates/configmap.yaml +++ b/mika/cloudflareddns/templates/configmap.yaml @@ -1,4 +1,5 @@ -{{- $config_path := .Values.cloudflareddns.configPath | default "/etc/cloudflare-ddns" | toString | quote }} +{{- $configPath := .Values.cloudflareddns.configPath | default "/etc/cloudflare-ddns" | toString | quote }} +--- apiVersion: v1 kind: ConfigMap metadata: @@ -6,4 +7,4 @@ metadata: labels: {{- include "cloudflareddns.labels" . | nindent 4 }} data: - CONFIG_PATH: {{ $config_path }} + CONFIG_PATH: {{ $configPath }} diff --git a/mika/cloudflareddns/templates/deployment.yaml b/mika/cloudflareddns/templates/deployment.yaml index d7addfaa..5bcf6ac2 100644 --- a/mika/cloudflareddns/templates/deployment.yaml +++ b/mika/cloudflareddns/templates/deployment.yaml @@ -1,9 +1,10 @@ -{{- $registry := .Values.image.cloudflareddns.registry | default "docker.io" | toString }} -{{- $repository := .Values.image.cloudflareddns.repository | default "timothyjmiller/cloudflare-ddns" | toString }} -{{- $tag := .Values.image.cloudflareddns.tag | default .Chart.AppVersion | toString }} -{{- $pullPolicy := .Values.image.cloudflareddns.pullPolicy | default "IfNotPresent" | toString | quote }} +{{- $cloudflareddns_registry := .Values.image.cloudflareddns.registry | default "docker.io" | toString }} +{{- $cloudflareddns_repository := .Values.image.cloudflareddns.repository | default "timothyjmiller/cloudflare-ddns" | toString }} +{{- $cloudflareddns_tag := .Values.image.cloudflareddns.tag | default .Chart.AppVersion | toString }} +{{- $cloudflareddns_pullPolicy := .Values.image.cloudflareddns.pullPolicy | default "IfNotPresent" | toString | quote }} {{- $replica_count := .Values.replicaCount | default "1" | toString }} -{{- $config_path := .Values.cloudflareddns.configPath | default "/etc/cloudflare-ddns" | toString }} +{{- $configPath := .Values.cloudflareddns.configPath | default "/etc/cloudflare-ddns" | toString }} +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -30,22 +31,19 @@ spec: {{- end }} containers: - name: cloudflareddns - image: {{ printf "%s/%s:%s" $registry $repository $tag | quote }} - imagePullPolicy: {{ $pullPolicy }} + image: {{ printf "%s/%s:%s" $cloudflareddns_registry $cloudflareddns_repository $cloudflareddns_tag | quote }} + imagePullPolicy: {{ $cloudflareddns_pullPolicy }} resources: - {{- toYaml .Values.resources | nindent 12 }} + {{- toYaml .Values.resources.cloudflareddns | nindent 12 }} envFrom: - configMapRef: name: {{ .Release.Name }}-cloudflareddns-cm volumeMounts: - name: {{ .Release.Name }}-cloudflareddns-config - mountPath: {{ $config_path }}/config.json - subPath: config.json + mountPath: {{ printf "%s/%s" $configPath "config.json" | quote }} + subPath: "config.json" readOnly: true volumes: - name: {{ .Release.Name }}-cloudflareddns-config secret: secretName: {{ .Release.Name }}-cloudflareddns-config - items: - - key: config.json - path: config.json diff --git a/mika/cloudflareddns/templates/secret.yaml b/mika/cloudflareddns/templates/secret.yaml index 7cc5adeb..1183a564 100644 --- a/mika/cloudflareddns/templates/secret.yaml +++ b/mika/cloudflareddns/templates/secret.yaml @@ -1,7 +1,10 @@ -{{- $token := .Values.cloudflareddns.token | toString }} -{{- $zone_id := .Values.cloudflareddns.zoneID | toString }} {{- $ipv4 := .Values.cloudflareddns.ipv4 | default "true" | toString }} {{- $ipv6 := .Values.cloudflareddns.ipv6 | default "false" | toString }} +{{- $purge := .Values.cloudflareddns.purge | default "false" | toString }} +{{- $token := .Values.cloudflareddns.token | toString }} +{{- $ttl := .Values.cloudflareddns.ttl | default "300" | toString }} +{{- $zoneID := .Values.cloudflareddns.zoneID | toString }} +--- apiVersion: v1 kind: Secret metadata: @@ -11,4 +14,4 @@ metadata: type: Opaque data: config.json: |- - {{- include "cloudflareddns.config-json" . | toString | replace "API_TOKEN" $token | replace "ZONE_ID" $zone_id | replace "ENABLE_IPV4" $ipv4 | replace "ENABLE_IPV6" $ipv6 | b64enc | nindent 4 }} + {{- include "cloudflareddns.config-json" . | toString | replace "API_TOKEN" $token | replace "ZONE_ID" $zoneID | replace "ENABLE_IPV4" $ipv4 | replace "ENABLE_IPV6" $ipv6 | replace "ENABLE_PURGE" $purge | replace "TTL_SECONDS" $ttl | b64enc | nindent 4 }} diff --git a/mika/cloudflareddns/values.yaml b/mika/cloudflareddns/values.yaml index ae626443..b74597ae 100644 --- a/mika/cloudflareddns/values.yaml +++ b/mika/cloudflareddns/values.yaml @@ -2,24 +2,25 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# The desired number of running replicas for cloudflareddns. +# The desired number of running replicas for Cloudflare DDNS. # Default: "1" replicaCount: "" -# Container images used for cloudflareddns. +# Container images used for Cloudflare DDNS. image: - # cloudflareddns container image configurations. + # Cloudflare DDNS container image configurations. + # Source: https://hub.docker.com/r/timothyjmiller/cloudflare-ddns cloudflareddns: - # The registry where the cloudflareddns container image is hosted. + # The registry where the Cloudflare DDNS container image is hosted. # Default: "docker.io" registry: "" - # The name of the repository that contains the cloudflareddns container image used. + # The name of the repository that contains the Cloudflare DDNS container image used. # Default: "timothyjmiller/cloudflare-ddns" repository: "" - # The tag that specifies the version of the cloudflareddns container image used. + # The tag that specifies the version of the Cloudflare DDNS container image used. # Default: Chart appVersion tag: "" - # The policy that determines when Kubernetes should pull the cloudflareddns container image. + # The policy that determines when Kubernetes should pull the Cloudflare DDNS container image. # Default: "IfNotPresent" pullPolicy: "" @@ -29,12 +30,12 @@ image: # - name: "ghcr-token-secret" imagePullSecrets: [] -# cloudflareddns configurations. +# Cloudflare DDNS configurations. cloudflareddns: - # The path to the cloudflareddns configuration directory. + # The path to the Cloudflare DDNS configuration directory. # Default: "/etc/cloudflare-ddns" # Example: - # configPath: "/etc/cloudflare-ddns" + # configPath: "/var/lib/cloudflare-ddns" configPath: "" # Specify whether to add an A record for each subdomain. # Default: "true" @@ -43,47 +44,65 @@ cloudflareddns: ipv4: "" # Specify whether to add an AAAA record for each subdomain. # Default: "false" - # Example + # Example: # ipv6: "true" ipv6: "" - # The list of subdomains to be updated, each with their own hostname and proxied setting. + # Specify whether to purge stale DNS records not defined in the configuration. + # Default: "false" # Example: - # subdomains: - # - hostname: "" - # proxied: true - # - hostname: "foo" - # proxied: false - # - hostname: "bar" - # proxied: false - subdomains: [] + # purge: "true" + purge: "" # The Cloudflare API token used to authenticate with the Cloudflare API. # Example: # token: "Na9E7VEY58COhA03l1ytm1r70u7jBsf8bNqh5AlZ" token: "" + # The Time-To-Live (TTL) duration defining how long DNS records are cached in seconds. + # Default: "300" + # Example: + # ttl: "86400" + ttl: "" # The ID of the zone that will get the records. # Example: # zoneID: "71fovu74p100z856k795umzl32h3240p" zoneID: "" + # The list of subdomains to be updated for a specified domain (zone). + # Items: `.hostname`, `.proxied` + # Example: + # subdomains: + # # The subdomain of the domain to be updated. + # # Example: + # # hostname: "foo" + # - hostname: "" + # # Specifies whether the subdomain should be proxied. + # # Default: "false" + # # Example: + # # proxied: "true" + # proxied: "" + subdomains: [] -# Resource requirements and limits for cloudflareddns container. +# Resource requirements and limits for Cloudflare DDNS containers. resources: - # The minimum amount of resources required by cloudflareddns to run. - requests: - # The minimum amount of CPU resources required by cloudflareddns. - # Example: - # cpu: "10m" - cpu: "10m" - # The minimum amount of memory required by cloudflareddns. - # Example: - # memory: "10Mi" - memory: "10Mi" - # The maximum amount of resources allowed for cloudflareddns. - limits: - # The maximum amount of CPU resources allowed for cloudflareddns. - # Example: - # cpu: "250m" - cpu: "50m" - # The maximum amount of memory allowed for cloudflareddns. - # Example: - # memory: "250Mi" - memory: "32Mi" + # Cloudflare DDNS container resources. + # Example: + # cloudflareddns: + # # The minimum amount of resources required by Cloudflare DDNS to run. + # requests: + # # The minimum amount of CPU resources required by Cloudflare DDNS. + # # Example: + # # cpu: "10m" + # cpu: "10m" + # # The minimum amount of memory required by Cloudflare DDNS. + # # Example: + # # memory: "10Mi" + # memory: "10Mi" + # # The maximum amount of resources allowed for Cloudflare DDNS. + # limits: + # # The maximum amount of CPU resources allowed for Cloudflare DDNS. + # # Example: + # # cpu: "250m" + # cpu: "50m" + # # The maximum amount of memory allowed for Cloudflare DDNS. + # # Example: + # # memory: "250Mi" + # memory: "32Mi" + cloudflareddns: {} diff --git a/mika/grocy/Chart.yaml b/mika/grocy/Chart.yaml index a59d5612..001bb326 100644 --- a/mika/grocy/Chart.yaml +++ b/mika/grocy/Chart.yaml @@ -2,12 +2,15 @@ apiVersion: v2 name: grocy description: Grocy is a web-based self-hosted groceries & household management solution for your home. type: application -version: 0.1.0 +version: 0.1.1 appVersion: "v3.3.2" keywords: - "grocy" + - "erp" + - "groceries" + - "household" home: "https://github.com/grocy/grocy" -icon: "https://raw.githubusercontent.com/grocy/grocy/master/public/img/logo.svg" +icon: "https://irfanhakim-as.github.io/charts/logos/grocy.svg" sources: - "https://github.com/grocy/grocy" - "https://github.com/irfanhakim-as/charts" diff --git a/mika/grocy/README.md b/mika/grocy/README.md index bcbaad98..8eeb0dca 100644 --- a/mika/grocy/README.md +++ b/mika/grocy/README.md @@ -1,98 +1,171 @@ -# [`grocy`](https://github.com/grocy/grocy) +# [Grocy](https://github.com/grocy/grocy) + +Grocy is a web-based self-hosted groceries & household management solution for your home. ## Prerequisites +> [!NOTE] +> You may refer to [Orked](https://github.com/irfanhakim-as/orked) for help with setting up a Kubernetes cluster that meets all the following prerequisites. + - Kubernetes 1.19+ - Helm 3.2.0+ +- Longhorn 1.4.1+ + +--- + +## Preflight checklist + +> [!IMPORTANT] +> The following items are required to be set up prior to installing this chart. + +**This section does not apply to this chart.** + +--- + +## Recommended configurations + +> [!NOTE] +> The following configuration recommendations might not be the default settings for this chart but are **highly recommended**. Please carefully consider them before configuring your installation. + +**This section does not apply to this chart.** + +--- + +## Application configurations + +> [!NOTE] +> The following configurations are expected or recommended to be set up from within the application after completing the installation. + +**This section does not apply to this chart.** + +--- + +## How to add the chart repo + +1. Add the repo to your local helm client: + + ```sh + helm repo add mika https://irfanhakim-as.github.io/charts + ``` + +2. Update the repo to retrieve the latest versions of the packages: + + ```sh + helm repo update + ``` + +--- + +## How to install or upgrade a chart release + +1. Get the values file of the Grocy chart or an existing installation (release). + + Get the latest Grocy chart values file for a new installation: + + ```sh + helm show values mika/grocy > values.yaml + ``` -## How to add repo + Alternatively, get the values file of an existing Grocy release: -Add the repo to your local helm client. + ```sh + helm get values ${releaseName} --namespace ${namespace} > values.yaml + ``` -```sh -helm repo add mika https://irfanhakim-as.github.io/charts -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Update the repo to retrieve the latest versions of the packages. +2. Edit your Grocy values file with the intended configurations: -```sh -helm repo update -``` + ```sh + nano values.yaml + ``` -## How to install + Pay extra attention to the descriptions and sample values provided in the chart values file. -### Prepare chart values +3. Install a new release for Grocy or upgrade an existing Grocy release: -Copy `values.yaml` from the chart you would like to install. + ```sh + helm upgrade --install ${releaseName} mika/grocy --namespace ${namespace} --create-namespace --values values.yaml --wait + ``` -```sh -cp mika/grocy/values.yaml . -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Edit `values.yaml` with the appropriate values. Please refer to the [Configurations](#configurations) section below, or the `values.yaml` file itself for details and sample values. +4. Verify that your Grocy release has been installed: -```sh -nano values.yaml -``` + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -### Perform installation + Replace `${namespace}` and `${releaseName}` accordingly. This should return the release information if the release has been installed. -Install the desired chart. Replace `$release_name` and `$namespace` accordingly. +--- -```sh -helm install $release_name mika/grocy --namespace $namespace --create-namespace --values values.yaml --wait -``` +## How to uninstall a chart release -Verify that your chart has been installed. Replace `$namespace` and `$release_name` accordingly. +> [!CAUTION] +> Uninstalling a release will irreversibly delete all the resources associated with the release, including any persistent data. -```sh -helm ls --namespace $namespace | grep "$release_name" -``` +1. Uninstall the desired release: -## How to upgrade + ```sh + helm uninstall ${releaseName} --namespace ${namespace} --wait + ``` -After making any necessary changes to the `values.yaml` file, upgrade the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${releaseName}` and `${namespace}` accordingly. -```sh -helm upgrade $release_name mika/grocy --namespace $namespace --values values.yaml --wait -``` +2. Verify that the release has been uninstalled: -## How to uninstall + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -Uninstall the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${namespace}` and `${releaseName}` accordingly. This should return nothing if the release has been uninstalled. -```sh -helm uninstall $release_name --namespace $namespace --wait -``` +--- -## Configurations +## Chart configurations | Key | Type | Default | Description | |-----|------|---------|-------------| | grocy.culture | string | `""` | The localisation of the Grocy application. Default: `"en_GB"`. | | grocy.currency | string | `""` | The currency used to format all monetary values in Grocy. Default: `"MYR"`. | -| grocy.data.storage | string | `""` | The amount of persistent storage allocated for the Grocy instance. Default: `"500Mi"`. | -| grocy.data.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the Grocy storage. Default: `"longhorn"`. | +| grocy.domain | string | `""` | The ingress domain name that hosts the Grocy server. | | grocy.energy | string | `""` | The preferred unit for displaying energy values in Grocy. Default: `"kcal"`. | +| grocy.initScript | string | `""` | Custom init script to run before the Grocy container starts. | | grocy.mode | string | `""` | The mode to deploy grocy in which determines whether to enable user authentication. Default: `"production"`. | | grocy.php.file_limit | string | `""` | Sets the maximum number of files that can be uploaded simultaneously through PHP. Default: `"200"`. | | grocy.php.memory_limit | string | `""` | Determines the maximum amount of memory that PHP can allocate for executing scripts. Default: `"512M"`. | | grocy.php.post_limit | string | `""` | Defines the maximum size of the entire HTTP POST request that PHP can handle. Default: `"100M"`. | | grocy.php.upload_limit | string | `""` | Specifies the maximum size of an individual file that can be uploaded through PHP. Default: `"50M"`. | -| image.backend.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the backend container image. Default: `"IfNotPresent"`. | -| image.backend.registry | string | `""` | The registry where the backend container image is hosted. Default: `"docker.io"`. | -| image.backend.repository | string | `""` | The name of the repository that contains the backend container image used. Default: `"grocy/backend"`. | -| image.backend.tag | string | `""` | The tag that specifies the version of the backend container image used. Default: `Chart appVersion`. | -| image.frontend.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the frontend container image. Default: `"IfNotPresent"`. | -| image.frontend.registry | string | `""` | The registry where the frontend container image is hosted. Default: `"docker.io"`. | -| image.frontend.repository | string | `""` | The name of the repository that contains the frontend container image used. Default: `"grocy/frontend"`. | -| image.frontend.tag | string | `""` | The tag that specifies the version of the frontend container image used. Default: `Chart appVersion`. | -| replicaCount | string | `""` | The desired number of running replicas for Grocy. | -| resources.backend.limits.cpu | string | `"100m"` | The maximum amount of CPU resources allowed for the backend. | -| resources.backend.limits.memory | string | `"100Mi"` | The maximum amount of memory allowed for the backend. | -| resources.backend.requests.cpu | string | `"50m"` | The minimum amount of CPU resources required by the backend. | -| resources.backend.requests.memory | string | `"50Mi"` | The minimum amount of memory required by the backend. | -| resources.frontend.limits.cpu | string | `"100m"` | The maximum amount of CPU resources allowed for the frontend. | -| resources.frontend.limits.memory | string | `"50Mi"` | The maximum amount of memory allowed for the frontend. | -| resources.frontend.requests.cpu | string | `"10m"` | The minimum amount of CPU resources required by the frontend. | -| resources.frontend.requests.memory | string | `"10Mi"` | The minimum amount of memory required by the frontend. | +| grocy.platform | string | `""` | The target operating system and architecture for the Grocy container. Default: `"linux/amd64"`. | +| image.backend.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the Backend container image. Default: `"IfNotPresent"`. | +| image.backend.registry | string | `""` | The registry where the Backend container image is hosted. Default: `"docker.io"`. | +| image.backend.repository | string | `""` | The name of the repository that contains the Backend container image used. Default: `"grocy/backend"`. | +| image.backend.tag | string | `""` | The tag that specifies the version of the Backend container image used. Default: `Chart appVersion`. | +| image.frontend.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the Frontend container image. Default: `"IfNotPresent"`. | +| image.frontend.registry | string | `""` | The registry where the Frontend container image is hosted. Default: `"docker.io"`. | +| image.frontend.repository | string | `""` | The name of the repository that contains the Frontend container image used. Default: `"grocy/frontend"`. | +| image.frontend.tag | string | `""` | The tag that specifies the version of the Frontend container image used. Default: `Chart appVersion`. | +| image.init.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the Init container image. Default: `"IfNotPresent"`. | +| image.init.registry | string | `""` | The registry where the Init container image is hosted. Default: `"docker.io"`. | +| image.init.repository | string | `""` | The name of the repository that contains the Init container image used. Default: `"grocy/backend"`. | +| image.init.tag | string | `""` | The tag that specifies the version of the Init container image used. Default: `Chart appVersion`. | +| imagePullSecrets | list | `[]` | Credentials used to securely authenticate and authorise the pulling of container images from private registries. | +| ingress.clusterIssuer | string | `""` | The name of the cluster issuer for Ingress. Default: `"letsencrypt-dns-prod"`. | +| ingress.customAnnotations | list | `[]` | Additional configuration annotations to be added to the Ingress resource. Items: `.prefix`, `.name`, `.value`. | +| ingress.enabled | bool | `false` | Specifies whether Ingress should be enabled for hosting Grocy services. | +| ingress.www | bool | `false` | Specifies whether the WWW subdomain should be enabled. | +| replicaCount | string | `""` | The desired number of running replicas for Grocy. Default: `"1"`. | +| resources.backend | object | `{}` | Backend container resources. | +| resources.frontend | object | `{}` | Frontend container resources. | +| service.backend.nodePort | string | `""` | The optional node port to expose for backend when the service type is NodePort. | +| service.backend.port | string | `""` | The backend port on which the Grocy server should listen. Default: `"9000"`. | +| service.frontend.nodePort | string | `""` | The optional node port to expose for frontend when the service type is NodePort. | +| service.frontend.port | string | `""` | The frontend port on which the Grocy server should listen. Default: `"8080"`. | +| service.type | string | `""` | The type of service used for Grocy services. Default: `"ClusterIP"`. | +| storage.data.accessMode | string | `""` | The access mode defining how the data storage can be mounted. Default: `"ReadWriteMany"`. | +| storage.data.enabled | bool | `false` | Specifies whether persistent storage should be provisioned for data storage. | +| storage.data.mountPath | string | `""` | The path where the data storage should be mounted on the container. Default: `"/var/www/data"`. | +| storage.data.storage | string | `""` | The default amount of persistent storage allocated for the data storage. Default: `"500Mi"`. | +| storage.data.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the data storage. Default: `"longhorn"`. | +| storage.data.subPath | string | `""` | The subpath within the data storage to mount to the container. Leave empty if not required. | \ No newline at end of file diff --git a/mika/grocy/templates/NOTES.txt b/mika/grocy/templates/NOTES.txt index 15b08f79..2c59968f 100644 --- a/mika/grocy/templates/NOTES.txt +++ b/mika/grocy/templates/NOTES.txt @@ -1,5 +1,46 @@ -Grocy is now installed and configured for {{ .Release.Name | toString }}. +{{- $serviceAddress := "" }} +{{- $ingress := .Values.ingress.enabled }} +{{- $domain := .Values.grocy.domain | toString }} +{{- $frontend := .Values.service.frontend.port | default "8080" | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +{{- $serviceName := printf "%s-grocy-svc" .Release.Name | toString }} +Grocy has been installed and configured for {{ .Release.Name | toString }} 🎉 -See the values.yaml file of this chart for more configuration options. +{{- if $ingress }} + {{- $serviceAddress = printf "https://%s" $domain | toString }} +{{- else if or (eq $type "ClusterIP") (eq $type "LoadBalancer") (eq $type "NodePort") }} -Please refer to the official documentation for more information on how to use Grocy. +Please run the following command(s) to obtain the right address to the service: + + ```sh + {{- if eq $type "ClusterIP" }} + {{- $forwardPort := "8080" | toString }} + {{- $serviceAddress = printf "http://127.0.0.1:%s" $forwardPort | toString }} + export POD_NAME=$(kubectl get pod --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "grocy.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} ${POD_NAME} -o jsonpath="{.spec.containers[1].ports[0].containerPort}") + kubectl port-forward --namespace {{ .Release.Namespace }} ${POD_NAME} {{ $forwardPort }}:${CONTAINER_PORT} + {{- else if eq $type "LoadBalancer" }} + {{- $serviceAddress = printf "$(echo http://${SERVICE_IP}:%s)" $frontend | toString }} + export SERVICE_IP=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} --template "{{"{{- range (index .status.loadBalancer.ingress 0) }}{{ . }}{{- end }}"}}") + {{- else if eq $type "NodePort" }} + {{- $serviceAddress = "$(echo http://${NODE_IP}:${NODE_PORT})" | toString }} + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} -o jsonpath="{.spec.ports[1].nodePort}") + {{- end }} + ``` + +{{- end }} + +Visit the following service(s) at the provided address: + +{{- if $serviceAddress }} + + - Grocy: {{ $serviceAddress }} + +{{- else }} + + ⚠️ This chart may have no accessible services available + +{{- end }} + +For more information on how to use and configure Grocy, please refer to the official documentation. \ No newline at end of file diff --git a/mika/grocy/templates/_helpers.tpl b/mika/grocy/templates/_helpers.tpl index 421135fb..3d76492d 100644 --- a/mika/grocy/templates/_helpers.tpl +++ b/mika/grocy/templates/_helpers.tpl @@ -60,29 +60,3 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} - -{{/* -Nginx common.conf template -*/}} -{{- define "grocy.common-conf" -}} -charset utf-8; - -location / { - try_files $uri /index.php$is_args$query_string; -} - -location ~* .(jpg|jpeg|png|gif|ico|css|js)$ { - expires 365d; -} - -location ~ \.php$ { - fastcgi_pass {{ .Release.Name }}-grocy-svc:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - include fastcgi_params; -} - -location ~ /\.ht { - deny all; -} -{{- end }} diff --git a/mika/grocy/templates/common.conf.tpl b/mika/grocy/templates/common.conf.tpl new file mode 100644 index 00000000..62faeaa2 --- /dev/null +++ b/mika/grocy/templates/common.conf.tpl @@ -0,0 +1,25 @@ +{{/* +Nginx common.conf template +*/}} +{{- define "grocy.common-conf" -}} +charset utf-8; + +location / { + try_files $uri /index.php$is_args$query_string; +} + +location ~* .(jpg|jpeg|png|gif|ico|css|js)$ { + expires 365d; +} + +location ~ \.php$ { + fastcgi_pass {{ .Release.Name }}-grocy-svc:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; +} + +location ~ /\.ht { + deny all; +} +{{- end }} diff --git a/mika/grocy/templates/configmap.yaml b/mika/grocy/templates/configmap.yaml index ddd8c6bc..5d410557 100644 --- a/mika/grocy/templates/configmap.yaml +++ b/mika/grocy/templates/configmap.yaml @@ -1,12 +1,14 @@ {{- $frontend_tag := .Values.image.frontend.tag | default .Chart.AppVersion | toString }} +{{- $platform := .Values.grocy.platform | default "linux/amd64" | toString | quote }} {{- $mode := .Values.grocy.mode | default "production" | toString | quote }} {{- $culture := .Values.grocy.culture | default "en_GB" | toString | quote }} {{- $currency := .Values.grocy.currency | default "MYR" | toString | quote }} {{- $energy := .Values.grocy.energy | default "kcal" | toString | quote }} -{{- $upload_limit := .Values.grocy.php.upload_limit | default "50M" | toString | quote }} -{{- $file_limit := .Values.grocy.php.file_limit | default "200" | toString | quote }} -{{- $post_limit := .Values.grocy.php.post_limit | default "100M" | toString | quote }} -{{- $memory_limit := .Values.grocy.php.memory_limit | default "512M" | toString | quote }} +{{- $uploadLimit := .Values.grocy.php.upload_limit | default "50M" | toString | quote }} +{{- $fileLimit := .Values.grocy.php.file_limit | default "200" | toString | quote }} +{{- $postLimit := .Values.grocy.php.post_limit | default "100M" | toString | quote }} +{{- $memoryLimit := .Values.grocy.php.memory_limit | default "512M" | toString | quote }} +--- apiVersion: v1 kind: ConfigMap metadata: @@ -15,15 +17,15 @@ metadata: {{- include "grocy.labels" . | nindent 4 }} data: GROCY_VERSION: {{ $frontend_tag }} - PLATFORM: "linux/amd64" + PLATFORM: {{ $platform }} GROCY_MODE: {{ $mode }} GROCY_CULTURE: {{ $culture }} GROCY_CURRENCY: {{ $currency }} GROCY_ENERGY_UNIT: {{ $energy }} - MAX_UPLOAD: {{ $upload_limit }} - PHP_MAX_FILE_UPLOAD: {{ $file_limit }} - PHP_MAX_POST: {{ $post_limit }} - PHP_MEMORY_LIMIT: {{ $memory_limit }} + MAX_UPLOAD: {{ $uploadLimit }} + PHP_MAX_FILE_UPLOAD: {{ $fileLimit }} + PHP_MAX_POST: {{ $postLimit }} + PHP_MEMORY_LIMIT: {{ $memoryLimit }} --- apiVersion: v1 kind: ConfigMap @@ -33,4 +35,4 @@ metadata: {{- include "grocy.labels" . | nindent 4 }} data: common.conf: | - {{- include "grocy.common-conf" . | nindent 4 }} + {{- include "grocy.common-conf" . | toString | nindent 4 }} diff --git a/mika/grocy/templates/deployment.yaml b/mika/grocy/templates/deployment.yaml index d67bf2b3..28b84287 100644 --- a/mika/grocy/templates/deployment.yaml +++ b/mika/grocy/templates/deployment.yaml @@ -1,3 +1,4 @@ +{{- $dataPersistence := .Values.storage.data.enabled }} {{- $backend_registry := .Values.image.backend.registry | default "docker.io" | toString }} {{- $backend_repository := .Values.image.backend.repository | default "grocy/backend" | toString }} {{- $backend_tag := .Values.image.backend.tag | default .Chart.AppVersion | toString }} @@ -6,7 +7,15 @@ {{- $frontend_repository := .Values.image.frontend.repository | default "grocy/frontend" | toString }} {{- $frontend_tag := .Values.image.frontend.tag | default .Chart.AppVersion | toString }} {{- $frontend_pullPolicy := .Values.image.frontend.pullPolicy | default "IfNotPresent" | toString | quote }} +{{- $init_registry := .Values.image.init.registry | default "docker.io" | toString }} +{{- $init_repository := .Values.image.init.repository | default "grocy/backend" | toString }} +{{- $init_tag := .Values.image.init.tag | default .Chart.AppVersion | toString }} +{{- $init_pullPolicy := .Values.image.init.pullPolicy | default "IfNotPresent" | toString | quote }} {{- $replica_count := .Values.replicaCount | default "1" | toString }} +{{- $dataMountPath := .Values.storage.data.mountPath | default "/var/www/data" | toString }} +{{- $dataSubPath := .Values.storage.data.subPath | toString }} +{{- $initScript := .Values.grocy.initScript | toString }} +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -31,14 +40,42 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} + {{- if or $dataPersistence $initScript }} + {{- $initDataMountPath := printf "/mnt/%s" ($dataMountPath | trimPrefix "/") | toString }} initContainers: - - name: copy-data - image: {{ printf "%s/%s:%s" $backend_registry $backend_repository $backend_tag | quote }} - imagePullPolicy: {{ $backend_pullPolicy }} - command: ["sh", "-c", "cp -rf /var/www/data/. /scratch/data"] + - name: init + image: {{ printf "%s/%s:%s" $init_registry $init_repository $init_tag | quote }} + imagePullPolicy: {{ $init_pullPolicy }} + command: ["/bin/sh"] + args: + - -c + - >- + {{- if $initScript }} + {{- $initScript | nindent 14 }} + {{- else }} + if [ -z "$(ls -A {{ $initDataMountPath }} | grep -v 'lost+found')" ]; then + echo "Initialising {{ $initDataMountPath }}" + cp -Ra /var/www/data/. {{ $initDataMountPath }} + chown -R 82:82 {{ $initDataMountPath }} + find {{ $initDataMountPath }} -type d -exec chmod 755 {} \; + find {{ $initDataMountPath }} -type f -exec chmod 644 {} \; + else + echo "Skipping initialisation as {{ $initDataMountPath }} is not empty" + fi + {{- end }} + {{- if or $dataPersistence }} volumeMounts: + {{- if $dataPersistence }} - name: {{ .Release.Name }}-grocy-data - mountPath: /scratch/data + mountPath: {{ $initDataMountPath | quote }} + {{- if $dataSubPath }} + subPath: {{ $dataSubPath | quote }} + {{- end }} + {{- end }} + {{- end }} + securityContext: + runAsUser: 0 + {{- end }} containers: - name: backend image: {{ printf "%s/%s:%s" $backend_registry $backend_repository $backend_tag | quote }} @@ -53,10 +90,13 @@ spec: - configMapRef: name: {{ .Release.Name }}-grocy-cm volumeMounts: - - name: {{ .Release.Name }}-tmp-volume - mountPath: /tmp + {{- if $dataPersistence }} - name: {{ .Release.Name }}-grocy-data - mountPath: /var/www/data + mountPath: {{ $dataMountPath | quote }} + {{- if $dataSubPath }} + subPath: {{ $dataSubPath | quote }} + {{- end }} + {{- end }} - name: frontend image: {{ printf "%s/%s:%s" $frontend_registry $frontend_repository $frontend_tag | quote }} imagePullPolicy: {{ $frontend_pullPolicy }} @@ -70,19 +110,15 @@ spec: - configMapRef: name: {{ .Release.Name }}-grocy-cm volumeMounts: - - name: {{ .Release.Name }}-tmp-volume - mountPath: /tmp - name: {{ .Release.Name }}-grocy-nginx-config mountPath: /etc/nginx/common.conf subPath: common.conf volumes: - - name: {{ .Release.Name }}-tmp-volume - emptyDir: {} - name: {{ .Release.Name }}-grocy-nginx-config configMap: name: {{ .Release.Name }}-grocy-nginx-config + {{- if $dataPersistence }} - name: {{ .Release.Name }}-grocy-data persistentVolumeClaim: claimName: {{ .Release.Name }}-grocy-data-pvc - securityContext: - fsGroup: 82 + {{- end }} diff --git a/mika/grocy/templates/ingress.yaml b/mika/grocy/templates/ingress.yaml new file mode 100644 index 00000000..e94db6ca --- /dev/null +++ b/mika/grocy/templates/ingress.yaml @@ -0,0 +1,60 @@ +{{- $ingress := .Values.ingress.enabled }} +{{- $www := .Values.ingress.www }} +{{- $clusterIssuer := .Values.ingress.clusterIssuer | default "letsencrypt-dns-prod" | toString | quote }} +{{- $customAnnotations := .Values.ingress.customAnnotations }} +{{- $domain := .Values.grocy.domain | toString }} +{{- $wwwDomain := printf "www.%s" $domain | toString | quote }} +{{- if and $ingress $domain }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-grocy-ingress + labels: + {{- include "grocy.labels" . | nindent 4 }} + annotations: + cert-manager.io/cluster-issuer: {{ $clusterIssuer }} + cert-manager.io/private-key-algorithm: "ECDSA" + nginx.ingress.kubernetes.io/affinity: "cookie" + nginx.ingress.kubernetes.io/affinity-mode: "persistent" + nginx.ingress.kubernetes.io/proxy-body-size: "100m" + nginx.ingress.kubernetes.io/session-cookie-expires: "172800" + nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" + nginx.ingress.kubernetes.io/session-cookie-name: "route" + nginx.org/client-max-body-size: "100m" + {{- range $customAnnotations }} + {{ printf "%s/%s" (.prefix | default "nginx.ingress.kubernetes.io") .name }}: {{ .value | quote }} + {{- end }} +spec: + ingressClassName: "nginx" + rules: + - host: {{ $domain | quote }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }}-grocy-svc + port: + name: frontend + path: / + pathType: Prefix + {{- if $www }} + - host: {{ $wwwDomain }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }}-grocy-svc + port: + name: frontend + path: / + pathType: Prefix + {{- end }} + tls: + - hosts: + - {{ $domain | quote }} + {{- if $www }} + - {{ $wwwDomain }} + {{- end }} + secretName: {{ .Release.Name }}-grocy-tls-cert +{{- end }} diff --git a/mika/grocy/templates/pvc.yaml b/mika/grocy/templates/pvc.yaml index 7d5c58bd..4d87ba86 100644 --- a/mika/grocy/templates/pvc.yaml +++ b/mika/grocy/templates/pvc.yaml @@ -1,5 +1,9 @@ -{{- $storage := .Values.grocy.data.storage | default "500Mi" | toString | quote }} -{{- $storage_class_name := .Values.grocy.data.storageClassName | default "longhorn" | toString | quote }} +{{- $dataPersistence := .Values.storage.data.enabled }} +{{- $dataAccessMode := .Values.storage.data.accessMode | default "ReadWriteMany" | toString | quote }} +{{- $dataStorage := .Values.storage.data.storage | default "500Mi" | toString | quote }} +{{- $dataStorageClassName := .Values.storage.data.storageClassName | default "longhorn" | toString | quote }} +{{- if $dataPersistence }} +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -8,8 +12,9 @@ metadata: {{- include "grocy.labels" . | nindent 4 }} spec: accessModes: - - ReadWriteMany + - {{ $dataAccessMode }} resources: requests: - storage: {{ $storage }} - storageClassName: {{ $storage_class_name }} + storage: {{ $dataStorage }} + storageClassName: {{ $dataStorageClassName }} +{{- end }} diff --git a/mika/grocy/templates/service.yaml b/mika/grocy/templates/service.yaml index 9b7bf687..e24844e0 100644 --- a/mika/grocy/templates/service.yaml +++ b/mika/grocy/templates/service.yaml @@ -1,3 +1,9 @@ +{{- $backend := .Values.service.backend.port | default "9000" | toString }} +{{- $backendNodePort := .Values.service.backend.nodePort | toString }} +{{- $frontend := .Values.service.frontend.port | default "8080" | toString }} +{{- $frontendNodePort := .Values.service.frontend.nodePort | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +--- apiVersion: v1 kind: Service metadata: @@ -5,15 +11,21 @@ metadata: labels: {{- include "grocy.labels" . | nindent 4 }} spec: - type: ClusterIP + type: {{ $type }} ports: - - port: 9000 + - port: {{ int $backend }} targetPort: backend + {{- if and (eq $type "NodePort") $backendNodePort }} + nodePort: {{ int $backendNodePort }} + {{- end }} protocol: TCP - name: {{ .Release.Name }}-grocy-backend - - port: 8080 + name: backend + - port: {{ int $frontend }} targetPort: frontend + {{- if and (eq $type "NodePort") $frontendNodePort }} + nodePort: {{ int $frontendNodePort }} + {{- end }} protocol: TCP - name: {{ .Release.Name }}-grocy-frontend + name: frontend selector: {{- include "grocy.selectorLabels" . | nindent 4 }} diff --git a/mika/grocy/values.yaml b/mika/grocy/values.yaml index 4d98546b..e0df0ebd 100644 --- a/mika/grocy/values.yaml +++ b/mika/grocy/values.yaml @@ -9,41 +9,59 @@ replicaCount: "" # Container images used for Grocy. image: # Backend container image configurations. + # Source: https://hub.docker.com/r/grocy/backend backend: - # The registry where the backend container image is hosted. + # The registry where the Backend container image is hosted. # Default: "docker.io" registry: "" - # The name of the repository that contains the backend container image used. + # The name of the repository that contains the Backend container image used. # Default: "grocy/backend" repository: "" - # The tag that specifies the version of the backend container image used. + # The tag that specifies the version of the Backend container image used. # Default: Chart appVersion tag: "" - # The policy that determines when Kubernetes should pull the backend container image. + # The policy that determines when Kubernetes should pull the Backend container image. # Default: "IfNotPresent" pullPolicy: "" # Frontend container image configurations. + # Source: https://hub.docker.com/r/grocy/frontend frontend: - # The registry where the frontend container image is hosted. + # The registry where the Frontend container image is hosted. # Default: "docker.io" registry: "" - # The name of the repository that contains the frontend container image used. + # The name of the repository that contains the Frontend container image used. # Default: "grocy/frontend" repository: "" - # The tag that specifies the version of the frontend container image used. + # The tag that specifies the version of the Frontend container image used. # Default: Chart appVersion tag: "" - # The policy that determines when Kubernetes should pull the frontend container image. + # The policy that determines when Kubernetes should pull the Frontend container image. + # Default: "IfNotPresent" + pullPolicy: "" + # Init container image configurations. + # Source: https://hub.docker.com/r/grocy/backend + init: + # The registry where the Init container image is hosted. + # Default: "docker.io" + registry: "" + # The name of the repository that contains the Init container image used. + # Default: "grocy/backend" + repository: "" + # The tag that specifies the version of the Init container image used. + # Default: Chart appVersion + tag: "" + # The policy that determines when Kubernetes should pull the Init container image. # Default: "IfNotPresent" pullPolicy: "" +# Credentials used to securely authenticate and authorise the pulling of container images from private registries. +# Example: +# imagePullSecrets: +# - name: "ghcr-token-secret" +imagePullSecrets: [] + # Grocy configurations. grocy: - # The mode to deploy grocy in which determines whether to enable user authentication. - # Default: "production" - # Example: - # mode: "demo" - mode: "" # The localisation of the Grocy application. # Default: "en_GB" # Example: @@ -54,89 +72,198 @@ grocy: # Example: # currency: "USD" currency: "" + # The ingress domain name that hosts the Grocy server. + # Example: + # domain: "grocy.example.com" + domain: "" # The preferred unit for displaying energy values in Grocy. # Default: "kcal" # Example: # energy: "kJ" energy: "" + # Custom init script to run before the Grocy container starts. + # Example: + # initScript: >- + # echo "Hello, World!" + # echo "This is a custom init script." + initScript: "" + # The mode to deploy grocy in which determines whether to enable user authentication. + # Default: "production" + # Example: + # mode: "demo" + mode: "" + # The target operating system and architecture for the Grocy container. + # Default: "linux/amd64" + # Example: + # platform: "linux/arm64" + platform: "" # Grocy PHP configurations. php: - # Specifies the maximum size of an individual file that can be uploaded through PHP. - # Default: "50M" - # Example: - # upload_limit: "100M" - upload_limit: "" # Sets the maximum number of files that can be uploaded simultaneously through PHP. # Default: "200" # Example: # file_limit: "100" file_limit: "" + # Determines the maximum amount of memory that PHP can allocate for executing scripts. + # Default: "512M" + # Example: + # memory_limit: "256M" + memory_limit: "" # Defines the maximum size of the entire HTTP POST request that PHP can handle. # Default: "100M" # Example: # post_limit: "200M" post_limit: "" - # Determines the maximum amount of memory that PHP can allocate for executing scripts. - # Default: "512M" + # Specifies the maximum size of an individual file that can be uploaded through PHP. + # Default: "50M" # Example: - # memory_limit: "256M" - memory_limit: "" - # Grocy data configurations. + # upload_limit: "100M" + upload_limit: "" + +# Ingress configurations. +ingress: + # Specifies whether Ingress should be enabled for hosting Grocy services. + # Example: + # enabled: true + enabled: false + # The name of the cluster issuer for Ingress. + # Default: "letsencrypt-dns-prod" + # Example: + # clusterIssuer: "letsencrypt-http-prod" + clusterIssuer: "" + # Specifies whether the WWW subdomain should be enabled. + # Example: + # www: true + www: false + # Additional configuration annotations to be added to the Ingress resource. + # Items: `.prefix`, `.name`, `.value` + # Example: + # customAnnotations: + # # The prefix of the annotation. + # # Default: "nginx.ingress.kubernetes.io" + # # Example: + # # prefix: "nginx.org" + # - prefix: "" + # # The name of the annotation. + # # Example: + # # name: "proxy-connect-timeout" + # name: "" + # # The value of the annotation. + # # Example: + # # value: "120" + # value: "" + customAnnotations: [] + +# Service configurations. +service: + # The type of service used for Grocy services. + # Default: "ClusterIP" + # Example: + # type: "NodePort" + type: "" + # Backend service port configurations. + backend: + # The optional node port to expose for backend when the service type is NodePort. + # Example: + # nodePort: "30000" + nodePort: "" + # The backend port on which the Grocy server should listen. + # Default: "9000" + # Example: + # port: "9090" + port: "" + # Frontend service port configurations. + frontend: + # The optional node port to expose for frontend when the service type is NodePort. + # Example: + # nodePort: "32000" + nodePort: "" + # The frontend port on which the Grocy server should listen. + # Default: "8080" + # Example: + # port: "80" + port: "" + +# Storage configurations. +storage: + # Data storage configurations. data: - # The amount of persistent storage allocated for the Grocy instance. + # Specifies whether persistent storage should be provisioned for data storage. + # Example: + # enabled: true + enabled: false + # The access mode defining how the data storage can be mounted. + # Default: "ReadWriteMany" + # Example: + # accessMode: "ReadWriteOnce" + accessMode: "" + # The path where the data storage should be mounted on the container. + # Default: "/var/www/data" + # Example: + # mountPath: "/data" + mountPath: "" + # The subpath within the data storage to mount to the container. Leave empty if not required. + # Example: + # subPath: "Data" + subPath: "" + # The default amount of persistent storage allocated for the data storage. # Default: "500Mi" # Example: - # storage: "1Gi" + # storage: "10Gi" storage: "" - # The storage class name used for dynamically provisioning a persistent volume for the Grocy storage. + # The storage class name used for dynamically provisioning a persistent volume for the data storage. # Default: "longhorn" # Example: - # storageClassName: "longhorn" + # storageClassName: "smb" storageClassName: "" # Resource requirements and limits for Grocy containers. resources: # Backend container resources. - backend: - # The minimum amount of resources required by the backend to run. - requests: - # The minimum amount of CPU resources required by the backend. - # Example: - # cpu: "10m" - cpu: "50m" - # The minimum amount of memory required by the backend. - # Example: - # memory: "10Mi" - memory: "50Mi" - # The maximum amount of resources allowed for the backend. - limits: - # The maximum amount of CPU resources allowed for the backend. - # Example: - # cpu: "250m" - cpu: "100m" - # The maximum amount of memory allowed for the backend. - # Example: - # memory: "250Mi" - memory: "100Mi" + # Example: + # backend: + # # The minimum amount of resources required by Backend to run. + # requests: + # # The minimum amount of CPU resources required by Backend. + # # Example: + # # cpu: "10m" + # cpu: "50m" + # # The minimum amount of memory required by Backend. + # # Example: + # # memory: "10Mi" + # memory: "50Mi" + # # The maximum amount of resources allowed for Backend. + # limits: + # # The maximum amount of CPU resources allowed for Backend. + # # Example: + # # cpu: "250m" + # cpu: "100m" + # # The maximum amount of memory allowed for Backend. + # # Example: + # # memory: "250Mi" + # memory: "100Mi" + backend: {} # Frontend container resources. - frontend: - # The minimum amount of resources required by the frontend to run. - requests: - # The minimum amount of CPU resources required by the frontend. - # Example: - # cpu: "10m" - cpu: "10m" - # The minimum amount of memory required by the frontend. - # Example: - # memory: "10Mi" - memory: "10Mi" - # The maximum amount of resources allowed for the frontend. - limits: - # The maximum amount of CPU resources allowed for the frontend. - # Example: - # cpu: "250m" - cpu: "100m" - # The maximum amount of memory allowed for the frontend. - # Example: - # memory: "250Mi" - memory: "50Mi" + # Example: + # frontend: + # # The minimum amount of resources required by Frontend to run. + # requests: + # # The minimum amount of CPU resources required by Frontend. + # # Example: + # # cpu: "10m" + # cpu: "10m" + # # The minimum amount of memory required by Frontend. + # # Example: + # # memory: "10Mi" + # memory: "10Mi" + # # The maximum amount of resources allowed for Frontend. + # limits: + # # The maximum amount of CPU resources allowed for Frontend. + # # Example: + # # cpu: "250m" + # cpu: "100m" + # # The maximum amount of memory allowed for Frontend. + # # Example: + # # memory: "250Mi" + # memory: "50Mi" + frontend: {} diff --git a/mika/kutt/Chart.yaml b/mika/kutt/Chart.yaml index a373ed0d..710a93a5 100644 --- a/mika/kutt/Chart.yaml +++ b/mika/kutt/Chart.yaml @@ -2,14 +2,14 @@ apiVersion: v2 name: kutt description: Kutt is a modern URL shortener with support for custom domains. Shorten URLs, manage your links and view the click rate statistics. type: application -version: 0.1.1 +version: 0.1.2 appVersion: "v2.7.4" keywords: - "kutt" - "url" - "shortener" home: "https://github.com/thedevs-network/kutt" -icon: "https://raw.githubusercontent.com/thedevs-network/kutt/develop/static/images/icons/icon-512x512.png" +icon: "https://irfanhakim-as.github.io/charts/logos/kutt.svg" sources: - "https://github.com/thedevs-network/kutt" - "https://github.com/irfanhakim-as/charts" diff --git a/mika/kutt/README.md b/mika/kutt/README.md index c6bd6721..269185a5 100644 --- a/mika/kutt/README.md +++ b/mika/kutt/README.md @@ -1,140 +1,202 @@ -# [`kutt`](https://github.com/thedevs-network/kutt) +# [Kutt](https://github.com/thedevs-network/kutt) + +Kutt is a modern URL shortener with support for custom domains. Shorten URLs, manage your links and view the click rate statistics. ## Prerequisites +> [!NOTE] +> You may refer to [Orked](https://github.com/irfanhakim-as/orked) for help with setting up a Kubernetes cluster that meets all the following prerequisites. + - Kubernetes 1.19+ - Helm 3.2.0+ +- Longhorn 1.4.1+ + +--- ## Preflight checklist -### Generate secret key for `kutt.secret` +> [!IMPORTANT] +> The following items are required to be set up prior to installing this chart. + +### Generate secret key + +A unique, secure secret key is required for each Kutt installation. + +1. Generate a secret key using the following command: + + ```sh + python -c 'import random; print("".join([random.choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for i in range(50)]))' + ``` + +2. Set the generated secret key as the value of the `kutt.secret` setting in your installation's values file: + + ```yaml + secret: "" + ``` + +--- + +## Recommended configurations + +> [!NOTE] +> The following configuration recommendations might not be the default settings for this chart but are **highly recommended**. Please carefully consider them before configuring your installation. + +**This section does not apply to this chart.** + +--- + +## Application configurations + +> [!NOTE] +> The following configurations are expected or recommended to be set up from within the application after completing the installation. + +**This section does not apply to this chart.** + +--- + +## How to add the chart repo + +1. Add the repo to your local helm client: + + ```sh + helm repo add mika https://irfanhakim-as.github.io/charts + ``` + +2. Update the repo to retrieve the latest versions of the packages: + + ```sh + helm repo update + ``` + +--- + +## How to install or upgrade a chart release -```sh -python -c 'import random; print("".join([random.choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for i in range(50)]))' -``` +1. Get the values file of the Kutt chart or an existing installation (release). -### Provision a PostgreSQL database + Get the latest Kutt chart values file for a new installation: -Deploy [`mika/postgres-agent`](../postgres-agent/) with `postgres.mode.create` set to `true`. This step can be skipped if you have an existing PostgreSQL database. + ```sh + helm show values mika/kutt > values.yaml + ``` -## How to add repo + Alternatively, get the values file of an existing Kutt release: -Add the repo to your local helm client. + ```sh + helm get values ${releaseName} --namespace ${namespace} > values.yaml + ``` -```sh -helm repo add mika https://irfanhakim-as.github.io/charts -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Update the repo to retrieve the latest versions of the packages. +2. Edit your Kutt values file with the intended configurations: -```sh -helm repo update -``` + ```sh + nano values.yaml + ``` -## How to install + Pay extra attention to the descriptions and sample values provided in the chart values file. -### Prepare chart values +3. Install a new release for Kutt or upgrade an existing Kutt release: -Copy `values.yaml` from the chart you would like to install. + ```sh + helm upgrade --install ${releaseName} mika/kutt --namespace ${namespace} --create-namespace --values values.yaml --wait + ``` -```sh -cp mika/kutt/values.yaml . -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Edit `values.yaml` with the appropriate values. Please refer to the [Configurations](#configurations) section below, or the `values.yaml` file itself for details and sample values. +4. Verify that your Kutt release has been installed: -```sh -nano values.yaml -``` + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -### Perform installation + Replace `${namespace}` and `${releaseName}` accordingly. This should return the release information if the release has been installed. -Install the desired chart. Replace `$release_name` and `$namespace` accordingly. +--- -```sh -helm install $release_name mika/kutt --namespace $namespace --create-namespace --values values.yaml --wait -``` +## How to uninstall a chart release -Verify that your chart has been installed. Replace `$namespace` and `$release_name` accordingly. +> [!CAUTION] +> Uninstalling a release will irreversibly delete all the resources associated with the release, including any persistent data. -```sh -helm ls --namespace $namespace | grep "$release_name" -``` +1. Uninstall the desired release: -## How to upgrade + ```sh + helm uninstall ${releaseName} --namespace ${namespace} --wait + ``` -After making any necessary changes to the `values.yaml` file, upgrade the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${releaseName}` and `${namespace}` accordingly. -```sh -helm upgrade $release_name mika/kutt --namespace $namespace --values values.yaml --wait -``` +2. Verify that the release has been uninstalled: -## How to uninstall + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -Uninstall the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${namespace}` and `${releaseName}` accordingly. This should return nothing if the release has been uninstalled. -```sh -helm uninstall $release_name --namespace $namespace --wait -``` +--- -## Configurations +## Chart configurations | Key | Type | Default | Description | |-----|------|---------|-------------| -| data.accessMode | string | `""` | The access mode that defines how the volume can be accessed by one or many nodes. Default: `"ReadWriteOnce"`. | -| data.storage | string | `""` | The amount of persistent storage allocated for the Kutt instance. Default: `"100Mi"`. | -| data.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the Kutt storage. Default: "longhorn". | -| db.host | string | `""` | The hostname or IP address of the Kutt database server. | -| db.name | string | `""` | The name of the database used by Kutt. | -| db.password | string | `""` | The password associated with the Kutt database's user. | -| db.port | string | `""` | The port number on which the Kutt database server is listening. Default: `"5432"`. | -| db.ssl | bool | `false` | Specifies whether the Kutt database server should use SSL. | -| db.user | string | `""` | The username or user account for accessing the Kutt database. | -| image.kutt.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the kutt container image. Default: `"IfNotPresent"`. | -| image.kutt.registry | string | `""` | The registry where the kutt container image is hosted. Default: `"docker.io"`. | -| image.kutt.repository | string | `""` | The name of the repository that contains the kutt container image used. Default: `"kutt/kutt"`. | -| image.kutt.tag | string | `""` | The tag that specifies the version of the kutt container image used. Default: `Chart appVersion`. | -| image.redis.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the redis container image. Default: `"IfNotPresent"`. | -| image.redis.registry | string | `""` | The registry where the redis container image is hosted. Default: `"docker.io"`. | -| image.redis.repository | string | `""` | The name of the repository that contains the redis container image used. Default: `"redis"`. | -| image.redis.tag | string | `""` | The tag that specifies the version of the redis container image used. Default: `"6.0-alpine"`. | +| google.recaptchaSecretKey | string | `""` | The Google reCAPTCHA secret key used for preventing spam. Refer to https://developers.google.com/recaptcha/intro. | +| google.recaptchaSiteKey | string | `""` | The Google reCAPTCHA site key used for preventing spam. Refer to https://developers.google.com/recaptcha/intro. | +| google.safeBrowsingKey | string | `""` | The Google API key used for Google Safe Browsing to prevent malicious links. Refer to https://developers.google.com/safe-browsing/v4/get-started. | +| image.kutt.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the Kutt container image. Default: `"IfNotPresent"`. | +| image.kutt.registry | string | `""` | The registry where the Kutt container image is hosted. Default: `"docker.io"`. | +| image.kutt.repository | string | `""` | The name of the repository that contains the Kutt container image used. Default: `"kutt/kutt"`. | +| image.kutt.tag | string | `""` | The tag that specifies the version of the Kutt container image used. Default: `Chart appVersion`. | +| image.redis.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the Redis container image. Default: `"IfNotPresent"`. | +| image.redis.registry | string | `""` | The registry where the Redis container image is hosted. Default: `"docker.io"`. | +| image.redis.repository | string | `""` | The name of the repository that contains the Redis container image used. Default: `"redis"`. | +| image.redis.tag | string | `""` | The tag that specifies the version of the Redis container image used. Default: `"6.0-alpine"`. | +| imagePullSecrets | list | `[]` | Credentials used to securely authenticate and authorise the pulling of container images from private registries. | | ingress.clusterIssuer | string | `""` | The name of the cluster issuer for Ingress. Default: `"letsencrypt-dns-prod"`. | -| ingress.enabled | bool | `false` | Specifies whether Kutt should be hosted using an Ingress.. | +| ingress.customAnnotations | list | `[]` | Additional configuration annotations to be added to the Ingress resource. Items: `.prefix`, `.name`, `.value`. | +| ingress.enabled | bool | `false` | Specifies whether Ingress should be enabled for hosting Kutt services. | +| ingress.www | bool | `false` | Specifies whether the WWW subdomain should be enabled. | +| kutt.administration.admins | list | `[]` | Email addresses of the administrators of the Kutt application so they can access admin actions. | | kutt.administration.dailyUserLimit | string | `""` | The maximum number of links that can be created by a user in a day. Default: `"50"`. | -| kutt.administration.disableAnonLinks | bool | `false` | Specifies whether Kutt should disallow creating links without an account. | -| kutt.administration.disableRegistration | bool | `false` | Specifies whether Kutt should disallow user registrations. | +| kutt.administration.disableAnonLinks | string | `""` | Specifies whether Kutt should disallow creating links without an account. Default: `"false"`. | +| kutt.administration.disableRegistration | string | `""` | Specifies whether Kutt should disallow user registrations. Default: `"false"`. | | kutt.administration.maxStatsPerLink | string | `""` | The maximum number of visits for a link to have detailed statistics. Default: `"5000"`. | | kutt.administration.nonUserCooldown | string | `""` | The number of minutes an anonymous user must wait before creating another link. Default: `"0"`. | -| kutt.admins | list | `[]` | Email addresses of the administrators of the Kutt application so they can access admin actions. | -| kutt.domain | string | `""` | The domain name that is hosting the Kutt application. Default: `"localhost:$service.kutt.port"` if `ingress` is disabled. | -| kutt.google.recaptchaSecretKey | string | `""` | The Google reCAPTCHA secret key used for preventing spam. Refer to https://developers.google.com/recaptcha/intro. | -| kutt.google.recaptchaSiteKey | string | `""` | The Google reCAPTCHA site key used for preventing spam. Refer to https://developers.google.com/recaptcha/intro. | -| kutt.google.safeBrowsingKey | string | `""` | The Google API key used for Google Safe Browsing to prevent malicious links. Refer to https://developers.google.com/safe-browsing/v4/get-started. | +| kutt.domain | string | `""` | The ingress domain name that hosts the Kutt server. Default: `"%s-kutt-svc:kutt .Release.Name"`. | | kutt.link_length | string | `""` | The length of the generated short links. Default: `"6"`. | -| kutt.mail.contact_email | string | `""` | The email address to be displayed as the contact email in the application. | -| kutt.mail.from_email | string | `""` | The email address used as the "from" address for sent emails. Default: `"$name <$mail.user>"`. | -| kutt.mail.host | string | `""` | The hostname or IP address of the SMTP server for sending emails. Default: `"smtp.gmail.com"`. | -| kutt.mail.password | string | `""` | The password for authenticating with the SMTP server. | -| kutt.mail.port | string | `""` | The port number on the SMTP server used for sending emails. Default: `"465"`. | -| kutt.mail.report_email | string | `""` | The email address that will receive submitted reports. | -| kutt.mail.secure | bool | `true` | Specifies whether Kutt should use a secure TLS connection when sending emails. | -| kutt.mail.user | string | `""` | The username for authenticating with the SMTP server. | | kutt.name | string | `""` | The name of the site where Kutt is hosted. Default: `"Kutt"`. | | kutt.secret | string | `""` | A 50-character secret key used for encrypting JSON Web Tokens (JWTs). | -| kutt.useHttps | bool | `true` | Specifies whether Kutt should use HTTPS for custom domains. | +| kutt.useHttps | string | `""` | Specifies whether Kutt should use HTTPS for custom domains. Default: `"true"`. | +| mail.contact_email | string | `""` | The email address to be displayed as the contact email in the application. | +| mail.from_email | string | `""` | The email address used as the "from" address for sent emails. Default: `"$name <$mail.smtp.user>"`. | +| mail.report_email | string | `""` | The email address that will receive submitted reports. | +| mail.secure | string | `""` | Specifies whether Kutt should use a secure TLS connection when sending emails. Default: `"true"`. | +| mail.smtp.host | string | `""` | The hostname or IP address of the SMTP server for sending emails. Default: `"smtp.gmail.com"`. | +| mail.smtp.password | string | `""` | The password for authenticating with the SMTP server. | +| mail.smtp.port | string | `""` | The port number on the SMTP server used for sending emails. Default: `"465"`. | +| mail.smtp.user | string | `""` | The username for authenticating with the SMTP server. | +| postgres.host | string | `""` | The hostname or IP address of the Kutt database server. | +| postgres.name | string | `""` | The name of the database being used by Kutt. | +| postgres.password | string | `""` | The password associated with the Kutt database user. | +| postgres.port | string | `""` | The port number the Kutt database server is listening for connections. Default: `"5432"`. | +| postgres.ssl | string | `""` | Specifies whether the Kutt database server should use SSL. Default: `"false"`. | +| postgres.user | string | `""` | The username or user account for accessing the Kutt database. | | redis.external | bool | `false` | Specifies whether Kutt should use an external Redis server. | -| redis.host | string | `""` | The hostname or IP address of the Redis server. Default: `"localhost"`. | -| redis.password | string | `""` | The password for authenticating with the Redis server. | -| redis.port | string | `""` | The port number on which the EXTERNAL Redis server is listening. Default: `"6379"`. | +| redis.host | string | `""` | The hostname or IP address of the external Redis server. | +| redis.password | string | `""` | The password for authenticating with the external Redis server. | +| redis.port | string | `""` | The port number on which the external Redis server is listening for connections. Default: `"6379"`. | | replicaCount | string | `""` | The desired number of running replicas for Kutt. Default: `"1"`. | -| resources.kutt.limits.cpu | string | `"150m"` | The maximum amount of CPU resources allowed for the kutt. | -| resources.kutt.limits.memory | string | `"400Mi"` | The maximum amount of memory allowed for the kutt. | -| resources.kutt.requests.cpu | string | `"100m"` | The minimum amount of CPU resources required by the kutt. | -| resources.kutt.requests.memory | string | `"200Mi"` | The minimum amount of memory required by the kutt. | -| resources.redis.limits.cpu | string | `"20m"` | The maximum amount of CPU resources allowed for the redis. | -| resources.redis.limits.memory | string | `"50Mi"` | The maximum amount of memory allowed for the redis. | -| resources.redis.requests.cpu | string | `"10m"` | The minimum amount of CPU resources required by the redis. | -| resources.redis.requests.memory | string | `"20Mi"` | The minimum amount of memory required by the redis. | -| service.kutt.port | string | `""` | The port number on which the Kutt service is listening. Default: `"3000"`. | -| service.kutt.protocol | string | `""` | The protocol used by the Kutt service. Default: `"TCP"`. | -| service.type | string | `""` | The type of service used for Kutt. Default: `"ClusterIP"`. | +| resources.kutt | object | `{}` | Kutt container resources. | +| resources.redis | object | `{}` | Redis container resources. | +| service.kutt.nodePort | string | `""` | The optional node port to expose for Kutt when the service type is NodePort. | +| service.kutt.port | string | `""` | The Kutt port on which the Kutt server should listen for connections. Default: `"3000"`. | +| service.redis.nodePort | string | `""` | The optional node port to expose for Redis when the service type is NodePort. | +| service.redis.port | string | `""` | The Redis port on which the Kutt server should listen for connections. Default: `"6379"`. | +| service.type | string | `""` | The type of service used to expose Kutt services. Default: `"ClusterIP"`. | +| storage.redis.accessMode | string | `""` | The access mode defining how the Redis storage can be mounted. Default: `"ReadWriteOnce"`. | +| storage.redis.enabled | bool | `true` | Specifies whether persistent storage should be provisioned for Redis storage. | +| storage.redis.mountPath | string | `""` | The path where the Redis storage should be mounted on the container. Default: `"/data"`. | +| storage.redis.storage | string | `""` | The default amount of persistent storage allocated for the Redis storage. Default: `"100Mi"`. | +| storage.redis.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the Redis storage. Default: `"longhorn"`. | +| storage.redis.subPath | string | `""` | The subpath within the Redis storage to mount to the container. Leave empty if not required. | \ No newline at end of file diff --git a/mika/kutt/templates/NOTES.txt b/mika/kutt/templates/NOTES.txt index dd23e0c4..a19497d2 100644 --- a/mika/kutt/templates/NOTES.txt +++ b/mika/kutt/templates/NOTES.txt @@ -1,22 +1,51 @@ -{{- $domain := .Values.kutt.domain | toString }} +{{- $serviceAddress := "" }} +{{- $urlProtocol := "http" | toString }} {{- $ingress := .Values.ingress.enabled }} -{{- $kutt_port := .Values.service.kutt.port | default "3000" | toString }} -{{- $useHttps := .Values.kutt.useHttps }} -{{- if not $ingress }} -{{- $domain = $domain | default (printf "localhost:%s" $kutt_port) | printf "http://%s" }} -{{- else }} -{{- if $useHttps }} -{{- $domain = $domain | printf "https://%s" }} -{{- else }} -{{- $domain = $domain | printf "http://%s" }} +{{- $domain := .Values.kutt.domain | toString }} +{{- $port := .Values.service.port | default "80" | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +{{- $serviceName := printf "%s-kutt-svc" .Release.Name | toString }} +{{- $useHttps := .Values.kutt.useHttps | default "true" | toString | quote }} +{{- if eq $useHttps "true" }} + {{- $urlProtocol = "https" | toString }} {{- end }} +Kutt has been installed and configured for {{ .Release.Name | toString }} 🎉 + +{{- if $ingress }} + {{- $serviceAddress = printf "%s://%s" $urlProtocol $domain | toString }} +{{- else if or (eq $type "ClusterIP") (eq $type "LoadBalancer") (eq $type "NodePort") }} + +Please run the following command(s) to obtain the right address to the service: + + ```sh + {{- if eq $type "ClusterIP" }} + {{- $forwardPort := "8080" | toString }} + {{- $serviceAddress = printf "http://127.0.0.1:%s" $forwardPort | toString }} + export POD_NAME=$(kubectl get pod --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "kutt.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} ${POD_NAME} -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + kubectl port-forward --namespace {{ .Release.Namespace }} ${POD_NAME} {{ $forwardPort }}:${CONTAINER_PORT} + {{- else if eq $type "LoadBalancer" }} + {{- $serviceAddress = printf "$(echo http://${SERVICE_IP}:%s)" $port | toString }} + export SERVICE_IP=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} --template "{{"{{- range (index .status.loadBalancer.ingress 0) }}{{ . }}{{- end }}"}}") + {{- else if eq $type "NodePort" }} + {{- $serviceAddress = "$(echo http://${NODE_IP}:${NODE_PORT})" | toString }} + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} -o jsonpath="{.spec.ports[0].nodePort}") + {{- end }} + ``` + {{- end }} -Kutt is now installed and configured for {{ .Release.Name | toString }}. -Visit the Kutt portal to get started: +Visit the following service(s) at the provided address: + +{{- if $serviceAddress }} + + - Kutt: {{ $serviceAddress }} - - {{ $domain }} +{{- else }} + + ⚠️ This chart may have no accessible services available -See the values.yaml file of this chart for more configuration options. +{{- end }} -Please refer to the official documentation for more information on how to use Kutt. +For more information on how to use and configure Kutt, please refer to the official documentation. \ No newline at end of file diff --git a/mika/kutt/templates/_helpers.tpl b/mika/kutt/templates/_helpers.tpl index f7211f3d..bbc0f10a 100644 --- a/mika/kutt/templates/_helpers.tpl +++ b/mika/kutt/templates/_helpers.tpl @@ -60,29 +60,3 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} - -{{/* -Nginx common.conf template -*/}} -{{- define "kutt.common-conf" -}} -charset utf-8; - -location / { - try_files $uri /index.php$is_args$query_string; -} - -location ~* .(jpg|jpeg|png|gif|ico|css|js)$ { - expires 365d; -} - -location ~ \.php$ { - fastcgi_pass {{ .Release.Name }}-kutt-svc:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - include fastcgi_params; -} - -location ~ /\.ht { - deny all; -} -{{- end }} diff --git a/mika/kutt/templates/configmap.yaml b/mika/kutt/templates/configmap.yaml index 5ba7344b..df9cb31b 100644 --- a/mika/kutt/templates/configmap.yaml +++ b/mika/kutt/templates/configmap.yaml @@ -1,18 +1,15 @@ -{{- $admins := .Values.kutt.admins | join "," | toString | quote }} +{{- $admins := .Values.kutt.administration.admins | join "," | toString | quote }} {{- $dailyUserLimit := .Values.kutt.administration.dailyUserLimit | default "50" | toString | quote }} -{{- $disableAnonLinks := .Values.kutt.administration.disableAnonLinks | toString | quote }} -{{- $disableRegistration := .Values.kutt.administration.disableRegistration | toString | quote }} -{{- $domain := .Values.kutt.domain | toString }} -{{- $ingress := .Values.ingress.enabled }} -{{- $kutt_port := .Values.service.kutt.port | default "3000" | toString }} -{{- $link_length := .Values.kutt.link_length | default "6" | toString | quote }} +{{- $disableAnonLinks := .Values.kutt.administration.disableAnonLinks | default "false" | toString | quote }} +{{- $disableRegistration := .Values.kutt.administration.disableRegistration | default "false" | toString | quote }} +{{- $domain := .Values.kutt.domain | default (printf "%s-kutt-svc:kutt" .Release.Name) | toString | quote }} +{{- $kuttPort := .Values.service.kutt.port | default "3000" | toString | quote }} +{{- $linkLength := .Values.kutt.link_length | default "6" | toString | quote }} {{- $maxStatsPerLink := .Values.kutt.administration.maxStatsPerLink | default "5000" | toString | quote }} {{- $name := .Values.kutt.name | default "Kutt" | toString | quote }} {{- $nonUserCooldown := .Values.kutt.administration.nonUserCooldown | default "0" | toString | quote }} -{{- $useHttps := .Values.kutt.useHttps | toString | quote }} -{{- if not $ingress }} -{{- $domain = $domain | default (printf "localhost:%s" $kutt_port) }} -{{- end }} +{{- $useHttps := .Values.kutt.useHttps | default "true" | toString | quote }} +--- apiVersion: v1 kind: ConfigMap metadata: @@ -20,10 +17,10 @@ metadata: labels: {{- include "kutt.labels" . | nindent 4 }} data: - PORT: {{ $kutt_port | quote }} + PORT: {{ $kuttPort }} SITE_NAME: {{ $name }} - DEFAULT_DOMAIN: {{ $domain | quote }} - LINK_LENGTH: {{ $link_length }} + DEFAULT_DOMAIN: {{ $domain }} + LINK_LENGTH: {{ $linkLength }} DISALLOW_REGISTRATION: {{ $disableRegistration }} DISALLOW_ANONYMOUS_LINKS: {{ $disableAnonLinks }} USER_LIMIT_PER_DAY: {{ $dailyUserLimit }} diff --git a/mika/kutt/templates/deployment.yaml b/mika/kutt/templates/deployment.yaml index a413e54a..9a16997b 100644 --- a/mika/kutt/templates/deployment.yaml +++ b/mika/kutt/templates/deployment.yaml @@ -1,3 +1,5 @@ +{{- $externalRedis := .Values.redis.external }} +{{- $redisPersistence := .Values.storage.redis.enabled }} {{- $kutt_registry := .Values.image.kutt.registry | default "docker.io" | toString }} {{- $kutt_repository := .Values.image.kutt.repository | default "kutt/kutt" | toString }} {{- $kutt_tag := .Values.image.kutt.tag | default .Chart.AppVersion | toString }} @@ -7,10 +9,9 @@ {{- $redis_tag := .Values.image.redis.tag | default "6.0-alpine" | toString }} {{- $redis_pullPolicy := .Values.image.redis.pullPolicy | default "IfNotPresent" | toString | quote }} {{- $replica_count := .Values.replicaCount | default "1" | toString }} -{{- $kutt_port := .Values.service.kutt.port | default "3000" | toString | int }} -{{- $kutt_protocol := .Values.service.kutt.protocol | default "TCP" | toString }} -{{- $external_redis := .Values.redis.external }} -{{- $redis_password := .Values.redis.password | toString }} +{{- $redisMountPath := .Values.storage.redis.mountPath | default "/data" | toString | quote }} +{{- $redisSubPath := .Values.storage.redis.subPath | toString }} +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -46,8 +47,8 @@ spec: ./wait-for-it.sh $(DB_HOST):$(DB_PORT) -- npm start ports: - name: kutt - containerPort: {{ $kutt_port }} - protocol: {{ $kutt_protocol }} + containerPort: 3000 + protocol: TCP resources: {{- toYaml .Values.resources.kutt | nindent 12 }} envFrom: @@ -57,16 +58,14 @@ spec: name: {{ .Release.Name }}-kutt-secret - secretRef: name: {{ .Release.Name }}-kutt-redis-secret - {{- if not $external_redis }} + {{- if not $externalRedis }} - name: redis image: {{ printf "%s/%s:%s" $redis_registry $redis_repository $redis_tag | quote }} imagePullPolicy: {{ $redis_pullPolicy }} - {{- if $redis_password }} - command: ["redis-server"] - args: - - "--requirepass" - - "$(REDIS_PASSWORD)" - {{- end }} + # command: ["redis-server"] + # args: + # - "--requirepass" + # - "$(REDIS_PASSWORD)" ports: - name: redis containerPort: 6379 @@ -76,11 +75,18 @@ spec: envFrom: - secretRef: name: {{ .Release.Name }}-kutt-redis-secret + {{- if or $redisPersistence }} volumeMounts: + {{- if $redisPersistence }} - name: {{ .Release.Name }}-kutt-redis-data - mountPath: /data + mountPath: {{ $redisMountPath }} + {{- if $redisSubPath }} + subPath: {{ $redisSubPath | quote }} + {{- end }} + {{- end }} + {{- end }} {{- end }} - {{- if not $external_redis }} + {{- if and (not $externalRedis) $redisPersistence }} volumes: - name: {{ .Release.Name }}-kutt-redis-data persistentVolumeClaim: diff --git a/mika/kutt/templates/ingress.yaml b/mika/kutt/templates/ingress.yaml index e784599f..5de59d74 100644 --- a/mika/kutt/templates/ingress.yaml +++ b/mika/kutt/templates/ingress.yaml @@ -1,7 +1,11 @@ {{- $ingress := .Values.ingress.enabled }} -{{- if $ingress }} -{{- $cluster_issuer := .Values.ingress.clusterIssuer | default "letsencrypt-dns-prod" | toString | quote }} -{{- $domain := .Values.kutt.domain | toString | quote }} +{{- $www := .Values.ingress.www }} +{{- $clusterIssuer := .Values.ingress.clusterIssuer | default "letsencrypt-dns-prod" | toString | quote }} +{{- $customAnnotations := .Values.ingress.customAnnotations }} +{{- $domain := .Values.kutt.domain | toString }} +{{- $wwwDomain := printf "www.%s" $domain | toString | quote }} +{{- if and $ingress $domain }} +--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -9,7 +13,7 @@ metadata: labels: {{- include "kutt.labels" . | nindent 4 }} annotations: - cert-manager.io/cluster-issuer: {{ $cluster_issuer }} + cert-manager.io/cluster-issuer: {{ $clusterIssuer }} cert-manager.io/private-key-algorithm: "ECDSA" nginx.ingress.kubernetes.io/affinity: "cookie" nginx.ingress.kubernetes.io/affinity-mode: "persistent" @@ -18,21 +22,39 @@ metadata: nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" nginx.ingress.kubernetes.io/session-cookie-name: "route" nginx.org/client-max-body-size: "100m" + {{- range $customAnnotations }} + {{ printf "%s/%s" (.prefix | default "nginx.ingress.kubernetes.io") .name }}: {{ .value | quote }} + {{- end }} spec: ingressClassName: "nginx" rules: - - host: {{ $domain }} - http: - paths: - - backend: - service: - name: {{ .Release.Name }}-kutt-svc - port: - name: kutt - path: / - pathType: Prefix + - host: {{ $domain | quote }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }}-kutt-svc + port: + name: kutt + path: / + pathType: Prefix + {{- if $www }} + - host: {{ $wwwDomain }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }}-kutt-svc + port: + name: kutt + path: / + pathType: Prefix + {{- end }} tls: - - hosts: - - {{ $domain }} - secretName: {{ .Release.Name }}-kutt-tls-cert + - hosts: + - {{ $domain | quote }} + {{- if $www }} + - {{ $wwwDomain }} + {{- end }} + secretName: {{ .Release.Name }}-kutt-tls-cert {{- end }} diff --git a/mika/kutt/templates/pvc.yaml b/mika/kutt/templates/pvc.yaml index 34c3384c..fc02dad8 100644 --- a/mika/kutt/templates/pvc.yaml +++ b/mika/kutt/templates/pvc.yaml @@ -1,8 +1,10 @@ -{{- $external_redis := .Values.redis.external }} -{{- if not $external_redis }} -{{- $access_mode := .Values.data.accessMode | default "ReadWriteOnce" | toString | quote }} -{{- $storage := .Values.data.storage | default "100Mi" | toString | quote }} -{{- $storage_class_name := .Values.data.storageClassName | default "longhorn" | toString | quote }} +{{- $externalRedis := .Values.redis.external }} +{{- $redisPersistence := .Values.storage.redis.enabled }} +{{- $redisAccessMode := .Values.storage.redis.accessMode | default "ReadWriteOnce" | toString | quote }} +{{- $redisStorage := .Values.storage.redis.storage | default "100Mi" | toString | quote }} +{{- $redisStorageClassName := .Values.storage.redis.storageClassName | default "longhorn" | toString | quote }} +{{- if and (not $externalRedis) $redisPersistence }} +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -11,9 +13,9 @@ metadata: {{- include "kutt.labels" . | nindent 4 }} spec: accessModes: - - {{ $access_mode }} + - {{ $redisAccessMode }} resources: requests: - storage: {{ $storage }} - storageClassName: {{ $storage_class_name }} + storage: {{ $redisStorage }} + storageClassName: {{ $redisStorageClassName }} {{- end }} diff --git a/mika/kutt/templates/secret.yaml b/mika/kutt/templates/secret.yaml index 2cc2203f..f0bf153c 100644 --- a/mika/kutt/templates/secret.yaml +++ b/mika/kutt/templates/secret.yaml @@ -1,26 +1,35 @@ +{{- $redisHost := "" }} +{{- $redisPort := "" }} +{{- $redisPassword := "" }} +{{- $externalRedis := .Values.redis.external }} {{- $secret := .Values.kutt.secret | toString | b64enc }} -{{- $db_name := .Values.db.name | toString | b64enc }} -{{- $db_user := .Values.db.user | toString | b64enc }} -{{- $db_password := .Values.db.password | toString | b64enc }} -{{- $db_host := .Values.db.host | toString | b64enc }} -{{- $db_port := .Values.db.port | default "5432" | toString | b64enc }} -{{- $db_ssl := .Values.db.ssl | toString | b64enc }} -{{- $mail_host := .Values.kutt.mail.host | default "smtp.gmail.com" | toString | b64enc }} -{{- $mail_port := .Values.kutt.mail.port | default "465" | toString | b64enc }} -{{- $mail_secure := .Values.kutt.mail.secure | toString | b64enc }} -{{- $mail_user := .Values.kutt.mail.user | toString }} -{{- $mail_password := .Values.kutt.mail.password | toString | b64enc }} +{{- $db_name := .Values.postgres.name | toString | b64enc }} +{{- $db_user := .Values.postgres.user | toString | b64enc }} +{{- $db_password := .Values.postgres.password | toString | b64enc }} +{{- $db_host := .Values.postgres.host | toString | b64enc }} +{{- $db_port := .Values.postgres.port | default "5432" | toString | b64enc }} +{{- $db_ssl := .Values.postgres.ssl | default "false" | toString | b64enc }} {{- $name := .Values.kutt.name | default "Kutt" | toString }} -{{- $from_email := .Values.kutt.mail.from_email | default (printf "%s <%s>" $name $mail_user) | toString | b64enc }} -{{- $contact_email := .Values.kutt.mail.contact_email | toString | b64enc }} -{{- $report_email := .Values.kutt.mail.report_email | toString | b64enc }} -{{- $external_redis := .Values.redis.external }} -{{- $redis_host := .Values.redis.host | default "localhost" | toString | b64enc }} -{{- $redis_port := .Values.redis.port | default "6379" | toString | b64enc }} -{{- $redis_password := .Values.redis.password | toString | b64enc }} -{{- $recaptchaSecretKey := .Values.kutt.google.recaptchaSecretKey | toString | b64enc }} -{{- $recaptchaSiteKey := .Values.kutt.google.recaptchaSiteKey | toString | b64enc }} -{{- $safeBrowsingKey := .Values.kutt.google.safeBrowsingKey | toString | b64enc }} +{{- $mailHost := .Values.mail.smtp.host | default "smtp.gmail.com" | toString | b64enc }} +{{- $mailPort := .Values.mail.smtp.port | default "465" | toString | b64enc }} +{{- $mailUser := .Values.mail.smtp.user | toString }} +{{- $mailPassword := .Values.mail.smtp.password | toString | b64enc }} +{{- $mailContact := .Values.mail.contact_email | toString | b64enc }} +{{- $mailFrom := .Values.mail.from_email | default (printf "%s <%s>" $name $mailUser) | toString | b64enc }} +{{- $mailReport := .Values.mail.report_email | toString | b64enc }} +{{- $mailSecure := .Values.mail.secure | default "true" | toString | b64enc }} +{{- $recaptchaSecretKey := .Values.google.recaptchaSecretKey | toString | b64enc }} +{{- $recaptchaSiteKey := .Values.google.recaptchaSiteKey | toString | b64enc }} +{{- $safeBrowsingKey := .Values.google.safeBrowsingKey | toString | b64enc }} +{{- if $externalRedis }} + {{- $redisHost = .Values.redis.host | toString | b64enc }} + {{- $redisPort = .Values.redis.port | default "6379" | toString | b64enc }} + {{- $redisPassword = .Values.redis.password | toString | b64enc }} +{{- else }} + {{- $redisHost = "localhost" | toString | b64enc }} + {{- $redisPort = .Values.service.redis.port | default "6379" | toString | b64enc }} +{{- end }} +--- apiVersion: v1 kind: Secret metadata: @@ -36,20 +45,20 @@ data: DB_HOST: {{ $db_host }} DB_PORT: {{ $db_port }} DB_SSL: {{ $db_ssl }} - MAIL_HOST: {{ $mail_host }} - MAIL_PORT: {{ $mail_port }} - MAIL_SECURE: {{ $mail_secure }} - MAIL_USER: {{ $mail_user | b64enc }} - MAIL_PASSWORD: {{ $mail_password }} - MAIL_FROM: {{ $from_email }} - CONTACT_EMAIL: {{ $contact_email }} - REPORT_EMAIL: {{ $report_email }} - {{- if $recaptchaSiteKey }} - RECAPTCHA_SITE_KEY: {{ $recaptchaSiteKey }} - {{- end }} + MAIL_HOST: {{ $mailHost }} + MAIL_PORT: {{ $mailPort }} + MAIL_SECURE: {{ $mailSecure }} + MAIL_USER: {{ $mailUser | b64enc }} + MAIL_PASSWORD: {{ $mailPassword }} + MAIL_FROM: {{ $mailFrom }} + CONTACT_EMAIL: {{ $mailContact }} + REPORT_EMAIL: {{ $mailReport }} {{- if $recaptchaSecretKey }} RECAPTCHA_SECRET_KEY: {{ $recaptchaSecretKey }} {{- end }} + {{- if $recaptchaSiteKey }} + RECAPTCHA_SITE_KEY: {{ $recaptchaSiteKey }} + {{- end }} {{- if $safeBrowsingKey }} GOOGLE_SAFE_BROWSING_KEY: {{ $safeBrowsingKey }} {{- end }} @@ -62,13 +71,9 @@ metadata: {{- include "kutt.labels" . | nindent 4 }} type: Opaque data: - REDIS_HOST: {{ $redis_host }} - {{- if not $external_redis }} - REDIS_PORT: {{ "6379" | toString | b64enc }} - {{- else }} - REDIS_PORT: {{ $redis_port }} - {{- end }} - {{- if $redis_password }} - REDIS_PASSWORD: {{ $redis_password }} + REDIS_HOST: {{ $redisHost }} + REDIS_PORT: {{ $redisPort }} + {{- if and $externalRedis $redisPassword }} + REDIS_PASSWORD: {{ $redisPassword }} {{- end }} # REDIS_DB: "" diff --git a/mika/kutt/templates/service.yaml b/mika/kutt/templates/service.yaml index cdd926e6..b2f7c486 100644 --- a/mika/kutt/templates/service.yaml +++ b/mika/kutt/templates/service.yaml @@ -1,7 +1,10 @@ +{{- $externalRedis := .Values.redis.external }} +{{- $kuttPort := .Values.service.kutt.port | default "3000" | toString }} +{{- $kuttNodePort := .Values.service.kutt.nodePort | toString }} +{{- $redisPort := .Values.service.redis.port | default "6379" | toString }} +{{- $redisNodePort := .Values.service.redis.nodePort | toString }} {{- $type := .Values.service.type | default "ClusterIP" | toString }} -{{- $kutt_port := .Values.service.kutt.port | default "3000" | toString | int }} -{{- $kutt_protocol := .Values.service.kutt.protocol | default "TCP" | toString }} -{{- $external_redis := .Values.redis.external }} +--- apiVersion: v1 kind: Service metadata: @@ -11,13 +14,19 @@ metadata: spec: type: {{ $type }} ports: - - port: {{ $kutt_port }} + - port: {{ int $kuttPort }} targetPort: kutt - protocol: {{ $kutt_protocol }} + {{- if and (eq $type "NodePort") $kuttNodePort }} + nodePort: {{ int $kuttNodePort }} + {{- end }} + protocol: TCP name: kutt - {{- if not $external_redis }} - - port: 6379 + {{- if not $externalRedis }} + - port: {{ int $redisPort }} targetPort: redis + {{- if and (eq $type "NodePort") $redisNodePort }} + nodePort: {{ int $redisNodePort }} + {{- end }} protocol: TCP name: redis {{- end }} diff --git a/mika/kutt/values.yaml b/mika/kutt/values.yaml index f3b33182..6ab3cdd9 100644 --- a/mika/kutt/values.yaml +++ b/mika/kutt/values.yaml @@ -9,44 +9,46 @@ replicaCount: "" # Container images used for Kutt. image: # Kutt container image configurations. + # Source: https://hub.docker.com/r/kutt/kutt kutt: - # The registry where the kutt container image is hosted. + # The registry where the Kutt container image is hosted. # Default: "docker.io" registry: "" - # The name of the repository that contains the kutt container image used. + # The name of the repository that contains the Kutt container image used. # Default: "kutt/kutt" repository: "" - # The tag that specifies the version of the kutt container image used. + # The tag that specifies the version of the Kutt container image used. # Default: Chart appVersion tag: "" - # The policy that determines when Kubernetes should pull the kutt container image. + # The policy that determines when Kubernetes should pull the Kutt container image. # Default: "IfNotPresent" pullPolicy: "" # Redis container image configurations. + # Source: https://hub.docker.com/_/redis redis: - # The registry where the redis container image is hosted. + # The registry where the Redis container image is hosted. # Default: "docker.io" registry: "" - # The name of the repository that contains the redis container image used. + # The name of the repository that contains the Redis container image used. # Default: "redis" repository: "" - # The tag that specifies the version of the redis container image used. + # The tag that specifies the version of the Redis container image used. # Default: "6.0-alpine" tag: "" - # The policy that determines when Kubernetes should pull the redis container image. + # The policy that determines when Kubernetes should pull the Redis container image. # Default: "IfNotPresent" pullPolicy: "" +# Credentials used to securely authenticate and authorise the pulling of container images from private registries. +# Example: +# imagePullSecrets: +# - name: "ghcr-token-secret" +imagePullSecrets: [] + # Kutt configurations. kutt: - # Email addresses of the administrators of the Kutt application so they can access admin actions. - # Example: - # admins: - # - "admin@example.com" - # - "su@example.com" - admins: [] - # The domain name that is hosting the Kutt application. - # Default: "localhost:$service.kutt.port" if `ingress` is disabled + # The ingress domain name that hosts the Kutt server. + # Default: "%s-kutt-svc:kutt .Release.Name" # Example: # domain: "kutt.example.com" domain: "" @@ -58,31 +60,40 @@ kutt: # The name of the site where Kutt is hosted. # Default: "Kutt" # Example: - # name: "Kutt" + # name: "URL Shortener" name: "" # A 50-character secret key used for encrypting JSON Web Tokens (JWTs). # Example: # secret: "6&p4%t)-$8a14fmfh92py8j55+us51r6%e52dzy&=a3-6yd4#e" secret: "" # Specifies whether Kutt should use HTTPS for custom domains. + # Default: "true" # Example: - # useHttps: false - useHttps: true + # useHttps: "false" + useHttps: "" # Kutt administration configurations. administration: + # Email addresses of the administrators of the Kutt application so they can access admin actions. + # Example: + # admins: + # - "admin@example.com" + # - "su@example.com" + admins: [] # The maximum number of links that can be created by a user in a day. # Default: "50" # Example: # dailyUserLimit: "15" dailyUserLimit: "" # Specifies whether Kutt should disallow creating links without an account. + # Default: "false" # Example: - # disableAnonLinks: true - disableAnonLinks: false + # disableAnonLinks: "true" + disableAnonLinks: "" # Specifies whether Kutt should disallow user registrations. + # Default: "false" # Example: - # disableRegistration: true - disableRegistration: false + # disableRegistration: "true" + disableRegistration: "" # The maximum number of visits for a link to have detailed statistics. # Default: "5000" # Example: @@ -93,31 +104,54 @@ kutt: # Example: # nonUserCooldown: "1" nonUserCooldown: "" - # Kutt Google configurations. - google: - # The Google reCAPTCHA secret key used for preventing spam. Refer to https://developers.google.com/recaptcha/intro. - # Example: - # recaptchaSecretKey: "01eHZ5I71tcYAhDOG9IlJqDk6sOx4X8rNsOFBcXz" - recaptchaSecretKey: "" - # The Google reCAPTCHA site key used for preventing spam. Refer to https://developers.google.com/recaptcha/intro. - # Example: - # recaptchaSiteKey: "01eHZ5I71tcYA4DYuVcw7mUqZAWujE7SUr9r7XAm" - recaptchaSiteKey: "" - # The Google API key used for Google Safe Browsing to prevent malicious links. Refer to https://developers.google.com/safe-browsing/v4/get-started. - # Example: - # safeBrowsingKey: "Z0VNqFK9NqYYwFP27v9-eC1St4HTz3uRTJRfii5" - safeBrowsingKey: "" - # Kutt mail configurations. - mail: + +# Google configurations. +google: + # The Google reCAPTCHA secret key used for preventing spam. Refer to https://developers.google.com/recaptcha/intro. + # Example: + # recaptchaSecretKey: "01eHZ5I71tcYAhDOG9IlJqDk6sOx4X8rNsOFBcXz" + recaptchaSecretKey: "" + # The Google reCAPTCHA site key used for preventing spam. Refer to https://developers.google.com/recaptcha/intro. + # Example: + # recaptchaSiteKey: "01eHZ5I71tcYA4DYuVcw7mUqZAWujE7SUr9r7XAm" + recaptchaSiteKey: "" + # The Google API key used for Google Safe Browsing to prevent malicious links. Refer to https://developers.google.com/safe-browsing/v4/get-started. + # Example: + # safeBrowsingKey: "Z0VNqFK9NqYYwFP27v9-eC1St4HTz3uRTJRfii5" + safeBrowsingKey: "" + +# Mail configurations. +mail: + # The email address to be displayed as the contact email in the application. + # Example: + # contact_email: "contact@example.com" + contact_email: "" + # The email address used as the "from" address for sent emails. + # Default: "$name <$mail.user>" + # Example: + # from_email: "Example User " + from_email: "" + # The email address that will receive submitted reports. + # Example: + # report_email: "report@example.com" + report_email: "" + # Specifies whether Kutt should use a secure TLS connection when sending emails. + # Note: In most cases, set this to true if the SMTP port is 465 (SSL) and false if you are using port 587 (TLS) or 25 (SSL/TLS). + # Default: "true" + # Example + # secure: "false" + secure: "" + # SMTP server configurations. + smtp: # The hostname or IP address of the SMTP server for sending emails. # Default: "smtp.gmail.com" # Example: - # host: "" + # host: "smtp.mail.yahoo.com" host: "" # The port number on the SMTP server used for sending emails. # Default: "465" # Example: - # port: "" + # port: "587" port: "" # The username for authenticating with the SMTP server. # Example: @@ -127,165 +161,200 @@ kutt: # Example: # password: "password" password: "" - # Specifies whether Kutt should use a secure TLS connection when sending emails. - # Note: In most cases, set this to true if the SMTP port is 465 (SSL) and false if you are using port 587 (TLS) or 25 (SSL/TLS). - # Example - # secure: false - secure: true - # The email address used as the "from" address for sent emails. - # Default: "$name <$mail.user>" - # Example: - # from_email: "Example User " - from_email: "" - # The email address to be displayed as the contact email in the application. - # Example: - # contact_email: "contact@example.com" - contact_email: "" - # The email address that will receive submitted reports. - # Example: - # report_email: "report@example.com" - report_email: "" -# Redis configurations. +# External Redis configurations. redis: # Specifies whether Kutt should use an external Redis server. # Example: # external: true external: false - # The hostname or IP address of the Redis server. - # Default: "localhost" + # The hostname or IP address of the external Redis server. # Example: # host: "redis.default.svc.cluster.local" host: "" - # The port number on which the EXTERNAL Redis server is listening. + # The port number on which the external Redis server is listening for connections. # Default: "6379" # Example: # port: "9763" port: "" - # The password for authenticating with the Redis server. + # The password for authenticating with the external Redis server. # Example: # password: "password" password: "" -# Data persistence configurations. -data: - # The access mode that defines how the volume can be accessed by one or many nodes. - # Default: "ReadWriteOnce" +# PostgreSQL configurations. +postgres: + # The hostname or IP address of the Kutt database server. # Example: - # accessMode: "ReadWriteMany" - accessMode: "" - # The amount of persistent storage allocated for the Kutt instance. - # Default: "100Mi" + # host: "kutt.default.svc.cluster.local" + host: "" + # The port number the Kutt database server is listening for connections. + # Default: "5432" # Example: - # storage: "1Gi" - storage: "" - # The storage class name used for dynamically provisioning a persistent volume for the Kutt storage. - # Default: "longhorn" + # port: "3306" + port: "" + # Specifies whether the Kutt database server should use SSL. + # Default: "false" # Example: - # storageClassName: "longhorn" - storageClassName: "" + # ssl: "true" + ssl: "" + # The name of the database being used by Kutt. + # Example: + # name: "kutt" + name: "" + # The username or user account for accessing the Kutt database. + # Example: + # user: "root" + user: "" + # The password associated with the Kutt database user. + # Example: + # password: "password" + password: "" # Ingress configurations. ingress: - # Specifies whether Kutt should be hosted using an Ingress. + # Specifies whether Ingress should be enabled for hosting Kutt services. # Example: # enabled: true enabled: false # The name of the cluster issuer for Ingress. # Default: "letsencrypt-dns-prod" + # Example: + # clusterIssuer: "letsencrypt-http-prod" clusterIssuer: "" + # Specifies whether the WWW subdomain should be enabled. + # Example: + # www: true + www: false + # Additional configuration annotations to be added to the Ingress resource. + # Items: `.prefix`, `.name`, `.value` + # Example: + # customAnnotations: + # # The prefix of the annotation. + # # Default: "nginx.ingress.kubernetes.io" + # # Example: + # # prefix: "nginx.org" + # - prefix: "" + # # The name of the annotation. + # # Example: + # # name: "proxy-connect-timeout" + # name: "" + # # The value of the annotation. + # # Example: + # # value: "120" + # value: "" + customAnnotations: [] # Service configurations. service: - # The type of service used for Kutt. + # The type of service used to expose Kutt services. # Default: "ClusterIP" # Example: - # type: "ClusterIP" + # type: "NodePort" type: "" - # Kutt service configurations. + # Kutt service port configurations. kutt: - # The port number on which the Kutt service is listening. + # The optional node port to expose for Kutt when the service type is NodePort. + # Example: + # nodePort: "30000" + nodePort: "" + # The Kutt port on which the Kutt server should listen for connections. # Default: "3000" # Example: - # port: "3500" + # port: "8080" port: "" - # The protocol used by the Kutt service. - # Default: "TCP" + # Redis service port configurations. + redis: + # The optional node port to expose for Redis when the service type is NodePort. # Example: - # protocol: "TCP" - protocol: "" + # nodePort: "32000" + nodePort: "" + # The Redis port on which the Kutt server should listen for connections. + # Default: "6379" + # Example: + # port: "8443" + port: "" -# Database configurations. -db: - # The hostname or IP address of the Kutt database server. - # Example: - # host: "kutt.default.svc.cluster.local" - host: "" - # The port number on which the Kutt database server is listening. - # Default: "5432" - # Example: - # port: "5432" - port: "" - # The name of the database used by Kutt. - # Example: - # name: "kutt" - name: "" - # The username or user account for accessing the Kutt database. - # Example: - # user: "root" - user: "" - # The password associated with the Kutt database's user. - # Example: - # password: "password" - password: "" - # Specifies whether the Kutt database server should use SSL. - # Example: - # ssl: true - ssl: false +# Storage configurations. +storage: + # Redis storage configurations. + redis: + # Specifies whether persistent storage should be provisioned for Redis storage. + # Example: + # enabled: false + enabled: true + # The access mode defining how the Redis storage can be mounted. + # Default: "ReadWriteOnce" + # Example: + # accessMode: "ReadWriteMany" + accessMode: "" + # The path where the Redis storage should be mounted on the container. + # Default: "/data" + # Example: + # mountPath: "/config" + mountPath: "" + # The subpath within the Redis storage to mount to the container. Leave empty if not required. + # Example: + # subPath: "Redis" + subPath: "" + # The default amount of persistent storage allocated for the Redis storage. + # Default: "100Mi" + # Example: + # storage: "10Gi" + storage: "" + # The storage class name used for dynamically provisioning a persistent volume for the Redis storage. + # Default: "longhorn" + # Example: + # storageClassName: "smb" + storageClassName: "" # Resource requirements and limits for Kutt containers. resources: # Kutt container resources. - kutt: - # The minimum amount of resources required by the kutt to run. - requests: - # The minimum amount of CPU resources required by the kutt. - # Example: - # cpu: "10m" - cpu: "100m" - # The minimum amount of memory required by the kutt. - # Example: - # memory: "10Mi" - memory: "200Mi" - # The maximum amount of resources allowed for the kutt. - limits: - # The maximum amount of CPU resources allowed for the kutt. - # Example: - # cpu: "250m" - cpu: "150m" - # The maximum amount of memory allowed for the kutt. - # Example: - # memory: "250Mi" - memory: "400Mi" + # Example: + # kutt: + # # The minimum amount of resources required by Kutt to run. + # requests: + # # The minimum amount of CPU resources required by Kutt. + # # Example: + # # cpu: "10m" + # cpu: "100m" + # # The minimum amount of memory required by Kutt. + # # Example: + # # memory: "10Mi" + # memory: "200Mi" + # # The maximum amount of resources allowed for Kutt. + # limits: + # # The maximum amount of CPU resources allowed for Kutt. + # # Example: + # # cpu: "250m" + # cpu: "150m" + # # The maximum amount of memory allowed for Kutt. + # # Example: + # # memory: "250Mi" + # memory: "400Mi" + kutt: {} # Redis container resources. - redis: - # The minimum amount of resources required by the redis to run. - requests: - # The minimum amount of CPU resources required by the redis. - # Example: - # cpu: "10m" - cpu: "10m" - # The minimum amount of memory required by the redis. - # Example: - # memory: "10Mi" - memory: "20Mi" - # The maximum amount of resources allowed for the redis. - limits: - # The maximum amount of CPU resources allowed for the redis. - # Example: - # cpu: "250m" - cpu: "20m" - # The maximum amount of memory allowed for the redis. - # Example: - # memory: "250Mi" - memory: "50Mi" + # Example: + # redis: + # # The minimum amount of resources required by Redis to run. + # requests: + # # The minimum amount of CPU resources required by Redis. + # # Example: + # # cpu: "10m" + # cpu: "10m" + # # The minimum amount of memory required by Redis. + # # Example: + # # memory: "10Mi" + # memory: "20Mi" + # # The maximum amount of resources allowed for Redis. + # limits: + # # The maximum amount of CPU resources allowed for Redis. + # # Example: + # # cpu: "250m" + # cpu: "20m" + # # The maximum amount of memory allowed for Redis. + # # Example: + # # memory: "250Mi" + # memory: "50Mi" + redis: {} diff --git a/mika/mango/.helmignore b/mika/mango/.helmignore deleted file mode 100644 index 0e8a0eb3..00000000 --- a/mika/mango/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# 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/mika/mango/Chart.yaml b/mika/mango/Chart.yaml deleted file mode 100644 index de747295..00000000 --- a/mika/mango/Chart.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v2 -name: mango -description: Mango is an easy to use Mastodon bot framework built on top of Django. -type: application -version: 0.2.1 -appVersion: "0.0.1-stable" -keywords: - - mango - - django - - mastodon -home: https://github.com/irfanhakim-as/mango -icon: https://irfanhakim-as.github.io/charts/logos/mika.png -sources: - - https://github.com/irfanhakim-as/mango - - https://github.com/irfanhakim-as/charts -maintainers: - - name: Irfan Hakim - email: irfanhakim.as@yahoo.com - url: https://github.com/irfanhakim-as diff --git a/mika/mango/README.md b/mika/mango/README.md deleted file mode 100644 index 633672d2..00000000 --- a/mika/mango/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# [`mango`](https://github.com/irfanhakim-as/mango) 🔒 - -## Prerequisites - -- Kubernetes 1.19+ -- Helm 3.2.0+ - -## Preflight checklist - -### Create image pull secret - -Replace `$github-username`, `$github-pass`, `$github-email` and `$namespace` accordingly. - -```sh -kubectl create secret docker-registry ghcr-token-secret --docker-server=https://ghcr.io --docker-username="$github-username" --docker-password="$github-pass" --docker-email="$github-email" -n $namespace -``` - -### Generate secret key for `mango.secret` - -```sh -python -c 'import random; print("".join([random.choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for i in range(50)]))' -``` - -## How to add repo - -Add the repo to your local helm client. - -```sh -helm repo add mika https://irfanhakim-as.github.io/charts -``` - -Update the repo to retrieve the latest versions of the packages. - -```sh -helm repo update -``` - -## How to install - -### Prepare chart values - -Copy `values.yaml` from the chart you would like to install. - -```sh -cp mika/mango/values.yaml . -``` - -Edit `values.yaml` with the appropriate values. Refer to the [Configurations](#Configurations) section for available options. - -```sh -nano values.yaml -``` - -### Perform installation - -Install the desired chart. Replace `$release_name` and `$namespace` accordingly. - -```sh -helm install $release_name mika/mango --namespace $namespace --create-namespace --values values.yaml --wait -``` - -Verify that your chart has been installed. Replace `$namespace` and `$release_name` accordingly. - -```sh -helm ls --namespace $namespace | grep "$release_name" -``` - -## How to uninstall - -Uninstall the desired chart. Replace `$release_name` and `$namespace` accordingly. - -```sh -helm uninstall $release_name --namespace $namespace --wait -``` - -## Configurations - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| db.host | string | `"postgres.default.svc.cluster.local"` | Database server | -| db.name | string | `""` | Database name | -| db.password | string | `""` | Database user password | -| db.port | string | `"5432"` | Database port | -| db.type | string | `"postgresql"` | Database type | -| db.user | string | `""` | Database user | -| image.mango.pullPolicy | string | `"IfNotPresent"` | Mango image pull policy | -| image.mango.registry | string | `"ghcr.io"` | Mango image registry | -| image.mango.repository | string | `"irfanhakim-as/mango"` | Mango image repository | -| image.mango.tag | string | `""` | Mango image version | -| image.redis.pullPolicy | string | `"IfNotPresent"` | Redis image pull policy | -| image.redis.registry | string | `"docker.io"` | Redis image registry | -| image.redis.repository | string | `"redis"` | Redis image repository | -| image.redis.tag | string | `"alpine"` | Redis image version | -| imagePullSecrets[0].name | string | `"ghcr-token-secret"` | Image pull secret name | -| mango.celery_timezone | string | `"Asia/Kuala_Lumpur"` | Timezone of the background scheduler | -| mango.debug | bool | `false` | Mango debug mode | -| mango.mastodon.api | string | `"https://botsin.space/"` | Mastodon base API URL | -| mango.mastodon.id | string | `"mango"` | Mastodon bot ID | -| mango.mastodon.token | string | `""` | Mastodon token secret | -| mango.secret | string | `""` | Mango secret key | -| mango.support | string | `"support@mikahomelab.com"` | Support email address | -| replicaCount | int | `1` | Mango replica count | -| resources.mango.limits.cpu | string | `"50m"` | Mango maximum cpu allocation | -| resources.mango.limits.memory | string | `"500Mi"` | Mango maximum memory allocation | -| resources.mango.requests.cpu | string | `"10m"` | Mango minimum cpu allocation | -| resources.mango.requests.memory | string | `"250Mi"` | Mango minimum memory allocation | -| resources.redis.limits.cpu | string | `"15m"` | Redis maximum cpu allocation | -| resources.redis.limits.memory | string | `"80Mi"` | Redis maximum memory allocation | -| resources.redis.requests.cpu | string | `"5m"` | Redis minimum cpu allocation | -| resources.redis.requests.memory | string | `"30Mi"` | Redis minimum memory allocation | diff --git a/mika/mango/templates/NOTES.txt b/mika/mango/templates/NOTES.txt deleted file mode 100644 index 2f4adba0..00000000 --- a/mika/mango/templates/NOTES.txt +++ /dev/null @@ -1 +0,0 @@ -mango is now installed and configured for {{ .Release.Name }}. diff --git a/mika/mango/templates/_helpers.tpl b/mika/mango/templates/_helpers.tpl deleted file mode 100644 index b2a967ed..00000000 --- a/mika/mango/templates/_helpers.tpl +++ /dev/null @@ -1,62 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "mango.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 "mango.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 "mango.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "mango.labels" -}} -helm.sh/chart: {{ include "mango.chart" . }} -{{ include "mango.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "mango.selectorLabels" -}} -app.kubernetes.io/name: {{ include "mango.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "mango.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "mango.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} diff --git a/mika/mango/templates/configmap.yaml b/mika/mango/templates/configmap.yaml deleted file mode 100644 index 43f2047c..00000000 --- a/mika/mango/templates/configmap.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- $domain := .Values.mango.domain | default "localhost" | toString }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Release.Name }}-mango-cm - labels: - {{- include "mango.labels" . | nindent 4 }} -data: - BOT_ID: {{ .Values.mango.mastodon.id | toString | quote }} - DEBUG: {{ .Values.mango.debug | toString | quote }} - API_BASE_URL: {{ .Values.mango.mastodon.api | toString | quote }} - CELERY_BROKER: redis://{{ .Release.Name }}-mango-svc - CELERY_BACKEND: redis://{{ .Release.Name }}-mango-svc - CELERY_TIMEZONE: {{ .Values.mango.celery_timezone | toString | quote }} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ .Release.Name }}-mango-site-config - labels: - {{- include "mango.labels" . | nindent 4 }} -data: - site-config.conf: |- - - {{ "ServerName $domain:443" | replace "$domain" $domain }} - UseCanonicalName On - ServerAdmin {{ .Values.mango.support | toString }} - DocumentRoot /base - WSGIScriptAlias / /base/base/wsgi.py - {{ "WSGIDaemonProcess $domain python-path=/base" | replace "$domain" $domain }} - {{ "WSGIProcessGroup $domain" | replace "$domain" $domain }} - - - - Require all granted - - - - Alias /static /static - - Require all granted - - - ErrorLog /var/log/apache2/apache.error.log - CustomLog /var/log/apache2/apache.access.log combined - diff --git a/mika/mango/templates/deployment.yaml b/mika/mango/templates/deployment.yaml deleted file mode 100644 index 80e54551..00000000 --- a/mika/mango/templates/deployment.yaml +++ /dev/null @@ -1,125 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ .Release.Name }}-mango - labels: - {{- include "mango.labels" . | nindent 4 }} -spec: - replicas: {{ .Values.replicaCount | default 1 }} - selector: - matchLabels: - {{- include "mango.selectorLabels" . | nindent 6 }} - template: - metadata: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "mango.selectorLabels" . | nindent 8 }} - spec: - {{- with .Values.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - containers: - - name: mango - image: "{{ .Values.image.mango.registry }}/{{ .Values.image.mango.repository }}:{{ .Values.image.mango.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.mango.pullPolicy }} - ports: - - name: mango - containerPort: 80 - protocol: TCP - resources: - {{- toYaml .Values.resources.mango | nindent 12 }} - env: - - name: BOT_ID - valueFrom: - configMapKeyRef: - name: {{ .Release.Name }}-mango-cm - key: BOT_ID - - name: DEBUG - valueFrom: - configMapKeyRef: - name: {{ .Release.Name }}-mango-cm - key: DEBUG - - name: API_BASE_URL - valueFrom: - configMapKeyRef: - name: {{ .Release.Name }}-mango-cm - key: API_BASE_URL - - name: CELERY_BROKER - valueFrom: - configMapKeyRef: - name: {{ .Release.Name }}-mango-cm - key: CELERY_BROKER - - name: CELERY_BACKEND - valueFrom: - configMapKeyRef: - name: {{ .Release.Name }}-mango-cm - key: CELERY_BACKEND - - name: CELERY_TIMEZONE - valueFrom: - configMapKeyRef: - name: {{ .Release.Name }}-mango-cm - key: CELERY_TIMEZONE - - name: SECRET_KEY - valueFrom: - secretKeyRef: - name: {{ .Release.Name }}-mango-secret - key: SECRET_KEY - - name: DB_TYPE - valueFrom: - secretKeyRef: - name: {{ .Release.Name }}-mango-secret - key: DB_TYPE - - name: DB_NAME - valueFrom: - secretKeyRef: - name: {{ .Release.Name }}-mango-secret - key: DB_NAME - - name: DB_USER - valueFrom: - secretKeyRef: - name: {{ .Release.Name }}-mango-secret - key: DB_USER - - name: DB_PASS - valueFrom: - secretKeyRef: - name: {{ .Release.Name }}-mango-secret - key: DB_PASS - - name: DB_HOST - valueFrom: - secretKeyRef: - name: {{ .Release.Name }}-mango-secret - key: DB_HOST - - name: DB_PORT - valueFrom: - secretKeyRef: - name: {{ .Release.Name }}-mango-secret - key: DB_PORT - volumeMounts: - - name: {{ .Release.Name }}-mango-site-config - mountPath: /etc/apache2/sites-available/000-default.conf - subPath: site-config.conf - readOnly: true - - name: {{ .Release.Name }}-mango-token-secret - mountPath: /base/base/mastodon.secret - subPath: mastodon.secret - readOnly: true - - name: redis - image: "{{ .Values.image.redis.registry }}/{{ .Values.image.redis.repository }}:{{ .Values.image.redis.tag | default .Chart.AppVersion }}" - imagePullPolicy: {{ .Values.image.redis.pullPolicy }} - ports: - - name: redis - containerPort: 6379 - protocol: TCP - resources: - {{- toYaml .Values.resources.redis | nindent 12 }} - volumes: - - name: {{ .Release.Name }}-mango-site-config - configMap: - name: {{ .Release.Name }}-mango-site-config - - name: {{ .Release.Name }}-mango-token-secret - secret: - secretName: {{ .Release.Name }}-mango-token-secret diff --git a/mika/mango/templates/secret.yaml b/mika/mango/templates/secret.yaml deleted file mode 100644 index 96c649c0..00000000 --- a/mika/mango/templates/secret.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }}-mango-secret - labels: - {{- include "mango.labels" . | nindent 4 }} -type: Opaque -data: - SECRET_KEY: {{ .Values.mango.secret | toString | b64enc }} - DB_TYPE: {{ .Values.db.type | toString | b64enc }} - DB_NAME: {{ .Values.db.name | toString | b64enc }} - DB_USER: {{ .Values.db.user | toString | b64enc }} - DB_PASS: {{ .Values.db.password | toString | b64enc }} - DB_HOST: {{ .Values.db.host | toString | b64enc }} - DB_PORT: {{ .Values.db.port | toString | b64enc }} ---- -apiVersion: v1 -kind: Secret -metadata: - name: {{ .Release.Name }}-mango-token-secret - labels: - {{- include "mango.labels" . | nindent 4 }} -type: Opaque -data: - mastodon.secret: |- - {{ .Values.mango.mastodon.token | toString | b64enc | nindent 4 }} diff --git a/mika/mango/templates/service.yaml b/mika/mango/templates/service.yaml deleted file mode 100644 index c9d9b1b2..00000000 --- a/mika/mango/templates/service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ .Release.Name }}-mango-svc - labels: - {{- include "mango.labels" . | nindent 4 }} -spec: - type: ClusterIP - ports: - - port: 80 - targetPort: mango - protocol: TCP - name: {{ .Release.Name }}-mango - - port: 6379 - targetPort: redis - protocol: TCP - name: {{ .Release.Name }}-redis - selector: - {{- include "mango.selectorLabels" . | nindent 4 }} diff --git a/mika/mango/values.yaml b/mika/mango/values.yaml deleted file mode 100644 index 2f9ffbff..00000000 --- a/mika/mango/values.yaml +++ /dev/null @@ -1,83 +0,0 @@ -# Default values for mango. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -replicaCount: 1 - -# Mango image configuration -image: - mango: - registry: ghcr.io - repository: irfanhakim-as/mango - tag: "" - pullPolicy: IfNotPresent - redis: - registry: docker.io - repository: redis - tag: "alpine" - pullPolicy: IfNotPresent - -# Image pull secrets for private registries -imagePullSecrets: - - name: ghcr-token-secret - -# Mango configuration -mango: - # Mango debug mode - debug: false - # Mango secret key - secret: "" - # Mango support email address - support: "support@mikahomelab.com" - # Timezone of the background scheduler - celery_timezone: "Asia/Kuala_Lumpur" - # Mastodon configuration - mastodon: - # ID of the bot account - id: "mango" - # Base API URL - api: "https://botsin.space/" - # Mastodon token secret - token: "" - -# Database configuration -db: - # Database type - type: "postgresql" - # Database name - name: "" - # Database user - user: "" - # Database user password - password: "" - # Database server - host: "postgres.default.svc.cluster.local" - # Database port - port: "5432" - -# Mango system resources -resources: - # Mango container resources - mango: - requests: - # Minimum CPU allocation - cpu: "10m" - # Minimum memory allocation - memory: "250Mi" - limits: - # Maximum CPU allocation - cpu: "50m" - # Maximum memory allocation - memory: "500Mi" - # Redis container resources - redis: - requests: - # Minimum CPU allocation - cpu: "5m" - # Minimum memory allocation - memory: "30Mi" - limits: - # Maximum CPU allocation - cpu: "15m" - # Maximum memory allocation - memory: "80Mi" diff --git a/mika/mariadb-agent/Chart.yaml b/mika/mariadb-agent/Chart.yaml index c611645a..8dbafcc9 100644 --- a/mika/mariadb-agent/Chart.yaml +++ b/mika/mariadb-agent/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: mariadb-agent description: Easily create or delete multiple pairs of databases and users in a remote MariaDB instance. type: application -version: 0.1.1 +version: 0.1.2 appVersion: "11.1.3-debian-11-r0" keywords: - "mariadb" @@ -10,7 +10,7 @@ keywords: - "agent" - "job" home: "https://github.com/irfanhakim-as/charts" -icon: "https://irfanhakim-as.github.io/charts/logos/mariadb.png" +icon: "https://irfanhakim-as.github.io/charts/logos/mariadb.svg" sources: - "https://github.com/irfanhakim-as/charts" maintainers: diff --git a/mika/mariadb-agent/README.md b/mika/mariadb-agent/README.md index 253620c9..19822a72 100644 --- a/mika/mariadb-agent/README.md +++ b/mika/mariadb-agent/README.md @@ -1,77 +1,129 @@ -# [`mariadb-agent`](https://github.com/mariadb/mariadb) +# [MariaDB-Agent](https://github.com/MariaDB/server) + +Easily create or delete multiple pairs of databases and users in a remote MariaDB instance. ## Prerequisites +> [!NOTE] +> You may refer to [Orked](https://github.com/irfanhakim-as/orked) for help with setting up a Kubernetes cluster that meets all the following prerequisites. + - Kubernetes 1.19+ - Helm 3.2.0+ +- Longhorn 1.4.1+ + +--- ## Preflight checklist -## How to add repo +> [!IMPORTANT] +> The following items are required to be set up prior to installing this chart. + +**This section does not apply to this chart.** + +--- + +## Recommended configurations + +> [!NOTE] +> The following configuration recommendations might not be the default settings for this chart but are **highly recommended**. Please carefully consider them before configuring your installation. + +**This section does not apply to this chart.** + +--- + +## Application configurations + +> [!NOTE] +> The following configurations are expected or recommended to be set up from within the application after completing the installation. + +**This section does not apply to this chart.** + +--- + +## How to add the chart repo + +1. Add the repo to your local helm client: + + ```sh + helm repo add mika https://irfanhakim-as.github.io/charts + ``` + +2. Update the repo to retrieve the latest versions of the packages: + + ```sh + helm repo update + ``` + +--- + +## How to install or upgrade a chart release + +1. Get the values file of the MariaDB-Agent chart or an existing installation (release). + + Get the latest MariaDB-Agent chart values file for a new installation: -Add the repo to your local helm client. + ```sh + helm show values mika/mariadb-agent > values.yaml + ``` -```sh -helm repo add mika https://irfanhakim-as.github.io/charts -``` + Alternatively, get the values file of an existing MariaDB-Agent release: -Update the repo to retrieve the latest versions of the packages. + ```sh + helm get values ${releaseName} --namespace ${namespace} > values.yaml + ``` -```sh -helm repo update -``` + Replace `${releaseName}` and `${namespace}` accordingly. -## How to install +2. Edit your MariaDB-Agent values file with the intended configurations: -### Prepare MariaDB host + ```sh + nano values.yaml + ``` -Install [`bitnami/mariadb`](https://github.com/bitnami/charts/tree/main/bitnami/mariadb). This step can be skipped if you have an existing MariaDB server. + Pay extra attention to the descriptions and sample values provided in the chart values file. -### Prepare chart values +3. Install a new release for MariaDB-Agent or upgrade an existing MariaDB-Agent release: -Copy `values.yaml` from the chart you would like to install. Refer to the [Configurations](#configurations) section for more information. + ```sh + helm upgrade --install ${releaseName} mika/mariadb-agent --namespace ${namespace} --create-namespace --values values.yaml --wait + ``` -```sh -cp mika/mariadb-agent/values.yaml . -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Edit `values.yaml` with the appropriate values. Refer to the [Configurations](#Configurations) section for available options. +4. Verify that your MariaDB-Agent release has been installed: -```sh -nano values.yaml -``` + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -### Perform installation + Replace `${namespace}` and `${releaseName}` accordingly. This should return the release information if the release has been installed. -Install the desired chart. Replace `$release_name` and `$namespace` accordingly. +--- -```sh -helm install $release_name mika/mariadb-agent --namespace $namespace --create-namespace --values values.yaml --wait -``` +## How to uninstall a chart release -Verify that your chart has been installed. Replace `$namespace` and `$release_name` accordingly. +> [!CAUTION] +> Uninstalling a release will irreversibly delete all the resources associated with the release, including any persistent data. -```sh -helm ls --namespace $namespace | grep "$release_name" -``` +1. Uninstall the desired release: -## How to upgrade + ```sh + helm uninstall ${releaseName} --namespace ${namespace} --wait + ``` -After making any necessary changes to the `values.yaml` file, upgrade the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${releaseName}` and `${namespace}` accordingly. -```sh -helm upgrade $release_name mika/mariadb-agent --namespace $namespace --values values.yaml --wait -``` +2. Verify that the release has been uninstalled: -## How to uninstall + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -Uninstall the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${namespace}` and `${releaseName}` accordingly. This should return nothing if the release has been uninstalled. -```sh -helm uninstall $release_name --namespace $namespace --wait -``` +--- -## Configurations +## Chart configurations | Key | Type | Default | Description | |-----|------|---------|-------------| @@ -79,7 +131,10 @@ helm uninstall $release_name --namespace $namespace --wait | image.mariadb.registry | string | `""` | The registry where the MariaDB container image is hosted. Default: `"docker.io"`. | | image.mariadb.repository | string | `""` | The name of the repository that contains the MariaDB container image used. Default: `"bitnami/mariadb"`. | | image.mariadb.tag | string | `""` | The tag that specifies the version of the MariaDB container image used. Default: `Chart appVersion`. | -| mariadb.databases | list | `[]` | Database configurations array. Elements: `.name`, `.user`, `.password`, `.create`, `.drop`, `.custom`, `.custom_command`. | +| imagePullSecrets | list | `[]` | Credentials used to securely authenticate and authorise the pulling of container images from private registries. | +| mariadb.databases | list | `[]` | Database configurations array. Items: `.name`, `.user`, `.password`, `.create`, `.drop`, `.custom`, `.custom_command`. | | mariadb.host | string | `""` | The hostname or IP address of the MariaDB database server. | -| mariadb.root.password | string | `""` | The password associated with the MariaDB database server root user. | -| mariadb.root.user | string | `""` | The username or user account for accessing the MariaDB database server as root. Default: `"root"`. | +| mariadb.port | string | `""` | The port number the MariaDB database server is listening for connections. Default: `"3306"`. | +| mariadb.root.password | string | `""` | The password associated with the root MariaDB database user. | +| mariadb.root.user | string | `""` | The root username or user account of the MariaDB database server. Default: `"root"`. | +| resources.mariadb | object | `{}` | MariaDB container resources. | diff --git a/mika/mariadb-agent/templates/NOTES.txt b/mika/mariadb-agent/templates/NOTES.txt index e3f9ee05..f636005b 100644 --- a/mika/mariadb-agent/templates/NOTES.txt +++ b/mika/mariadb-agent/templates/NOTES.txt @@ -1,5 +1,45 @@ -mariadb-agent job has been deployed for {{ .Release.Name | toString }}. +{{- $index := 0 | int }} +{{- $databases := .Values.mariadb.databases }} +{{- $mariadbHost := .Values.mariadb.host | toString }} +{{- $mariadbPort := .Values.mariadb.port | default "3306" | toString }} +MariaDB-Agent has been installed and configured for {{ .Release.Name | toString }} 🎉 -See the values.yaml file of this chart for more configuration options. +The following are a list of database(s) you have supplied to be updated: -Please refer to the official documentation for more information on how to use mariadb-agent. +{{- range $database := $databases }} + {{- $custom_command := "false" }} + {{- $create := $database.create }} + {{- $drop := $database.drop }} + {{- $custom := $database.custom }} + {{- $command := $database.custom_command }} + {{- $db := $database.name | toString }} + {{- $user := $database.user | toString }} + {{- $password := $database.password | toString }} + + {{- if and $custom $command }} + {{- $custom_command = "true" | toString }} + {{- end }} + + {{- if or $create $drop (eq $custom_command "true") }} + {{- $index = add $index 1 }} + + {{ printf "%s. db=%s | user=%s | password=%s | create=%s | drop=%s | custom=%s" ($index | toString) $db $user $password ($create | toString) ($drop | toString) $custom_command }} + + {{- end }} +{{- end }} + +{{- if eq ($index | toString) "0" }} + + ⚠️ No databases were supplied for MariaDB-Agent to update + +{{- else }} + +Please run the following command for each database and check if they have been updated accordingly: + + ```sh + mysql -h {{ $mariadbHost }} -P {{ $mariadbPort }} -u -p -D + ``` + +{{- end }} + +For more information on how to use and configure MariaDB-Agent, please refer to the official documentation. diff --git a/mika/mariadb-agent/templates/deployment.yaml b/mika/mariadb-agent/templates/deployment.yaml deleted file mode 100644 index 4f86ba81..00000000 --- a/mika/mariadb-agent/templates/deployment.yaml +++ /dev/null @@ -1,55 +0,0 @@ -{{- $host := .Values.mariadb.host | default "mariadb" | toString }} -{{- $registry := .Values.image.mariadb.registry | default "docker.io" | toString }} -{{- $repository := .Values.image.mariadb.repository | default "bitnami/mariadb" | toString }} -{{- $tag := .Values.image.mariadb.tag | default .Chart.AppVersion | toString }} -{{- $pullPolicy := .Values.image.mariadb.pullPolicy | default "IfNotPresent" | toString | quote }} -{{- $databases := .Values.mariadb.databases }} -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ printf "%s-%s-%s" (index (splitList "." $host) 0) .Release.Name "mariadb-agent" }} - labels: - {{- include "mariadb-agent.labels" . | nindent 4 }} -spec: - ttlSecondsAfterFinished: 120 - backoffLimit: 0 - template: - metadata: - {{- with .Values.podAnnotations }} - annotations: - {{- toYaml . | nindent 8 }} - {{- end }} - labels: - {{- include "mariadb-agent.selectorLabels" . | nindent 8 }} - spec: - containers: - - name: mariadb-agent - image: {{ printf "%s/%s:%s" $registry $repository $tag | quote }} - imagePullPolicy: {{ $pullPolicy }} - resources: - {{- toYaml .Values.resources | nindent 12 }} - command: ["/bin/bash"] - args: - - -c - - >- - mysql -h $(DB_HOST) -u $(ROOT_USER) -e ' - {{- range $databases }} - {{- if .create }} - CREATE DATABASE IF NOT EXISTS {{ .name }}; - CREATE USER IF NOT EXISTS "{{ .user }}"@"%"; - SET PASSWORD FOR "{{ .user }}"@"%" = PASSWORD("{{ .password }}"); - GRANT ALL PRIVILEGES ON {{ .name }}.* TO "{{ .user }}"@"%"; - {{- else if .drop }} - DROP DATABASE IF EXISTS {{ .name }}; - DROP USER IF EXISTS "{{ .user }}"@"%"; - {{- end }} - {{- if and .custom .custom_command }} - {{- .custom_command | replace "$.name" .name | replace "$.user" .user | replace "$.password" .password | nindent 16 }} - {{- end }} - {{- end }} - FLUSH PRIVILEGES; - ' - envFrom: - - secretRef: - name: {{ .Release.Name }}-mariadb-agent-secret - restartPolicy: Never diff --git a/mika/mariadb-agent/templates/job.yaml b/mika/mariadb-agent/templates/job.yaml new file mode 100644 index 00000000..0af8eb2e --- /dev/null +++ b/mika/mariadb-agent/templates/job.yaml @@ -0,0 +1,68 @@ +{{- $mariadb_registry := .Values.image.mariadb.registry | default "docker.io" | toString }} +{{- $mariadb_repository := .Values.image.mariadb.repository | default "bitnami/mariadb" | toString }} +{{- $mariadb_tag := .Values.image.mariadb.tag | default .Chart.AppVersion | toString }} +{{- $mariadb_pullPolicy := .Values.image.mariadb.pullPolicy | default "IfNotPresent" | toString | quote }} +{{- $databases := .Values.mariadb.databases }} +{{- $mariadbHost := .Values.mariadb.host | default "mariadb" | toString }} +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ printf "%s-%s-%s" (index (splitList "." $mariadbHost) 0) .Release.Name "mariadb-agent" }} + labels: + {{- include "mariadb-agent.labels" . | nindent 4 }} +spec: + ttlSecondsAfterFinished: 120 + backoffLimit: 0 + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "mariadb-agent.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: mariadb-agent + image: {{ printf "%s/%s:%s" $mariadb_registry $mariadb_repository $mariadb_tag | quote }} + imagePullPolicy: {{ $mariadb_pullPolicy }} + resources: + {{- toYaml .Values.resources.mariadb | nindent 12 }} + command: ["/bin/bash"] + args: + - -c + - >- + mariadb -h $(DB_HOST) -P $(DB_PORT) -u $(ROOT_USER) -e ' + {{- range $databases }} + {{- $create := .create }} + {{- $drop := .drop }} + {{- $custom := .custom }} + {{- $command := .custom_command }} + {{- $db := .name | toString }} + {{- $user := .user | toString }} + {{- $password := .password | toString }} + {{- if $drop }} + DROP DATABASE IF EXISTS {{ $db }}; + DROP USER IF EXISTS {{ $user | quote }}@"%"; + {{- end }} + {{- if $create }} + CREATE USER IF NOT EXISTS {{ $user | quote }}@"%"; + SET PASSWORD FOR {{ $user | quote }}@"%" = PASSWORD({{ $password | quote }}); + CREATE DATABASE IF NOT EXISTS {{ $db }}; + GRANT ALL PRIVILEGES ON {{ $db }}.* TO {{ $user | quote }}@"%"; + {{- end }} + {{- if and $custom $command }} + {{- $command | toString | replace "$.name" $db | replace "$.user" $user | replace "$.password" $password | nindent 16 }} + {{- end }} + {{- end }} + FLUSH PRIVILEGES; + ' + envFrom: + - secretRef: + name: {{ .Release.Name }}-mariadb-agent-secret + restartPolicy: Never diff --git a/mika/mariadb-agent/templates/secret.yaml b/mika/mariadb-agent/templates/secret.yaml index a49a755a..3ca8a606 100644 --- a/mika/mariadb-agent/templates/secret.yaml +++ b/mika/mariadb-agent/templates/secret.yaml @@ -1,6 +1,8 @@ -{{- $db_host := .Values.mariadb.host | toString | b64enc }} -{{- $root_user := .Values.mariadb.root.user | default "root" | toString | b64enc }} -{{- $root_password := .Values.mariadb.root.password | toString | b64enc }} +{{- $mariadbHost := .Values.mariadb.host | toString | b64enc }} +{{- $mariadbPort := .Values.mariadb.port | default "3306" | toString | b64enc }} +{{- $rootUser := .Values.mariadb.root.user | default "root" | toString | b64enc }} +{{- $rootPassword := .Values.mariadb.root.password | toString | b64enc }} +--- apiVersion: v1 kind: Secret metadata: @@ -9,6 +11,7 @@ metadata: {{- include "mariadb-agent.labels" . | nindent 4 }} type: Opaque data: - DB_HOST: {{ $db_host }} - ROOT_USER: {{ $root_user }} - MYSQL_PWD: {{ $root_password }} + DB_HOST: {{ $mariadbHost }} + DB_PORT: {{ $mariadbPort }} + ROOT_USER: {{ $rootUser }} + MYSQL_PWD: {{ $rootPassword }} diff --git a/mika/mariadb-agent/values.yaml b/mika/mariadb-agent/values.yaml index 99d4aa26..5b7a9285 100644 --- a/mika/mariadb-agent/values.yaml +++ b/mika/mariadb-agent/values.yaml @@ -2,9 +2,10 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. -# Container image used for MariaDB. +# Container images used for MariaDB-Agent. image: # MariaDB container image configurations. + # Source: https://hub.docker.com/r/bitnami/mariadb mariadb: # The registry where the MariaDB container image is hosted. # Default: "docker.io" @@ -19,48 +20,100 @@ image: # Default: "IfNotPresent" pullPolicy: "" -# MariaDB configurations. +# Credentials used to securely authenticate and authorise the pulling of container images from private registries. +# Example: +# imagePullSecrets: +# - name: "ghcr-token-secret" +imagePullSecrets: [] + +# MariaDB-Agent configurations. mariadb: - # Database configurations array. - # Elements: `.name`, `.user`, `.password`, `.create`, `.drop`, `.custom`, `.custom_command`. - # .name: The name of the intended MariaDB database. - # .user: The username or user account for accessing the intended MariaDB database. - # .password: The password associated with the intended MariaDB database user. - # .create: Specifies whether to create the database and user in the remote MariaDB instance. - # .drop: Specifies whether to delete the database and user in the remote MariaDB instance. - # .custom: Specifies whether to run a custom command against the remote MariaDB instance. - # .custom_command: Specify a custom command to run against the remote MariaDB instance. - # Example: - # databases: - # - name: "mariadb" - # user: "mariadbuser" - # password: "mariadbuserpassword" - # create: true - # drop: false - # custom: false - # custom_command: >- - # CREATE TABLE IF NOT EXISTS `$.name`.`StorageRecords` ( - # `id` int(11) NOT NULL AUTO_INCREMENT, - # `key` varchar(255) NOT NULL, - # `value` text NOT NULL, - # `created_at` datetime NOT NULL, - # `updated_at` datetime NOT NULL, - # PRIMARY KEY (`id`), - # UNIQUE KEY `key` (`key`) - # ); - databases: [] # The hostname or IP address of the MariaDB database server. # Example: # host: "mariadb.default.svc.cluster.local" host: "" + # The port number the MariaDB database server is listening for connections. + # Default: "3306" + # Example: + # port: "5432" + port: "" # MariaDB database server root user configurations. root: - # The username or user account for accessing the MariaDB database server as root. + # The root username or user account of the MariaDB database server. # Default: "root" # Example: - # user: "root" + # user: "mariadb" user: "" - # The password associated with the MariaDB database server root user. + # The password associated with the root MariaDB database user. # Example: # password: "password" password: "" + # Database configurations array. + # Items: `.name`, `.user`, `.password`, `.create`, `.drop`, `.custom`, `.custom_command` + # Example: + # databases: + # # The name of the intended MariaDB database. + # # Example: + # # name: "mariadb" + # - name: "" + # # The username or user account for accessing the intended MariaDB database. + # # Example: + # # user: "mariadbuser" + # user: "" + # # The password associated with the intended MariaDB database user. + # # Example: + # # password: "mariadbuserpassword" + # password: "" + # # Specifies whether to create the database and user in the remote MariaDB instance. + # # Example: + # # create: true + # create: false + # # Specifies whether to delete the database and user in the remote MariaDB instance. + # # Example: + # # drop: true + # drop: false + # # Specifies whether to run a custom command against the remote MariaDB instance. + # # Example: + # # custom: true + # custom: false + # # Specify a custom command to run against the remote MariaDB instance. + # # Example: + # # custom_command: >- + # # CREATE TABLE IF NOT EXISTS `$.name`.`StorageRecords` ( + # # `id` int(11) NOT NULL AUTO_INCREMENT, + # # `key` varchar(255) NOT NULL, + # # `value` text NOT NULL, + # # `created_at` datetime NOT NULL, + # # `updated_at` datetime NOT NULL, + # # PRIMARY KEY (`id`), + # # UNIQUE KEY `key` (`key`) + # # ); + # custom_command: "" + databases: [] + +# Resource requirements and limits for MariaDB-Agent containers. +resources: + # MariaDB container resources. + # Example: + # mariadb: + # # The minimum amount of resources required by MariaDB to run. + # requests: + # # The minimum amount of CPU resources required by MariaDB. + # # Example: + # # cpu: "10m" + # cpu: "10m" + # # The minimum amount of memory required by MariaDB. + # # Example: + # # memory: "10Mi" + # memory: "10Mi" + # # The maximum amount of resources allowed for MariaDB. + # limits: + # # The maximum amount of CPU resources allowed for MariaDB. + # # Example: + # # cpu: "250m" + # cpu: "250m" + # # The maximum amount of memory allowed for MariaDB. + # # Example: + # # memory: "250Mi" + # memory: "250Mi" + mariadb: {} diff --git a/mika/postgres-agent/Chart.yaml b/mika/postgres-agent/Chart.yaml index f4aa7883..9fd3a304 100644 --- a/mika/postgres-agent/Chart.yaml +++ b/mika/postgres-agent/Chart.yaml @@ -2,14 +2,14 @@ apiVersion: v2 name: postgres-agent description: Easily create or delete a database and user pair in a remote PostgreSQL instance. type: application -version: 0.3.1 +version: 0.3.2 appVersion: "16.3.0-debian-12-r12" keywords: - "postgresql" - "agent" - "job" home: "https://github.com/irfanhakim-as/charts" -icon: "https://irfanhakim-as.github.io/charts/logos/postgres.png" +icon: "https://irfanhakim-as.github.io/charts/logos/postgres.svg" sources: - "https://github.com/irfanhakim-as/charts" maintainers: diff --git a/mika/postgres-agent/README.md b/mika/postgres-agent/README.md index 65aa4eb5..0f157bc6 100644 --- a/mika/postgres-agent/README.md +++ b/mika/postgres-agent/README.md @@ -1,4 +1,4 @@ -# Postgres-Agent +# [Postgres-Agent](https://github.com/postgres/postgres) Easily create or delete a database and user pair in a remote PostgreSQL instance. @@ -13,7 +13,7 @@ Easily create or delete a database and user pair in a remote PostgreSQL instance --- -## External dependencies +## Preflight checklist > [!IMPORTANT] > The following items are required to be set up prior to installing this chart. @@ -132,9 +132,10 @@ Easily create or delete a database and user pair in a remote PostgreSQL instance | image.postgres.repository | string | `""` | The name of the repository that contains the PostgreSQL container image used. Default: `"bitnami/postgresql"`. | | image.postgres.tag | string | `""` | The tag that specifies the version of the PostgreSQL container image used. Default: `Chart appVersion`. | | imagePullSecrets | list | `[]` | Credentials used to securely authenticate and authorise the pulling of container images from private registries. | -| postgres.databases | list | `[]` | Database configurations array. Elements: `.name`, `.user`, `.password`, `.create`, `.drop`, `.custom`, `.custom_command`. | +| postgres.databases | list | `[]` | Database configurations array. Items: `.name`, `.user`, `.password`, `.create`, `.drop`, `.custom`, `.custom_command`. | | postgres.host | string | `""` | The hostname or IP address of the PostgreSQL database server. | -| postgres.root.database | string | `""` | The name of the database of the PostgreSQL database server root user. Default: `$user`. | -| postgres.root.password | string | `""` | The password associated with the PostgreSQL database server root user. | -| postgres.root.user | string | `""` | The username or user account for accessing the PostgreSQL database server as root. Default: `"postgres"`. | +| postgres.port | string | `""` | The port number the PostgreSQL database server is listening for connections. Default: `"5432"`. | +| postgres.root.database | string | `""` | The name of the default database of the root PostgreSQL database user. Default: `$user`. | +| postgres.root.password | string | `""` | The password associated with the root PostgreSQL database user. | +| postgres.root.user | string | `""` | The root username or user account of the PostgreSQL database server. Default: `"postgres"`. | | resources.postgres | object | `{}` | PostgreSQL container resources. | \ No newline at end of file diff --git a/mika/postgres-agent/templates/NOTES.txt b/mika/postgres-agent/templates/NOTES.txt index 8f118730..e5c7de76 100644 --- a/mika/postgres-agent/templates/NOTES.txt +++ b/mika/postgres-agent/templates/NOTES.txt @@ -1,5 +1,45 @@ -Postgres-Agent job has been deployed for {{ .Release.Name | toString }}. +{{- $index := 0 | int }} +{{- $databases := .Values.postgres.databases }} +{{- $postgresHost := .Values.postgres.host | toString }} +{{- $postgresPort := .Values.postgres.port | default "5432" | toString }} +Postgres-Agent has been installed and configured for {{ .Release.Name | toString }} 🎉 -See the values.yaml file of this chart for more configuration options. +The following are a list of database(s) you have supplied to be updated: -Please refer to the official documentation for more information on how to use Postgres-Agent. +{{- range $database := $databases }} + {{- $custom_command := "false" }} + {{- $create := $database.create }} + {{- $drop := $database.drop }} + {{- $custom := $database.custom }} + {{- $command := $database.custom_command }} + {{- $db := $database.name | toString }} + {{- $user := $database.user | toString }} + {{- $password := $database.password | toString }} + + {{- if and $custom $command }} + {{- $custom_command = "true" | toString }} + {{- end }} + + {{- if or $create $drop (eq $custom_command "true") }} + {{- $index = add $index 1 }} + + {{ printf "%s. db=%s | user=%s | password=%s | create=%s | drop=%s | custom=%s" ($index | toString) $db $user $password ($create | toString) ($drop | toString) $custom_command }} + + {{- end }} +{{- end }} + +{{- if eq ($index | toString) "0" }} + + ⚠️ No databases were supplied for Postgres-Agent to update + +{{- else }} + +Please run the following command for each database and check if they have been updated accordingly: + + ```sh + psql -h {{ $postgresHost }} -p {{ $postgresPort }} -U -d + ``` + +{{- end }} + +For more information on how to use and configure Postgres-Agent, please refer to the official documentation. diff --git a/mika/postgres-agent/templates/job.yaml b/mika/postgres-agent/templates/job.yaml index 1bd38c57..58bfdeae 100644 --- a/mika/postgres-agent/templates/job.yaml +++ b/mika/postgres-agent/templates/job.yaml @@ -1,14 +1,15 @@ -{{- $host := .Values.postgres.host | default "postgres" | toString }} -{{- $registry := .Values.image.postgres.registry | default "docker.io" | toString }} -{{- $repository := .Values.image.postgres.repository | default "bitnami/postgresql" | toString }} -{{- $tag := .Values.image.postgres.tag | default .Chart.AppVersion | toString }} -{{- $pullPolicy := .Values.image.postgres.pullPolicy | default "IfNotPresent" | toString | quote }} -{{- $rootDB := .Values.postgres.root.database | default "$(ROOT_USER)" | toString }} +{{- $postgres_registry := .Values.image.postgres.registry | default "docker.io" | toString }} +{{- $postgres_repository := .Values.image.postgres.repository | default "bitnami/postgresql" | toString }} +{{- $postgres_tag := .Values.image.postgres.tag | default .Chart.AppVersion | toString }} +{{- $postgres_pullPolicy := .Values.image.postgres.pullPolicy | default "IfNotPresent" | toString | quote }} {{- $databases := .Values.postgres.databases }} +{{- $postgresHost := .Values.postgres.host | default "postgres" | toString }} +{{- $rootDB := .Values.postgres.root.database | default "$(ROOT_USER)" | toString | quote }} +--- apiVersion: batch/v1 kind: Job metadata: - name: {{ printf "%s-%s-%s" (index (splitList "." $host) 0) .Release.Name "postgres-agent" }} + name: {{ printf "%s-%s-%s" (index (splitList "." $postgresHost) 0) .Release.Name "postgres-agent" }} labels: {{- include "postgres-agent.labels" . | nindent 4 }} spec: @@ -29,32 +30,40 @@ spec: {{- end }} containers: - name: postgres-agent - image: {{ printf "%s/%s:%s" $registry $repository $tag | quote }} - imagePullPolicy: {{ $pullPolicy }} + image: {{ printf "%s/%s:%s" $postgres_registry $postgres_repository $postgres_tag | quote }} + imagePullPolicy: {{ $postgres_pullPolicy }} resources: {{- toYaml .Values.resources.postgres | nindent 12 }} command: ["/bin/bash"] args: - -c - >- - psql -h $(DB_HOST) -U $(ROOT_USER) -d {{ $rootDB | quote }} <- - # CREATE TABLE IF NOT EXISTS public.StorageRecords ( - # context VARCHAR(255) NOT NULL, - # expires BIGINT DEFAULT NULL, - # id SERIAL NOT NULL, - # value TEXT NOT NULL, - # version BIGINT NOT NULL, - # PRIMARY KEY (context, id) - # ); - databases: [] # The hostname or IP address of the PostgreSQL database server. # Example: # host: "postgres.default.svc.cluster.local" host: "" + # The port number the PostgreSQL database server is listening for connections. + # Default: "5432" + # Example: + # port: "3306" + port: "" # PostgreSQL database server root user configurations. root: - # The username or user account for accessing the PostgreSQL database server as root. + # The name of the default database of the root PostgreSQL database user. + # Default: $user + # Example: + # database: "postgres" + database: "" + # The root username or user account of the PostgreSQL database server. # Default: "postgres" # Example: # user: "root" user: "" - # The password associated with the PostgreSQL database server root user. + # The password associated with the root PostgreSQL database user. # Example: # password: "password" password: "" - # The name of the database of the PostgreSQL database server root user. - # Default: $user - # Example: - # database: "postgres" - database: "" + # Database configurations array. + # Items: `.name`, `.user`, `.password`, `.create`, `.drop`, `.custom`, `.custom_command` + # Example: + # databases: + # # The name of the intended PostgreSQL database. + # # Example: + # # name: "postgres" + # - name: "" + # # The username or user account for accessing the intended PostgreSQL database. + # # Example: + # # user: "postgresuser" + # user: "" + # # The password associated with the intended PostgreSQL database user. + # # Example: + # # password: "postgresuserpassword" + # password: "" + # # Specifies whether to create the database and user in the remote PostgreSQL instance. + # # Example: + # # create: true + # create: false + # # Specifies whether to delete the database and user in the remote PostgreSQL instance. + # # Example: + # # drop: true + # drop: false + # # Specifies whether to run a custom command against the remote PostgreSQL instance. + # # Example: + # # custom: true + # custom: false + # # Specify a custom command to run against the remote PostgreSQL instance. + # # Example: + # # custom_command: >- + # # CREATE TABLE IF NOT EXISTS public.StorageRecords ( + # # context VARCHAR(255) NOT NULL, + # # expires BIGINT DEFAULT NULL, + # # id SERIAL NOT NULL, + # # value TEXT NOT NULL, + # # version BIGINT NOT NULL, + # # PRIMARY KEY (context, id) + # # ); + # custom_command: "" + databases: [] # Resource requirements and limits for Postgres-Agent containers. resources: diff --git a/mika/postgres/Chart.yaml b/mika/postgres/Chart.yaml index e5f6de49..60a04518 100644 --- a/mika/postgres/Chart.yaml +++ b/mika/postgres/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: postgres description: Easy tool to deploy a PostgreSQL instance on Kubernetes. type: application -version: 0.2.1 +version: 0.2.2 appVersion: "13.3" keywords: - "PostgreSQL" @@ -11,7 +11,7 @@ keywords: - "Relational" - "Database" home: "https://github.com/irfanhakim-as/charts" -icon: "https://irfanhakim-as.github.io/charts/logos/postgres.png" +icon: "https://irfanhakim-as.github.io/charts/logos/postgres.svg" sources: - "https://github.com/irfanhakim-as/charts" maintainers: diff --git a/mika/postgres/README.md b/mika/postgres/README.md index d70404a4..d170532d 100644 --- a/mika/postgres/README.md +++ b/mika/postgres/README.md @@ -1,85 +1,153 @@ -# [`postgres`](https://github.com/postgres/postgres) +# [PostgreSQL](https://github.com/postgres/postgres) + +Easy tool to deploy a PostgreSQL instance on Kubernetes. ## Prerequisites +> [!NOTE] +> You may refer to [Orked](https://github.com/irfanhakim-as/orked) for help with setting up a Kubernetes cluster that meets all the following prerequisites. + - Kubernetes 1.19+ - Helm 3.2.0+ +- Longhorn 1.4.1+ + +--- + +## Preflight checklist + +> [!IMPORTANT] +> The following items are required to be set up prior to installing this chart. + +**This section does not apply to this chart.** + +--- + +## Recommended configurations + +> [!NOTE] +> The following configuration recommendations might not be the default settings for this chart but are **highly recommended**. Please carefully consider them before configuring your installation. + +**This section does not apply to this chart.** + +--- + +## Application configurations + +> [!NOTE] +> The following configurations are expected or recommended to be set up from within the application after completing the installation. + +**This section does not apply to this chart.** + +--- + +## How to add the chart repo + +1. Add the repo to your local helm client: + + ```sh + helm repo add mika https://irfanhakim-as.github.io/charts + ``` + +2. Update the repo to retrieve the latest versions of the packages: + + ```sh + helm repo update + ``` + +--- + +## How to install or upgrade a chart release + +1. Get the values file of the PostgreSQL chart or an existing installation (release). + + Get the latest PostgreSQL chart values file for a new installation: + + ```sh + helm show values mika/postgres > values.yaml + ``` -## How to add repo + Alternatively, get the values file of an existing PostgreSQL release: -Add the repo to your local helm client. + ```sh + helm get values ${releaseName} --namespace ${namespace} > values.yaml + ``` -```sh -helm repo add mika https://irfanhakim-as.github.io/charts -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Update the repo to retrieve the latest versions of the packages. +2. Edit your PostgreSQL values file with the intended configurations: -```sh -helm repo update -``` + ```sh + nano values.yaml + ``` -## How to install + Pay extra attention to the descriptions and sample values provided in the chart values file. -### Prepare chart values +3. Install a new release for PostgreSQL or upgrade an existing PostgreSQL release: -Copy `values.yaml` from the chart you would like to install. + ```sh + helm upgrade --install ${releaseName} mika/postgres --namespace ${namespace} --create-namespace --values values.yaml --wait + ``` -```sh -cp mika/postgres/values.yaml . -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Edit `values.yaml` with the appropriate values. Refer to the [Configurations](#Configurations) section for available options. +4. Verify that your PostgreSQL release has been installed: -```sh -nano values.yaml -``` + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -### Perform installation + Replace `${namespace}` and `${releaseName}` accordingly. This should return the release information if the release has been installed. -Install the desired chart. Replace `$release_name` and `$namespace` accordingly. +--- -```sh -helm install $release_name mika/postgres --namespace $namespace --create-namespace --values values.yaml --wait -``` +## How to uninstall a chart release -Verify that your chart has been installed. Replace `$namespace` and `$release_name` accordingly. +> [!CAUTION] +> Uninstalling a release will irreversibly delete all the resources associated with the release, including any persistent data. -```sh -helm ls --namespace $namespace | grep "$release_name" -``` +1. Uninstall the desired release: -## How to upgrade + ```sh + helm uninstall ${releaseName} --namespace ${namespace} --wait + ``` -After making any necessary changes to the `values.yaml` file, upgrade the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${releaseName}` and `${namespace}` accordingly. -```sh -helm upgrade $release_name mika/postgres --namespace $namespace --values values.yaml --wait -``` +2. Verify that the release has been uninstalled: -## How to uninstall + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -Uninstall the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${namespace}` and `${releaseName}` accordingly. This should return nothing if the release has been uninstalled. -```sh -helm uninstall $release_name --namespace $namespace --wait -``` +--- -## Configurations +## Chart configurations | Key | Type | Default | Description | |-----|------|---------|-------------| -| image.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the PostgreSQL container image. Default: `"IfNotPresent"`. | -| image.registry | string | `""` | The registry where the PostgreSQL container image is hosted. Default: `"docker.io"`. | -| image.repository | string | `""` | The name of the repository that contains the PostgreSQL container image used. Default: `"postgres"`. | -| image.tag | string | `""` | The tag that specifies the version of the PostgreSQL container image used. Default: `Chart appVersion`. | -| postgres.data.storage | string | `"1Gi"` | The amount of persistent storage allocated for the PostgreSQL instance. Default: `"1Gi"`. | -| postgres.data.storageClassName | string | `"longhorn"` | The storage class name used for dynamically provisioning a persistent volume for the PostgreSQL storage. Default: `"longhorn"`. | -| postgres.name | string | `""` | The name of the default PostgreSQL database. Default: `"default"`. | -| postgres.pass | string | `""` | The password for accessing the PostgreSQL instance. | -| postgres.user | string | `""` | The username for accessing the PostgreSQL instance. Default: `"root"`. | -| replicaCount | int | `""` | The desired number of running replicas for PostgreSQL. Default: `"1"`. | -| resources.limits.cpu | string | `"250m"` | The maximum amount of CPU resources allowed for PostgreSQL. | -| resources.limits.memory | string | `"250Mi"` | The maximum amount of memory allowed for PostgreSQL. | -| resources.requests.cpu | string | `"10m"` | The minimum amount of CPU resources required by PostgreSQL. | -| resources.requests.memory | string | `"100Mi"` | The minimum amount of memory required by PostgreSQL. | +| image.postgres.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the PostgreSQL container image. Default: `"IfNotPresent"`. | +| image.postgres.registry | string | `""` | The registry where the PostgreSQL container image is hosted. Default: `"docker.io"`. | +| image.postgres.repository | string | `""` | The name of the repository that contains the PostgreSQL container image used. Default: `"postgres"`. | +| image.postgres.tag | string | `""` | The tag that specifies the version of the PostgreSQL container image used. Default: `Chart appVersion`. | +| imagePullSecrets | list | `[]` | Credentials used to securely authenticate and authorise the pulling of container images from private registries. | +| ingress.clusterIssuer | string | `""` | The name of the cluster issuer for Ingress. Default: `"letsencrypt-dns-prod"`. | +| ingress.customAnnotations | list | `[]` | Additional configuration annotations to be added to the Ingress resource. Items: `.prefix`, `.name`, `.value`. | +| ingress.enabled | bool | `false` | Specifies whether Ingress should be enabled for hosting PostgreSQL services. | +| ingress.www | bool | `false` | Specifies whether the WWW subdomain should be enabled. | +| postgres.domain | string | `""` | The ingress domain name that hosts the PostgreSQL server. | +| postgres.name | string | `""` | The name of the default database of the root PostgreSQL database user. Default: `"default"`. | +| postgres.password | string | `""` | The password associated with the root PostgreSQL database user. | +| postgres.user | string | `""` | The root username or user account of the PostgreSQL database server. Default: `"root"`. | +| replicaCount | string | `""` | The desired number of running replicas for PostgreSQL. Default: `"1"`. | +| resources.postgres | object | `{}` | PostgreSQL container resources. | +| service.nodePort | string | `""` | The optional node port to expose when the service type is NodePort. | +| service.port | string | `""` | The port on which the PostgreSQL server should listen for connections. Default: `"5432"`. | +| service.type | string | `""` | The type of service used to expose PostgreSQL services. Default: `"ClusterIP"`. | +| storage.data.accessMode | string | `""` | The access mode defining how the data storage can be mounted. Default: `"ReadWriteMany"`. | +| storage.data.enabled | bool | `false` | Specifies whether persistent storage should be provisioned for data storage. | +| storage.data.mountPath | string | `""` | The path where the data storage should be mounted on the container. Default: `"/var/lib/postgresql/data"`. | +| storage.data.storage | string | `""` | The default amount of persistent storage allocated for the data storage. Default: `"1Gi"`. | +| storage.data.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the data storage. Default: `"longhorn"`. | +| storage.data.subPath | string | `""` | The subpath within the data storage to mount to the container. Leave empty if not required. | \ No newline at end of file diff --git a/mika/postgres/templates/NOTES.txt b/mika/postgres/templates/NOTES.txt index 1d671717..5bab21b8 100644 --- a/mika/postgres/templates/NOTES.txt +++ b/mika/postgres/templates/NOTES.txt @@ -1,5 +1,46 @@ -PostgreSQL is now installed and configured for {{ .Release.Name | toString }}. +{{- $serviceAddress := "" }} +{{- $ingress := .Values.ingress.enabled }} +{{- $domain := .Values.postgres.domain | toString }} +{{- $port := .Values.service.port | default "5432" | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +{{- $serviceName := printf "%s-postgres-svc" .Release.Name | toString }} +PostgreSQL has been installed and configured for {{ .Release.Name | toString }} 🎉 -See the values.yaml file of this chart for more configuration options. +{{- if $ingress }} + {{- $serviceAddress = printf "https://%s" $domain | toString }} +{{- else if or (eq $type "ClusterIP") (eq $type "LoadBalancer") (eq $type "NodePort") }} -Please refer to the official documentation for more information on how to use PostgreSQL. +Please run the following command(s) to obtain the right address to the service: + + ```sh + {{- if eq $type "ClusterIP" }} + {{- $forwardPort := "8080" | toString }} + {{- $serviceAddress = printf "http://127.0.0.1:%s" $forwardPort | toString }} + export POD_NAME=$(kubectl get pod --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "postgres.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} ${POD_NAME} -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + kubectl port-forward --namespace {{ .Release.Namespace }} ${POD_NAME} {{ $forwardPort }}:${CONTAINER_PORT} + {{- else if eq $type "LoadBalancer" }} + {{- $serviceAddress = printf "$(echo http://${SERVICE_IP}:%s)" $port | toString }} + export SERVICE_IP=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} --template "{{"{{- range (index .status.loadBalancer.ingress 0) }}{{ . }}{{- end }}"}}") + {{- else if eq $type "NodePort" }} + {{- $serviceAddress = "$(echo http://${NODE_IP}:${NODE_PORT})" | toString }} + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} -o jsonpath="{.spec.ports[0].nodePort}") + {{- end }} + ``` + +{{- end }} + +Visit the following service(s) at the provided address: + +{{- if $serviceAddress }} + + - PostgreSQL: {{ $serviceAddress }} + +{{- else }} + + ⚠️ This chart may have no accessible services available + +{{- end }} + +For more information on how to use and configure PostgreSQL, please refer to the official documentation. \ No newline at end of file diff --git a/mika/postgres/templates/deployment.yaml b/mika/postgres/templates/deployment.yaml index 9de7da90..4bf0d9cf 100644 --- a/mika/postgres/templates/deployment.yaml +++ b/mika/postgres/templates/deployment.yaml @@ -1,8 +1,12 @@ +{{- $dataPersistence := .Values.storage.data.enabled }} +{{- $postgres_registry := .Values.image.postgres.registry | default "docker.io" | toString }} +{{- $postgres_repository := .Values.image.postgres.repository | default "postgres" | toString }} +{{- $postgres_tag := .Values.image.postgres.tag | default .Chart.AppVersion | toString }} +{{- $postgres_pullPolicy := .Values.image.postgres.pullPolicy | default "IfNotPresent" | toString | quote }} {{- $replica_count := .Values.replicaCount | default "1" | toString }} -{{- $registry := .Values.image.registry | default "docker.io" | toString }} -{{- $repository := .Values.image.repository | default "postgres" | toString }} -{{- $tag := .Values.image.tag | default .Chart.AppVersion | toString }} -{{- $pullPolicy := .Values.image.pullPolicy | default "IfNotPresent" | toString | quote }} +{{- $dataMountPath := .Values.storage.data.mountPath | default "/var/lib/postgresql/data" | toString | quote }} +{{- $dataSubPath := .Values.storage.data.subPath | toString }} +--- apiVersion: apps/v1 kind: Deployment metadata: @@ -23,38 +27,40 @@ spec: labels: {{- include "postgres.selectorLabels" . | nindent 8 }} spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} containers: - name: postgres - image: {{ printf "%s/%s:%s" $registry $repository $tag | quote }} - imagePullPolicy: {{ $pullPolicy }} + image: {{ printf "%s/%s:%s" $postgres_registry $postgres_repository $postgres_tag | quote }} + imagePullPolicy: {{ $postgres_pullPolicy }} ports: - name: postgres containerPort: 5432 protocol: TCP resources: - {{- toYaml .Values.resources | nindent 12 }} - env: - - name: POSTGRES_DB - valueFrom: - secretKeyRef: - name: {{ .Release.Name }}-postgres-secret - key: DB_NAME - - name: POSTGRES_USER - valueFrom: - secretKeyRef: - name: {{ .Release.Name }}-postgres-secret - key: DB_USER - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: {{ .Release.Name }}-postgres-secret - key: DB_PASS - - name: PGDATA - value: /var/lib/postgresql/data/pgdata + {{- toYaml .Values.resources.postgres | nindent 12 }} + envFrom: + - secretRef: + name: {{ .Release.Name }}-postgres-secret + {{- if or $dataPersistence }} volumeMounts: + {{- if $dataPersistence }} - name: {{ .Release.Name }}-postgres-data - mountPath: /var/lib/postgresql/data + mountPath: {{ $dataMountPath }} + {{- if $dataSubPath }} + subPath: {{ $dataSubPath | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- if or $dataPersistence }} volumes: + {{- if $dataPersistence }} - name: {{ .Release.Name }}-postgres-data persistentVolumeClaim: claimName: {{ .Release.Name }}-postgres-data-pvc + {{- end }} + {{- end }} + securityContext: + fsGroup: 999 diff --git a/mika/postgres/templates/pvc.yaml b/mika/postgres/templates/pvc.yaml index 93e8a4db..a9da2beb 100644 --- a/mika/postgres/templates/pvc.yaml +++ b/mika/postgres/templates/pvc.yaml @@ -1,5 +1,9 @@ -{{- $storage := .Values.postgres.data.storage | default "1Gi" | toString | quote }} -{{- $storage_class_name := .Values.postgres.data.storageClassName | default "longhorn" | toString | quote }} +{{- $dataPersistence := .Values.storage.data.enabled }} +{{- $dataAccessMode := .Values.storage.data.accessMode | default "ReadWriteMany" | toString | quote }} +{{- $dataStorage := .Values.storage.data.storage | default "1Gi" | toString | quote }} +{{- $dataStorageClassName := .Values.storage.data.storageClassName | default "longhorn" | toString | quote }} +{{- if $dataPersistence }} +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -8,8 +12,9 @@ metadata: {{- include "postgres.labels" . | nindent 4 }} spec: accessModes: - - ReadWriteMany + - {{ $dataAccessMode }} resources: requests: - storage: {{ $storage }} - storageClassName: {{ $storage_class_name }} + storage: {{ $dataStorage }} + storageClassName: {{ $dataStorageClassName }} +{{- end }} diff --git a/mika/postgres/templates/secret.yaml b/mika/postgres/templates/secret.yaml index 700c9c15..2de74cfe 100644 --- a/mika/postgres/templates/secret.yaml +++ b/mika/postgres/templates/secret.yaml @@ -1,6 +1,8 @@ -{{- $postgres_name := .Values.postgres.name | default "default" | toString | b64enc }} -{{- $postgres_user := .Values.postgres.user | default "root" | toString | b64enc }} -{{- $postgres_pass := .Values.postgres.pass | toString | b64enc }} +{{- $postgresDB := .Values.postgres.name | default "default" | toString | b64enc }} +{{- $postgresUser := .Values.postgres.user | default "root" | toString | b64enc }} +{{- $postgresPassword := .Values.postgres.password | toString | b64enc }} +{{- $dataMountPath := .Values.storage.data.mountPath | default "/var/lib/postgresql/data" | toString }} +--- apiVersion: v1 kind: Secret metadata: @@ -9,6 +11,7 @@ metadata: {{- include "postgres.labels" . | nindent 4 }} type: Opaque data: - DB_NAME: {{ $postgres_name }} - DB_USER: {{ $postgres_user }} - DB_PASS: {{ $postgres_pass }} + POSTGRES_DB: {{ $postgresDB }} + POSTGRES_USER: {{ $postgresUser }} + POSTGRES_PASSWORD: {{ $postgresPassword }} + PGDATA: {{ printf "%s/pgdata" $dataMountPath | toString | b64enc }} diff --git a/mika/postgres/templates/service.yaml b/mika/postgres/templates/service.yaml index a097dbbe..56666814 100644 --- a/mika/postgres/templates/service.yaml +++ b/mika/postgres/templates/service.yaml @@ -1,3 +1,7 @@ +{{- $nodePort := .Values.service.nodePort | toString }} +{{- $port := .Values.service.port | default "5432" | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +--- apiVersion: v1 kind: Service metadata: @@ -5,11 +9,14 @@ metadata: labels: {{- include "postgres.labels" . | nindent 4 }} spec: - type: ClusterIP + type: {{ $type }} ports: - - port: 5432 + - port: {{ int $port }} targetPort: postgres + {{- if and (eq $type "NodePort") $nodePort }} + nodePort: {{ int $nodePort }} + {{- end }} protocol: TCP - name: {{ .Release.Name }}-postgres + name: postgres selector: {{- include "postgres.selectorLabels" . | nindent 4 }} diff --git a/mika/postgres/values.yaml b/mika/postgres/values.yaml index 145d2e9f..0ed12de9 100644 --- a/mika/postgres/values.yaml +++ b/mika/postgres/values.yaml @@ -6,69 +6,158 @@ # Default: "1" replicaCount: "" -# Container image used for PostgreSQL. +# Container images used for PostgreSQL. image: - # The registry where the PostgreSQL container image is hosted. - # Default: "docker.io" - registry: "" - # The name of the repository that contains the PostgreSQL container image used. - # Default: "postgres" - repository: "" - # The tag that specifies the version of the PostgreSQL container image used. - # Default: Chart appVersion - tag: "" - # The policy that determines when Kubernetes should pull the PostgreSQL container image. - # Default: "IfNotPresent" - pullPolicy: "" + # PostgreSQL container image configurations. + # Source: https://hub.docker.com/_/postgres + postgres: + # The registry where the PostgreSQL container image is hosted. + # Default: "docker.io" + registry: "" + # The name of the repository that contains the PostgreSQL container image used. + # Default: "postgres" + repository: "" + # The tag that specifies the version of the PostgreSQL container image used. + # Default: Chart appVersion + tag: "" + # The policy that determines when Kubernetes should pull the PostgreSQL container image. + # Default: "IfNotPresent" + pullPolicy: "" + +# Credentials used to securely authenticate and authorise the pulling of container images from private registries. +# Example: +# imagePullSecrets: +# - name: "ghcr-token-secret" +imagePullSecrets: [] # PostgreSQL configurations. postgres: - # The name of the default PostgreSQL database. + # The ingress domain name that hosts the PostgreSQL server. + # Example: + # domain: "postgres.example.com" + domain: "" + # The name of the default database of the root PostgreSQL database user. # Default: "default" # Example: - # name: "default" + # name: "postgres" name: "" - # The username for accessing the PostgreSQL instance. + # The root username or user account of the PostgreSQL database server. # Default: "root" # Example: - # user: "root" + # user: "postgres" user: "" - # The password for accessing the PostgreSQL instance. + # The password associated with the root PostgreSQL database user. + # Example: + # password: "password" + password: "" + +# Ingress configurations. +ingress: + # Specifies whether Ingress should be enabled for hosting PostgreSQL services. + # Example: + # enabled: true + enabled: false + # The name of the cluster issuer for Ingress. + # Default: "letsencrypt-dns-prod" + # Example: + # clusterIssuer: "letsencrypt-http-prod" + clusterIssuer: "" + # Specifies whether the WWW subdomain should be enabled. + # Example: + # www: true + www: false + # Additional configuration annotations to be added to the Ingress resource. + # Items: `.prefix`, `.name`, `.value` + # Example: + # customAnnotations: + # # The prefix of the annotation. + # # Default: "nginx.ingress.kubernetes.io" + # # Example: + # # prefix: "nginx.org" + # - prefix: "" + # # The name of the annotation. + # # Example: + # # name: "proxy-connect-timeout" + # name: "" + # # The value of the annotation. + # # Example: + # # value: "120" + # value: "" + customAnnotations: [] + +# Service configurations. +service: + # The optional node port to expose when the service type is NodePort. + # Example: + # nodePort: "32000" + nodePort: "" + # The port on which the PostgreSQL server should listen for connections. + # Default: "5432" + # Example: + # port: "8080" + port: "" + # The type of service used to expose PostgreSQL services. + # Default: "ClusterIP" # Example: - # pass: "password" - pass: "" - # PostgreSQL data configurations. + # type: "NodePort" + type: "" + +# Storage configurations. +storage: + # Data storage configurations. data: - # The amount of persistent storage allocated for the PostgreSQL instance. + # Specifies whether persistent storage should be provisioned for data storage. + # Example: + # enabled: true + enabled: false + # The access mode defining how the data storage can be mounted. + # Default: "ReadWriteMany" + # Example: + # accessMode: "ReadWriteOnce" + accessMode: "" + # The path where the data storage should be mounted on the container. + # Default: "/var/lib/postgresql/data" + # Example: + # mountPath: "/data" + mountPath: "" + # The subpath within the data storage to mount to the container. Leave empty if not required. + # Example: + # subPath: "Data" + subPath: "" + # The default amount of persistent storage allocated for the data storage. # Default: "1Gi" # Example: - # storage: "1Gi" + # storage: "10Gi" storage: "" - # The storage class name used for dynamically provisioning a persistent volume for the PostgreSQL storage. + # The storage class name used for dynamically provisioning a persistent volume for the data storage. # Default: "longhorn" # Example: - # storageClassName: "longhorn" + # storageClassName: "smb" storageClassName: "" -# Resource requirements and limits for PostgreSQL. +# Resource requirements and limits for PostgreSQL containers. resources: - # The minimum amount of resources required by PostgreSQL to run. - requests: - # The minimum amount of CPU resources required by PostgreSQL. - # Example: - # cpu: "10m" - cpu: "10m" - # The minimum amount of memory required by PostgreSQL. - # Example: - # memory: "10Mi" - memory: "100Mi" - # The maximum amount of resources allowed for PostgreSQL. - limits: - # The maximum amount of CPU resources allowed for PostgreSQL. - # Example: - # cpu: "250m" - cpu: "250m" - # The maximum amount of memory allowed for PostgreSQL. - # Example: - # memory: "250Mi" - memory: "250Mi" + # PostgreSQL container resources. + # Example: + # postgres: + # # The minimum amount of resources required by PostgreSQL to run. + # requests: + # # The minimum amount of CPU resources required by PostgreSQL. + # # Example: + # # cpu: "10m" + # cpu: "10m" + # # The minimum amount of memory required by PostgreSQL. + # # Example: + # # memory: "10Mi" + # memory: "100Mi" + # # The maximum amount of resources allowed for PostgreSQL. + # limits: + # # The maximum amount of CPU resources allowed for PostgreSQL. + # # Example: + # # cpu: "250m" + # cpu: "250m" + # # The maximum amount of memory allowed for PostgreSQL. + # # Example: + # # memory: "250Mi" + # memory: "250Mi" + postgres: {} diff --git a/mika/rizz/Chart.yaml b/mika/rizz/Chart.yaml index 2e4bd2fb..8f179b6f 100644 --- a/mika/rizz/Chart.yaml +++ b/mika/rizz/Chart.yaml @@ -1,13 +1,14 @@ apiVersion: v2 name: rizz -description: Rizz is a simple web application that tracks and posts content from RSS Feeds to Mastodon. +description: Rizz is a simple web application that tracks and posts content from RSS Feeds to federated social network. type: application -version: 0.1.2 -appVersion: "0.1.1-stable-r1" +version: 0.2.0 +appVersion: "0.2.0-stable-r2" keywords: - "rss" - "monitor" - "mastodon" + - "bluesky" home: "https://github.com/irfanhakim-as/rizz" icon: "https://irfanhakim-as.github.io/charts/logos/mika.png" sources: diff --git a/mika/rizz/README.md b/mika/rizz/README.md index 79650889..1314bea5 100644 --- a/mika/rizz/README.md +++ b/mika/rizz/README.md @@ -1,95 +1,230 @@ -# [`rizz`](https://github.com/irfanhakim-as/rizz) 🔒 +# [Rizz](https://github.com/irfanhakim-as/rizz) + +> [!WARNING] +> This chart requires access to a private image registry, please request access from the owner of the repository. + +Rizz is a simple web application that tracks and posts content from RSS Feeds to federated social network. ## Prerequisites +> [!NOTE] +> You may refer to [Orked](https://github.com/irfanhakim-as/orked) for help with setting up a Kubernetes cluster that meets all the following prerequisites. + - Kubernetes 1.19+ - Helm 3.2.0+ +- Longhorn 1.4.1+ + +--- ## Preflight checklist -### Create image pull secret +> [!IMPORTANT] +> The following items are required to be set up prior to installing this chart. + +### Image pull secret + +An image pull secret is required to access the private image registry that hosts the required image. + +1. If you have the necessary credentials, create a named image pull secret (i.e. `ghcr-token-secret`) in the `default` namespace: + + ```sh + kubectl create secret docker-registry ghcr-token-secret --docker-server= --docker-username= --docker-password= --docker-email= -n default + ``` + +2. Copy the image pull secret from the `default` namespace to the destination namespace: + + ```sh + kubectl get secret ghcr-token-secret -n default -o yaml | sed "s/namespace: .*/namespace: /" | kubectl apply -f - + ``` + +3. Add the name of the image pull secret to the `imagePullSecrets` array in your installation's values file: + + ```yaml + imagePullSecrets: + - name: "ghcr-token-secret" + ``` + +### Generate secret key + +A unique, secure secret key is required for each Rizz installation. + +1. Generate a secret key using the following command: + + ```sh + python -c 'import random; print("".join([random.choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for i in range(50)]))' + ``` + +2. Set the generated secret key as the value of the `rizz.secret` setting in your installation's values file: + + ```yaml + secret: "" + ``` + +### Application access token + +A secure application access token is required for each configured account. + +1. Follow the subsections below on how to generate an access token for each account. + +2. Set the access token as the value of the `rizz.account` account's `token` setting in your installation's values file: + + ```yaml + token: "" + ``` + + Replace `` with the account's generated access token. + +#### Mastodon + +1. Login to your Mastodon (bot) account. If you do not currently have one, you will need to register one first on any available Mastodon instance. + +2. Click the **Preferences** menu item. + +3. In the **Preferences** page, navigate to the **Development** section. + +4. From the **Your applications** list, click the **New application** button. + +5. In the **New application** form, fill in the following required details: + + - Application name: Add in a unique, descriptive name for your application i.e. `Rizz` + + - Scopes: + + - `read` + - `write` + +6. Click the **Save changes** button. + +7. After being redirected back to the **Your applications** page, click the link on the name of the application you just created. + +8. In the specific **Application** page, copy the value of the confidential **Your access token** field. + +#### Bluesky + +1. Login to your Bluesky (bot) account. If you do not currently have one, you will need to register one first on any available Bluesky instance. + +2. Click the **Settings** menu item. + +3. In the **Settings** page, navigate to the **App Passwords** section. + +4. In the **App Passwords** page, click the **Add App Password** button. + +5. In the prompted form, add in a unique, descriptive name for the App Password (i.e. `Rizz`) and click the **Create App Password** button to submit the form. + +6. Copy the value of the confidential App Password that has been generated and click the **Done** button. + +--- + +## Recommended configurations + +> [!NOTE] +> The following configuration recommendations might not be the default settings for this chart but are **highly recommended**. Please carefully consider them before configuring your installation. + +**This section does not apply to this chart.** + +--- + +## Application configurations + +> [!NOTE] +> The following configurations are expected or recommended to be set up from within the application after completing the installation. + +**This section does not apply to this chart.** + +--- + +## How to add the chart repo + +1. Add the repo to your local helm client: + + ```sh + helm repo add mika https://irfanhakim-as.github.io/charts + ``` + +2. Update the repo to retrieve the latest versions of the packages: + + ```sh + helm repo update + ``` + +--- -Replace `$github-username`, `$github-pass`, `$github-email` and `$namespace` accordingly. +## How to install or upgrade a chart release -```sh -kubectl create secret docker-registry ghcr-token-secret --docker-server=https://ghcr.io --docker-username="$github-username" --docker-password="$github-pass" --docker-email="$github-email" -n $namespace -``` +1. Get the values file of the Rizz chart or an existing installation (release). -### Generate secret key for `rizz.secret` + Get the latest Rizz chart values file for a new installation: -```sh -python -c 'import random; print("".join([random.choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for i in range(50)]))' -``` + ```sh + helm show values mika/rizz > values.yaml + ``` -## How to add repo + Alternatively, get the values file of an existing Rizz release: -Add the repo to your local helm client. + ```sh + helm get values ${releaseName} --namespace ${namespace} > values.yaml + ``` -```sh -helm repo add mika https://irfanhakim-as.github.io/charts -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Update the repo to retrieve the latest versions of the packages. +2. Edit your Rizz values file with the intended configurations: -```sh -helm repo update -``` + ```sh + nano values.yaml + ``` -## How to install + Pay extra attention to the descriptions and sample values provided in the chart values file. -### Prepare chart values +3. Install a new release for Rizz or upgrade an existing Rizz release: -Copy `values.yaml` from the chart you would like to install. + ```sh + helm upgrade --install ${releaseName} mika/rizz --namespace ${namespace} --create-namespace --values values.yaml --wait + ``` -```sh -cp mika/rizz/values.yaml . -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Edit `values.yaml` with the appropriate values. Refer to the [Configurations](#Configurations) section for available options. +4. Verify that your Rizz release has been installed: -```sh -nano values.yaml -``` + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -### Perform installation + Replace `${namespace}` and `${releaseName}` accordingly. This should return the release information if the release has been installed. -Install the desired chart. Replace `$release_name` and `$namespace` accordingly. +--- -```sh -helm install $release_name mika/rizz --namespace $namespace --create-namespace --values values.yaml --wait -``` +## How to uninstall a chart release -Verify that your chart has been installed. Replace `$namespace` and `$release_name` accordingly. +> [!CAUTION] +> Uninstalling a release will irreversibly delete all the resources associated with the release, including any persistent data. -```sh -helm ls --namespace $namespace | grep "$release_name" -``` +1. Uninstall the desired release: -## How to upgrade + ```sh + helm uninstall ${releaseName} --namespace ${namespace} --wait + ``` -After making any necessary changes to the `values.yaml` file, upgrade the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${releaseName}` and `${namespace}` accordingly. -```sh -helm upgrade $release_name mika/rizz --namespace $namespace --values values.yaml --wait -``` +2. Verify that the release has been uninstalled: -## How to uninstall + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -Uninstall the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${namespace}` and `${releaseName}` accordingly. This should return nothing if the release has been uninstalled. -```sh -helm uninstall $release_name --namespace $namespace --wait -``` +--- -## Configurations +## Chart configurations | Key | Type | Default | Description | |-----|------|---------|-------------| | db.host | string | `""` | The hostname or IP address of the Rizz database server. | -| db.name | string | `""` | The name of the database used by Rizz. | -| db.password | string | `""` | The password associated with the Rizz database's user. | -| db.port | string | `""` | The port number on which the Rizz database server is listening. Default: `"5432"`. | -| db.type | string | `""` | The type of the database used by Rizz. Default: `"postgresql"`. | +| db.name | string | `""` | The name of the database being used by Rizz. | +| db.password | string | `""` | The password associated with the Rizz database user. | +| db.port | string | `""` | The port number the Rizz database server is listening for connections. Default: `"5432"`. | +| db.type | string | `""` | The database engine or backend being used by Rizz. Default: `"postgresql"`. | | db.user | string | `""` | The username or user account for accessing the Rizz database. | | image.redis.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the Redis container image. Default: `"IfNotPresent"`. | | image.redis.registry | string | `""` | The registry where the Redis container image is hosted. Default: `"docker.io"`. | @@ -100,36 +235,43 @@ helm uninstall $release_name --namespace $namespace --wait | image.rizz.repository | string | `""` | The name of the repository that contains the Rizz container image used. Default: `"irfanhakim-as/rizz"`. | | image.rizz.tag | string | `""` | The tag that specifies the version of the Rizz container image used. Default: `Chart appVersion`. | | imagePullSecrets | list | `[]` | Credentials used to securely authenticate and authorise the pulling of container images from private registries. | +| ingress.clusterIssuer | string | `""` | The name of the cluster issuer for Ingress. Default: `"letsencrypt-dns-prod"`. | +| ingress.customAnnotations | list | `[]` | Additional configuration annotations to be added to the Ingress resource. Items: `.prefix`, `.name`, `.value`. | +| ingress.enabled | bool | `false` | Specifies whether Ingress should be enabled for hosting Rizz services. | +| ingress.www | bool | `false` | Specifies whether the WWW subdomain should be enabled. | | replicaCount | string | `""` | The desired number of running replicas for Rizz. Default: `"1"`. | -| resources.rizz.limits.cpu | string | `"50m"` | The maximum amount of CPU resources allowed for Rizz. | -| resources.rizz.limits.memory | string | `"120Mi"` | The maximum amount of memory allowed for Rizz. | -| resources.rizz.requests.cpu | string | `"30m"` | The minimum amount of CPU resources required by Rizz. | -| resources.rizz.requests.memory | string | `"60Mi"` | The minimum amount of memory required by Rizz. | -| resources.scheduler.limits.cpu | string | `"20m"` | The maximum amount of CPU resources allowed for Scheduler. | -| resources.scheduler.limits.memory | string | `"200Mi"` | The maximum amount of memory allowed for Scheduler. | -| resources.scheduler.requests.cpu | string | `"10m"` | The minimum amount of CPU resources required by Scheduler. | -| resources.scheduler.requests.memory | string | `"100Mi"` | The minimum amount of memory required by Scheduler. | -| rizz.debug | bool | `false` | Specifies whether Rizz should run in debug mode. Default: `false`. | -| rizz.domain | string | `""` | The domain name of the Rizz service. Default: `"localhost"`. | -| rizz.feed | list | `[]` | Rizz feed configurations. | -| rizz.mastodon | list | `[]` | Rizz Mastodon configurations. | -| rizz.organic | bool | `true` | Specifies whether to enable posting in organic numbers. Default: `true`. | -| rizz.persistence.enabled | bool | `false` | Specifies whether Rizz should persist its storage. | -| rizz.persistence.logs.storage | string | `""` | The amount of persistent storage allocated for Rizz logs. Default: `"20Mi"`. | -| rizz.persistence.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the Rizz storage. Default: `"longhorn"`. | +| resources.rizz | object | `{}` | Rizz container resources. | +| resources.scheduler | object | `{}` | Scheduler container resources. | +| rizz.account | list | `[]` | Account configurations. Items: `.api`, `.id`, `.host`, `.token`, `.bot`, `.discoverable`, `.enabled`, `.display_name`, `.fields`, `.locked`, `.note`. | +| rizz.debug | string | `""` | Specifies whether Rizz should run in debug mode. Default: `"false"`. | +| rizz.domain | string | `""` | The ingress domain name that hosts the Rizz server. Default: `"localhost"`. | +| rizz.feed | list | `[]` | RSS feed configurations. Items: `.endpoint`, `.id`, `.enabled`. | +| rizz.organic | string | `""` | Specifies whether to enable posting in organic numbers. Default: `"true"`. | | rizz.post_limit | string | `""` | The limit number of posts to be scheduled for posting per run. Default: `"3"`. | -| rizz.retry_post | bool | `true` | Specifies whether to retry posting if the post fails to be sent. Default: `true`. | -| rizz.scheduler.apscheduler | bool | `true` | Specifies whether APScheduler should be used by Rizz as the task scheduler. | -| rizz.scheduler.celery | bool | `false` | Specifies whether Celery should be used by Rizz as the task scheduler. | -| rizz.scheduler.schedule.clean_data.hour | string | `""` | The hours at which the task scheduler cleans up the database. Default: `"0"`. | -| rizz.scheduler.schedule.clean_data.minute | string | `""` | The minutes at which the task scheduler cleans up the database. Default: `"0"`. | -| rizz.scheduler.schedule.clean_data.second | string | `""` | The seconds at which the task scheduler cleans up the database. Default: `"0"` for `apscheduler`. | -| rizz.scheduler.schedule.post_scheduler.hour | string | `""` | The hours at which the task scheduler posts scheduled posts. Default: `"8-23/3"`. | -| rizz.scheduler.schedule.post_scheduler.minute | string | `""` | The minutes at which the task scheduler posts scheduled posts. Default: `"0"`. | -| rizz.scheduler.schedule.post_scheduler.second | string | `""` | The seconds at which the task scheduler posts scheduled posts. Default: `"0"` for `apscheduler`. | -| rizz.scheduler.schedule.update_data.hour | string | `""` | The hours at which the task scheduler updates the database. Default: `"7-22/3"`. | -| rizz.scheduler.schedule.update_data.minute | string | `""` | The minutes at which the task scheduler updates the database. Default: `"0"`. | -| rizz.scheduler.schedule.update_data.second | string | `""` | The seconds at which the task scheduler updates the database. Default: `"0"` for `apscheduler`. | -| rizz.scheduler.timezone | string | `""` | The timezone for the task scheduler used by Rizz to schedule time-dependent operations. Default: `"Asia/Kuala_Lumpur"`. | +| rizz.retry_post | string | `""` | Specifies whether to retry posting if the post fails to be sent. Default: `"true"`. | | rizz.secret | string | `""` | A 50-character secret key used for secure session management and cryptographic operations within the Rizz service. | +| rizz.serverAdmin | string | `""` | The email address displayed by Apache for server administration contact. Default: `"admin@example.com"`. | | rizz.visibility | string | `""` | The default visibility of posts made by the Rizz service. Default: `"public"`. | +| scheduler.apscheduler | bool | `true` | Specifies whether APScheduler should be used by Rizz as the task scheduler. | +| scheduler.celery | bool | `false` | Specifies whether Celery should be used by Rizz as the task scheduler. | +| scheduler.schedule.clean_data.hour | string | `""` | The hours at which the task scheduler cleans up the database. Default: `"0"`. | +| scheduler.schedule.clean_data.minute | string | `""` | The minutes at which the task scheduler cleans up the database. Default: `"0"`. | +| scheduler.schedule.clean_data.second | string | `""` | The seconds at which the task scheduler cleans up the database. Default: `"0"` (`apscheduler`). | +| scheduler.schedule.post_scheduler.hour | string | `""` | The hours at which the task scheduler posts scheduled posts. Default: `"8-23/3"`. | +| scheduler.schedule.post_scheduler.minute | string | `""` | The minutes at which the task scheduler posts scheduled posts. Default: `"0"`. | +| scheduler.schedule.post_scheduler.second | string | `""` | The seconds at which the task scheduler posts scheduled posts. Default: `"0"` (`apscheduler`). | +| scheduler.schedule.update_data.hour | string | `""` | The hours at which the task scheduler updates the database. Default: `"7-22/3"`. | +| scheduler.schedule.update_data.minute | string | `""` | The minutes at which the task scheduler updates the database. Default: `"0"`. | +| scheduler.schedule.update_data.second | string | `""` | The seconds at which the task scheduler updates the database. Default: `"0"` (`apscheduler`). | +| scheduler.timezone | string | `""` | The timezone for the task scheduler used by Rizz to schedule time-dependent operations. Default: `"Etc/UTC"`. | +| service.redis.nodePort | string | `""` | The optional node port to expose for Redis when the service type is NodePort. | +| service.redis.port | string | `""` | The Redis port on which the Rizz server should listen for connections. Default: `"6379"`. | +| service.rizz.nodePort | string | `""` | The optional node port to expose for Rizz when the service type is NodePort. | +| service.rizz.port | string | `""` | The Rizz port on which the Rizz server should listen for connections. Default: `"80"`. | +| service.type | string | `""` | The type of service used to expose Rizz services. Default: `"ClusterIP"`. | +| storage.log.accessMode | string | `""` | The access mode defining how the log storage can be mounted. Default: `"ReadWriteMany"`. | +| storage.log.enabled | bool | `false` | Specifies whether persistent storage should be provisioned for log storage. | +| storage.log.mountPath | string | `""` | The path where the log storage should be mounted on the container. Default: `"/var/log/apache2"`. | +| storage.log.storage | string | `""` | The default amount of persistent storage allocated for the log storage. Default: `"50Mi"`. | +| storage.log.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the log storage. Default: `"longhorn"`. | +| storage.log.subPath | string | `""` | The subpath within the log storage to mount to the container. Leave empty if not required. | \ No newline at end of file diff --git a/mika/rizz/templates/NOTES.txt b/mika/rizz/templates/NOTES.txt index 55be8054..124c454f 100644 --- a/mika/rizz/templates/NOTES.txt +++ b/mika/rizz/templates/NOTES.txt @@ -1,5 +1,105 @@ -rizz is now installed and configured for {{ .Release.Name | toString }}. +{{- $serviceAddress := "" }} +{{- $accounts := .Values.rizz.account }} +{{- $feeds := .Values.rizz.feed }} +{{- $ingress := .Values.ingress.enabled }} +{{- $domain := .Values.rizz.domain | toString }} +{{- $rizzPort := .Values.service.rizz.port | default "80" | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +{{- $serviceName := printf "%s-rizz-svc" .Release.Name | toString }} +Rizz has been installed and configured for {{ .Release.Name | toString }} 🎉 -See the values.yaml file of this chart for more configuration options. +{{- if $ingress }} + {{- $serviceAddress = printf "https://%s" $domain | toString }} +{{- else if or (eq $type "ClusterIP") (eq $type "LoadBalancer") (eq $type "NodePort") }} -Please refer to the official documentation for more information on how to use rizz. +Please run the following command(s) to obtain the right address to the service: + + ```sh + {{- if eq $type "ClusterIP" }} + {{- $forwardPort := "8080" | toString }} + {{- $serviceAddress = printf "http://127.0.0.1:%s" $forwardPort | toString }} + export POD_NAME=$(kubectl get pod --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "rizz.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} ${POD_NAME} -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + kubectl port-forward --namespace {{ .Release.Namespace }} ${POD_NAME} {{ $forwardPort }}:${CONTAINER_PORT} + {{- else if eq $type "LoadBalancer" }} + {{- $serviceAddress = printf "$(echo http://${SERVICE_IP}:%s)" $rizzPort | toString }} + export SERVICE_IP=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} --template "{{"{{- range (index .status.loadBalancer.ingress 0) }}{{ . }}{{- end }}"}}") + {{- else if eq $type "NodePort" }} + {{- $serviceAddress = "$(echo http://${NODE_IP}:${NODE_PORT})" | toString }} + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} -o jsonpath="{.spec.ports[0].nodePort}") + {{- end }} + ``` + +{{- end }} + +Visit the following service(s) at the provided address: + +{{- if $serviceAddress }} + + - Rizz: {{ $serviceAddress }} + +{{- else }} + + ⚠️ This chart may have no accessible services available + +{{- end }} + +The following are a list of account(s) you have supplied to be managed: + +{{- if not $accounts }} + + ⚠️ No accounts were supplied for Rizz to manage + +{{- else }} + + {{- range $index, $account := $accounts }} + {{- $enabled := $account.enabled | default "true" | toString }} + {{- $api := $account.api | toString }} + {{- $id := $account.id | toString }} + {{- $url := printf "%s/%s" ($api | trimSuffix "/") $id | toString }} + {{- $entry := printf "%s. %s (%s)" ($index | add1 | toString) $id $url | toString }} + + {{- if eq $enabled "true" }} + + {{ $entry }} + + {{- else }} + + {{ printf "%s [%s]" $entry "disabled" }} + + {{- end }} + + {{- end }} + +The following are a list of RSS feed(s) you have supplied to be monitored: + + {{- if not $feeds }} + + ⚠️ No RSS feeds were supplied for Rizz to monitor + + {{- else }} + + {{- range $index, $feed := $feeds }} + {{- $enabled := $feed.enabled | default "true" | toString }} + {{- $uid := $feed.id | toString }} + {{- $endpoint := $feed.endpoint | toString | trimSuffix "/" }} + {{- $entry := printf "%s. %s (%s)" ($index | add1 | toString) $uid $endpoint | toString }} + + {{- if eq $enabled "true" }} + + {{ $entry }} + + {{- else }} + + {{ printf "%s [%s]" $entry "disabled" }} + + {{- end }} + + {{- end }} + + {{- end }} + +{{- end }} + +For more information on how to use and configure Rizz, please refer to the official documentation. \ No newline at end of file diff --git a/mika/rizz/templates/accounts.json.tpl b/mika/rizz/templates/accounts.json.tpl index 834d21c5..aeafa22e 100644 --- a/mika/rizz/templates/accounts.json.tpl +++ b/mika/rizz/templates/accounts.json.tpl @@ -1,10 +1,10 @@ {{/* -Mastodon /base/lib/accounts.json template +Rizz /base/lib/accounts.json template */}} {{- define "rizz.accounts-json" -}} { "accounts": [ - {{- $accounts := .Values.rizz.mastodon }} + {{- $accounts := .Values.rizz.account }} {{- range $index, $account := $accounts }} {{- $normalised_api := $account.api | toString | replace "https" "" | replace ":" "" | replace "/" "" | replace "." "-" }} {{- $token_secret := printf "%s-%s.secret" $account.id $normalised_api | toString | replace " " "" }} @@ -29,6 +29,7 @@ Mastodon /base/lib/accounts.json template ]{{ if ne $i (sub (len $fields) 1) }},{{ end }} {{- end }} ], + "host": {{ $account.host | default "mastodon" | toString | quote }}, "is_locked": {{ $account.locked | default "false" | toString }}, {{- if $account.note }} "note": {{ $account.note | toString | quote }} diff --git a/mika/rizz/templates/celery.py.tpl b/mika/rizz/templates/celery.py.tpl index 91150a25..de8a5c2f 100644 --- a/mika/rizz/templates/celery.py.tpl +++ b/mika/rizz/templates/celery.py.tpl @@ -3,21 +3,22 @@ Celery /base/base/celery.py template */}} {{- define "rizz.celery-py" -}} -{{- $clean_data_hour := .Values.rizz.scheduler.schedule.clean_data.hour | default "0" | toString -}} -{{- $clean_data_minute := .Values.rizz.scheduler.schedule.clean_data.minute | default "0" | toString -}} -{{- $clean_data_second := .Values.rizz.scheduler.schedule.clean_data.second | toString -}} -{{- $post_scheduler_hour := .Values.rizz.scheduler.schedule.post_scheduler.hour | default "8-23/3" | toString -}} -{{- $post_scheduler_minute := .Values.rizz.scheduler.schedule.post_scheduler.minute | default "0" | toString -}} -{{- $post_scheduler_second := .Values.rizz.scheduler.schedule.post_scheduler.second | toString -}} -{{- $update_data_hour := .Values.rizz.scheduler.schedule.update_data.hour | default "7-22/3" | toString -}} -{{- $update_data_minute := .Values.rizz.scheduler.schedule.update_data.minute | default "0" | toString -}} -{{- $update_data_second := .Values.rizz.scheduler.schedule.update_data.second | toString -}} +{{- $clean_data_hour := .Values.scheduler.schedule.clean_data.hour | default "0" | toString -}} +{{- $clean_data_minute := .Values.scheduler.schedule.clean_data.minute | default "0" | toString -}} +{{- $clean_data_second := .Values.scheduler.schedule.clean_data.second | toString -}} +{{- $post_scheduler_hour := .Values.scheduler.schedule.post_scheduler.hour | default "8-23/3" | toString -}} +{{- $post_scheduler_minute := .Values.scheduler.schedule.post_scheduler.minute | default "0" | toString -}} +{{- $post_scheduler_second := .Values.scheduler.schedule.post_scheduler.second | toString -}} +{{- $update_data_hour := .Values.scheduler.schedule.update_data.hour | default "7-22/3" | toString -}} +{{- $update_data_minute := .Values.scheduler.schedule.update_data.minute | default "0" | toString -}} +{{- $update_data_second := .Values.scheduler.schedule.update_data.second | toString -}} from __future__ import absolute_import, unicode_literals import os import re from celery import Celery from celery.schedules import crontab +from datetime import timedelta os.environ.setdefault("DJANGO_SETTINGS_MODULE", "base.conf.main") app = Celery("base") app.config_from_object("django.conf:settings", namespace="CELERY") @@ -26,8 +27,8 @@ app.autodiscover_tasks() app.conf.beat_schedule = { # clean data - "clean_data" : { - "task" : "base.tasks.clean_data_task", + "clean_data": { + "task": "base.tasks.clean_data_task", {{- if $clean_data_second }} "schedule": timedelta(seconds=int(re.sub(r"\D", "", {{ $clean_data_second | quote }}))), {{- else }} @@ -35,8 +36,8 @@ app.conf.beat_schedule = { {{- end }} }, # check for any posts that need to be posted - "post_scheduler" : { - "task" : "base.tasks.post_scheduler_task", + "post_scheduler": { + "task": "base.tasks.post_scheduler_task", {{- if $post_scheduler_second }} "schedule": timedelta(seconds=int(re.sub(r"\D", "", {{ $post_scheduler_second | quote }}))), {{- else }} @@ -44,8 +45,8 @@ app.conf.beat_schedule = { {{- end }} }, # update data - "update_data" : { - "task" : "base.tasks.update_data_task", + "update_data": { + "task": "base.tasks.update_data_task", {{- if $update_data_second }} "schedule": timedelta(seconds=int(re.sub(r"\D", "", {{ $update_data_second | quote }}))), {{- else }} diff --git a/mika/rizz/templates/configmap.yaml b/mika/rizz/templates/configmap.yaml index 5a5a41b4..7691ab96 100644 --- a/mika/rizz/templates/configmap.yaml +++ b/mika/rizz/templates/configmap.yaml @@ -1,13 +1,16 @@ +{{- $apscheduler := .Values.scheduler.apscheduler }} +{{- $celery := .Values.scheduler.celery }} {{- $debug := .Values.rizz.debug | default "false" | toString | quote }} -{{- $scheduler_timezone := .Values.rizz.scheduler.timezone | default "Asia/Kuala_Lumpur" | toString | quote }} +{{- $scheduler_timezone := .Values.scheduler.timezone | default "Etc/UTC" | toString | quote }} {{- $visibility := .Values.rizz.visibility | default "public" | toString | quote }} {{- $organic := .Values.rizz.organic | default "true" | toString | quote }} {{- $post_limit := .Values.rizz.post_limit | default "3" | toString | quote }} {{- $retry_post := .Values.rizz.retry_post | default "true" | toString | quote }} {{- $redis_service := printf "redis://%s-rizz-svc" .Release.Name | quote }} {{- $domain := .Values.rizz.domain | default "localhost" | toString }} -{{- $apscheduler := .Values.rizz.scheduler.apscheduler }} -{{- $celery := .Values.rizz.scheduler.celery }} +{{- $serverAdmin := .Values.rizz.serverAdmin | default "admin@example.com" | toString }} +{{- $logMountPath := .Values.storage.log.mountPath | default "/var/log/apache2" | toString }} +--- apiVersion: v1 kind: ConfigMap metadata: @@ -36,7 +39,7 @@ metadata: {{- include "rizz.labels" . | nindent 4 }} data: site-config.conf: |- - {{- include "rizz.site-config-conf" . | replace "DOMAIN" $domain | nindent 4 }} + {{- include "rizz.site-config-conf" . | toString | replace "DOMAIN" $domain | replace "SERVER_ADMIN" $serverAdmin | replace "LOG_MOUNT_PATH" $logMountPath | nindent 4 }} --- apiVersion: v1 kind: ConfigMap @@ -57,7 +60,7 @@ metadata: {{- include "rizz.labels" . | nindent 4 }} data: entrypoint.sh: |- - {{- include "rizz.apscheduler-entrypoint-sh" . | nindent 4 }} + {{- include "rizz.apscheduler-entrypoint-sh" . | toString | nindent 4 }} {{- else if $celery }} --- apiVersion: v1 @@ -68,7 +71,7 @@ metadata: {{- include "rizz.labels" . | nindent 4 }} data: celeryd: |- - {{- include "rizz.default-celeryd" . | nindent 4 }} + {{- include "rizz.default-celeryd" . | toString | nindent 4 }} --- apiVersion: v1 kind: ConfigMap @@ -78,9 +81,9 @@ metadata: {{- include "rizz.labels" . | nindent 4 }} data: celerybeat: |- - {{- include "rizz.initd-celerybeat" . | nindent 4 }} + {{- include "rizz.initd-celerybeat" . | toString | nindent 4 }} celeryd: |- - {{- include "rizz.initd-celeryd" . | nindent 4 }} + {{- include "rizz.initd-celeryd" . | toString | nindent 4 }} {{- end }} {{- if or $apscheduler $celery }} --- @@ -93,17 +96,17 @@ metadata: data: {{- if $apscheduler }} apps.py: |- - {{- include "rizz.apscheduler-apps-py" . | nindent 4 }} + {{- include "rizz.apscheduler-apps-py" . | toString | nindent 4 }} {{- else if $celery }} celery.py: |- - {{- include "rizz.celery-py" . | nindent 4 }} + {{- include "rizz.celery-py" . | toString | nindent 4 }} init.py: |- - {{- include "rizz.celery-init-py" . | nindent 4 }} + {{- include "rizz.celery-init-py" . | toString | nindent 4 }} {{- end }} tasks.py: |- {{- if $apscheduler }} - {{- include "rizz.apscheduler-tasks-py" . | nindent 4 }} + {{- include "rizz.apscheduler-tasks-py" . | toString | nindent 4 }} {{- else if $celery }} - {{- include "rizz.celery-tasks-py" . | nindent 4 }} + {{- include "rizz.celery-tasks-py" . | toString | nindent 4 }} {{- end }} {{- end }} diff --git a/mika/rizz/templates/deployment.yaml b/mika/rizz/templates/deployment.yaml index bf1086bd..cb086cba 100644 --- a/mika/rizz/templates/deployment.yaml +++ b/mika/rizz/templates/deployment.yaml @@ -1,5 +1,7 @@ -{{- $release_name := .Release.Name | toString }} -{{- $replica_count := .Values.replicaCount | default "1" | toString }} +{{- $accounts := .Values.rizz.account }} +{{- $apscheduler := .Values.scheduler.apscheduler }} +{{- $celery := .Values.scheduler.celery }} +{{- $logPersistence := .Values.storage.log.enabled }} {{- $rizz_registry := .Values.image.rizz.registry | default "ghcr.io" | toString }} {{- $rizz_repository := .Values.image.rizz.repository | default "irfanhakim-as/rizz" | toString }} {{- $rizz_tag := .Values.image.rizz.tag | default .Chart.AppVersion | toString }} @@ -8,9 +10,10 @@ {{- $redis_repository := .Values.image.redis.repository | default "redis" | toString }} {{- $redis_tag := .Values.image.redis.tag | default "alpine" | toString }} {{- $redis_pullPolicy := .Values.image.redis.pullPolicy | default "IfNotPresent" | toString | quote }} -{{- $apscheduler := .Values.rizz.scheduler.apscheduler }} -{{- $celery := .Values.rizz.scheduler.celery }} -{{- $persistence := .Values.rizz.persistence.enabled }} +{{- $release_name := .Release.Name | toString }} +{{- $replica_count := .Values.replicaCount | default "1" | toString }} +{{- $logMountPath := .Values.storage.log.mountPath | default "/var/log/apache2" | toString | quote }} +{{- $logSubPath := .Values.storage.log.subPath | toString }} apiVersion: apps/v1 kind: Deployment metadata: @@ -55,14 +58,14 @@ spec: mountPath: /etc/apache2/sites-available/000-default.conf subPath: site-config.conf readOnly: true + - name: {{ .Release.Name }}-rizz-account-config + mountPath: /base/data/accounts.json + subPath: accounts.json + readOnly: true - name: {{ .Release.Name }}-rizz-feed-config mountPath: /base/data/feeds.json subPath: feeds.json readOnly: true - - name: {{ .Release.Name }}-rizz-mastodon-config - mountPath: /base/data/accounts.json - subPath: accounts.json - readOnly: true {{- if $celery }} - name: {{ .Release.Name }}-rizz-default-celery-config mountPath: /etc/default/celeryd @@ -83,7 +86,7 @@ spec: mountPath: /base/base/__init__.py subPath: init.py {{- end }} - {{- range .Values.rizz.mastodon }} + {{- range $accounts }} {{- $normalised_api := .api | toString | replace "https" "" | replace ":" "" | replace "/" "" | replace "." "-" }} {{- $token_secret := printf "%s-%s.secret" .id $normalised_api | toString | replace " " "" }} - name: {{ $release_name }}-rizz-token-secret @@ -91,9 +94,12 @@ spec: subPath: {{ $token_secret }} readOnly: true {{- end }} - {{- if $persistence }} - - name: {{ .Release.Name }}-rizz-logs - mountPath: /var/log/apache2 + {{- if $logPersistence }} + - name: {{ .Release.Name }}-rizz-log + mountPath: {{ $logMountPath }} + {{- if $logSubPath }} + subPath: {{ $logSubPath | quote }} + {{- end }} {{- end }} {{- if $apscheduler }} - name: apscheduler @@ -111,14 +117,14 @@ spec: - secretRef: name: {{ .Release.Name }}-rizz-secret volumeMounts: + - name: {{ .Release.Name }}-rizz-account-config + mountPath: /base/data/accounts.json + subPath: accounts.json + readOnly: true - name: {{ .Release.Name }}-rizz-feed-config mountPath: /base/data/feeds.json subPath: feeds.json readOnly: true - - name: {{ .Release.Name }}-rizz-mastodon-config - mountPath: /base/data/accounts.json - subPath: accounts.json - readOnly: true - name: {{ .Release.Name }}-rizz-apscheduler-config mountPath: /entrypoint.sh subPath: entrypoint.sh @@ -128,7 +134,7 @@ spec: - name: {{ .Release.Name }}-rizz-scheduler-config mountPath: /base/base/tasks.py subPath: tasks.py - {{- range .Values.rizz.mastodon }} + {{- range $accounts }} {{- $normalised_api := .api | toString | replace "https" "" | replace ":" "" | replace "/" "" | replace "." "-" }} {{- $token_secret := printf "%s-%s.secret" .id $normalised_api | toString | replace " " "" }} - name: {{ $release_name }}-rizz-token-secret @@ -136,9 +142,12 @@ spec: subPath: {{ $token_secret }} readOnly: true {{- end }} - {{- if $persistence }} - - name: {{ .Release.Name }}-rizz-logs - mountPath: /var/log/apache2 + {{- if $logPersistence }} + - name: {{ .Release.Name }}-rizz-log + mountPath: {{ $logMountPath }} + {{- if $logSubPath }} + subPath: {{ $logSubPath | quote }} + {{- end }} {{- end }} {{- else if $celery }} - name: redis @@ -155,12 +164,12 @@ spec: - name: {{ .Release.Name }}-rizz-site-config configMap: name: {{ .Release.Name }}-rizz-site-config + - name: {{ .Release.Name }}-rizz-account-config + secret: + secretName: {{ .Release.Name }}-rizz-account-config - name: {{ .Release.Name }}-rizz-feed-config configMap: name: {{ .Release.Name }}-rizz-feed-config - - name: {{ .Release.Name }}-rizz-mastodon-config - secret: - secretName: {{ .Release.Name }}-rizz-mastodon-config {{- if $apscheduler }} - name: {{ .Release.Name }}-rizz-apscheduler-config configMap: @@ -205,22 +214,22 @@ spec: - key: tasks.py path: tasks.py {{- end }} - {{- if .Values.rizz.mastodon }} + {{- if $accounts }} - name: {{ .Release.Name }}-rizz-token-secret secret: secretName: {{ .Release.Name }}-rizz-token-secret items: - {{- range .Values.rizz.mastodon }} + {{- range $accounts }} {{- $normalised_api := .api | toString | replace "https" "" | replace ":" "" | replace "/" "" | replace "." "-" }} {{- $token_secret := printf "%s-%s.secret" .id $normalised_api | toString | replace " " "" }} - key: {{ $token_secret }} path: {{ $token_secret }} {{- end }} {{- end }} - {{- if $persistence }} - - name: {{ .Release.Name }}-rizz-logs + {{- if $logPersistence }} + - name: {{ .Release.Name }}-rizz-log persistentVolumeClaim: - claimName: {{ .Release.Name }}-rizz-logs-pvc + claimName: {{ .Release.Name }}-rizz-log-pvc {{- end }} securityContext: fsGroup: 33 diff --git a/mika/rizz/templates/feeds.json.tpl b/mika/rizz/templates/feeds.json.tpl index ef69dbd7..c7b041cc 100644 --- a/mika/rizz/templates/feeds.json.tpl +++ b/mika/rizz/templates/feeds.json.tpl @@ -1,5 +1,5 @@ {{/* -Mastodon /base/lib/feeds.json template +Rizz /base/lib/feeds.json template */}} {{- define "rizz.feeds-json" -}} { @@ -9,8 +9,7 @@ Mastodon /base/lib/feeds.json template { "uid": {{ $feed.id | toString | quote }}, "endpoint": {{ $feed.endpoint | toString | quote }}, - "is_enabled": {{ $feed.enabled | default "true" | toString }}, - "date_format": {{ $feed.pubdate_format | default "%a, %d %b %Y %H:%M:%S %z" | toString | quote }} + "is_enabled": {{ $feed.enabled | default "true" | toString }} }{{ if ne $index (sub (len $feeds) 1) }},{{ end }} {{- end }} ] diff --git a/mika/rizz/templates/ingress.yaml b/mika/rizz/templates/ingress.yaml new file mode 100644 index 00000000..247b7e1e --- /dev/null +++ b/mika/rizz/templates/ingress.yaml @@ -0,0 +1,60 @@ +{{- $ingress := .Values.ingress.enabled }} +{{- $www := .Values.ingress.www }} +{{- $clusterIssuer := .Values.ingress.clusterIssuer | default "letsencrypt-dns-prod" | toString | quote }} +{{- $customAnnotations := .Values.ingress.customAnnotations }} +{{- $domain := .Values.rizz.domain | toString }} +{{- $wwwDomain := printf "www.%s" $domain | toString | quote }} +{{- if and $ingress $domain }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-rizz-ingress + labels: + {{- include "rizz.labels" . | nindent 4 }} + annotations: + cert-manager.io/cluster-issuer: {{ $clusterIssuer }} + cert-manager.io/private-key-algorithm: "ECDSA" + nginx.ingress.kubernetes.io/affinity: "cookie" + nginx.ingress.kubernetes.io/affinity-mode: "persistent" + nginx.ingress.kubernetes.io/proxy-body-size: "100m" + nginx.ingress.kubernetes.io/session-cookie-expires: "172800" + nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" + nginx.ingress.kubernetes.io/session-cookie-name: "route" + nginx.org/client-max-body-size: "100m" + {{- range $customAnnotations }} + {{ printf "%s/%s" (.prefix | default "nginx.ingress.kubernetes.io") .name }}: {{ .value | quote }} + {{- end }} +spec: + ingressClassName: "nginx" + rules: + - host: {{ $domain | quote }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }}-rizz-svc + port: + name: rizz + path: / + pathType: Prefix + {{- if $www }} + - host: {{ $wwwDomain }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }}-rizz-svc + port: + name: rizz + path: / + pathType: Prefix + {{- end }} + tls: + - hosts: + - {{ $domain | quote }} + {{- if $www }} + - {{ $wwwDomain }} + {{- end }} + secretName: {{ .Release.Name }}-rizz-tls-cert +{{- end }} diff --git a/mika/rizz/templates/pvc.yaml b/mika/rizz/templates/pvc.yaml index e5b339a4..b355046c 100644 --- a/mika/rizz/templates/pvc.yaml +++ b/mika/rizz/templates/pvc.yaml @@ -1,18 +1,20 @@ -{{- $logs_storage := .Values.rizz.persistence.logs.storage | default "20Mi" | toString | quote }} -{{- $storage_class_name := .Values.rizz.persistence.storageClassName | default "longhorn" | toString | quote }} -{{- $persistence := .Values.rizz.persistence.enabled }} -{{- if $persistence }} +{{- $logPersistence := .Values.storage.log.enabled }} +{{- $logAccessMode := .Values.storage.log.accessMode | default "ReadWriteMany" | toString | quote }} +{{- $logStorage := .Values.storage.log.storage | default "50Mi" | toString | quote }} +{{- $logStorageClassName := .Values.storage.log.storageClassName | default "longhorn" | toString | quote }} +{{- if $logPersistence }} +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ .Release.Name }}-rizz-logs-pvc + name: {{ .Release.Name }}-rizz-log-pvc labels: {{- include "rizz.labels" . | nindent 4 }} spec: accessModes: - - ReadWriteMany + - {{ $logAccessMode }} resources: requests: - storage: {{ $logs_storage }} - storageClassName: {{ $storage_class_name }} + storage: {{ $logStorage }} + storageClassName: {{ $logStorageClassName }} {{- end }} diff --git a/mika/rizz/templates/secret.yaml b/mika/rizz/templates/secret.yaml index e20c847b..398a84fa 100644 --- a/mika/rizz/templates/secret.yaml +++ b/mika/rizz/templates/secret.yaml @@ -1,3 +1,4 @@ +{{- $accounts := .Values.rizz.account }} {{- $secret := .Values.rizz.secret | toString | b64enc }} {{- $db_type := .Values.db.type | default "postgresql" | toString | b64enc }} {{- $db_name := .Values.db.name | toString | b64enc }} @@ -5,6 +6,7 @@ {{- $db_password := .Values.db.password | toString | b64enc }} {{- $db_host := .Values.db.host | toString | b64enc }} {{- $db_port := .Values.db.port | default "5432" | toString | b64enc }} +--- apiVersion: v1 kind: Secret metadata: @@ -24,14 +26,14 @@ data: apiVersion: v1 kind: Secret metadata: - name: {{ .Release.Name }}-rizz-mastodon-config + name: {{ .Release.Name }}-rizz-account-config labels: {{- include "rizz.labels" . | nindent 4 }} type: Opaque data: accounts.json: |- {{- include "rizz.accounts-json" . | toString | b64enc | nindent 4 }} -{{- if .Values.rizz.mastodon }} +{{- if $accounts }} --- apiVersion: v1 kind: Secret @@ -41,10 +43,10 @@ metadata: {{- include "rizz.labels" . | nindent 4 }} type: Opaque data: - {{- range .Values.rizz.mastodon }} + {{- range $accounts }} {{- $normalised_api := .api | toString | replace "https" "" | replace ":" "" | replace "/" "" | replace "." "-" }} {{- $token_secret := printf "%s-%s.secret" .id $normalised_api | toString | replace " " "" }} {{ $token_secret }}: |- - {{ .token | toString | b64enc | nindent 4 }} + {{- .token | toString | b64enc | nindent 4 }} {{- end }} {{- end }} diff --git a/mika/rizz/templates/service.yaml b/mika/rizz/templates/service.yaml index d288ee0c..a0bedd7a 100644 --- a/mika/rizz/templates/service.yaml +++ b/mika/rizz/templates/service.yaml @@ -1,4 +1,10 @@ -{{- $celery := .Values.rizz.scheduler.celery }} +{{- $celery := .Values.scheduler.celery }} +{{- $rizzPort := .Values.service.rizz.port | default "80" | toString }} +{{- $rizzNodePort := .Values.service.rizz.nodePort | toString }} +{{- $redisPort := .Values.service.redis.port | default "6379" | toString }} +{{- $redisNodePort := .Values.service.redis.nodePort | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +--- apiVersion: v1 kind: Service metadata: @@ -6,17 +12,23 @@ metadata: labels: {{- include "rizz.labels" . | nindent 4 }} spec: - type: ClusterIP + type: {{ $type }} ports: - - port: 80 + - port: {{ int $rizzPort }} targetPort: rizz + {{- if and (eq $type "NodePort") $rizzNodePort }} + nodePort: {{ int $rizzNodePort }} + {{- end }} protocol: TCP - name: {{ .Release.Name }}-rizz + name: rizz {{- if $celery }} - - port: 6379 + - port: {{ int $redisPort }} targetPort: redis + {{- if and (eq $type "NodePort") $redisNodePort }} + nodePort: {{ int $redisNodePort }} + {{- end }} protocol: TCP - name: {{ .Release.Name }}-redis + name: redis {{- end }} selector: {{- include "rizz.selectorLabels" . | nindent 4 }} diff --git a/mika/rizz/templates/site-config.conf.tpl b/mika/rizz/templates/site-config.conf.tpl index ec32f96e..e812754f 100644 --- a/mika/rizz/templates/site-config.conf.tpl +++ b/mika/rizz/templates/site-config.conf.tpl @@ -5,7 +5,7 @@ Apache site-config.conf template ServerName DOMAIN:443 UseCanonicalName On - ServerAdmin support@mikahomelab.com + ServerAdmin SERVER_ADMIN DocumentRoot /base WSGIScriptAlias / /base/base/wsgi.py WSGIDaemonProcess DOMAIN python-path=/base @@ -22,7 +22,7 @@ Apache site-config.conf template Require all granted - ErrorLog /var/log/apache2/apache.error.log - CustomLog /var/log/apache2/apache.access.log combined + ErrorLog LOG_MOUNT_PATH/apache.error.log + CustomLog LOG_MOUNT_PATH/apache.access.log combined {{- end }} diff --git a/mika/rizz/templates/tasks.py.tpl b/mika/rizz/templates/tasks.py.tpl index c27f99a6..f95ef760 100644 --- a/mika/rizz/templates/tasks.py.tpl +++ b/mika/rizz/templates/tasks.py.tpl @@ -3,15 +3,15 @@ APScheduler /base/base/tasks.py template */}} {{- define "rizz.apscheduler-tasks-py" -}} -{{- $clean_data_hour := .Values.rizz.scheduler.schedule.clean_data.hour | default "0" | toString -}} -{{- $clean_data_minute := .Values.rizz.scheduler.schedule.clean_data.minute | default "0" | toString -}} -{{- $clean_data_second := .Values.rizz.scheduler.schedule.clean_data.second | default "0" | toString -}} -{{- $post_scheduler_hour := .Values.rizz.scheduler.schedule.post_scheduler.hour | default "8-23/3" | toString -}} -{{- $post_scheduler_minute := .Values.rizz.scheduler.schedule.post_scheduler.minute | default "0" | toString -}} -{{- $post_scheduler_second := .Values.rizz.scheduler.schedule.post_scheduler.second | default "0" | toString -}} -{{- $update_data_hour := .Values.rizz.scheduler.schedule.update_data.hour | default "7-22/3" | toString -}} -{{- $update_data_minute := .Values.rizz.scheduler.schedule.update_data.minute | default "0" | toString -}} -{{- $update_data_second := .Values.rizz.scheduler.schedule.update_data.second | default "0" | toString -}} +{{- $clean_data_hour := .Values.scheduler.schedule.clean_data.hour | default "0" | toString -}} +{{- $clean_data_minute := .Values.scheduler.schedule.clean_data.minute | default "0" | toString -}} +{{- $clean_data_second := .Values.scheduler.schedule.clean_data.second | default "0" | toString -}} +{{- $post_scheduler_hour := .Values.scheduler.schedule.post_scheduler.hour | default "8-23/3" | toString -}} +{{- $post_scheduler_minute := .Values.scheduler.schedule.post_scheduler.minute | default "0" | toString -}} +{{- $post_scheduler_second := .Values.scheduler.schedule.post_scheduler.second | default "0" | toString -}} +{{- $update_data_hour := .Values.scheduler.schedule.update_data.hour | default "7-22/3" | toString -}} +{{- $update_data_minute := .Values.scheduler.schedule.update_data.minute | default "0" | toString -}} +{{- $update_data_second := .Values.scheduler.schedule.update_data.second | default "0" | toString -}} from apscheduler.schedulers.blocking import BlockingScheduler from django.conf import settings diff --git a/mika/rizz/values.yaml b/mika/rizz/values.yaml index 965366d2..41d37f98 100644 --- a/mika/rizz/values.yaml +++ b/mika/rizz/values.yaml @@ -9,6 +9,7 @@ replicaCount: "" # Container images used for Rizz. image: # Rizz container image configurations. + # Source: https://github.com/irfanhakim-as/rizz/pkgs/container/rizz rizz: # The registry where the Rizz container image is hosted. # Default: "ghcr.io" @@ -23,6 +24,7 @@ image: # Default: "IfNotPresent" pullPolicy: "" # Redis container image configurations. + # Source: https://hub.docker.com/_/redis redis: # The registry where the Redis container image is hosted. # Default: "docker.io" @@ -46,76 +48,90 @@ imagePullSecrets: [] # Rizz configurations. rizz: # Specifies whether Rizz should run in debug mode. - # Default: false + # Default: "false" # Example: - # debug: true - debug: false - # The domain name of the Rizz service. + # debug: "true" + debug: "" + # The ingress domain name that hosts the Rizz server. # Default: "localhost" # Example: - # domain: "localhost" + # domain: "rizz.example.com" domain: "" # Specifies whether to enable posting in organic numbers. - # Default: true + # Default: "true" # Example: - # organic: false - organic: true + # organic: "false" + organic: "" # The limit number of posts to be scheduled for posting per run. # Default: "3" # Example: # post_limit: "5" post_limit: "" # Specifies whether to retry posting if the post fails to be sent. - # Default: true + # Default: "true" # Example: - # retry_post: false - retry_post: true + # retry_post: "false" + retry_post: "" # A 50-character secret key used for secure session management and cryptographic operations within the Rizz service. # Example: # secret: "6&p4%t)-$8a14fmfh92py8j55+us51r6%e52dzy&=a3-6yd4#e" secret: "" + # The email address displayed by Apache for server administration contact. + # Default: "admin@example.com" + # Example: + # serverAdmin: "foo@example.com" + serverAdmin: "" # The default visibility of posts made by the Rizz service. # Default: "public" # Example: # visibility: "unlisted" visibility: "" - # Rizz Mastodon configurations. + # Account configurations. + # Items: `.api`, `.id`, `.host`, `.token`, `.bot`, `.discoverable`, `.enabled`, `.display_name`, `.fields`, `.locked`, `.note` # Example: - # mastodon: - # # API endpoint or URL for the Mastodon instance of the Rizz bot. + # account: + # # API endpoint or URL for the server instance of the Rizz bot. # # Example: # # api: "https://botsin.space" # - api: "" - # # The username or user account for the Mastodon instance of the Rizz bot. + # # The username or user account for the server instance of the Rizz bot. # # Example: # # id: "rizz" # id: "" - # # A secure token required to authenticate the Rizz service with the Mastodon instance's API. + # # The underlying host service of the server instance. + # # Default: "mastodon" + # # Example: + # # host: "bluesky" + # host: "" + # # The application access token required to authenticate the Rizz service with the server instance's API. # # Example: - # # token: "6&p4%t)-$8a14fmfh92py8j55+us51r6%e52dzy&=a3-6yd4#e" + # # token: "rinoSZiIvRHLw6PL1QCSia+8liGDau0MZ336JAnL0IQ" # token: "" # # Specifies whether the Rizz bot should be marked as a bot. - # # Default: true + # # Note: Bluesky does not currently support this field. + # # Default: "true" # # Example: - # # bot: false + # # bot: "false" # bot: "" # # Specifies whether the Rizz bot should appear in the user directory. - # # Default: true + # # Note: Bluesky does not currently support this field. + # # Default: "true" # # Example: - # # discoverable: false + # # discoverable: "false" # discoverable: "" # # Specifies whether the Rizz bot should be active. - # # Default: true + # # Default: "true" # # Example: - # # enabled: false + # # enabled: "false" # enabled: "" # # The display name of the Rizz bot. - # # Default: null + # # Note: Bluesky does not currently support this field. + # # Default: "null" # # Example: # # display_name: "Rizz" # display_name: "" # # A list of up to four name-value pairs information to be displayed on the Rizz bot's profile. - # # Default: [] + # # Note: Bluesky does not officially support this field. # # Example: # # fields: # # - name: "Website 1" @@ -124,134 +140,125 @@ rizz: # # value: "https://domain2.example.org" # fields: [] # # Specifies whether the Rizz bot needs to manually approve follow requests. - # # Default: false + # # Note: Bluesky does not currently support this field. + # # Default: "false" # # Example: - # # locked: true + # # locked: "true" # locked: "" # # The bio of the Rizz bot. - # # Default: null + # # Note: Bluesky does not currently support this field. + # # Default: "null" # # Example: # # note: "This is the bio of the Rizz bot." # note: "" - mastodon: [] - # Rizz storage persistence configurations. - persistence: - # Specifies whether Rizz should persist its storage. - # Example: - # enabled: true - enabled: false - # The storage class name used for dynamically provisioning a persistent volume for the Rizz storage. - # Default: "longhorn" - # Example: - # storageClassName: "longhorn" - storageClassName: "" - # Rizz logs persistence configurations. - logs: - # The amount of persistent storage allocated for Rizz logs. - # Default: "20Mi" - # Example: - # storage: "1Gi" - storage: "" - # Rizz feed configurations. + account: [] + # RSS feed configurations. + # Items: `.endpoint`, `.id`, `.enabled` # Example: # feed: # # The URL of the RSS feed to be tracked by Rizz. # # Example: # # endpoint: "https://www.reddit.com/r/programming/.rss" # - endpoint: "" - # # The publishing date format of the RSS feed entry. - # # Default: "%a, %d %b %Y %H:%M:%S %z" - # # Example: - # # pubdate_format: "%a, %d %b %Y %H:%M:%S %Z" - # pubdate_format: "" # # The unique identifier of the RSS feed entry. # # Example: # # id: "MyFeed" # id: "" # # Specifies whether the RSS feed entry should be actively processed. - # # Default: true + # # Default: "true" # # Example: - # # enabled: false + # # enabled: "false" # enabled: "" feed: [] - # Rizz scheduler configurations. - scheduler: - # Specifies whether APScheduler should be used by Rizz as the task scheduler. - # Example: - # apscheduler: false - apscheduler: true - # Specifies whether Celery should be used by Rizz as the task scheduler. - # Example: - # celery: true - celery: false - # The schedule for the task scheduler used by Rizz. - # Note: The `apscheduler` scheduler supports the `hour`, `minute`, and `second` fields simultaneously. The `celery` scheduler only supports a combination of the `hour` and `minute` fields, or the `second` field alone. - schedule: - # The schedule for cleaning up the database. - clean_data: - # The hours at which the task scheduler cleans up the database. - # Default: "0" - # Example: - # hour: "1" - hour: "" - # The minutes at which the task scheduler cleans up the database. - # Default: "0" - # Example: - # minute: "30" - minute: "" - # The seconds at which the task scheduler cleans up the database. - # Default: "0" for `apscheduler` - # Example: - # second: "30" - second: "" - # The schedule for posting scheduled posts. - post_scheduler: - # The hours at which the task scheduler posts scheduled posts. - # Default: "8-23/3" - # Example: - # hour: "*" - hour: "" - # The minutes at which the task scheduler posts scheduled posts. - # Default: "0" - # Example: - # minute: "*/30" - minute: "" - # The seconds at which the task scheduler posts scheduled posts. - # Default: "0" for `apscheduler` - # Example: - # second: "30" - second: "" - # The schedule for updating up the database. - update_data: - # The hours at which the task scheduler updates the database. - # Default: "7-22/3" - # Example: - # hour: "*/2" - hour: "" - # The minutes at which the task scheduler updates the database. - # Default: "0" - # Example: - # minute: "15" - minute: "" - # The seconds at which the task scheduler updates the database. - # Default: "0" for `apscheduler` - # Example: - # second: "30" - second: "" - # The timezone for the task scheduler used by Rizz to schedule time-dependent operations. - # Default: "Asia/Kuala_Lumpur" - # Example: - # timezone: "Asia/Kuala_Lumpur" - timezone: "" + +# Scheduler configurations. +scheduler: + # Specifies whether APScheduler should be used by Rizz as the task scheduler. + # Example: + # apscheduler: false + apscheduler: true + # Specifies whether Celery should be used by Rizz as the task scheduler. + # Example: + # celery: true + celery: false + # The timezone for the task scheduler used by Rizz to schedule time-dependent operations. + # Default: "Etc/UTC" + # Example: + # timezone: "Asia/Kuala_Lumpur" + timezone: "" + # The schedule for the task scheduler used by Rizz. + # Note: The `apscheduler` scheduler supports the `hour`, `minute`, and `second` fields simultaneously. + # The `celery` scheduler only supports a combination of the `hour` and `minute` fields, or the `second` field alone. + schedule: + # The schedule for cleaning up the database. + clean_data: + # The hours at which the task scheduler cleans up the database. + # Default: "0" + # Example: + # hour: "1" + hour: "" + # The minutes at which the task scheduler cleans up the database. + # Default: "0" + # Example: + # minute: "30" + minute: "" + # The seconds at which the task scheduler cleans up the database. + # Default: "0" (`apscheduler`) + # Example: + # second: "30" + second: "" + # The schedule for posting scheduled posts. + post_scheduler: + # The hours at which the task scheduler posts scheduled posts. + # Default: "8-23/3" + # Example: + # hour: "*" + hour: "" + # The minutes at which the task scheduler posts scheduled posts. + # Default: "0" + # Example: + # minute: "*/30" + minute: "" + # The seconds at which the task scheduler posts scheduled posts. + # Default: "0" (`apscheduler`) + # Example: + # second: "30" + second: "" + # The schedule for updating the database. + update_data: + # The hours at which the task scheduler updates the database. + # Default: "7-22/3" + # Example: + # hour: "*/2" + hour: "" + # The minutes at which the task scheduler updates the database. + # Default: "0" + # Example: + # minute: "15" + minute: "" + # The seconds at which the task scheduler updates the database. + # Default: "0" (`apscheduler`) + # Example: + # second: "30" + second: "" # Database configurations. db: - # The type of the database used by Rizz. + # The database engine or backend being used by Rizz. # Default: "postgresql" # Example: - # type: "postgresql" + # type: "mysql" type: "" - # The name of the database used by Rizz. + # The hostname or IP address of the Rizz database server. + # Example: + # host: "rizz.default.svc.cluster.local" + host: "" + # The port number the Rizz database server is listening for connections. + # Default: "5432" + # Example: + # port: "3306" + port: "" + # The name of the database being used by Rizz. # Example: # name: "rizz" name: "" @@ -259,71 +266,163 @@ db: # Example: # user: "root" user: "" - # The password associated with the Rizz database's user. + # The password associated with the Rizz database user. # Example: # password: "password" password: "" - # The hostname or IP address of the Rizz database server. + +# Ingress configurations. +ingress: + # Specifies whether Ingress should be enabled for hosting Rizz services. # Example: - # host: "rizz.default.svc.cluster.local" - host: "" - # The port number on which the Rizz database server is listening. - # Default: "5432" + # enabled: true + enabled: false + # The name of the cluster issuer for Ingress. + # Default: "letsencrypt-dns-prod" # Example: - # port: "5432" - port: "" + # clusterIssuer: "letsencrypt-http-prod" + clusterIssuer: "" + # Specifies whether the WWW subdomain should be enabled. + # Example: + # www: true + www: false + # Additional configuration annotations to be added to the Ingress resource. + # Items: `.prefix`, `.name`, `.value` + # Example: + # customAnnotations: + # # The prefix of the annotation. + # # Default: "nginx.ingress.kubernetes.io" + # # Example: + # # prefix: "nginx.org" + # - prefix: "" + # # The name of the annotation. + # # Example: + # # name: "proxy-connect-timeout" + # name: "" + # # The value of the annotation. + # # Example: + # # value: "120" + # value: "" + customAnnotations: [] + +# Service configurations. +service: + # The type of service used to expose Rizz services. + # Default: "ClusterIP" + # Example: + # type: "NodePort" + type: "" + # Rizz service port configurations. + rizz: + # The optional node port to expose for Rizz when the service type is NodePort. + # Example: + # nodePort: "30000" + nodePort: "" + # The Rizz port on which the Rizz server should listen for connections. + # Default: "80" + # Example: + # port: "8080" + port: "" + # Redis service port configurations. + redis: + # The optional node port to expose for Redis when the service type is NodePort. + # Example: + # nodePort: "32000" + nodePort: "" + # The Redis port on which the Rizz server should listen for connections. + # Default: "6379" + # Example: + # port: "8443" + port: "" + +# Storage configurations. +storage: + # Log storage configurations. + log: + # Specifies whether persistent storage should be provisioned for log storage. + # Example: + # enabled: true + enabled: false + # The access mode defining how the log storage can be mounted. + # Default: "ReadWriteMany" + # Example: + # accessMode: "ReadWriteOnce" + accessMode: "" + # The path where the log storage should be mounted on the container. + # Default: "/var/log/apache2" + # Example: + # mountPath: "/log" + mountPath: "" + # The subpath within the log storage to mount to the container. Leave empty if not required. + # Example: + # subPath: "Log" + subPath: "" + # The default amount of persistent storage allocated for the log storage. + # Default: "50Mi" + # Example: + # storage: "10Gi" + storage: "" + # The storage class name used for dynamically provisioning a persistent volume for the log storage. + # Default: "longhorn" + # Example: + # storageClassName: "smb" + storageClassName: "" # Resource requirements and limits for Rizz containers. resources: # Rizz container resources. - rizz: - # The minimum amount of resources required by Rizz to run. - requests: - # The minimum amount of CPU resources required by Rizz. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "100m" or more if using `celery` as the scheduler. - # Example: - # cpu: "20m" - cpu: "30m" - # The minimum amount of memory required by Rizz. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "250Mi" or more if using `celery` as the scheduler. - # Example: - # memory: "250Mi" - memory: "60Mi" - # The maximum amount of resources allowed for Rizz. - limits: - # The maximum amount of CPU resources allowed for Rizz. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "200m" or more if using `celery` as the scheduler. - # Example: - # cpu: "50m" - cpu: "50m" - # The maximum amount of memory allowed for Rizz. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "400Mi" or more if using `celery` as the scheduler. - # Example: - # memory: "450Mi" - memory: "120Mi" + # Example: + # rizz: + # # The minimum amount of resources required by Rizz to run. + # requests: + # # The minimum amount of CPU resources required by Rizz. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "500m" or more if using `celery` as the scheduler. + # # Example: + # # cpu: "10m" + # cpu: "200m" + # # The minimum amount of memory required by Rizz. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "550Mi" or more if using `celery` as the scheduler. + # # Example: + # # memory: "10Mi" + # memory: "100Mi" + # # The maximum amount of resources allowed for Rizz. + # limits: + # # The maximum amount of CPU resources allowed for Rizz. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "1" or more if using `celery` as the scheduler. + # # Example: + # # cpu: "250m" + # cpu: "300m" + # # The maximum amount of memory allowed for Rizz. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "650Mi" or more if using `celery` as the scheduler. + # # Example: + # # memory: "250Mi" + # memory: "350Mi" + rizz: {} # Scheduler container resources. - scheduler: - # The minimum amount of resources required by Scheduler to run. - requests: - # The minimum amount of CPU resources required by Scheduler. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "10m" or more if using `celery` as the scheduler. - # Example: - # cpu: "5m" - cpu: "10m" - # The minimum amount of memory required by Scheduler. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "50Mi" or more if using `celery` as the scheduler. - # Example: - # memory: "30Mi" - memory: "100Mi" - # The maximum amount of resources allowed for Scheduler. - limits: - # The maximum amount of CPU resources allowed for Scheduler. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "20m" or more if using `celery` as the scheduler. - # Example: - # cpu: "15m" - cpu: "20m" - # The maximum amount of memory allowed for Scheduler. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "100Mi" or more if using `celery` as the scheduler. - # Example: - # memory: "50Mi" - memory: "200Mi" + # Example: + # scheduler: + # # The minimum amount of resources required by Scheduler to run. + # requests: + # # The minimum amount of CPU resources required by Scheduler. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "10m" or more if using `celery` as the scheduler. + # # Example: + # # cpu: "10m" + # cpu: "200m" + # # The minimum amount of memory required by Scheduler. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "50Mi" or more if using `celery` as the scheduler. + # # Example: + # # memory: "10Mi" + # memory: "250Mi" + # # The maximum amount of resources allowed for Scheduler. + # limits: + # # The maximum amount of CPU resources allowed for Scheduler. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "20m" or more if using `celery` as the scheduler. + # # Example: + # # cpu: "250m" + # cpu: "300m" + # # The maximum amount of memory allowed for Scheduler. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "100Mi" or more if using `celery` as the scheduler. + # # Example: + # # memory: "250Mi" + # memory: "350Mi" + scheduler: {} diff --git a/mika/waktusolat/Chart.yaml b/mika/waktusolat/Chart.yaml index 487f0d48..85b5e47e 100644 --- a/mika/waktusolat/Chart.yaml +++ b/mika/waktusolat/Chart.yaml @@ -1,13 +1,14 @@ apiVersion: v2 name: waktusolat -description: Waktu Solat is a simple web application that posts local prayer times on Mastodon. +description: Waktu Solat is a simple web application that posts local prayer times to federated social network. type: application -version: 0.3.4 -appVersion: "0.2.2-stable-r1" +version: 0.4.0 +appVersion: "0.3.0-stable-r2" keywords: - "waktu solat" - "prayer time" - "mastodon" + - "bluesky" home: "https://github.com/irfanhakim-as/waktusolat" icon: "https://irfanhakim-as.github.io/charts/logos/mika.png" sources: diff --git a/mika/waktusolat/README.md b/mika/waktusolat/README.md index 4c2dc712..956e9c75 100644 --- a/mika/waktusolat/README.md +++ b/mika/waktusolat/README.md @@ -1,95 +1,230 @@ -# [`waktusolat`](https://github.com/irfanhakim-as/waktusolat) 🔒 +# [WaktuSolat](https://github.com/irfanhakim-as/waktusolat) + +> [!WARNING] +> This chart requires access to a private image registry, please request access from the owner of the repository. + +Waktu Solat is a simple web application that posts local prayer times to federated social network. ## Prerequisites +> [!NOTE] +> You may refer to [Orked](https://github.com/irfanhakim-as/orked) for help with setting up a Kubernetes cluster that meets all the following prerequisites. + - Kubernetes 1.19+ - Helm 3.2.0+ +- Longhorn 1.4.1+ + +--- ## Preflight checklist -### Create image pull secret +> [!IMPORTANT] +> The following items are required to be set up prior to installing this chart. + +### Image pull secret + +An image pull secret is required to access the private image registry that hosts the required image. + +1. If you have the necessary credentials, create a named image pull secret (i.e. `ghcr-token-secret`) in the `default` namespace: + + ```sh + kubectl create secret docker-registry ghcr-token-secret --docker-server= --docker-username= --docker-password= --docker-email= -n default + ``` + +2. Copy the image pull secret from the `default` namespace to the destination namespace: + + ```sh + kubectl get secret ghcr-token-secret -n default -o yaml | sed "s/namespace: .*/namespace: /" | kubectl apply -f - + ``` + +3. Add the name of the image pull secret to the `imagePullSecrets` array in your installation's values file: + + ```yaml + imagePullSecrets: + - name: "ghcr-token-secret" + ``` + +### Generate secret key + +A unique, secure secret key is required for each WaktuSolat installation. + +1. Generate a secret key using the following command: + + ```sh + python -c 'import random; print("".join([random.choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for i in range(50)]))' + ``` + +2. Set the generated secret key as the value of the `waktusolat.secret` setting in your installation's values file: + + ```yaml + secret: "" + ``` + +### Application access token + +A secure application access token is required for each configured account. + +1. Follow the subsections below on how to generate an access token for each account. + +2. Set the access token as the value of the `waktusolat.account` account's `token` setting in your installation's values file: + + ```yaml + token: "" + ``` + + Replace `` with the account's generated access token. + +#### Mastodon + +1. Login to your Mastodon (bot) account. If you do not currently have one, you will need to register one first on any available Mastodon instance. + +2. Click the **Preferences** menu item. + +3. In the **Preferences** page, navigate to the **Development** section. + +4. From the **Your applications** list, click the **New application** button. + +5. In the **New application** form, fill in the following required details: + + - Application name: Add in a unique, descriptive name for your application i.e. `WaktuSolat` + + - Scopes: + + - `read` + - `write` + +6. Click the **Save changes** button. + +7. After being redirected back to the **Your applications** page, click the link on the name of the application you just created. + +8. In the specific **Application** page, copy the value of the confidential **Your access token** field. + +#### Bluesky + +1. Login to your Bluesky (bot) account. If you do not currently have one, you will need to register one first on any available Bluesky instance. + +2. Click the **Settings** menu item. + +3. In the **Settings** page, navigate to the **App Passwords** section. + +4. In the **App Passwords** page, click the **Add App Password** button. + +5. In the prompted form, add in a unique, descriptive name for the App Password (i.e. `WaktuSolat`) and click the **Create App Password** button to submit the form. + +6. Copy the value of the confidential App Password that has been generated and click the **Done** button. + +--- + +## Recommended configurations + +> [!NOTE] +> The following configuration recommendations might not be the default settings for this chart but are **highly recommended**. Please carefully consider them before configuring your installation. + +**This section does not apply to this chart.** + +--- + +## Application configurations + +> [!NOTE] +> The following configurations are expected or recommended to be set up from within the application after completing the installation. + +**This section does not apply to this chart.** + +--- + +## How to add the chart repo + +1. Add the repo to your local helm client: + + ```sh + helm repo add mika https://irfanhakim-as.github.io/charts + ``` + +2. Update the repo to retrieve the latest versions of the packages: + + ```sh + helm repo update + ``` + +--- -Replace `$github-username`, `$github-pass`, `$github-email` and `$namespace` accordingly. +## How to install or upgrade a chart release -```sh -kubectl create secret docker-registry ghcr-token-secret --docker-server=https://ghcr.io --docker-username="$github-username" --docker-password="$github-pass" --docker-email="$github-email" -n $namespace -``` +1. Get the values file of the WaktuSolat chart or an existing installation (release). -### Generate secret key for `waktusolat.secret` + Get the latest WaktuSolat chart values file for a new installation: -```sh -python -c 'import random; print("".join([random.choice("abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)") for i in range(50)]))' -``` + ```sh + helm show values mika/waktusolat > values.yaml + ``` -## How to add repo + Alternatively, get the values file of an existing WaktuSolat release: -Add the repo to your local helm client. + ```sh + helm get values ${releaseName} --namespace ${namespace} > values.yaml + ``` -```sh -helm repo add mika https://irfanhakim-as.github.io/charts -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Update the repo to retrieve the latest versions of the packages. +2. Edit your WaktuSolat values file with the intended configurations: -```sh -helm repo update -``` + ```sh + nano values.yaml + ``` -## How to install + Pay extra attention to the descriptions and sample values provided in the chart values file. -### Prepare chart values +3. Install a new release for WaktuSolat or upgrade an existing WaktuSolat release: -Copy `values.yaml` from the chart you would like to install. + ```sh + helm upgrade --install ${releaseName} mika/waktusolat --namespace ${namespace} --create-namespace --values values.yaml --wait + ``` -```sh -cp mika/waktusolat/values.yaml . -``` + Replace `${releaseName}` and `${namespace}` accordingly. -Edit `values.yaml` with the appropriate values. Refer to the [Configurations](#Configurations) section for available options. +4. Verify that your WaktuSolat release has been installed: -```sh -nano values.yaml -``` + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -### Perform installation + Replace `${namespace}` and `${releaseName}` accordingly. This should return the release information if the release has been installed. -Install the desired chart. Replace `$release_name` and `$namespace` accordingly. +--- -```sh -helm install $release_name mika/waktusolat --namespace $namespace --create-namespace --values values.yaml --wait -``` +## How to uninstall a chart release -Verify that your chart has been installed. Replace `$namespace` and `$release_name` accordingly. +> [!CAUTION] +> Uninstalling a release will irreversibly delete all the resources associated with the release, including any persistent data. -```sh -helm ls --namespace $namespace | grep "$release_name" -``` +1. Uninstall the desired release: -## How to upgrade + ```sh + helm uninstall ${releaseName} --namespace ${namespace} --wait + ``` -After making any necessary changes to the `values.yaml` file, upgrade the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${releaseName}` and `${namespace}` accordingly. -```sh -helm upgrade $release_name mika/waktusolat --namespace $namespace --values values.yaml --wait -``` +2. Verify that the release has been uninstalled: -## How to uninstall + ```sh + helm ls --namespace ${namespace} | grep "${releaseName}" + ``` -Uninstall the desired chart. Replace `$release_name` and `$namespace` accordingly. + Replace `${namespace}` and `${releaseName}` accordingly. This should return nothing if the release has been uninstalled. -```sh -helm uninstall $release_name --namespace $namespace --wait -``` +--- -## Configurations +## Chart configurations | Key | Type | Default | Description | |-----|------|---------|-------------| | db.host | string | `""` | The hostname or IP address of the WaktuSolat database server. | -| db.name | string | `""` | The name of the database used by WaktuSolat. | -| db.password | string | `""` | The password associated with the WaktuSolat database's user. | -| db.port | string | `""` | The port number on which the WaktuSolat database server is listening. Default: `"5432"`. | -| db.type | string | `""` | The type of the database used by WaktuSolat. Default: `"postgresql"`. | +| db.name | string | `""` | The name of the database being used by WaktuSolat. | +| db.password | string | `""` | The password associated with the WaktuSolat database user. | +| db.port | string | `""` | The port number the WaktuSolat database server is listening for connections. Default: `"5432"`. | +| db.type | string | `""` | The database engine or backend being used by WaktuSolat. Default: `"postgresql"`. | | db.user | string | `""` | The username or user account for accessing the WaktuSolat database. | | image.redis.pullPolicy | string | `""` | The policy that determines when Kubernetes should pull the Redis container image. Default: `"alpine"`. | | image.redis.registry | string | `""` | The registry where the Redis container image is hosted. Default: `"docker.io"`. | @@ -100,39 +235,46 @@ helm uninstall $release_name --namespace $namespace --wait | image.waktusolat.repository | string | `""` | The name of the repository that contains the WaktuSolat container image used. Default: `"irfanhakim-as/waktusolat"`. | | image.waktusolat.tag | string | `""` | The tag that specifies the version of the WaktuSolat container image used. Default: `Chart appVersion`. | | imagePullSecrets | list | `[]` | Credentials used to securely authenticate and authorise the pulling of container images from private registries. | +| ingress.clusterIssuer | string | `""` | The name of the cluster issuer for Ingress. Default: `"letsencrypt-dns-prod"`. | +| ingress.customAnnotations | list | `[]` | Additional configuration annotations to be added to the Ingress resource. Items: `.prefix`, `.name`, `.value`. | +| ingress.enabled | bool | `false` | Specifies whether Ingress should be enabled for hosting WaktuSolat services. | +| ingress.www | bool | `false` | Specifies whether the WWW subdomain should be enabled. | | replicaCount | string | `""` | The desired number of running replicas for WaktuSolat. Default: `"1"`. | -| resources.scheduler.limits.cpu | string | `"20m"` | The maximum amount of CPU resources allowed for Scheduler. | -| resources.scheduler.limits.memory | string | `"200Mi"` | The maximum amount of memory allowed for Scheduler. | -| resources.scheduler.requests.cpu | string | `"10m"` | The minimum amount of CPU resources required by Scheduler. | -| resources.scheduler.requests.memory | string | `"100Mi"` | The minimum amount of memory required by Scheduler. | -| resources.waktusolat.limits.cpu | string | `"50m"` | The maximum amount of CPU resources allowed for WaktuSolat. | -| resources.waktusolat.limits.memory | string | `"120Mi"` | The maximum amount of memory allowed for WaktuSolat. | -| resources.waktusolat.requests.cpu | string | `"30m"` | The minimum amount of CPU resources required by WaktuSolat. | -| resources.waktusolat.requests.memory | string | `"60Mi"` | The minimum amount of memory required by WaktuSolat. | +| resources.scheduler | object | `{}` | Scheduler container resources. | +| resources.waktusolat | object | `{}` | WaktuSolat container resources. | +| scheduler.apscheduler | bool | `true` | Specifies whether APScheduler should be used by WaktuSolat as the task scheduler. | +| scheduler.celery | bool | `false` | Specifies whether Celery should be used by WaktuSolat as the task scheduler. | +| scheduler.schedule.clean_db.hour | string | `""` | The hours at which the task scheduler cleans up the database. Default: `"0"`. | +| scheduler.schedule.clean_db.minute | string | `""` | The minutes at which the task scheduler cleans up the database. Default: `"0"`. | +| scheduler.schedule.clean_db.second | string | `""` | The seconds at which the task scheduler cleans up the database. Default: "0" (`apscheduler`). | +| scheduler.schedule.notify_solat_schedule.hour | string | `""` | The hours at which the task scheduler schedules the daily prayer time post. Default: `"5"`. | +| scheduler.schedule.notify_solat_schedule.minute | string | `""` | The minutes at which the task scheduler schedules the daily prayer time post. Default: `"0"`. | +| scheduler.schedule.notify_solat_schedule.second | string | `""` | The seconds at which the task scheduler schedules the daily prayer time post. Default: "0" (`apscheduler`). | +| scheduler.schedule.notify_solat_times.hour | string | `""` | The hours at which the task scheduler schedules the daily prayer time notifications. Default: `"*"`. | +| scheduler.schedule.notify_solat_times.minute | string | `""` | The minutes at which the task scheduler schedules the daily prayer time notifications. Default: `"*/1"`. | +| scheduler.schedule.notify_solat_times.second | string | `""` | The seconds at which the task scheduler schedules the daily prayer time notifications. Default: "0" (`apscheduler`). | +| scheduler.schedule.post_scheduler.hour | string | `""` | The hours at which the task scheduler posts scheduled posts. Default: `"*"`. | +| scheduler.schedule.post_scheduler.minute | string | `""` | The minutes at which the task scheduler posts scheduled posts. Default: `"*"`. | +| scheduler.schedule.post_scheduler.second | string | `""` | The seconds at which the task scheduler posts scheduled posts. Default: "*/1" (`apscheduler`). | +| scheduler.timezone | string | `""` | The timezone for the task scheduler used by WaktuSolat to schedule time-dependent operations. Default: `"Etc/UTC"`. | +| service.redis.nodePort | string | `""` | The optional node port to expose for Redis when the service type is NodePort. | +| service.redis.port | string | `""` | The Redis port on which the WaktuSolat server should listen for connections. Default: `"6379"`. | +| service.type | string | `""` | The type of service used to expose WaktuSolat services. Default: `"ClusterIP"`. | +| service.waktusolat.nodePort | string | `""` | The optional node port to expose for WaktuSolat when the service type is NodePort. | +| service.waktusolat.port | string | `""` | The WaktuSolat port on which the WaktuSolat server should listen for connections. Default: `"80"`. | +| storage.log.accessMode | string | `""` | The access mode defining how the log storage can be mounted. Default: `"ReadWriteMany"`. | +| storage.log.enabled | bool | `false` | Specifies whether persistent storage should be provisioned for log storage. | +| storage.log.mountPath | string | `""` | The path where the log storage should be mounted on the container. Default: `"/var/log/apache2"`. | +| storage.log.storage | string | `""` | The default amount of persistent storage allocated for the log storage. Default: `"50Mi"`. | +| storage.log.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the log storage. Default: `"longhorn"`. | +| storage.log.subPath | string | `""` | The subpath within the log storage to mount to the container. Leave empty if not required. | +| waktusolat.account | list | `[]` | Account configurations. Items: `.api`, `.id`, `.host`, `.token`, `.bot`, `.discoverable`, `.enabled`, `.display_name`, `.fields`, `.locked`, `.note`. | | waktusolat.debug | bool | `false` | Specifies whether WaktuSolat should run in debug mode. Default: `false`. | -| waktusolat.domain | string | `""` | The domain name of the WaktuSolat service. Default: `"localhost"`. | -| waktusolat.feed | list | `[]` | WaktuSolat feed configurations. | +| waktusolat.domain | string | `""` | The ingress domain name that hosts the WaktuSolat server. Default: `"localhost"`. | +| waktusolat.feed | list | `[]` | WaktuSolat feed configurations. Items: `.endpoint`, `.id`, `.enabled`. | | waktusolat.location | list | `[]` | The code of locations WaktuSolat should fetch and update prayer times for. Default: `"wlp-0"`. | -| waktusolat.mastodon | list | `[]` | WaktuSolat Mastodon configurations. | -| waktusolat.persistence.enabled | bool | `false` | Specifies whether WaktuSolat should persist its storage. | -| waktusolat.persistence.logs.storage | string | `""` | The amount of persistent storage allocated for WaktuSolat logs. Default: `"20Mi"`. | -| waktusolat.persistence.storageClassName | string | `""` | The storage class name used for dynamically provisioning a persistent volume for the WaktuSolat storage. Default: `"longhorn"`. | | waktusolat.post_limit | string | `""` | The limit number of posts to be scheduled for posting per run. Default: `"0"` (Unlimited). | -| waktusolat.retry_post | bool | `false` | Specifies whether to retry posting if the post fails to be sent. Default: `false`. | -| waktusolat.scheduler.apscheduler | bool | `true` | Specifies whether APScheduler should be used by WaktuSolat as the task scheduler. | -| waktusolat.scheduler.celery | bool | `false` | Specifies whether Celery should be used by WaktuSolat as the task scheduler. | -| waktusolat.scheduler.schedule.clean_db.hour | string | `""` | The hours at which the task scheduler cleans up the database. Default: `"0"`. | -| waktusolat.scheduler.schedule.clean_db.minute | string | `""` | The minutes at which the task scheduler cleans up the database. Default: `"0"`. | -| waktusolat.scheduler.schedule.clean_db.second | string | `""` | The seconds at which the task scheduler cleans up the database. Default: `"0"` for `apscheduler`. | -| waktusolat.scheduler.schedule.notify_solat_schedule.hour | string | `""` | The hours at which the task scheduler schedules the daily prayer time schedule posts. Default: `"5"`. | -| waktusolat.scheduler.schedule.notify_solat_schedule.minute | string | `""` | The minutes at which the task scheduler schedules the daily prayer time schedule posts. Default: `"0"`. | -| waktusolat.scheduler.schedule.notify_solat_schedule.second | string | `""` | The seconds at which the task scheduler schedules the daily prayer time schedule posts. Default: `"0"` for `apscheduler`. | -| waktusolat.scheduler.schedule.notify_solat_times.hour | string | `""` | The hours at which the task scheduler schedules prayer time notifications. Default: `"*"`. | -| waktusolat.scheduler.schedule.notify_solat_times.minute | string | `""` | The minutes at which the task scheduler schedules prayer time notifications. Default: `"*/1"`. | -| waktusolat.scheduler.schedule.notify_solat_times.second | string | `""` | The seconds at which the task scheduler schedules prayer time notifications. Default: `"0"` for `apscheduler`. | -| waktusolat.scheduler.schedule.post_scheduler.hour | string | `""` | The hours at which the task scheduler posts scheduled posts. Default: `"*"`. | -| waktusolat.scheduler.schedule.post_scheduler.minute | string | `""` | The minutes at which the task scheduler posts scheduled posts. Default: `"*"`. | -| waktusolat.scheduler.schedule.post_scheduler.second | string | `""` | The seconds at which the task scheduler posts scheduled posts. Default: `"*/1"`. | -| waktusolat.scheduler.timezone | string | `""` | The timezone for the task scheduler used by WaktuSolat to schedule time-dependent operations. Default: `"Asia/Kuala_Lumpur"`. | +| waktusolat.retry_post | string | `""` | Specifies whether to retry posting if the post fails to be sent. Default: `"false"`. | | waktusolat.secret | string | `""` | A 50-character secret key used for secure session management and cryptographic operations within the WaktuSolat service. | +| waktusolat.serverAdmin | string | `""` | The email address displayed by Apache for server administration contact. Default: "admin@example.com". | | waktusolat.visibility | string | `""` | The default visibility of posts made by the WaktuSolat service. Default: `"public"`. | diff --git a/mika/waktusolat/templates/NOTES.txt b/mika/waktusolat/templates/NOTES.txt index 786eb894..a8c0376f 100644 --- a/mika/waktusolat/templates/NOTES.txt +++ b/mika/waktusolat/templates/NOTES.txt @@ -1,5 +1,105 @@ -waktusolat is now installed and configured for {{ .Release.Name | toString }}. +{{- $serviceAddress := "" }} +{{- $accounts := .Values.waktusolat.account }} +{{- $feeds := .Values.waktusolat.feed }} +{{- $ingress := .Values.ingress.enabled }} +{{- $domain := .Values.waktusolat.domain | toString }} +{{- $waktusolatPort := .Values.service.waktusolat.port | default "80" | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +{{- $serviceName := printf "%s-waktusolat-svc" .Release.Name | toString }} +WaktuSolat has been installed and configured for {{ .Release.Name | toString }} 🎉 -See the values.yaml file of this chart for more configuration options. +{{- if $ingress }} + {{- $serviceAddress = printf "https://%s" $domain | toString }} +{{- else if or (eq $type "ClusterIP") (eq $type "LoadBalancer") (eq $type "NodePort") }} -Please refer to the official documentation for more information on how to use waktusolat. +Please run the following command(s) to obtain the right address to the service: + + ```sh + {{- if eq $type "ClusterIP" }} + {{- $forwardPort := "8080" | toString }} + {{- $serviceAddress = printf "http://127.0.0.1:%s" $forwardPort | toString }} + export POD_NAME=$(kubectl get pod --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "waktusolat.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} ${POD_NAME} -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + kubectl port-forward --namespace {{ .Release.Namespace }} ${POD_NAME} {{ $forwardPort }}:${CONTAINER_PORT} + {{- else if eq $type "LoadBalancer" }} + {{- $serviceAddress = printf "$(echo http://${SERVICE_IP}:%s)" $waktusolatPort | toString }} + export SERVICE_IP=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} --template "{{"{{- range (index .status.loadBalancer.ingress 0) }}{{ . }}{{- end }}"}}") + {{- else if eq $type "NodePort" }} + {{- $serviceAddress = "$(echo http://${NODE_IP}:${NODE_PORT})" | toString }} + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get service --namespace {{ .Release.Namespace }} {{ $serviceName }} -o jsonpath="{.spec.ports[0].nodePort}") + {{- end }} + ``` + +{{- end }} + +Visit the following service(s) at the provided address: + +{{- if $serviceAddress }} + + - WaktuSolat: {{ $serviceAddress }} + +{{- else }} + + ⚠️ This chart may have no accessible services available + +{{- end }} + +The following are a list of account(s) you have supplied to be managed: + +{{- if not $accounts }} + + ⚠️ No accounts were supplied for WaktuSolat to manage + +{{- else }} + + {{- range $index, $account := $accounts }} + {{- $enabled := $account.enabled | default "true" | toString }} + {{- $api := $account.api | toString }} + {{- $id := $account.id | toString }} + {{- $url := printf "%s/%s" ($api | trimSuffix "/") $id | toString }} + {{- $entry := printf "%s. %s (%s)" ($index | add1 | toString) $id $url | toString }} + + {{- if eq $enabled "true" }} + + {{ $entry }} + + {{- else }} + + {{ printf "%s [%s]" $entry "disabled" }} + + {{- end }} + + {{- end }} + +The following are a list of prayer time feed(s) you have supplied to be monitored: + + {{- if not $feeds }} + + ⚠️ No prayer time feeds were supplied for WaktuSolat to monitor - image defaults will apply instead + + {{- else }} + + {{- range $index, $feed := $feeds }} + {{- $enabled := $feed.enabled | default "true" | toString }} + {{- $uid := $feed.id | toString }} + {{- $endpoint := $feed.endpoint | toString | trimSuffix "/" }} + {{- $entry := printf "%s. %s (%s)" ($index | add1 | toString) $uid $endpoint | toString }} + + {{- if eq $enabled "true" }} + + {{ $entry }} + + {{- else }} + + {{ printf "%s [%s]" $entry "disabled" }} + + {{- end }} + + {{- end }} + + {{- end }} + +{{- end }} + +For more information on how to use and configure WaktuSolat, please refer to the official documentation. \ No newline at end of file diff --git a/mika/waktusolat/templates/accounts.json.tpl b/mika/waktusolat/templates/accounts.json.tpl index 28080f56..9e80ace8 100644 --- a/mika/waktusolat/templates/accounts.json.tpl +++ b/mika/waktusolat/templates/accounts.json.tpl @@ -1,10 +1,10 @@ {{/* -Mastodon /base/lib/accounts.json template +WaktuSolat /base/lib/accounts.json template */}} {{- define "waktusolat.accounts-json" -}} { "accounts": [ - {{- $accounts := .Values.waktusolat.mastodon }} + {{- $accounts := .Values.waktusolat.account }} {{- range $index, $account := $accounts }} {{- $normalised_api := $account.api | toString | replace "https" "" | replace ":" "" | replace "/" "" | replace "." "-" }} {{- $token_secret := printf "%s-%s.secret" $account.id $normalised_api | toString | replace " " "" }} @@ -29,6 +29,7 @@ Mastodon /base/lib/accounts.json template ]{{ if ne $i (sub (len $fields) 1) }},{{ end }} {{- end }} ], + "host": {{ $account.host | default "mastodon" | toString | quote }}, "is_locked": {{ $account.locked | default "false" | toString }}, {{- if $account.note }} "note": {{ $account.note | toString | quote }} diff --git a/mika/waktusolat/templates/celery.py.tpl b/mika/waktusolat/templates/celery.py.tpl index ec0d1644..189d9852 100644 --- a/mika/waktusolat/templates/celery.py.tpl +++ b/mika/waktusolat/templates/celery.py.tpl @@ -3,18 +3,18 @@ Celery /base/base/celery.py template */}} {{- define "waktusolat.celery-py" -}} -{{- $clean_db_hour := .Values.waktusolat.scheduler.schedule.clean_db.hour | default "0" | toString -}} -{{- $clean_db_minute := .Values.waktusolat.scheduler.schedule.clean_db.minute | default "0" | toString -}} -{{- $clean_db_second := .Values.waktusolat.scheduler.schedule.clean_db.second | toString -}} -{{- $notify_solat_schedule_hour := .Values.waktusolat.scheduler.schedule.notify_solat_schedule.hour | default "5" | toString -}} -{{- $notify_solat_schedule_minute := .Values.waktusolat.scheduler.schedule.notify_solat_schedule.minute | default "0" | toString -}} -{{- $notify_solat_schedule_second := .Values.waktusolat.scheduler.schedule.notify_solat_schedule.second | toString -}} -{{- $notify_solat_times_hour := .Values.waktusolat.scheduler.schedule.notify_solat_times.hour | default "*" | toString -}} -{{- $notify_solat_times_minute := .Values.waktusolat.scheduler.schedule.notify_solat_times.minute | default "*/1" | toString -}} -{{- $notify_solat_times_second := .Values.waktusolat.scheduler.schedule.notify_solat_times.second | toString -}} -{{- $post_scheduler_hour := .Values.waktusolat.scheduler.schedule.post_scheduler.hour | default "*" | toString -}} -{{- $post_scheduler_minute := .Values.waktusolat.scheduler.schedule.post_scheduler.minute | default "*" | toString -}} -{{- $post_scheduler_second := .Values.waktusolat.scheduler.schedule.post_scheduler.second | default "*/1" | toString -}} +{{- $clean_db_hour := .Values.scheduler.schedule.clean_db.hour | default "0" | toString -}} +{{- $clean_db_minute := .Values.scheduler.schedule.clean_db.minute | default "0" | toString -}} +{{- $clean_db_second := .Values.scheduler.schedule.clean_db.second | toString -}} +{{- $notify_solat_schedule_hour := .Values.scheduler.schedule.notify_solat_schedule.hour | default "5" | toString -}} +{{- $notify_solat_schedule_minute := .Values.scheduler.schedule.notify_solat_schedule.minute | default "0" | toString -}} +{{- $notify_solat_schedule_second := .Values.scheduler.schedule.notify_solat_schedule.second | toString -}} +{{- $notify_solat_times_hour := .Values.scheduler.schedule.notify_solat_times.hour | default "*" | toString -}} +{{- $notify_solat_times_minute := .Values.scheduler.schedule.notify_solat_times.minute | default "*/1" | toString -}} +{{- $notify_solat_times_second := .Values.scheduler.schedule.notify_solat_times.second | toString -}} +{{- $post_scheduler_hour := .Values.scheduler.schedule.post_scheduler.hour | default "*" | toString -}} +{{- $post_scheduler_minute := .Values.scheduler.schedule.post_scheduler.minute | default "*" | toString -}} +{{- $post_scheduler_second := .Values.scheduler.schedule.post_scheduler.second | toString -}} from __future__ import absolute_import, unicode_literals import os diff --git a/mika/waktusolat/templates/configmap.yaml b/mika/waktusolat/templates/configmap.yaml index bfa3193b..d7db4afd 100644 --- a/mika/waktusolat/templates/configmap.yaml +++ b/mika/waktusolat/templates/configmap.yaml @@ -1,13 +1,18 @@ +{{- $apscheduler := .Values.scheduler.apscheduler }} +{{- $celery := .Values.scheduler.celery }} +{{- $feeds := .Values.waktusolat.feed }} {{- $debug := .Values.waktusolat.debug | default "false" | toString | quote }} -{{- $location := .Values.waktusolat.location | default "wlp-0" | join "," | toString | quote }} +{{- $scheduler_timezone := .Values.scheduler.timezone | default "Etc/UTC" | toString | quote }} {{- $visibility := .Values.waktusolat.visibility | default "public" | toString | quote }} +{{- $location := .Values.waktusolat.location | default "wlp-0" | join "," | toString | quote }} +{{- $organic := .Values.waktusolat.organic | default "true" | toString | quote }} {{- $post_limit := .Values.waktusolat.post_limit | default "0" | toString | quote }} -{{- $retry_post := .Values.waktusolat.retry_post | default "false" | toString | quote }} -{{- $scheduler_timezone := .Values.waktusolat.scheduler.timezone | default "Asia/Kuala_Lumpur" | toString | quote }} +{{- $retry_post := .Values.waktusolat.retry_post | default "true" | toString | quote }} {{- $redis_service := printf "redis://%s-waktusolat-svc" .Release.Name | quote }} {{- $domain := .Values.waktusolat.domain | default "localhost" | toString }} -{{- $apscheduler := .Values.waktusolat.scheduler.apscheduler }} -{{- $celery := .Values.waktusolat.scheduler.celery }} +{{- $serverAdmin := .Values.waktusolat.serverAdmin | default "admin@example.com" | toString }} +{{- $logMountPath := .Values.storage.log.mountPath | default "/var/log/apache2" | toString }} +--- apiVersion: v1 kind: ConfigMap metadata: @@ -16,8 +21,9 @@ metadata: {{- include "waktusolat.labels" . | nindent 4 }} data: DEBUG: {{ $debug }} - LOCATION_CODES: {{ $location }} DEFAULT_VISIBILITY: {{ $visibility }} + LOCATION_CODES: {{ $location }} + ORGANIC_POSTS: {{ $organic }} POST_LIMIT: {{ $post_limit }} RETRY_POST: {{ $retry_post }} {{- if $celery }} @@ -36,8 +42,8 @@ metadata: {{- include "waktusolat.labels" . | nindent 4 }} data: site-config.conf: |- - {{- include "waktusolat.site-config-conf" . | replace "DOMAIN" $domain | nindent 4 }} -{{- if .Values.waktusolat.feed }} + {{- include "waktusolat.site-config-conf" . | toString | replace "DOMAIN" $domain | replace "SERVER_ADMIN" $serverAdmin | replace "LOG_MOUNT_PATH" $logMountPath | nindent 4 }} +{{- if $feeds }} --- apiVersion: v1 kind: ConfigMap @@ -59,7 +65,7 @@ metadata: {{- include "waktusolat.labels" . | nindent 4 }} data: entrypoint.sh: |- - {{- include "waktusolat.apscheduler-entrypoint-sh" . | nindent 4 }} + {{- include "waktusolat.apscheduler-entrypoint-sh" . | toString | nindent 4 }} {{- else if $celery }} --- apiVersion: v1 @@ -70,7 +76,7 @@ metadata: {{- include "waktusolat.labels" . | nindent 4 }} data: celeryd: |- - {{- include "waktusolat.default-celeryd" . | nindent 4 }} + {{- include "waktusolat.default-celeryd" . | toString | nindent 4 }} --- apiVersion: v1 kind: ConfigMap @@ -80,9 +86,9 @@ metadata: {{- include "waktusolat.labels" . | nindent 4 }} data: celerybeat: |- - {{- include "waktusolat.initd-celerybeat" . | nindent 4 }} + {{- include "waktusolat.initd-celerybeat" . | toString | nindent 4 }} celeryd: |- - {{- include "waktusolat.initd-celeryd" . | nindent 4 }} + {{- include "waktusolat.initd-celeryd" . | toString | nindent 4 }} {{- end }} {{- if or $apscheduler $celery }} --- @@ -95,17 +101,17 @@ metadata: data: {{- if $apscheduler }} apps.py: |- - {{- include "waktusolat.apscheduler-apps-py" . | nindent 4 }} + {{- include "waktusolat.apscheduler-apps-py" . | toString | nindent 4 }} {{- else if $celery }} celery.py: |- - {{- include "waktusolat.celery-py" . | nindent 4 }} + {{- include "waktusolat.celery-py" . | toString | nindent 4 }} init.py: |- - {{- include "waktusolat.celery-init-py" . | nindent 4 }} + {{- include "waktusolat.celery-init-py" . | toString | nindent 4 }} {{- end }} tasks.py: |- {{- if $apscheduler }} - {{- include "waktusolat.apscheduler-tasks-py" . | nindent 4 }} + {{- include "waktusolat.apscheduler-tasks-py" . | toString | nindent 4 }} {{- else if $celery }} - {{- include "waktusolat.celery-tasks-py" . | nindent 4 }} + {{- include "waktusolat.celery-tasks-py" . | toString | nindent 4 }} {{- end }} {{- end }} diff --git a/mika/waktusolat/templates/deployment.yaml b/mika/waktusolat/templates/deployment.yaml index 0a531188..1f14a7b4 100644 --- a/mika/waktusolat/templates/deployment.yaml +++ b/mika/waktusolat/templates/deployment.yaml @@ -1,5 +1,8 @@ -{{- $release_name := .Release.Name | toString }} -{{- $replica_count := .Values.replicaCount | default "1" | toString }} +{{- $accounts := .Values.waktusolat.account }} +{{- $apscheduler := .Values.scheduler.apscheduler }} +{{- $celery := .Values.scheduler.celery }} +{{- $feeds := .Values.waktusolat.feed }} +{{- $logPersistence := .Values.storage.log.enabled }} {{- $waktusolat_registry := .Values.image.waktusolat.registry | default "ghcr.io" | toString }} {{- $waktusolat_repository := .Values.image.waktusolat.repository | default "irfanhakim-as/waktusolat" | toString }} {{- $waktusolat_tag := .Values.image.waktusolat.tag | default .Chart.AppVersion | toString }} @@ -8,9 +11,10 @@ {{- $redis_repository := .Values.image.redis.repository | default "redis" | toString }} {{- $redis_tag := .Values.image.redis.tag | default "alpine" | toString }} {{- $redis_pullPolicy := .Values.image.redis.pullPolicy | default "IfNotPresent" | toString | quote }} -{{- $apscheduler := .Values.waktusolat.scheduler.apscheduler }} -{{- $celery := .Values.waktusolat.scheduler.celery }} -{{- $persistence := .Values.waktusolat.persistence.enabled }} +{{- $release_name := .Release.Name | toString }} +{{- $replica_count := .Values.replicaCount | default "1" | toString }} +{{- $logMountPath := .Values.storage.log.mountPath | default "/var/log/apache2" | toString | quote }} +{{- $logSubPath := .Values.storage.log.subPath | toString }} apiVersion: apps/v1 kind: Deployment metadata: @@ -55,11 +59,11 @@ spec: mountPath: /etc/apache2/sites-available/000-default.conf subPath: site-config.conf readOnly: true - - name: {{ .Release.Name }}-waktusolat-mastodon-config + - name: {{ .Release.Name }}-waktusolat-account-config mountPath: /base/data/accounts.json subPath: accounts.json readOnly: true - {{- if .Values.waktusolat.feed }} + {{- if $feeds }} - name: {{ .Release.Name }}-waktusolat-feed-config mountPath: /base/data/feeds.json subPath: feeds.json @@ -85,7 +89,7 @@ spec: mountPath: /base/base/__init__.py subPath: init.py {{- end }} - {{- range .Values.waktusolat.mastodon }} + {{- range $accounts }} {{- $normalised_api := .api | toString | replace "https" "" | replace ":" "" | replace "/" "" | replace "." "-" }} {{- $token_secret := printf "%s-%s.secret" .id $normalised_api | toString | replace " " "" }} - name: {{ $release_name }}-waktusolat-token-secret @@ -93,9 +97,12 @@ spec: subPath: {{ $token_secret }} readOnly: true {{- end }} - {{- if $persistence }} - - name: {{ .Release.Name }}-waktusolat-logs - mountPath: /var/log/apache2 + {{- if $logPersistence }} + - name: {{ .Release.Name }}-waktusolat-log + mountPath: {{ $logMountPath }} + {{- if $logSubPath }} + subPath: {{ $logSubPath | quote }} + {{- end }} {{- end }} {{- if $apscheduler }} - name: apscheduler @@ -113,7 +120,7 @@ spec: - secretRef: name: {{ .Release.Name }}-waktusolat-secret volumeMounts: - - name: {{ .Release.Name }}-waktusolat-mastodon-config + - name: {{ .Release.Name }}-waktusolat-account-config mountPath: /base/data/accounts.json subPath: accounts.json readOnly: true @@ -126,7 +133,7 @@ spec: - name: {{ .Release.Name }}-waktusolat-scheduler-config mountPath: /base/base/tasks.py subPath: tasks.py - {{- range .Values.waktusolat.mastodon }} + {{- range $accounts }} {{- $normalised_api := .api | toString | replace "https" "" | replace ":" "" | replace "/" "" | replace "." "-" }} {{- $token_secret := printf "%s-%s.secret" .id $normalised_api | toString | replace " " "" }} - name: {{ $release_name }}-waktusolat-token-secret @@ -134,15 +141,18 @@ spec: subPath: {{ $token_secret }} readOnly: true {{- end }} - {{- if .Values.waktusolat.feed }} + {{- if $feeds }} - name: {{ .Release.Name }}-waktusolat-feed-config mountPath: /base/data/feeds.json subPath: feeds.json readOnly: true {{- end }} - {{- if $persistence }} - - name: {{ .Release.Name }}-waktusolat-logs - mountPath: /var/log/apache2 + {{- if $logPersistence }} + - name: {{ .Release.Name }}-waktusolat-log + mountPath: {{ $logMountPath }} + {{- if $logSubPath }} + subPath: {{ $logSubPath | quote }} + {{- end }} {{- end }} {{- else if $celery }} - name: redis @@ -159,10 +169,10 @@ spec: - name: {{ .Release.Name }}-waktusolat-site-config configMap: name: {{ .Release.Name }}-waktusolat-site-config - - name: {{ .Release.Name }}-waktusolat-mastodon-config + - name: {{ .Release.Name }}-waktusolat-account-config secret: - secretName: {{ .Release.Name }}-waktusolat-mastodon-config - {{- if .Values.waktusolat.feed }} + secretName: {{ .Release.Name }}-waktusolat-account-config + {{- if $feeds }} - name: {{ .Release.Name }}-waktusolat-feed-config configMap: name: {{ .Release.Name }}-waktusolat-feed-config @@ -211,22 +221,22 @@ spec: - key: tasks.py path: tasks.py {{- end }} - {{- if .Values.waktusolat.mastodon }} + {{- if $accounts }} - name: {{ .Release.Name }}-waktusolat-token-secret secret: secretName: {{ .Release.Name }}-waktusolat-token-secret items: - {{- range .Values.waktusolat.mastodon }} + {{- range $accounts }} {{- $normalised_api := .api | toString | replace "https" "" | replace ":" "" | replace "/" "" | replace "." "-" }} {{- $token_secret := printf "%s-%s.secret" .id $normalised_api | toString | replace " " "" }} - key: {{ $token_secret }} path: {{ $token_secret }} {{- end }} {{- end }} - {{- if $persistence }} - - name: {{ .Release.Name }}-waktusolat-logs + {{- if $logPersistence }} + - name: {{ .Release.Name }}-waktusolat-log persistentVolumeClaim: - claimName: {{ .Release.Name }}-waktusolat-logs-pvc + claimName: {{ .Release.Name }}-waktusolat-log-pvc {{- end }} securityContext: fsGroup: 33 diff --git a/mika/waktusolat/templates/feeds.json.tpl b/mika/waktusolat/templates/feeds.json.tpl index 56fd6175..38ea6201 100644 --- a/mika/waktusolat/templates/feeds.json.tpl +++ b/mika/waktusolat/templates/feeds.json.tpl @@ -1,5 +1,5 @@ {{/* -Mastodon /base/lib/feeds.json template +WaktuSolat /base/lib/feeds.json template */}} {{- define "waktusolat.feeds-json" -}} { @@ -9,7 +9,7 @@ Mastodon /base/lib/feeds.json template { "uid": {{ $feed.id | toString | quote }}, "endpoint": {{ $feed.endpoint | toString | quote }}, - "is_enabled": {{ $feed.enabled | default "true" | toString }}, + "is_enabled": {{ $feed.enabled | default "true" | toString }} }{{ if ne $index (sub (len $feeds) 1) }},{{ end }} {{- end }} ] diff --git a/mika/waktusolat/templates/ingress.yaml b/mika/waktusolat/templates/ingress.yaml new file mode 100644 index 00000000..9f3413a0 --- /dev/null +++ b/mika/waktusolat/templates/ingress.yaml @@ -0,0 +1,60 @@ +{{- $ingress := .Values.ingress.enabled }} +{{- $www := .Values.ingress.www }} +{{- $clusterIssuer := .Values.ingress.clusterIssuer | default "letsencrypt-dns-prod" | toString | quote }} +{{- $customAnnotations := .Values.ingress.customAnnotations }} +{{- $domain := .Values.waktusolat.domain | toString }} +{{- $wwwDomain := printf "www.%s" $domain | toString | quote }} +{{- if and $ingress $domain }} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ .Release.Name }}-waktusolat-ingress + labels: + {{- include "waktusolat.labels" . | nindent 4 }} + annotations: + cert-manager.io/cluster-issuer: {{ $clusterIssuer }} + cert-manager.io/private-key-algorithm: "ECDSA" + nginx.ingress.kubernetes.io/affinity: "cookie" + nginx.ingress.kubernetes.io/affinity-mode: "persistent" + nginx.ingress.kubernetes.io/proxy-body-size: "100m" + nginx.ingress.kubernetes.io/session-cookie-expires: "172800" + nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" + nginx.ingress.kubernetes.io/session-cookie-name: "route" + nginx.org/client-max-body-size: "100m" + {{- range $customAnnotations }} + {{ printf "%s/%s" (.prefix | default "nginx.ingress.kubernetes.io") .name }}: {{ .value | quote }} + {{- end }} +spec: + ingressClassName: "nginx" + rules: + - host: {{ $domain | quote }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }}-waktusolat-svc + port: + name: waktusolat + path: / + pathType: Prefix + {{- if $www }} + - host: {{ $wwwDomain }} + http: + paths: + - backend: + service: + name: {{ .Release.Name }}-waktusolat-svc + port: + name: waktusolat + path: / + pathType: Prefix + {{- end }} + tls: + - hosts: + - {{ $domain | quote }} + {{- if $www }} + - {{ $wwwDomain }} + {{- end }} + secretName: {{ .Release.Name }}-waktusolat-tls-cert +{{- end }} diff --git a/mika/waktusolat/templates/pvc.yaml b/mika/waktusolat/templates/pvc.yaml index 40ea8c1d..2f8fd038 100644 --- a/mika/waktusolat/templates/pvc.yaml +++ b/mika/waktusolat/templates/pvc.yaml @@ -1,18 +1,20 @@ -{{- $logs_storage := .Values.waktusolat.persistence.logs.storage | default "20Mi" | toString | quote }} -{{- $storage_class_name := .Values.waktusolat.persistence.storageClassName | default "longhorn" | toString | quote }} -{{- $persistence := .Values.waktusolat.persistence.enabled }} -{{- if $persistence }} +{{- $logPersistence := .Values.storage.log.enabled }} +{{- $logAccessMode := .Values.storage.log.accessMode | default "ReadWriteMany" | toString | quote }} +{{- $logStorage := .Values.storage.log.storage | default "50Mi" | toString | quote }} +{{- $logStorageClassName := .Values.storage.log.storageClassName | default "longhorn" | toString | quote }} +{{- if $logPersistence }} +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ .Release.Name }}-waktusolat-logs-pvc + name: {{ .Release.Name }}-waktusolat-log-pvc labels: {{- include "waktusolat.labels" . | nindent 4 }} spec: accessModes: - - ReadWriteMany + - {{ $logAccessMode }} resources: requests: - storage: {{ $logs_storage }} - storageClassName: {{ $storage_class_name }} + storage: {{ $logStorage }} + storageClassName: {{ $logStorageClassName }} {{- end }} diff --git a/mika/waktusolat/templates/secret.yaml b/mika/waktusolat/templates/secret.yaml index fd1ae2ea..f15579a7 100644 --- a/mika/waktusolat/templates/secret.yaml +++ b/mika/waktusolat/templates/secret.yaml @@ -1,3 +1,4 @@ +{{- $accounts := .Values.waktusolat.account }} {{- $secret := .Values.waktusolat.secret | toString | b64enc }} {{- $db_type := .Values.db.type | default "postgresql" | toString | b64enc }} {{- $db_name := .Values.db.name | toString | b64enc }} @@ -5,6 +6,7 @@ {{- $db_password := .Values.db.password | toString | b64enc }} {{- $db_host := .Values.db.host | toString | b64enc }} {{- $db_port := .Values.db.port | default "5432" | toString | b64enc }} +--- apiVersion: v1 kind: Secret metadata: @@ -24,14 +26,14 @@ data: apiVersion: v1 kind: Secret metadata: - name: {{ .Release.Name }}-waktusolat-mastodon-config + name: {{ .Release.Name }}-waktusolat-account-config labels: {{- include "waktusolat.labels" . | nindent 4 }} type: Opaque data: accounts.json: |- {{- include "waktusolat.accounts-json" . | toString | b64enc | nindent 4 }} -{{- if .Values.waktusolat.mastodon }} +{{- if $accounts }} --- apiVersion: v1 kind: Secret @@ -41,10 +43,10 @@ metadata: {{- include "waktusolat.labels" . | nindent 4 }} type: Opaque data: - {{- range .Values.waktusolat.mastodon }} + {{- range $accounts }} {{- $normalised_api := .api | toString | replace "https" "" | replace ":" "" | replace "/" "" | replace "." "-" }} {{- $token_secret := printf "%s-%s.secret" .id $normalised_api | toString | replace " " "" }} {{ $token_secret }}: |- - {{ .token | toString | b64enc | nindent 4 }} + {{- .token | toString | b64enc | nindent 4 }} {{- end }} {{- end }} diff --git a/mika/waktusolat/templates/service.yaml b/mika/waktusolat/templates/service.yaml index c423e77a..76f80ac1 100644 --- a/mika/waktusolat/templates/service.yaml +++ b/mika/waktusolat/templates/service.yaml @@ -1,4 +1,10 @@ -{{- $celery := .Values.waktusolat.scheduler.celery }} +{{- $celery := .Values.scheduler.celery }} +{{- $waktusolatPort := .Values.service.waktusolat.port | default "80" | toString }} +{{- $waktusolatNodePort := .Values.service.waktusolat.nodePort | toString }} +{{- $redisPort := .Values.service.redis.port | default "6379" | toString }} +{{- $redisNodePort := .Values.service.redis.nodePort | toString }} +{{- $type := .Values.service.type | default "ClusterIP" | toString }} +--- apiVersion: v1 kind: Service metadata: @@ -6,17 +12,23 @@ metadata: labels: {{- include "waktusolat.labels" . | nindent 4 }} spec: - type: ClusterIP + type: {{ $type }} ports: - - port: 80 + - port: {{ int $waktusolatPort }} targetPort: waktusolat + {{- if and (eq $type "NodePort") $waktusolatNodePort }} + nodePort: {{ int $waktusolatNodePort }} + {{- end }} protocol: TCP - name: {{ .Release.Name }}-waktusolat + name: waktusolat {{- if $celery }} - - port: 6379 + - port: {{ int $redisPort }} targetPort: redis + {{- if and (eq $type "NodePort") $redisNodePort }} + nodePort: {{ int $redisNodePort }} + {{- end }} protocol: TCP - name: {{ .Release.Name }}-redis + name: redis {{- end }} selector: {{- include "waktusolat.selectorLabels" . | nindent 4 }} diff --git a/mika/waktusolat/templates/site-config-conf.tpl b/mika/waktusolat/templates/site-config-conf.tpl index bfd17433..994fd5c4 100644 --- a/mika/waktusolat/templates/site-config-conf.tpl +++ b/mika/waktusolat/templates/site-config-conf.tpl @@ -5,7 +5,7 @@ Apache site-config.conf template ServerName DOMAIN:443 UseCanonicalName On - ServerAdmin support@mikahomelab.com + ServerAdmin SERVER_ADMIN DocumentRoot /base WSGIScriptAlias / /base/base/wsgi.py WSGIDaemonProcess DOMAIN python-path=/base @@ -22,7 +22,7 @@ Apache site-config.conf template Require all granted - ErrorLog /var/log/apache2/apache.error.log - CustomLog /var/log/apache2/apache.access.log combined + ErrorLog LOG_MOUNT_PATH/apache.error.log + CustomLog LOG_MOUNT_PATH/apache.access.log combined {{- end }} diff --git a/mika/waktusolat/templates/tasks.py.tpl b/mika/waktusolat/templates/tasks.py.tpl index ce7693b6..9caac9da 100644 --- a/mika/waktusolat/templates/tasks.py.tpl +++ b/mika/waktusolat/templates/tasks.py.tpl @@ -3,18 +3,18 @@ APScheduler /base/base/tasks.py template */}} {{- define "waktusolat.apscheduler-tasks-py" -}} -{{- $clean_db_hour := .Values.waktusolat.scheduler.schedule.clean_db.hour | default "0" | toString -}} -{{- $clean_db_minute := .Values.waktusolat.scheduler.schedule.clean_db.minute | default "0" | toString -}} -{{- $clean_db_second := .Values.waktusolat.scheduler.schedule.clean_db.second | default "0" | toString -}} -{{- $notify_solat_schedule_hour := .Values.waktusolat.scheduler.schedule.notify_solat_schedule.hour | default "5" | toString -}} -{{- $notify_solat_schedule_minute := .Values.waktusolat.scheduler.schedule.notify_solat_schedule.minute | default "0" | toString -}} -{{- $notify_solat_schedule_second := .Values.waktusolat.scheduler.schedule.notify_solat_schedule.second | default "0" | toString -}} -{{- $notify_solat_times_hour := .Values.waktusolat.scheduler.schedule.notify_solat_times.hour | default "*" | toString -}} -{{- $notify_solat_times_minute := .Values.waktusolat.scheduler.schedule.notify_solat_times.minute | default "*/1" | toString -}} -{{- $notify_solat_times_second := .Values.waktusolat.scheduler.schedule.notify_solat_times.second | default "0" | toString -}} -{{- $post_scheduler_hour := .Values.waktusolat.scheduler.schedule.post_scheduler.hour | default "*" | toString -}} -{{- $post_scheduler_minute := .Values.waktusolat.scheduler.schedule.post_scheduler.minute | default "*" | toString -}} -{{- $post_scheduler_second := .Values.waktusolat.scheduler.schedule.post_scheduler.second | default "*/1" | toString -}} +{{- $clean_db_hour := .Values.scheduler.schedule.clean_db.hour | default "0" | toString -}} +{{- $clean_db_minute := .Values.scheduler.schedule.clean_db.minute | default "0" | toString -}} +{{- $clean_db_second := .Values.scheduler.schedule.clean_db.second | default "0" | toString -}} +{{- $notify_solat_schedule_hour := .Values.scheduler.schedule.notify_solat_schedule.hour | default "5" | toString -}} +{{- $notify_solat_schedule_minute := .Values.scheduler.schedule.notify_solat_schedule.minute | default "0" | toString -}} +{{- $notify_solat_schedule_second := .Values.scheduler.schedule.notify_solat_schedule.second | default "0" | toString -}} +{{- $notify_solat_times_hour := .Values.scheduler.schedule.notify_solat_times.hour | default "*" | toString -}} +{{- $notify_solat_times_minute := .Values.scheduler.schedule.notify_solat_times.minute | default "*/1" | toString -}} +{{- $notify_solat_times_second := .Values.scheduler.schedule.notify_solat_times.second | default "0" | toString -}} +{{- $post_scheduler_hour := .Values.scheduler.schedule.post_scheduler.hour | default "*" | toString -}} +{{- $post_scheduler_minute := .Values.scheduler.schedule.post_scheduler.minute | default "*" | toString -}} +{{- $post_scheduler_second := .Values.scheduler.schedule.post_scheduler.second | default "*/1" | toString -}} from apscheduler.schedulers.blocking import BlockingScheduler from django.conf import settings diff --git a/mika/waktusolat/values.yaml b/mika/waktusolat/values.yaml index 539c3dac..68553712 100644 --- a/mika/waktusolat/values.yaml +++ b/mika/waktusolat/values.yaml @@ -9,6 +9,7 @@ replicaCount: "" # Container images used for WaktuSolat. image: # WaktuSolat container image configurations. + # Source: https://github.com/irfanhakim-as/waktusolat/pkgs/container/waktusolat waktusolat: # The registry where the WaktuSolat container image is hosted. # Default: "ghcr.io" @@ -23,6 +24,7 @@ image: # Default: "IfNotPresent" pullPolicy: "" # Redis container image configurations. + # Source: https://hub.docker.com/_/redis redis: # The registry where the Redis container image is hosted. # Default: "docker.io" @@ -50,10 +52,10 @@ waktusolat: # Example: # debug: true debug: false - # The domain name of the WaktuSolat service. + # The ingress domain name that hosts the WaktuSolat server. # Default: "localhost" # Example: - # domain: "localhost" + # domain: "waktusolat.example.com" domain: "" # The limit number of posts to be scheduled for posting per run. # Default: "0" (Unlimited) @@ -61,14 +63,19 @@ waktusolat: # post_limit: "5" post_limit: "" # Specifies whether to retry posting if the post fails to be sent. - # Default: false + # Default: "false" # Example: - # retry_post: true - retry_post: false + # retry_post: "true" + retry_post: "" # A 50-character secret key used for secure session management and cryptographic operations within the WaktuSolat service. # Example: # secret: "6&p4%t)-$8a14fmfh92py8j55+us51r6%e52dzy&=a3-6yd4#e" secret: "" + # The email address displayed by Apache for server administration contact. + # Default: "admin@example.com" + # Example: + # serverAdmin: "foo@example.com" + serverAdmin: "" # The default visibility of posts made by the WaktuSolat service. # Default: "public" # Example: @@ -81,43 +88,52 @@ waktusolat: # - "swk-33" # - "wlp-1" location: [] - # WaktuSolat Mastodon configurations. + # Account configurations. + # Items: `.api`, `.id`, `.host`, `.token`, `.bot`, `.discoverable`, `.enabled`, `.display_name`, `.fields`, `.locked`, `.note` # Example: - # mastodon: - # # API endpoint or URL for the Mastodon instance of the WaktuSolat bot. + # account: + # # API endpoint or URL for the server instance of the WaktuSolat bot. # # Example: # # api: "https://botsin.space" # - api: "" - # # The username or user account for the Mastodon instance of the WaktuSolat bot. + # # The username or user account for the server instance of the WaktuSolat bot. # # Example: # # id: "waktusolat" # id: "" - # # A secure token required to authenticate the WaktuSolat service with the Mastodon instance's API. + # # The underlying host service of the server instance. + # # Default: "mastodon" + # # Example: + # # host: "bluesky" + # host: "" + # # The application access token required to authenticate the WaktuSolat service with the server instance's API. # # Example: - # # token: "6&p4%t)-$8a14fmfh92py8j55+us51r6%e52dzy&=a3-6yd4#e" + # # token: "rinoSZiIvRHLw6PL1QCSia+8liGDau0MZ336JAnL0IQ" # token: "" # # Specifies whether the WaktuSolat bot should be marked as a bot. - # # Default: true + # # Note: Bluesky does not currently support this field. + # # Default: "true" # # Example: - # # bot: false + # # bot: "false" # bot: "" # # Specifies whether the WaktuSolat bot should appear in the user directory. - # # Default: true + # # Note: Bluesky does not currently support this field. + # # Default: "true" # # Example: - # # discoverable: false + # # discoverable: "false" # discoverable: "" # # Specifies whether the WaktuSolat bot should be active. - # # Default: true + # # Default: "true" # # Example: - # # enabled: false + # # enabled: "false" # enabled: "" # # The display name of the WaktuSolat bot. - # # Default: null + # # Note: Bluesky does not currently support this field. + # # Default: "null" # # Example: # # display_name: "WaktuSolat" # display_name: "" # # A list of up to four name-value pairs information to be displayed on the WaktuSolat bot's profile. - # # Default: [] + # # Note: Bluesky does not officially support this field. # # Example: # # fields: # # - name: "Website 1" @@ -126,146 +142,142 @@ waktusolat: # # value: "https://domain2.example.org" # fields: [] # # Specifies whether the WaktuSolat bot needs to manually approve follow requests. - # # Default: false + # # Note: Bluesky does not currently support this field. + # # Default: "false" # # Example: - # # locked: true + # # locked: "true" # locked: "" # # The bio of the WaktuSolat bot. - # # Default: null + # # Note: Bluesky does not currently support this field. + # # Default: "null" # # Example: # # note: "This is the bio of the WaktuSolat bot." # note: "" - mastodon: [] - # WaktuSolat storage persistence configurations. - persistence: - # Specifies whether WaktuSolat should persist its storage. - # Example: - # enabled: true - enabled: false - # The storage class name used for dynamically provisioning a persistent volume for the WaktuSolat storage. - # Default: "longhorn" - # Example: - # storageClassName: "longhorn" - storageClassName: "" - # WaktuSolat logs persistence configurations. - logs: - # The amount of persistent storage allocated for WaktuSolat logs. - # Default: "20Mi" - # Example: - # storage: "1Gi" - storage: "" + account: [] # WaktuSolat feed configurations. + # Items: `.endpoint`, `.id`, `.enabled` # Example: # feed: - # # The URL of the prayer time API feed to be used by WaktuSolat. + # # The URL of the prayer time API feed to be tracked by WaktuSolat. # # Example: # # endpoint: "https://mpt.i906.my/api/prayer/%s" # - endpoint: "" - # # The unique identifier of the API feed entry, must be an ISO 3166 Alpha-2 country code in uppercase. + # # The unique identifier of the API feed entry - must be an ISO 3166 Alpha-2 country code in uppercase. # # Example: # # id: "MY" # id: "" - # # Specifies whether the API feed entry should be active to be used. - # # Default: true + # # Specifies whether the prayer time API feed entry should be actively processed. + # # Default: "true" # # Example: - # # enabled: false + # # enabled: "false" # enabled: "" feed: [] - # WaktuSolat scheduler configurations. - scheduler: - # Specifies whether APScheduler should be used by WaktuSolat as the task scheduler. - # Example: - # apscheduler: false - apscheduler: true - # Specifies whether Celery should be used by WaktuSolat as the task scheduler. - # Example: - # celery: true - celery: false - # The schedule for the task scheduler used by WaktuSolat. - # Note: The `apscheduler` scheduler supports the `hour`, `minute`, and `second` fields simultaneously. The `celery` scheduler only supports a combination of the `hour` and `minute` fields, or the `second` field alone. - schedule: - # The schedule for cleaning up the database. - clean_db: - # The hours at which the task scheduler cleans up the database. - # Default: "0" - # Example: - # hour: "1" - hour: "" - # The minutes at which the task scheduler cleans up the database. - # Default: "0" - # Example: - # minute: "15" - minute: "" - # The seconds at which the task scheduler cleans up the database. - # Default: "0" for `apscheduler` - # Example: - # second: "30" - second: "" - # The schedule for scheduling the daily prayer time schedule posts. - notify_solat_schedule: - # The hours at which the task scheduler schedules the daily prayer time schedule posts. - # Default: "5" - # Example: - # hour: "4" - hour: "" - # The minutes at which the task scheduler schedules the daily prayer time schedule posts. - # Default: "0" - # Example: - # minute: "15" - minute: "" - # The seconds at which the task scheduler schedules the daily prayer time schedule posts. - # Default: "0" for `apscheduler` - # Example: - # second: "30" - second: "" - # The schedule for scheduling prayer time notifications. - notify_solat_times: - # The hours at which the task scheduler schedules prayer time notifications. - # Default: "*" - # Example: - # hour: "6,13,16,19,20" - hour: "" - # The minutes at which the task scheduler schedules prayer time notifications. - # Default: "*/1" - # Example: - # minute: "*" - minute: "" - # The seconds at which the task scheduler schedules prayer time notifications. - # Default: "0" for `apscheduler` - # Example: - # second: "30" - second: "" - # The schedule for posting scheduled posts. - post_scheduler: - # The hours at which the task scheduler posts scheduled posts. - # Default: "*" - # Example: - # hour: "4-20" - hour: "" - # The minutes at which the task scheduler posts scheduled posts. - # Default: "*" - # Example: - # minute: "0" - minute: "" - # The seconds at which the task scheduler posts scheduled posts. - # Default: "*/1" - # Example: - # second: "5" - second: "" - # The timezone for the task scheduler used by WaktuSolat to schedule time-dependent operations. - # Default: "Asia/Kuala_Lumpur" - # Example: - # timezone: "Asia/Kuala_Lumpur" - timezone: "" + +# Scheduler configurations. +scheduler: + # Specifies whether APScheduler should be used by WaktuSolat as the task scheduler. + # Example: + # apscheduler: false + apscheduler: true + # Specifies whether Celery should be used by WaktuSolat as the task scheduler. + # Example: + # celery: true + celery: false + # The timezone for the task scheduler used by WaktuSolat to schedule time-dependent operations. + # Default: "Etc/UTC" + # Example: + # timezone: "Asia/Kuala_Lumpur" + timezone: "" + # The schedule for the task scheduler used by WaktuSolat. + # Note: The `apscheduler` scheduler supports the `hour`, `minute`, and `second` fields simultaneously. + # The `celery` scheduler only supports a combination of the `hour` and `minute` fields, or the `second` field alone. + schedule: + # The schedule for cleaning up the database. + clean_db: + # The hours at which the task scheduler cleans up the database. + # Default: "0" + # Example: + # hour: "1" + hour: "" + # The minutes at which the task scheduler cleans up the database. + # Default: "0" + # Example: + # minute: "30" + minute: "" + # The seconds at which the task scheduler cleans up the database. + # Default: "0" (`apscheduler`) + # Example: + # second: "30" + second: "" + # The schedule for the daily prayer time post. + notify_solat_schedule: + # The hours at which the task scheduler schedules the daily prayer time post. + # Default: "5" + # Example: + # hour: "4" + hour: "" + # The minutes at which the task scheduler schedules the daily prayer time post. + # Default: "0" + # Example: + # minute: "15" + minute: "" + # The seconds at which the task scheduler schedules the daily prayer time post. + # Default: "0" (`apscheduler`) + # Example: + # second: "30" + second: "" + # The schedule for the daily prayer time notifications. + notify_solat_times: + # The hours at which the task scheduler schedules the daily prayer time notifications. + # Default: "*" + # Example: + # hour: "6,13,16,19,20" + hour: "" + # The minutes at which the task scheduler schedules the daily prayer time notifications. + # Default: "*/1" + # Example: + # minute: "*" + minute: "" + # The seconds at which the task scheduler schedules the daily prayer time notifications. + # Default: "0" (`apscheduler`) + # Example: + # second: "30" + second: "" + # The schedule for posting scheduled posts. + post_scheduler: + # The hours at which the task scheduler posts scheduled posts. + # Default: "*" + # Example: + # hour: "4-20" + hour: "" + # The minutes at which the task scheduler posts scheduled posts. + # Default: "*" + # Example: + # minute: "*/30" + minute: "" + # The seconds at which the task scheduler posts scheduled posts. + # Default: "*/1" (`apscheduler`) + # Example: + # second: "30" + second: "" # Database configurations. db: - # The type of the database used by WaktuSolat. + # The database engine or backend being used by WaktuSolat. # Default: "postgresql" # Example: - # type: "postgresql" + # type: "mysql" type: "" - # The name of the database used by WaktuSolat. + # The hostname or IP address of the WaktuSolat database server. + # Example: + # host: "waktusolat.default.svc.cluster.local" + host: "" + # The port number the WaktuSolat database server is listening for connections. + # Default: "5432" + # Example: + # port: "3306" + port: "" + # The name of the database being used by WaktuSolat. # Example: # name: "waktusolat" name: "" @@ -273,71 +285,163 @@ db: # Example: # user: "root" user: "" - # The password associated with the WaktuSolat database's user. + # The password associated with the WaktuSolat database user. # Example: # password: "password" password: "" - # The hostname or IP address of the WaktuSolat database server. + +# Ingress configurations. +ingress: + # Specifies whether Ingress should be enabled for hosting WaktuSolat services. # Example: - # host: "waktusolat.default.svc.cluster.local" - host: "" - # The port number on which the WaktuSolat database server is listening. - # Default: "5432" + # enabled: true + enabled: false + # The name of the cluster issuer for Ingress. + # Default: "letsencrypt-dns-prod" # Example: - # port: "5432" - port: "" + # clusterIssuer: "letsencrypt-http-prod" + clusterIssuer: "" + # Specifies whether the WWW subdomain should be enabled. + # Example: + # www: true + www: false + # Additional configuration annotations to be added to the Ingress resource. + # Items: `.prefix`, `.name`, `.value` + # Example: + # customAnnotations: + # # The prefix of the annotation. + # # Default: "nginx.ingress.kubernetes.io" + # # Example: + # # prefix: "nginx.org" + # - prefix: "" + # # The name of the annotation. + # # Example: + # # name: "proxy-connect-timeout" + # name: "" + # # The value of the annotation. + # # Example: + # # value: "120" + # value: "" + customAnnotations: [] + +# Service configurations. +service: + # The type of service used to expose WaktuSolat services. + # Default: "ClusterIP" + # Example: + # type: "NodePort" + type: "" + # WaktuSolat service port configurations. + waktusolat: + # The optional node port to expose for WaktuSolat when the service type is NodePort. + # Example: + # nodePort: "30000" + nodePort: "" + # The WaktuSolat port on which the WaktuSolat server should listen for connections. + # Default: "80" + # Example: + # port: "8080" + port: "" + # Redis service port configurations. + redis: + # The optional node port to expose for Redis when the service type is NodePort. + # Example: + # nodePort: "32000" + nodePort: "" + # The Redis port on which the WaktuSolat server should listen for connections. + # Default: "6379" + # Example: + # port: "8443" + port: "" + +# Storage configurations. +storage: + # Log storage configurations. + log: + # Specifies whether persistent storage should be provisioned for log storage. + # Example: + # enabled: true + enabled: false + # The access mode defining how the log storage can be mounted. + # Default: "ReadWriteMany" + # Example: + # accessMode: "ReadWriteOnce" + accessMode: "" + # The path where the log storage should be mounted on the container. + # Default: "/var/log/apache2" + # Example: + # mountPath: "/log" + mountPath: "" + # The subpath within the log storage to mount to the container. Leave empty if not required. + # Example: + # subPath: "Log" + subPath: "" + # The default amount of persistent storage allocated for the log storage. + # Default: "50Mi" + # Example: + # storage: "10Gi" + storage: "" + # The storage class name used for dynamically provisioning a persistent volume for the log storage. + # Default: "longhorn" + # Example: + # storageClassName: "smb" + storageClassName: "" # Resource requirements and limits for WaktuSolat containers. resources: # WaktuSolat container resources. - waktusolat: - # The minimum amount of resources required by WaktuSolat to run. - requests: - # The minimum amount of CPU resources required by WaktuSolat. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "100m" or more if using `celery` as the scheduler. - # Example: - # cpu: "20m" - cpu: "30m" - # The minimum amount of memory required by WaktuSolat. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "250Mi" or more if using `celery` as the scheduler. - # Example: - # memory: "250Mi" - memory: "60Mi" - # The maximum amount of resources allowed for WaktuSolat. - limits: - # The maximum amount of CPU resources allowed for WaktuSolat. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "200m" or more if using `celery` as the scheduler. - # Example: - # cpu: "50m" - cpu: "50m" - # The maximum amount of memory allowed for WaktuSolat. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "400Mi" or more if using `celery` as the scheduler. - # Example: - # memory: "450Mi" - memory: "120Mi" + # Example: + # waktusolat: + # # The minimum amount of resources required by WaktuSolat to run. + # requests: + # # The minimum amount of CPU resources required by WaktuSolat. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "500m" or more if using `celery` as the scheduler. + # # Example: + # # cpu: "10m" + # cpu: "200m" + # # The minimum amount of memory required by WaktuSolat. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "550Mi" or more if using `celery` as the scheduler. + # # Example: + # # memory: "10Mi" + # memory: "100Mi" + # # The maximum amount of resources allowed for WaktuSolat. + # limits: + # # The maximum amount of CPU resources allowed for WaktuSolat. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "1" or more if using `celery` as the scheduler. + # # Example: + # # cpu: "250m" + # cpu: "300m" + # # The maximum amount of memory allowed for WaktuSolat. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "650Mi" or more if using `celery` as the scheduler. + # # Example: + # # memory: "250Mi" + # memory: "350Mi" + waktusolat: {} # Scheduler container resources. - scheduler: - # The minimum amount of resources required by Scheduler to run. - requests: - # The minimum amount of CPU resources required by Scheduler. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "10m" or more if using `celery` as the scheduler. - # Example: - # cpu: "5m" - cpu: "10m" - # The minimum amount of memory required by Scheduler. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "50Mi" or more if using `celery` as the scheduler. - # Example: - # memory: "30Mi" - memory: "100Mi" - # The maximum amount of resources allowed for Scheduler. - limits: - # The maximum amount of CPU resources allowed for Scheduler. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "20m" or more if using `celery` as the scheduler. - # Example: - # cpu: "15m" - cpu: "20m" - # The maximum amount of memory allowed for Scheduler. - # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "100Mi" or more if using `celery` as the scheduler. - # Example: - # memory: "50Mi" - memory: "200Mi" + # Example: + # scheduler: + # # The minimum amount of resources required by Scheduler to run. + # requests: + # # The minimum amount of CPU resources required by Scheduler. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "10m" or more if using `celery` as the scheduler. + # # Example: + # # cpu: "10m" + # cpu: "200m" + # # The minimum amount of memory required by Scheduler. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "50Mi" or more if using `celery` as the scheduler. + # # Example: + # # memory: "10Mi" + # memory: "250Mi" + # # The maximum amount of resources allowed for Scheduler. + # limits: + # # The maximum amount of CPU resources allowed for Scheduler. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "20m" or more if using `celery` as the scheduler. + # # Example: + # # cpu: "250m" + # cpu: "300m" + # # The maximum amount of memory allowed for Scheduler. + # # Note: This is the recommended default when using `apscheduler` as the scheduler. Allocate "100Mi" or more if using `celery` as the scheduler. + # # Example: + # # memory: "250Mi" + # memory: "350Mi" + scheduler: {} diff --git a/template/chartName/README.md b/template/chartName/README.md index 3336b3c1..337cb170 100644 --- a/template/chartName/README.md +++ b/template/chartName/README.md @@ -14,7 +14,7 @@ A Helm chart for deploying ChartName. --- -## External dependencies +## Preflight checklist > [!IMPORTANT] > The following items are required to be set up prior to installing this chart. @@ -148,8 +148,8 @@ A Helm chart for deploying ChartName. | replicaCount | string | `""` | The desired number of running replicas for ChartName. Default: `"1"`. | | resources.chartName | object | `{}` | ChartName container resources. | | service.nodePort | string | `""` | The optional node port to expose when the service type is NodePort. | -| service.port | string | `""` | The port on which the ChartName server should listen. Default: `"80"`. | -| service.type | string | `""` | The type of service used for ChartName services. Default: `"ClusterIP"`. | +| service.port | string | `""` | The port on which the ChartName server should listen for connections. Default: `"80"`. | +| service.type | string | `""` | The type of service used to expose ChartName services. Default: `"ClusterIP"`. | | storage.data.accessMode | string | `""` | The access mode defining how the data storage can be mounted. Default: `"ReadWriteMany"`. | | storage.data.enabled | bool | `false` | Specifies whether persistent storage should be provisioned for data storage. | | storage.data.mountPath | string | `""` | The path where the data storage should be mounted on the container. Default: `"/config"`. | diff --git a/template/chartName/templates/NOTES.txt b/template/chartName/templates/NOTES.txt index def1029d..0d9d3ba4 100644 --- a/template/chartName/templates/NOTES.txt +++ b/template/chartName/templates/NOTES.txt @@ -1,9 +1,9 @@ +{{- $serviceAddress := "" }} {{- $ingress := .Values.ingress.enabled }} {{- $domain := .Values.chartName.domain | toString }} {{- $port := .Values.service.port | default "80" | toString }} {{- $type := .Values.service.type | default "ClusterIP" | toString }} {{- $serviceName := printf "%s-chartName-svc" .Release.Name | toString }} -{{- $serviceAddress := "" }} ChartName has been installed and configured for {{ .Release.Name | toString }} 🎉 {{- if $ingress }} diff --git a/template/chartName/values.yaml b/template/chartName/values.yaml index 3d129af7..976b3060 100644 --- a/template/chartName/values.yaml +++ b/template/chartName/values.yaml @@ -79,6 +79,10 @@ ingress: # Example: # clusterIssuer: "letsencrypt-http-prod" clusterIssuer: "" + # Specifies whether the WWW subdomain should be enabled. + # Example: + # www: true + www: false # Additional configuration annotations to be added to the Ingress resource. # Items: `.prefix`, `.name`, `.value` # Example: @@ -97,10 +101,6 @@ ingress: # # value: "120" # value: "" customAnnotations: [] - # Specifies whether the WWW subdomain should be enabled. - # Example: - # www: true - www: false # Service configurations. service: @@ -108,12 +108,12 @@ service: # Example: # nodePort: "32000" nodePort: "" - # The port on which the ChartName server should listen. + # The port on which the ChartName server should listen for connections. # Default: "80" # Example: # port: "8080" port: "" - # The type of service used for ChartName services. + # The type of service used to expose ChartName services. # Default: "ClusterIP" # Example: # type: "NodePort" @@ -149,7 +149,7 @@ storage: # The storage class name used for dynamically provisioning a persistent volume for the data storage. # Default: "longhorn" # Example: - # storageClassName: "longhorn" + # storageClassName: "smb" storageClassName: "" # Resource requirements and limits for ChartName containers.