diff --git a/charts/stable/grist/Chart.yaml b/charts/stable/grist/Chart.yaml index c90f1f3d58e..04dc8841a54 100644 --- a/charts/stable/grist/Chart.yaml +++ b/charts/stable/grist/Chart.yaml @@ -4,6 +4,10 @@ dependencies: - name: common repository: https://library-charts.truecharts.org version: 10.7.0 + - condition: postgresql.enabled + name: postgresql + repository: https://charts.truecharts.org/ + version: 8.0.97 - condition: redis.enabled name: redis repository: https://charts.truecharts.org @@ -26,7 +30,7 @@ sources: - https://hub.docker.com/r/gristlabs/grist - https://github.com/gristlabs/grist-core - https://support.getgrist.com/ -version: 3.0.44 +version: 4.0.0 annotations: truecharts.org/catagories: | - productivity diff --git a/charts/stable/grist/questions.yaml b/charts/stable/grist/questions.yaml index f816b8c5cc9..b223768b34e 100644 --- a/charts/stable/grist/questions.yaml +++ b/charts/stable/grist/questions.yaml @@ -12,135 +12,218 @@ questions: # Include{recreate} # Include{controllerExpert} # Include{controllerExpertExtraArgs} - - variable: env - group: "Container Configuration" - label: "Image Environment" + - variable: grist + group: Container Configuration + label: Grist Configuration schema: additional_attrs: true type: dict attrs: - - variable: GRIST_DEFAULT_EMAIL - label: "GRIST_DEFAULT_EMAIL" - description: "If set, login as this user if no other credentials presented" + - variable: domain + label: Domain + description: In hosted Grist, Grist is served from subdomains of this domain + schema: + type: string + required: true + default: "" + - variable: single_org + label: Single Org + description: Set to an org "domain" to pin client to that org schema: type: string default: "" - - variable: GRIST_DOMAIN - label: "GRIST_DOMAIN" - description: "In hosted Grist, Grist is served from subdomains of this domain" + - variable: home_url + label: Home URL + description: URL prefix for home API schema: type: string default: "" - - variable: GRIST_SUPPORT_ANON - label: "GRIST_SUPPORT_ANON" - description: "If set to true, show UI for anonymous access." + - variable: default_email + label: Default Email + description: If set, login as this user if no other credentials presented schema: - type: boolean - default: false - - variable: GRIST_THROTTLE_CPU - label: "GRIST_THROTTLE_CPU" - description: "If set, CPU throttling is enabled" + type: string + default: "" + - variable: default_product + label: Default Product + description: If set, this controls enabled features and limits of new sites. schema: - type: boolean - default: false - - variable: GRIST_BACKUP_DELAY_SECS - label: "GRIST_BACKUP_DELAY_SECS" - description: "Wait this long after a doc change before making a backup" + type: string + default: "" + - variable: default_locale + label: Default Locale + description: Locale to use as fallback when Grist cannot honour the browser locale. + schema: + type: string + default: "" + - variable: allowed_webhook_domains + label: Allowed Webhook Domains + description: Permitted domains to use in webhooks + schema: + type: list + default: [] + items: + - variable: webhook_domain + label: Allowed Webhook Domain + schema: + type: string + default: "" + - variable: allowed_hosts + label: Allowed Hosts + description: Permitted domains origin for requests + schema: + type: list + default: [] + items: + - variable: webhook_host + label: Allowed Webhook Host + schema: + type: string + default: "" + - variable: hide_ui_elements + label: Hide UI Elements + description: Parts of the UI to hide + schema: + type: list + default: [] + items: + - variable: ui_element + label: UI Element to Hide + schema: + type: string + default: "" + enum: + - value: helpCenter + description: helpCenter + - value: billing + description: billing + - value: templates + description: templates + - value: multiSite + description: multiSite + - value: multiAccounts + description: multiAccounts + - variable: default_locale + label: Default Locale + description: Locale to use as fallback when Grist cannot honour the browser locale. + schema: + type: string + default: "" + - variable: max_upload_import_mb + label: Max Upload Import in MB + description: Max allowed size for imports (except .grist files) (0 for unlimited). schema: type: int - default: 15 - - variable: ALLOWED_WEBHOOK_DOMAINS - label: "ALLOWED_WEBHOOK_DOMAINS" - description: "Comma-separated list of permitted domains to use in webhooks" + default: 0 + - variable: max_upload_attachment_mb + label: Max Upload Attachment in MB + description: Max allowed size for attachments (except .grist files) (0 for unlimited). + schema: + type: int + default: 0 + - variable: title_suffix + label: Title Suffix + description: A string to append to the end of the in HTML documents. + schema: + type: string + default: " - Grist" + - variable: proxy_auth_header + label: Proxy Auth Header + description: Header which will be set by a (reverse) proxy web server with an authorized users email. schema: type: string default: "" - - variable: enabledsandbox - label: "Sandbox" + - variable: cookie_max_age + label: Cookie Max Age + description: Session cookie max age + schema: + type: int + default: 90 + - variable: force_login + label: Force Login + description: When set to true disables anonymous access + schema: + type: boolean + default: true + - variable: ignore_session + label: Ignore Session + description: If set, Grist will not use a session for authentication. schema: type: boolean default: false - show_subquestions_if: true - subquestions: - - variable: GRIST_SANDBOX_FLAVOR - label: "GRIST_SANDBOX_FLAVOR" - description: "If set, forces Grist to use the specified kind of sandbox." - schema: - type: string - default: "" - enum: - - value: "" - description: "Default" - - value: "pynbox" - description: "pynbox" - - value: "unsandboxed" - description: "unsandboxed" - - value: "docker" - description: "docker" - - value: "macSandboxExec" - description: "macSandboxExec" - - variable: GRIST_SANDBOX - label: "GRIST_SANDBOX" - description: "A program or image name to run as the sandbox. See NSandbox.ts for nerdy details." - schema: - type: string - default: "" - - variable: PYTHON_VERSION - label: "PYTHON_VERSION" - description: "If set, documents without an engine setting are assumed to use the specified version of python. Not all sandboxes support all versions." - schema: - type: string - default: "" - enum: - - value: "" - description: "Default" - - value: "2" - description: "2" - - value: "3" - description: "3" - - variable: PYTHON_VERSION_ON_CREATION - label: "PYTHON_VERSION_ON_CREATION" - description: "If set, newly created documents have an engine setting set to python2 or python3. Not all sandboxes support all versions." - schema: - type: string - default: "" - enum: - - value: "" - description: "Default" - - value: "2" - description: "2" - - value: "3" - description: "3" - - variable: enabledgdrive - label: "Google Drive Integration" + - variable: support_anon + label: Support Anon + description: When set to true, show UI for anonymous access schema: type: boolean default: false - show_subquestions_if: true - subquestions: - - variable: GOOGLE_CLIENT_ID - label: "GOOGLE_CLIENT_ID" - description: "Set to the Google Client Id to be used with Google API client" - schema: - type: string - default: "" - - variable: GOOGLE_CLIENT_SECRET - label: "GOOGLE_CLIENT_SECRET" - description: "Set to the Google Client Secret to be used with Google API client" + - variable: throttle_cpu + label: Throttle CPU + description: When set to true, CPU throttling is enabled + schema: + type: boolean + default: false + - variable: include_custom_css + label: Include Custom CSS + description: Set to true to include custom.css in static pages + schema: + type: boolean + default: false + - variable: google + label: Google Configuration + schema: + additional_attrs: true + type: dict + attrs: + - variable: client_id + label: Client ID + description: Set to the Google Client Id to be used with Google API client schema: type: string private: true default: "" - - variable: GOOGLE_API_KEY - label: "GOOGLE_API_KEY" - description: "Set to the Google API Key to be used with Google API client (accessing public files)" + - variable: client_secret + label: Client Secret + description: Set to the Google Client Secret to be used with Google API client schema: type: string private: true default: "" - - variable: GOOGLE_DRIVE_SCOPE - label: "GOOGLE_DRIVE_SCOPE" - description: "Set to the scope requested for Google Drive integration (defaults to drive.file)" + - variable: api_key + label: API Key + description: Set to the Google API Key to be used with Google API client (accessing public files) + schema: + type: string + private: true + default: "" + - variable: drive_scope + label: Drive Scope + description: Set to the scope requested for Google Drive integration + schema: + type: string + default: drive.file + - variable: forward_auth + label: Forward Auth + schema: + additional_attrs: true + type: dict + attrs: + - variable: header + label: Header + description: If set, trust the specified header (e.g. "x-forwarded-user") to contain authorized user emails, and enable "forward auth" logins. + schema: + type: string + default: "" + - variable: login_path + label: Login Path + description: If Header is set, Grist will listen at this path for logins. + schema: + type: string + private: true + default: /auth/login + - variable: logout_path + label: Logout Path + description: If Header is set, Grist will forward to this path when user logs out. schema: type: string private: true @@ -148,8 +231,8 @@ questions: # Include{containerConfig} # Include{serviceRoot} - variable: main - label: "Main Service" - description: "The Primary service on which the healthcheck runs, often the webUI" + label: Main Service + description: The Primary service on which the healthcheck runs, often the webUI schema: additional_attrs: true type: dict @@ -157,28 +240,28 @@ questions: # Include{serviceSelectorLoadBalancer} # Include{serviceSelectorExtras} - variable: main - label: "Main Service Port Configuration" + 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" + label: Port + description: This port exposes the container port on the service schema: type: int default: 10163 required: true # Include{advancedPortHTTP} - variable: targetPort - label: "Target Port" - description: "The internal(!) port on the container the Application runs on" + label: Target Port + description: The internal(!) port on the container the Application runs on schema: type: int default: 10163 - variable: api - label: "API Service" - description: "API service" + label: API Service + description: API service schema: additional_attrs: true type: dict @@ -186,22 +269,22 @@ questions: # Include{serviceSelectorLoadBalancer} # Include{serviceSelectorExtras} - variable: api - label: "API Service Port Configuration" + label: API Service Port Configuration schema: additional_attrs: true type: dict attrs: - variable: port - label: "Port" - description: "This port exposes the container port on the service" + label: Port + description: This port exposes the container port on the service schema: type: int default: 10164 required: true # Include{advancedPortHTTP} - variable: targetPort - label: "Target Port" - description: "The internal(!) port on the container the Application runs on" + label: Target Port + description: The internal(!) port on the container the Application runs on schema: type: int default: 10164 @@ -211,8 +294,8 @@ questions: # Include{serviceList} # Include{persistenceRoot} - variable: persist - label: "App Persist Storage" - description: "Stores the Application Persist." + label: App Persist Storage + description: Stores the Application Persist. schema: additional_attrs: true type: dict @@ -222,7 +305,7 @@ questions: # Include{persistenceList} # Include{ingressRoot} - variable: main - label: "Main Ingress" + label: Main Ingress schema: additional_attrs: true type: dict @@ -235,42 +318,42 @@ questions: # Include{security} # Include{securityContextAdvancedRoot} - variable: privileged - label: "Privileged mode" + label: Privileged mode schema: type: boolean default: false - variable: readOnlyRootFilesystem - label: "ReadOnly Root Filesystem" + label: ReadOnly Root Filesystem schema: type: boolean default: false - variable: allowPrivilegeEscalation - label: "Allow Privilege Escalation" + label: Allow Privilege Escalation schema: type: boolean default: false - variable: runAsNonRoot - label: "runAsNonRoot" + label: runAsNonRoot schema: type: boolean default: false # Include{securityContextAdvanced} # Include{podSecurityContextRoot} - variable: runAsUser - label: "runAsUser" - description: "The UserID of the user running the application" + 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" + 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." + label: fsGroup + description: The group that should own ALL storage. schema: type: int default: 568 diff --git a/charts/stable/grist/templates/_config.tpl b/charts/stable/grist/templates/_config.tpl new file mode 100644 index 00000000000..6bd1b0e0383 --- /dev/null +++ b/charts/stable/grist/templates/_config.tpl @@ -0,0 +1,85 @@ +{{/* Define the configmap */}} +{{- define "grist.config" -}} + +{{- $configName := printf "%s-grist-config" (include "tc.common.names.fullname" .) }} + +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ $configName }} + labels: + {{- include "tc.common.labels" . | nindent 4 }} +data: + {{/* Dependencies */}} + TYPEORM_TYPE: postgres + TYPEORM_PORT: "5432" + TYPEORM_HOST: {{ printf "%v-%v" .Release.Name "postgresql" }} + TYPEORM_DATABASE: {{ .Values.postgresql.postgresqlDatabase }} + TYPEORM_USERNAME: {{ .Values.postgresql.postgresqlUsername }} + {{/* Ports */}} + PORT: {{ .Values.service.main.ports.main.port | quote }} + HOME_PORT: {{ .Values.service.api.ports.api.port | quote }} + {{/* Google */}} + {{- with .Values.grist.google.drive_scope }} + GOOGLE_DRIVE_SCOPE: {{ . }} + {{- end }} + {{/* Forward Auth */}} + {{- with .Values.grist.forward_auth.header }} + GRIST_FORWARD_AUTH_HEADER: {{ . }} + {{- end }} + {{- with .Values.grist.forward_auth.login_path }} + GRIST_FORWARD_AUTH_LOGIN_PATH: {{ . }} + {{- end }} + {{- with .Values.grist.forward_auth.logout_path }} + GRIST_FORWARD_AUTH_LOGOUT_PATH: {{ . }} + {{- end }} + {{/* APP */}} + {{- with .Values.grist.home_url }} + APP_HOME_URL: + {{- end }} + {{- with .Values.grist.allowed_webhook_domains }} + ALLOWED_WEBHOOK_DOMAINS: {{ join "," . }} + {{- end }} + {{- with .Values.grist.allowed_hosts }} + GRIST_ALLOWED_HOSTS: {{ join "," . }} + {{- end }} + {{- with .Values.grist.backup_delay_secs }} + GRIST_BACKUP_DELAY_SECS: {{ . | quote }} + {{- end }} + {{- with .Values.grist.default_email }} + GRIST_DEFAULT_EMAIL: {{ . }} + {{- end }} + {{- with .Values.grist.default_product }} + GRIST_DEFAULT_PRODUCT: {{ . }} + {{- end }} + {{- with .Values.grist.default_locale }} + GRIST_DEFAULT_LOCALE: + {{- end }} + {{- with .Values.grist.domain }} + GRIST_DOMAIN: {{ . }} + {{- end }} + {{- with .Values.grist.hide_ui_elements }} + GRIST_HIDE_UI_ELEMENTS: {{ join "," . }} + {{- end }} + {{- with .Values.grist.title_suffix }} + GRIST_PAGE_TITLE_SUFFIX: {{ . | quote }} + {{- end }} + {{- with .Values.grist.proxy_auth_header }} + GRIST_PROXY_AUTH_HEADER: {{ . }} + {{- end }} + {{- with .Values.grist.cookie_max_age }} + COOKIE_MAX_AGE: {{ . | quote }} + {{- end }} + {{- with .Values.grist.single_org }} + GRIST_SINGLE_ORG: {{ . }} + {{- end }} + GRIST_IGNORE_SESSION: {{ .Values.grist.ignore_session | quote }} + GRIST_FORCE_LOGIN: {{ .Values.grist.force_login | quote }} + GRIST_SUPPORT_ANON: {{ .Values.grist.support_anon | quote }} + GRIST_THROTTLE_CPU: {{ .Values.grist.throttle_cpu | quote }} + APP_STATIC_INCLUDE_CUSTOM_CSS: {{ .Values.grist.include_custom_css | quote }} + GRIST_MAX_UPLOAD_ATTACHMENT_MB: {{ .Values.grist.max_upload_attachment_mb | quote }} + GRIST_MAX_UPLOAD_IMPORT_MB: {{ .Values.grist.max_upload_import_mb | quote }} +{{- end -}} diff --git a/charts/stable/grist/templates/_secret.tpl b/charts/stable/grist/templates/_secret.tpl new file mode 100644 index 00000000000..7f9d56441b5 --- /dev/null +++ b/charts/stable/grist/templates/_secret.tpl @@ -0,0 +1,35 @@ +{{/* Define the secret */}} +{{- define "grist.secret" -}} + +{{- $secretName := printf "%s-grist-secret" (include "tc.common.names.fullname" .) }} + +--- + +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: {{ $secretName }} + labels: + {{- include "tc.common.labels" . | nindent 4 }} +data: + {{/* Secret Key */}} + {{- with (lookup "v1" "Secret" .Release.Namespace $secretName) }} + GRIST_SESSION_SECRET: {{ index .data "GRIST_SESSION_SECRET" }} + {{- else }} + GRIST_SESSION_SECRET: {{ randAlphaNum 32 | b64enc }} + {{- end }} + {{/* Dependencies */}} + TYPEORM_PASSWORD: {{ .Values.postgresql.postgresqlPassword | trimAll "\"" | b64enc }} + REDIS_URL: {{ printf "redis://:%v@%v-redis:6379/%v" ( .Values.redis.redisPassword | trimAll "\"" ) .Release.Name "0" | b64enc }} + {{/* Google */}} + {{- with .Values.grist.google.client_id }} + GOOGLE_CLIENT_ID: {{ . }} + {{- end }} + {{- with .Values.grist.google.client_secret }} + GOOGLE_CLIENT_SECRET: {{ . }} + {{- end }} + {{- with .Values.grist.google.api_key }} + GOOGLE_API_KEY: {{ . }} + {{- end }} +{{- end }} diff --git a/charts/stable/grist/templates/common.yaml b/charts/stable/grist/templates/common.yaml index c1a366e1cf0..cb50edbcc64 100644 --- a/charts/stable/grist/templates/common.yaml +++ b/charts/stable/grist/templates/common.yaml @@ -1 +1,11 @@ -{{ include "tc.common.loader.all" . }} +{{/* Make sure all variables are set properly */}} +{{- include "tc.common.loader.init" . }} + +{{/* Render secret */}} +{{- include "grist.secret" . }} + +{{/* Render config */}} +{{- include "grist.config" . }} + +{{/* Render the templates */}} +{{ include "tc.common.loader.apply" . }} diff --git a/charts/stable/grist/values.yaml b/charts/stable/grist/values.yaml index 6ac85a439d8..906d14eea72 100644 --- a/charts/stable/grist/values.yaml +++ b/charts/stable/grist/values.yaml @@ -1,6 +1,6 @@ image: repository: tccr.io/truecharts/grist - tag: v0.7.9@sha256:277902644b6444f90cf81cdb04b4749377585e3e2b4cefd17f1469d5f440349a + tag: v1.0.3@sha256:d924a73ae31e0818331ca5d744a4103caa1ddf902dbd0c7a0e74e20cf9b953cc pullPolicy: IfNotPresent securityContext: @@ -11,50 +11,69 @@ podSecurityContext: runAsUser: 0 runAsGroup: 0 -env: - PORT: "{{ .Values.service.main.ports.main.port }}" - HOME_PORT: "{{ .Values.service.api.ports.api.port }}" - GRIST_DEFAULT_EMAIL: "user@mydomain.com" - GRIST_DOMAIN: "" - GRIST_SUPPORT_ANON: false - GRIST_THROTTLE_CPU: false - GRIST_BACKUP_DELAY_SECS: 15 - ALLOWED_WEBHOOK_DOMAINS: "" - GRIST_SANDBOX_FLAVOR: "" - GRIST_SANDBOX: "" - PYTHON_VERSION: "" - PYTHON_VERSION_ON_CREATION: "" - GOOGLE_CLIENT_ID: "" - GOOGLE_CLIENT_SECRET: "" - GOOGLE_API_KEY: "" - GOOGLE_DRIVE_SCOPE: "" - REDIS_URL: - secretKeyRef: - name: rediscreds - key: url +grist: + domain: "" + single_org: "" + home_url: "" + default_email: user@mydomain.com + default_product: "" + default_locale: "" + allowed_webhook_domains: [] + allowed_hosts: [] + hide_ui_elements: [] + backup_delay_secs: 15 + max_upload_import_mb: 0 + max_upload_attachment_mb: 0 + title_suffix: " - Grist" + proxy_auth_header: "" + cookie_max_age: 90 + force_login: true + ignore_session: false + support_anon: false + throttle_cpu: false + include_custom_css: false + google: + client_id: "" + client_secret: "" + api_key: "" + drive_scope: drive.file + forward_auth: + header: "" + login_path: /auth/login + logout_path: "" + +envFrom: + - secretRef: + name: '{{ include "tc.common.names.fullname" . }}-grist-secret' + - configMapRef: + name: '{{ include "tc.common.names.fullname" . }}-grist-config' service: main: ports: main: port: 10163 - targetPort: 10163 api: enabled: true ports: api: enabled: true port: 10164 - targetPort: 10164 persistence: persist: enabled: true mountPath: "/persist" +postgresql: + enabled: true + existingSecret: dbcreds + postgresqlUsername: grist + postgresqlDatabase: grist + redis: enabled: true - existingSecret: "rediscreds" + existingSecret: rediscreds portal: enabled: true