diff --git a/charts/incubator/wger/Chart.yaml b/charts/incubator/wger/Chart.yaml new file mode 100644 index 00000000000..c109bb7319e --- /dev/null +++ b/charts/incubator/wger/Chart.yaml @@ -0,0 +1,34 @@ +apiVersion: v2 +appVersion: "10.6.2" +dependencies: +- name: common + repository: https://library-charts.truecharts.org + version: 10.1.3 +- condition: postgresql.enabled + name: postgresql + repository: https://charts.truecharts.org/ + version: 8.0.15 +- condition: redis.enabled + name: redis + repository: https://charts.truecharts.org + version: 3.0.15 +description: Workout Manager is a free, open source web application that helps you manage your personal workouts, weight and diet plans and can also be used as a simple gym management utility. +home: https://github.com/truecharts/apps/tree/master/charts/stable/wger +icon: https://truecharts.org/_static/img/appicons/wger.png +keywords: +- workout +kubeVersion: '>=1.16.0-0' +maintainers: +- email: info@truecharts.org + name: TrueCharts + url: https://truecharts.org +name: wger +sources: +- https://github.com/wger-project/wger +- https://github.com/wger-project/docker +version: 0.0.1 +annotations: + truecharts.org/catagories: | + - life + truecharts.org/SCALE-support: "true" + truecharts.org/grade: U diff --git a/charts/incubator/wger/questions.yaml b/charts/incubator/wger/questions.yaml new file mode 100644 index 00000000000..d643ef431fe --- /dev/null +++ b/charts/incubator/wger/questions.yaml @@ -0,0 +1,394 @@ +# Include{groups} +portals: + open: + protocols: + - "$kubernetes-resource_configmap_portal_protocol" + host: + - "$kubernetes-resource_configmap_portal_host" + ports: + - "$kubernetes-resource_configmap_portal_port" +questions: + - variable: portal + group: "Container Image" + label: "Configure Portal Button" + schema: + type: dict + hidden: true + attrs: + - variable: enabled + label: "Enable" + description: "enable the portal button" + schema: + hidden: true + editable: false + type: boolean + default: true +# Include{global} + - variable: controller + group: "Controller" + label: "" + schema: + additional_attrs: true + type: dict + attrs: + - variable: advanced + label: "Show Advanced Controller Settings" + schema: + type: boolean + default: false + show_subquestions_if: true + subquestions: + - variable: type + description: "Please specify type of workload to deploy" + label: "(Advanced) Controller Type" + schema: + type: string + default: "deployment" + required: true + enum: + - value: "deployment" + description: "Deployment" + - value: "statefulset" + description: "Statefulset" + - value: "daemonset" + description: "Daemonset" + - variable: replicas + description: "Number of desired pod replicas" + label: "Desired Replicas" + schema: + type: int + default: 1 + required: true + - variable: strategy + description: "Please specify type of workload to deploy" + label: "(Advanced) Update Strategy" + schema: + type: string + default: "Recreate" + required: true + enum: + - value: "Recreate" + description: "Recreate: Kill existing pods before creating new ones" + - value: "RollingUpdate" + description: "RollingUpdate: Create new pods and then kill old ones" + - value: "OnDelete" + description: "(Legacy) OnDelete: ignore .spec.template changes" +# Include{controllerExpert} + - variable: wger + group: "Container Configuration" + label: "Image Environment" + schema: + additional_attrs: true + type: dict + attrs: + - variable: site_url + label: "SITE_URL" + description: "eg. https://wger.mydomain.com" + schema: + type: string + required: true + default: "" + - variable: sync_exercises_on_startup + label: "SYNC_EXERCISES_ON_STARTUP" + schema: + type: boolean + default: false + - variable: download_exercise_images_on_startup + label: "DOWNLOAD_EXERCISE_IMAGES_ON_STARTUP" + schema: + type: boolean + default: false + - variable: allow_registration + label: "ALLOW_REGISTRATION" + schema: + type: boolean + default: true + - variable: allow_guest_users + label: "ALLOW_GUEST_USERS" + schema: + type: boolean + default: true + - variable: allow_upload_videos + label: "ALLOW_UPLOAD_VIDEOS" + schema: + type: boolean + default: true + - variable: exercise_cache_ttl + label: "EXERCISE_CACHE_TTL" + schema: + type: string + required: true + default: "3600" + - variable: django_perform_migrations + label: "DJANGO_PERFORM_MIGRATIONS" + schema: + type: boolean + default: true + - variable: django_debug + label: "DJANGO_DEBUG" + schema: + type: boolean + default: false + - variable: enable_email + label: "Email Settings" + schema: + type: boolean + default: false + show_subquestions_if: true + subquestions: + - variable: from_email + label: "FROM_EMAIL" + schema: + type: string + default: "" + - variable: email_host + label: "EMAIL_HOST" + schema: + type: string + default: "" + - variable: email_port + label: "EMAIL_PORT" + schema: + type: string + required: true + default: "587" + - variable: email_host_user + label: "EMAIL_HOST_USER" + schema: + type: string + default: "" + - variable: email_host_password + label: "EMAIL_HOST_PASSWORD" + schema: + type: string + private: true + default: "" + - variable: email_use_tls + label: "EMAIL_USE_TLS" + schema: + type: boolean + default: false + - variable: email_use_ssl + label: "EMAIL_USE_SSL" + schema: + type: boolean + default: false + - variable: captchasettings + label: "Captcha Settings" + schema: + type: boolean + default: false + show_subquestions_if: true + subquestions: + - variable: recaptha_public_key + label: "RECAPTCHA_PUBLIC_KEY" + schema: + type: string + default: "" + - variable: recaptha_private_key + label: "RECAPTCHA_PRIVATE_KEY" + schema: + type: string + private: true + default: "" + - variable: nocaptcha + label: "NOCAPTCHA" + schema: + type: boolean + default: true +# Include{containerConfig} + + - variable: service + group: "Networking and Services" + label: "Configure Service(s)" + schema: + additional_attrs: true + type: dict + attrs: + - variable: main + label: "Main Service" + description: "The Primary service on which the healthcheck runs, often the webUI" + schema: + additional_attrs: true + type: dict + attrs: +# Include{serviceSelector} + - variable: main + label: "Main Service Port Configuration" + schema: + additional_attrs: true + type: dict + attrs: + - variable: port + label: "Port" + description: "This port exposes the container port on the service" + schema: + type: int + default: 10249 + required: true + - variable: advanced + label: "Show Advanced settings" + schema: + type: boolean + default: false + show_subquestions_if: true + subquestions: + - variable: protocol + label: "Port Type" + schema: + type: string + default: "HTTP" + enum: + - value: HTTP + description: "HTTP" + - value: "HTTPS" + description: "HTTPS" + - value: TCP + description: "TCP" + - value: "UDP" + description: "UDP" + - variable: nodePort + label: "Node Port (Optional)" + description: "This port gets exposed to the node. Only considered when service type is NodePort, Simple or LoadBalancer" + schema: + type: int + min: 9000 + max: 65535 + - variable: targetPort + label: "Target Port" + description: "The internal(!) port on the container the Application runs on" + schema: + type: int + default: 80 + + - variable: serviceexpert + group: "Networking and Services" + label: "Show Expert Config" + schema: + type: boolean + default: false + show_subquestions_if: true + subquestions: + - variable: hostNetwork + group: "Networking and Services" + label: "Host-Networking (Complicated)" + schema: + type: boolean + default: false + +# Include{serviceExpert} + +# Include{serviceList} + - variable: persistence + label: "Integrated Persistent Storage" + description: "Integrated Persistent Storage" + group: "Storage and Persistence" + schema: + additional_attrs: true + type: dict + attrs: + - variable: media + label: "App Media Storage" + description: "Stores the Application Media." + schema: + additional_attrs: true + type: dict + attrs: +# Include{persistenceBasic} +# Include{persistenceAdvanced} + +# Include{persistenceList} + + - variable: ingress + label: "" + group: "Ingress" + schema: + additional_attrs: true + type: dict + attrs: + - variable: main + label: "Main Ingress" + schema: + additional_attrs: true + type: dict + attrs: +# Include{ingressDefault} + +# Include{ingressTLS} + +# Include{ingressTraefik} + +# Include{ingressExpert} + +# Include{ingressList} + +# Include{security} + + - variable: advancedSecurity + label: "Show Advanced Security Settings" + group: "Security and Permissions" + schema: + type: boolean + default: false + show_subquestions_if: true + subquestions: + - variable: securityContext + label: "Security Context" + schema: + additional_attrs: true + type: dict + attrs: + - variable: privileged + label: "Privileged mode" + schema: + type: boolean + default: false + - variable: readOnlyRootFilesystem + label: "ReadOnly Root Filesystem" + schema: + type: boolean + default: false + - variable: allowPrivilegeEscalation + label: "Allow Privilege Escalation" + schema: + type: boolean + default: false + - variable: runAsNonRoot + label: "runAsNonRoot" + schema: + type: boolean + default: false +# Include{securityContextAdvanced} + + - variable: podSecurityContext + group: "Security and Permissions" + label: "Pod Security Context" + schema: + additional_attrs: true + type: dict + attrs: + - variable: runAsUser + label: "runAsUser" + description: "The UserID of the user running the application" + schema: + type: int + default: 0 + - variable: runAsGroup + label: "runAsGroup" + description: "The groupID this App of the user running the application" + schema: + type: int + default: 0 + - variable: fsGroup + label: "fsGroup" + description: "The group that should own ALL storage." + schema: + type: int + default: 568 +# Include{podSecurityContextAdvanced} + +# Include{resources} + +# Include{advanced} + +# Include{addons} diff --git a/charts/incubator/wger/templates/_secrets.tpl b/charts/incubator/wger/templates/_secrets.tpl new file mode 100644 index 00000000000..701c43d1733 --- /dev/null +++ b/charts/incubator/wger/templates/_secrets.tpl @@ -0,0 +1,20 @@ +{{/* Define the secrets */}} +{{- define "wger.secrets" -}} +--- + +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: wger-secrets +{{- $wgerprevious := lookup "v1" "Secret" .Release.Namespace "wger-secrets" }} +{{- $secret_key := "" }} +data: + {{- if $wgerprevious}} + SECRET_KEY: {{ index $wgerprevious.data "SECRET_KEY" }} + {{- else }} + {{- $secret_key := randAlphaNum 32 }} + SECRET_KEY: {{ $secret_key | b64enc }} + {{- end }} + +{{- end -}} diff --git a/charts/incubator/wger/templates/common.yaml b/charts/incubator/wger/templates/common.yaml new file mode 100644 index 00000000000..d1a6f6a4650 --- /dev/null +++ b/charts/incubator/wger/templates/common.yaml @@ -0,0 +1,7 @@ +{{- include "tc.common.loader.init" . }} + +{{/* Render secrets for wger */}} +{{- include "wger.secrets" . }} + +{{/* Render the templates */}} +{{ include "tc.common.loader.apply" . }} diff --git a/charts/incubator/wger/values.yaml b/charts/incubator/wger/values.yaml new file mode 100644 index 00000000000..396a0825b40 --- /dev/null +++ b/charts/incubator/wger/values.yaml @@ -0,0 +1,179 @@ +image: + repository: wger/server + tag: latest@sha256:504626e67e709b00a23fb2daf8edd420f30b9e2d1c2c72efb2c3e3907fc636a1 + pullPolicy: IfNotPresent + +nginxImage: + repository: tccr.io/truecharts/nginx + tag: v1.22.0@sha256:9829252d9891aa3dfc654df8a98f65567ca8b43683e3ef2898944bc44287aeef + +securityContext: + runAsNonRoot: false + readOnlyRootFilesystem: false + +podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + +env: + DJANGO_DB_ENGINE: "django.db.backends.postgresql" + DJANGO_DB_DATABASE: "{{ .Values.postgresql.postgresqlDatabase }}" + DJANGO_DB_USER: "{{ .Values.postgresql.postgresqlUsername }}" + DJANGO_DB_PORT: "5432" + DJANGO_DB_HOST: + secretKeyRef: + name: dbcreds + key: plainhost + DJANGO_DB_PASSWORD: + secretKeyRef: + name: dbcreds + key: postgresql-password + DJANGO_CACHE_BACKEND: "django_redis.cache.RedisCache" + DJANGO_CACHE_CLIENT_CLASS: "django_redis.client.DefaultClient" + DJANGO_CACHE_TIMEOUT: "1296000" + DJANGO_CACHE_LOCATION: + secretKeyRef: + name: rediscreds + key: url + SECRET_KEY: + secretKeyRef: + name: wger-secrets + key: SECRET_KEY + TIME_ZONE: "{{ .Values.TZ }}" + # True, not true + WGER_USE_GUNICORN: "True" + # User Defined + SITE_URL: "{{ .Values.wger.site_url }}" + FROM_EMAIL: "{{ .Values.wger.from_email }}" + EXERCISE_CACHE_TTL: "{{ .Values.wger.exercise_cache_ttl }}" + EMAIL_HOST: "{{ .Values.wger.email_host }}" + EMAIL_PORT: "{{ .Values.wger.email_port }}" + EMAIL_HOST_USER: "{{ .Values.wger.email_host_user }}" + EMAIL_HOST_PASSWORD: "{{ .Values.wger.email_host_password }}" + RECAPTCHA_PUBLIC_KEY: "{{ .Values.wger.recaptha_public_key }}" + RECAPTCHA_PRIVATE_KEY: "{{ .Values.wger.recaptha_private_key }}" + +envFrom: + - configMapRef: + name: '{{ include "tc.common.names.fullname" . }}-wger' + +wger: + site_url: "http://localhost:8000" + sync_exercises_on_startup: false + download_exercise_images_on_startup: false + allow_registration: true + allow_guest_users: true + allow_upload_videos: true + exercise_cache_ttl: "3600" + django_perform_migrations: true + django_debug: false + enable_email: false + from_email: "" + email_host: "" + email_port: "587" + email_host_user: "" + email_host_password: "" + email_use_tls: true + email_use_ssl: true + recaptha_public_key: "" + recaptha_private_key: "" + nocaptcha: true + +configmap: + wger: + enabled: true + data: + SYNC_EXERCISES_ON_STARTUP: "{{ ternary \"True\" \"False\" .Values.wger.sync_exercises_on_startup }}" + DOWNLOAD_EXERCISE_IMAGES_ON_STARTUP: "{{ ternary \"True\" \"False\" .Values.wger.download_exercise_images_on_startup }}" + ALLOW_REGISTRATION: "{{ ternary \"True\" \"False\" .Values.wger.allow_registration }}" + ALLOW_GUEST_USERS: "{{ ternary \"True\" \"False\" .Values.wger.allow_guest_users }}" + ALLOW_UPLOAD_VIDEOS: "{{ ternary \"True\" \"False\" .Values.wger.allow_upload_videos }}" + DJANGO_PERFORM_MIGRATIONS: "{{ ternary \"True\" \"False\" .Values.wger.django_perform_migrations }}" + DJANGO_DEBUG: "{{ ternary \"True\" \"False\" .Values.wger.django_debug }}" + ENABLE_EMAIL: "{{ ternary \"True\" \"False\" .Values.wger.enable_email }}" + EMAIL_USE_TLS: "{{ ternary \"True\" \"False\" .Values.wger.email_use_tls }}" + EMAIL_USE_SSL: "{{ ternary \"True\" \"False\" .Values.wger.email_use_ssl }}" + NOCAPTCHA: "{{ ternary \"True\" \"False\" .Values.wger.nocaptcha }}" + config: + enabled: true + data: + nginx-config: |- + upstream wger { + server localhost:8000; + } + server { + listen 80; + location / { + proxy_pass http://localhost; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_redirect off; + } + location /static/ { + alias /static/; + } + location /media/ { + alias /media/; + } + # Increase max body size to allow for video uploads + client_max_body_size 100M; + } + +probes: + liveness: + path: "/" + readiness: + path: "/" + startup: + path: "/" + +service: + main: + ports: + main: + port: 10249 + targetPort: 80 + +additionalContainers: + nginx: + name: nginx + image: "{{ .Values.nginxImage.repository }}:{{ .Values.nginxImage.tag }}" + ports: + - containerPort: 80 + name: main + volumeMounts: + - name: wger-config + mountPath: "/etc/nginx/conf.d/default.conf" + subPath: nginx-config + readOnly: true + - name: media + mountPath: "/media" + - name: static + mountPath: "/static" + +persistence: + media: + enabled: true + mountPath: "/home/wger/media" + static: + enabled: true + type: emptyDir + mountPath: "/home/wger/static" + wger-config: + enabled: "true" + mountPath: "/etc/nginx/conf.d/default.conf" + subPath: "default.conf" + type: "custom" + volumeSpec: + configMap: + name: '{{ printf "%v-config" (include "tc.common.names.fullname" .) }}' + +postgresql: + enabled: true + existingSecret: "dbcreds" + postgresqlUsername: wger + postgresqlDatabase: wger + +redis: + enabled: true + existingSecret: "rediscreds"