From 909d52ef204bd49a5324fffb97fb0d4b7e8a6731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Colombaro?= Date: Tue, 22 Feb 2022 00:21:03 +0100 Subject: [PATCH] Init function chart --- charts/function/.helmignore | 28 ++ charts/function/Chart.lock | 9 + charts/function/Chart.yaml | 44 +++ charts/function/README.md | 0 charts/function/templates/_helpers.tpl | 102 +++++++ charts/function/templates/configmaps.yaml | 14 + .../templates/externaldb-secrets.yaml | 16 + charts/function/templates/secrets.yaml | 18 ++ charts/function/templates/service.yaml | 50 ++++ charts/function/values.schema.json | 283 ++++++++++++++++++ charts/function/values.yaml | 154 ++++++++++ 11 files changed, 718 insertions(+) create mode 100644 charts/function/.helmignore create mode 100644 charts/function/Chart.lock create mode 100644 charts/function/Chart.yaml create mode 100644 charts/function/README.md create mode 100644 charts/function/templates/_helpers.tpl create mode 100644 charts/function/templates/configmaps.yaml create mode 100644 charts/function/templates/externaldb-secrets.yaml create mode 100644 charts/function/templates/secrets.yaml create mode 100644 charts/function/templates/service.yaml create mode 100644 charts/function/values.schema.json create mode 100644 charts/function/values.yaml diff --git a/charts/function/.helmignore b/charts/function/.helmignore new file mode 100644 index 0000000..7eb7cb2 --- /dev/null +++ b/charts/function/.helmignore @@ -0,0 +1,28 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj + +# OWNERS file for Kubernetes +OWNERS +# example production yaml +values-production.yaml +# ci files +ci/ diff --git a/charts/function/Chart.lock b/charts/function/Chart.lock new file mode 100644 index 0000000..2b49d11 --- /dev/null +++ b/charts/function/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: common + repository: https://charts.bitnami.com/bitnami + version: 1.11.1 +- name: redis + repository: https://charts.bitnami.com/bitnami + version: 16.4.0 +digest: sha256:18eac17e69c4871e29365d14fe5822d00dfeb97c5a2624407ad6c506b6542937 +generated: "2022-02-22T00:08:54.6743331+01:00" diff --git a/charts/function/Chart.yaml b/charts/function/Chart.yaml new file mode 100644 index 0000000..bcdd311 --- /dev/null +++ b/charts/function/Chart.yaml @@ -0,0 +1,44 @@ +apiVersion: v2 +version: 0.0.1 +name: function +description: Serverless Function +appVersion: "1.0.0" +type: application +keywords: + - shortener + - url + - bitly +home: https://yourls.org +icon: https://yourls.org/images/yourls-logo.png +sources: + - https://github.com/YOURLS/function + - https://github.com/YOURLS/charts +maintainers: + - name: YOURLS + email: yourls@yourls.org + - name: LeoColomb + email: git@colombaro.fr +kubeVersion: ">=1.20.0-0" +dependencies: + - name: common + repository: https://charts.bitnami.com/bitnami + version: ^1.11.1 + tags: + - bitnami-common + - condition: redis.enabled + name: redis + repository: https://charts.bitnami.com/bitnami + version: ^16.4.0 + tags: + - function-database +annotations: + artifacthub.io/license: MIT + artifacthub.io/links: | + - name: Upstream Project + url: https://github.com/YOURLS/function + artifacthub.io/signKey: | + fingerprint: 6FCD850E18E4A4FF76DD1184A3A42A61961E423F + url: https://yourls.org/.well-known/openpgpkey/hu/6e4gbtp15q1znf3unweeducn7urty4mr + artifacthub.io/changes: | + - kind: added + description: First version diff --git a/charts/function/README.md b/charts/function/README.md new file mode 100644 index 0000000..e69de29 diff --git a/charts/function/templates/_helpers.tpl b/charts/function/templates/_helpers.tpl new file mode 100644 index 0000000..40c228a --- /dev/null +++ b/charts/function/templates/_helpers.tpl @@ -0,0 +1,102 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +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). +*/}} +{{- define "function.redis.fullname" -}} +{{- include "common.names.dependency.fullname" (dict "chartName" "redis" "chartValues" .Values.redis "context" $) -}} +{{- end -}} + +{{/* +Return the proper YOURLS image name +*/}} +{{- define "function.image" -}} +{{- $imageRoot := .Values.image -}} +{{- if not .Values.image.tag }} + {{- $tag := (dict "tag" .Chart.AppVersion) -}} + {{- $imageRoot := merge .Values.image $tag -}} +{{- end -}} +{{- include "common.images.image" (dict "imageRoot" $imageRoot "global" .Values.global) -}} +{{- end -}} + +{{/* +Return the Function Secret Name +*/}} +{{- define "function.secretName" -}} +{{- if .Values.function.existingSecret }} + {{- printf "%s" .Values.function.existingSecret -}} +{{- else -}} + {{- printf "%s" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Redis™ hostname +*/}} +{{- define "function.redisHost" -}} +{{- if .Values.redis.enabled }} + {{- printf "%s-master" (include "function.redis.fullname" .) -}} +{{- else -}} + {{- printf "%s" .Values.externalDatabase.host -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Redis™ port +*/}} +{{- define "function.redisPort" -}} +{{- if .Values.redis.enabled }} + {{- printf "6379" | quote -}} +{{- else -}} + {{- .Values.externalDatabase.port | quote -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object for Redis™ should be created +*/}} +{{- define "function.redis.createSecret" -}} +{{- if and (not .Values.redis.enabled) (not .Values.externalDatabase.existingSecret) .Values.externalDatabase.password }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Redis™ secret name +*/}} +{{- define "function.redis.secretName" -}} +{{- if .Values.redis.enabled }} + {{- if .Values.redis.auth.existingSecret }} + {{- printf "%s" .Values.redis.auth.existingSecret -}} + {{- else -}} + {{- printf "%s" (include "function.redis.fullname" .) -}} + {{- end -}} +{{- else if .Values.externalDatabase.existingSecret }} + {{- printf "%s" .Values.externalDatabase.existingSecret -}} +{{- else -}} + {{- printf "%s-redis" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the Redis™ secret key +*/}} +{{- define "function.redis.secretPasswordKey" -}} +{{- if and .Values.redis.enabled .Values.redis.auth.existingSecret }} + {{- required "You need to provide existingSecretPasswordKey when an existingSecret is specified in redis" .Values.redis.auth.existingSecretPasswordKey | printf "%s" }} +{{- else if and (not .Values.redis.enabled) .Values.externalDatabase.existingSecret }} + {{- required "You need to provide existingSecretPasswordKey when an existingSecret is specified in redis" .Values.externalDatabase.existingSecretPasswordKey | printf "%s" }} +{{- else -}} + {{- printf "redis-password" -}} +{{- end -}} +{{- end -}} + +{{/* +Return whether Redis™ uses password authentication or not +*/}} +{{- define "function.redis.auth.enabled" -}} +{{- if or (and .Values.redis.enabled .Values.redis.auth.enabled) (and (not .Values.redis.enabled) (or .Values.externalDatabase.password .Values.externalDatabase.existingSecret)) }} + {{- true -}} +{{- end -}} +{{- end -}} diff --git a/charts/function/templates/configmaps.yaml b/charts/function/templates/configmaps.yaml new file mode 100644 index 0000000..f68999f --- /dev/null +++ b/charts/function/templates/configmaps.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "common.names.fullname" . }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +data: + REDIS_HOST: {{ template "function.redisHost" . }} + REDIS_PORT_NUMBER: {{ template "function.redisPort" . }} diff --git a/charts/function/templates/externaldb-secrets.yaml b/charts/function/templates/externaldb-secrets.yaml new file mode 100644 index 0000000..87fa488 --- /dev/null +++ b/charts/function/templates/externaldb-secrets.yaml @@ -0,0 +1,16 @@ +{{- if (include "function.redis.createSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "common.names.fullname" . }}-redis + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + redis-password: {{ .Values.externalDatabase.password | b64enc | quote }} +{{- end }} diff --git a/charts/function/templates/secrets.yaml b/charts/function/templates/secrets.yaml new file mode 100644 index 0000000..dac590f --- /dev/null +++ b/charts/function/templates/secrets.yaml @@ -0,0 +1,18 @@ +{{- if not .Values.function.existingSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + endpoint: {{ .Values.function.endpoint | b64enc | quote }} + token: {{ .Values.function.token | b64enc | quote }} +{{- end }} diff --git a/charts/function/templates/service.yaml b/charts/function/templates/service.yaml new file mode 100644 index 0000000..070cc26 --- /dev/null +++ b/charts/function/templates/service.yaml @@ -0,0 +1,50 @@ +apiVersion: serving.knative.dev/v1 +kind: Service +metadata: + name: {{ include "common.names.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonLabels }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + template: + metadata: + labels: {{- include "common.labels.standard" . | nindent 8 }} + {{- if .Values.podLabels }} + {{- include "common.tplvalues.render" (dict "value" .Values.podLabels "context" $) | nindent 8 }} + {{- end }} + {{- if or .Values.podAnnotations }} + annotations: + {{- if .Values.podAnnotations }} + {{- include "common.tplvalues.render" (dict "value" .Values.podAnnotations "context" $) | nindent 8 }} + {{- end }} + {{- end }} + spec: + containers: + - name: function + image: {{ template "function.image" . }} + env: + {{- if (include "function.redis.auth.enabled" .) }} + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "function.redis.secretName" . }} + key: {{ include "function.redis.secretPasswordKey" . }} + {{- end }} + - name: YOURLS_ENDPOINT + valueFrom: + secretKeyRef: + name: {{ include "function.secretName" . }} + key: endpoint + - name: YOURLS_TOKEN + valueFrom: + secretKeyRef: + name: {{ include "function.secretName" . }} + key: token + envFrom: + - configMapRef: + name: {{ include "common.names.fullname" . }} diff --git a/charts/function/values.schema.json b/charts/function/values.schema.json new file mode 100644 index 0000000..edb0c9d --- /dev/null +++ b/charts/function/values.schema.json @@ -0,0 +1,283 @@ +{ + "$schema": "https://json-schema.org/schema#", + "title": "YOURLS Function Chart JSON Schema", + "type": "object", + "$defs": { + "image": { + "title": "Container image description", + "type": "object", + "properties": { + "pullPolicy": { + "title": "Specify a imagePullPolicy", + "description": "Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'", + "type": "string", + "enum": [ + "IfNotPresent", + "Always", + "Never" + ] + }, + "pullSecrets": { + "title": "Optionally specify an array of imagePullSecrets", + "description": "https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/", + "type": "array" + }, + "registry": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + }, + "required": [ + "repository", + "pullPolicy" + ] + }, + "probe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "failureThreshold": { + "type": "integer" + }, + "httpGet": { + "type": "object", + "properties": { + "httpHeaders": { + "type": "array" + }, + "path": { + "type": "string" + }, + "port": { + "type": "string" + }, + "scheme": { + "type": "string" + } + } + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + } + }, + "resources": { + "type": "object", + "title": "Required Resources", + "description": "Configure resource requests", + "form": true, + "properties": { + "requests": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "form": true, + "render": "slider", + "title": "Memory Request", + "sliderMin": 10, + "sliderMax": 2048, + "sliderUnit": "Mi" + }, + "cpu": { + "type": "string", + "form": true, + "render": "slider", + "title": "CPU Request", + "sliderMin": 10, + "sliderMax": 2000, + "sliderUnit": "m" + } + } + }, + "limits": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "form": true, + "render": "slider", + "title": "Memory Request", + "sliderMin": 10, + "sliderMax": 2048, + "sliderUnit": "Mi" + }, + "cpu": { + "type": "string", + "form": true, + "render": "slider", + "title": "CPU Request", + "sliderMin": 10, + "sliderMax": 2000, + "sliderUnit": "m" + } + } + } + } + } + }, + "properties": { + "function": { + "type": "object", + "title": "Function Configuration parameters", + "description": "https://github.com/YOURLS/function", + "form": true, + "properties": { + "endpoint": { + "type": "string", + "title": "YOURLS API endpoint name for the function", + "examples": [ + "https://exemple.com" + ], + "form": true + }, + "token": { + "type": "string", + "title": "YOURLS API token for the function", + "form": true + }, + "existingSecret": { + "type": "string" + } + } + }, + "redis": { + "title": "Redis chart configuration", + "description": "https://artifacthub.io/packages/helm/bitnami/redis", + "allOf": [ + { + "$ref": "https://raw.githubusercontent.com/bitnami/charts/master/bitnami/redis/values.schema.json" + }, + { + "properties": { + "enabled": { + "type": "boolean", + "default": true, + "description": "Deploy a Redis server to satisfy the application database" + } + } + } + ] + }, + "externalDatabase": { + "type": "object", + "title": "External Database Details", + "description": "If Redis is disabled. Use this section to specify the external database details", + "form": true, + "properties": { + "host": { + "type": "string", + "form": true, + "title": "Database Host", + "hidden": "redis/enabled" + }, + "password": { + "type": "string", + "form": true, + "title": "Database Password", + "hidden": "redis/enabled" + }, + "port": { + "type": "integer", + "form": true, + "title": "Database Port", + "hidden": "redis/enabled" + }, + "existingSecret": { + "type": "string" + } + } + }, + "commonAnnotations": { + "type": "object" + }, + "commonLabels": { + "type": "object" + }, + "diagnosticMode": { + "type": "object", + "properties": { + "args": { + "type": "array", + "items": { + "type": "string" + } + }, + "command": { + "type": "array", + "items": { + "type": "string" + } + }, + "enabled": { + "type": "boolean" + } + } + }, + "extraDeploy": { + "type": "array" + }, + "fullnameOverride": { + "type": "string" + }, + "global": { + "type": "object", + "properties": { + "imagePullSecrets": { + "type": "array" + }, + "imageRegistry": { + "type": "string" + }, + "storageClass": { + "type": "string" + } + } + }, + "image": { + "title": "Function container image", + "allOf": [ + { + "$ref": "#/$defs/image" + }, + { + "properties": { + "debug": { + "title": "Enable image debug mode", + "default": false, + "type": "boolean" + } + } + } + ] + }, + "kubeVersion": { + "type": "string" + }, + "nameOverride": { + "type": "string" + }, + "podAnnotations": { + "type": "object" + }, + "podLabels": { + "type": "object" + } + } +} diff --git a/charts/function/values.yaml b/charts/function/values.yaml new file mode 100644 index 0000000..3c63c14 --- /dev/null +++ b/charts/function/values.yaml @@ -0,0 +1,154 @@ +## @section Global parameters +## Global Docker image parameters +## Please, note that this will override the image parameters, including dependencies, configured to use the global value +## Current available global Docker image parameters: imageRegistry, imagePullSecrets and storageClass +## + +## @param global.imageRegistry Global Docker image registry +## @param global.imagePullSecrets Global Docker registry secret names as an array +## @param global.storageClass Global StorageClass for Persistent Volume(s) +## +global: + imageRegistry: "" + ## E.g. + ## imagePullSecrets: + ## - myRegistryKeySecretName + ## + imagePullSecrets: [] + storageClass: "" + +## @section Common parameters +## + +## @param kubeVersion Override Kubernetes version +## +kubeVersion: "" +## @param nameOverride String to partially override common.names.fullname +## +nameOverride: "" +## @param fullnameOverride String to fully override common.names.fullname +## +fullnameOverride: "" +## @param commonLabels Labels to add to all deployed objects +## +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} +## @param clusterDomain Kubernetes cluster domain name +## +clusterDomain: cluster.local +## @param extraDeploy Array of extra objects to deploy with the release +## +extraDeploy: [] + +## Enable diagnostic mode in the deployment +## +diagnosticMode: + ## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden) + ## + enabled: false + ## @param diagnosticMode.command Command to override all containers in the deployment + ## + command: + - sleep + ## @param diagnosticMode.args Args to override all containers in the deployment + ## + args: + - infinity + +## @section Function container image +## + +## @param image.registry Image registry +## @param image.repository Image repository +## @param image.tag Image tag (immutable tags are recommended) +## @param image.pullPolicy Image pull policy +## @param image.pullSecrets Image pull secrets +## @param image.debug Enable image debug mode +## +image: + registry: ghcr.io + repository: yourls/function + ## Defaults to '{{ .Chart.AppVersion }}' + ## + tag: "" + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: Always + ## Optionally specify an array of imagePullSecrets. + ## Secrets must be manually created in the namespace. + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## e.g: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Enable debug mode + ## + debug: false + +## @section Function parameters +## +function: + endpoint: "" + token: "" + existingSecret: "" + +## @param podAnnotations Additional pod annotations +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +## +podAnnotations: {} +## @param podLabels Additional pod labels +## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} + +## @section Redis™ parameters + +## Redis™ chart configuration +## https://github.com/bitnami/charts/blob/master/bitnami/redis/values.yaml +## +redis: + ## @param redis.enabled Whether to deploy a redis server to satisfy the applications requirements. To use an external redis instance set this to false and configure the externalRedis parameters + ## + enabled: true + ## Use password authentication + ## @param redis.auth.enabled Use password authentication + ## @param redis.auth.password Redis™ password (both master and replica) + ## @param redis.auth.existingSecret Name of an existing Kubernetes secret object containing the password + ## @param redis.auth.existingSecretPasswordKey Name of the key pointing to the password in your Kubernetes secret + ## + auth: + enabled: false + ## Defaults to a random 10-character alphanumeric string if not set and auth.enabled is true. + ## It should always be set using the password value or in the existingSecret to avoid issues + ## with Discourse. + ## The password value is ignored if existingSecret is set + password: "" + existingSecret: "" + existingSecretPasswordKey: 'redis-password' + ## @param redis.architecture Cluster settings + ## + architecture: standalone + ## Redis™ Master parameters + ## @param redis.master.persistence.enabled Enable database persistence using PVC + ## + master: + persistence: + enabled: true +## External Redis™ +## @param externalRedis.host Host of the external database +## @param externalRedis.port Database port number +## @param externalRedis.password Password for the external Redis. Ignored if existingSecret is set +## @param externalRedis.existingSecret Name of an existing Kubernetes secret object containing the password +## @param externalRedis.existingSecretPasswordKey Name of the key pointing to the password in your Kubernetes secret +## +externalDatabase: + host: "" + port: 6379 + password: "" + existingSecret: "" + existingSecretPasswordKey: 'redis-password'