diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 262b6742c8fb2e53311ef78c079c2c16334baa20..bd1a297784a1a84cbfe7470dd83a7989646d32ed 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ include: - project: 'platform-one/big-bang/pipeline-templates/pipeline-templates' - ref: remove-helm-dependency + ref: master file: '/templates/package-tests.yml' diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..05d02216a8120efcb2177e19bbf1f1dd14dfdb41 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +--- + +## [0.1.0-bb.0] - 2021-02-X + +### Added + +- Initial chart built from operator v1.12.0 using Ironbank images diff --git a/CODEOWNERS b/CODEOWNERS index 60163cef49c05947a606962d541a060f7728a3cd..9c87a4c6d25fe9bfd18df30621d2a97867c03b1d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @kevin.wilder @ryan.j.garcia +* @micah.nagel @branden.cobb diff --git a/docs/CONTRIBUTING.md b/CONTRIBUTING.md similarity index 100% rename from docs/CONTRIBUTING.md rename to CONTRIBUTING.md diff --git a/README.md b/README.md index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..972ffcc7e65f9815a1483b45aff929276ab20da6 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,16 @@ +# Mattermost + +Mattermost is an open source, private cloud, Slack-alternative from https://mattermost.com. It is used for enterprise collaboration/chat within P1 and for Big Bang. + +This repo provides an implementation of Mattermost for Big Bang. Installation requires that the [Mattermost Operator](https://repo1.dso.mil/platform-one/big-bang/apps/collaboration-tools/mattermost-operator) be installed in your cluster as a prerequisite. + +Several of the important values to take note of when installing include: +- `istio.enabled`: This will enable istio networking for Mattermost within your cluster. +- `users`: This changes the maximum users for your instance, allowable values are 100, 1000, 5000, 10000, 25000 (NOTE: this may be limited on whether you have an enterprise license). +- `replicaCount`: The desired number of replicas for your instance. Defaults to 3 with the `chart/values.yaml`. +- `enterprise.enabled`: Enable enterprise features (if you don't also specify a license this only affects monitoring). +- `enterprise.license`: Value to add your license (entire license file contents - format shown in values). You can also manually add your license via the system console in Mattermost. +- `minio.install`: Install a minio instance standalone for Mattermost, for production you should specify a `fileStore` url, secret, and bucket. +- `postgresql.install`: Install a postgres instance standalone for Mattermost, for production you should specify a `database` secret +- `sso.enabled`: Enable SSO integration w/ Keycloak, requires additional config/values to point to your Keycloak. +- `monitoring.enabled`: Enabled Prometheus monitoring integration with Mattermost, this will only work if you toggle `enterprise.enabled` to true as well. diff --git a/chart/Chart.yaml b/chart/Chart.yaml index f2f4a61e704d04bdb6a533be346ed6bf1b35a5df..3b4c101f43cee8a0c344cb23bc1cc882d528d887 100644 --- a/chart/Chart.yaml +++ b/chart/Chart.yaml @@ -1,16 +1,21 @@ --- apiVersion: v2 -appVersion: "5.27.0" -dependencies: ~ -description: "Deployment of mattermost operator using Helm" +name: mattermost +type: application +version: "0.1.0-bb.0" +appVersion: "5.31.0" +description: "Deployment of mattermost" keywords: - Mattermost - Instance kubeVersion: ">=1.12.0-0" -maintainers: - - - email: ~ - name: ~ -name: mattermost-operator -type: application -version: "1.5.0" + +dependencies: + - name: postgresql + version: 10.3.5 + alias: postgresql + condition: postgresql.install + - name: minio + version: 0.1.0-bb.0 + alias: minio + condition: minio.install diff --git a/chart/charts/minio/Chart.yaml b/chart/charts/minio/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..99204bad6c4cc41cb58a1f397ef695a26eb8dffe --- /dev/null +++ b/chart/charts/minio/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: minio +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0-bb.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: 2.0.9 diff --git a/chart/charts/minio/templates/_helpers.tpl b/chart/charts/minio/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..28d56868c487fee95f819e919dcbfb369792b178 --- /dev/null +++ b/chart/charts/minio/templates/_helpers.tpl @@ -0,0 +1,50 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "minio.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 "minio.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 "minio.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "minio.labels" -}} +helm.sh/chart: {{ include "minio.chart" . }} +{{ include "minio.selectorLabels" . }} +app.kubernetes.io/version: {{ .Chart.Version | quote }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "minio.selectorLabels" -}} +app.kubernetes.io/name: {{ include "minio.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/part-of: {{ include "mattermost.name" . }} +{{- end }} diff --git a/chart/charts/minio/templates/instance.yaml b/chart/charts/minio/templates/instance.yaml new file mode 100644 index 0000000000000000000000000000000000000000..eb82f789f2000dcb909953b3b1266b54a68efce7 --- /dev/null +++ b/chart/charts/minio/templates/instance.yaml @@ -0,0 +1,104 @@ +apiVersion: operator.min.io/v1 +kind: MinIOInstance +metadata: + name: minio + namespace: {{ .Release.Namespace }} +## If specified, MinIOInstance pods will be dispatched by specified scheduler. +## If not specified, the pod will be dispatched by default scheduler. +# scheduler: +# name: my-custom-scheduler +spec: + ## Add metadata to the all pods created by the StatefulSet + metadata: + ## Optionally pass labels to be applied to the statefulset pods + labels: + app: minio + {{ include "minio.labels" . | nindent 6 }} + app.kubernetes.io/component: "objectstorage" + annotations: + prometheus.io/path: /minio/prometheus/metrics + prometheus.io/port: "9000" + prometheus.io/scrape: "true" + ## Registry location and Tag to download MinIO Server image + image: {{ .Values.image.name }}:{{ .Values.image.tag }} + serviceAccountName: minio-service-account + ## A ClusterIP Service will be created with the given name + serviceName: minio-internal-service + zones: + - name: "zone-0" + ## Number of MinIO servers/pods in this zone. + ## For standalone mode, supply 1. For distributed mode, supply 4 or more. + ## Note that the operator does not support upgrading from standalone to distributed mode. + servers: {{ .Values.zones.servers }} + ## Supply number of volumes to be mounted per MinIO server instance. + ## 2 is minimum volumes with 3 servers + volumesPerServer: {{ .Values.volumesPerServer }} + ## Mount path where PV will be mounted inside container(s). Defaults to "/export". + mountPath: /export + ## Sub path inside Mount path where MinIO starts. Defaults to "". + # subPath: /data + ## This VolumeClaimTemplate is used across all the volumes provisioned for MinIO cluster. + ## Please do not change the volumeClaimTemplate field while expanding the cluster, this may + ## lead to unbound PVCs and missing data + volumeClaimTemplate: + metadata: + name: data + spec: + accessModes: + - {{ .Values.volumeClaimTemplate.accessModes}} + resources: + requests: + storage: {{ .Values.volumeClaimTemplate.storage}} + ## Secret with credentials to be used by MinIO instance. + credsSecret: + name: {{ .Values.minioUICreds }} + ## PodManagement policy for pods created by StatefulSet. Can be "OrderedReady" or "Parallel" + ## Refer https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#pod-management-policy + ## for details. Defaults to "Parallel" + podManagementPolicy: Parallel + ## Secret with certificates to configure TLS for MinIO certs. Create secrets as explained + ## here: https://github.com/minio/minio/tree/master/docs/tls/kubernetes#2-create-kubernetes-secret + # externalCertSecret: + # name: tls-ssl-minio + ## Enable Kubernetes based certificate generation and signing as explained in + ## https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster + requestAutoCert: false + ## Used when "requestAutoCert" is set to true. Set CommonName for the auto-generated certificate. + ## Internal DNS name for the pod will be used if CommonName is not provided. + ## DNS name format is minio-{0...3}.minio.default.svc.cluster.local + certConfig: + commonName: "" + organizationName: [] + dnsNames: [] + ## Used to specify a toleration for a pod + # tolerations: + # - effect: NoSchedule + # key: dedicated + # operator: Equal + # value: storage + ## Add environment variables to be set in MinIO container (https://github.com/minio/minio/tree/master/docs/config) + # env: + # - name: MINIO_BROWSER + # value: "off" # to turn-off browser + # - name: MINIO_STORAGE_CLASS_STANDARD + # value: "EC:2" + ## Configure resource requests and limits for MinIO containers + # resources: + # requests: + # memory: 20Gi + ## Liveness probe detects situations where MinIO server instance + ## is not working properly and needs restart. Kubernetes automatically + ## restarts the pods if liveness checks fail. + liveness: + initialDelaySeconds: 10 + periodSeconds: 1 + timeoutSeconds: 1 + ## nodeSelector parameters for MinIO Pods. It specifies a map of key-value pairs. For the pod to be + ## eligible to run on a node, the node must have each of the + ## indicated key-value pairs as labels. + ## Read more here: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + # nodeSelector: + # disktype: ssd + ## Affinity settings for MinIO pods. Read more about affinity + ## here: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity. + # affinity: diff --git a/chart/charts/minio/templates/secret.yaml b/chart/charts/minio/templates/secret.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ab7ee388914fc87c241235f70b5806380a9c8300 --- /dev/null +++ b/chart/charts/minio/templates/secret.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Secret +metadata: + name: minio-creds-secret + namespace: {{ .Release.Namespace }} + labels: + {{ include "minio.labels" . | nindent 4 }} + app.kubernetes.io/component: "objectstorage" +type: Opaque +data: + accesskey: {{ .Values.accessKey | b64enc }} + secretkey: {{ .Values.secretKey | b64enc }} diff --git a/chart/charts/minio/templates/service.yaml b/chart/charts/minio/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..db0c4b98e21b231163d92d40ab74d073345bc3e8 --- /dev/null +++ b/chart/charts/minio/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: minio-service + namespace: {{ .Release.Namespace }} + labels: + {{ include "minio.labels" . | nindent 4 }} + app.kubernetes.io/component: "objectstorage" +spec: + type: ClusterIP + ports: + - port: 9000 + targetPort: 9000 + protocol: TCP + selector: + app: minio diff --git a/chart/charts/minio/templates/serviceaccount.yaml b/chart/charts/minio/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c0a1a361cfcda748d0891ff4f90127e789e0d87d --- /dev/null +++ b/chart/charts/minio/templates/serviceaccount.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: minio-service-account + namespace: {{ .Release.Namespace }} + labels: + {{ include "minio.labels" . | nindent 4 }} + app.kubernetes.io/component: "objectstorage" +imagePullSecrets: + {{ toYaml .Values.global.imagePullSecrets | indent 2 }} diff --git a/chart/charts/minio/values.yaml b/chart/charts/minio/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d0796fa5147181dcefa8b98c5fdea4ad67a0210e --- /dev/null +++ b/chart/charts/minio/values.yaml @@ -0,0 +1,26 @@ +# Configure number of MinIO Operator Deployment Replicas +replicas: + count: 1 + +# Configure repo and tag of MinIO Operator Image +image: + name: registry1.dso.mil/ironbank/opensource/minio/minio + tag: RELEASE.2020-07-02T00-15-09Z + imagePullPolicy: IfNotPresent + +zones: + # refer to documentation for number of servers versus volumes per server + # https://docs.min.io/docs/minio-server-limits-per-tenant.html + servers: 3 # scale to 3 for dev + +volumesPerServer: 2 # 2 is minimum volumes with 3 servers + +volumeClaimTemplate: + accessModes: ReadWriteOnce + storage: 1Gi # scale down for dev + +minioUICreds: minio-creds-secret # Modify if you want to use an existing secret, minio-creds-secret is created by default and uses the below values +accessKey: minio +secretKey: minio#123 + +imagePullSecrets: [ ] diff --git a/chart/charts/postgresql/.helmignore b/chart/charts/postgresql/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..f0c13194444163d1cba5c67d9e79231a62bc8f44 --- /dev/null +++ b/chart/charts/postgresql/.helmignore @@ -0,0 +1,21 @@ +# 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 diff --git a/chart/charts/postgresql/Chart.lock b/chart/charts/postgresql/Chart.lock new file mode 100644 index 0000000000000000000000000000000000000000..2be1d093282360604205ccecee7cbe6140c2bc45 --- /dev/null +++ b/chart/charts/postgresql/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: https://charts.bitnami.com/bitnami + version: 1.4.0 +digest: sha256:af8a0894ca6f099e57ebfe9ce25a50d9e7548aeaa53b69d051ecc1681d6d77bb +generated: "2021-02-22T16:26:47.159006+01:00" diff --git a/chart/charts/postgresql/Chart.yaml b/chart/charts/postgresql/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..53e0c06d76c2ecf63020fb87d329302506cdc926 --- /dev/null +++ b/chart/charts/postgresql/Chart.yaml @@ -0,0 +1,29 @@ +annotations: + category: Database +apiVersion: v2 +appVersion: 11.11.0 +dependencies: + - name: common + repository: https://charts.bitnami.com/bitnami + version: 1.x.x +description: Chart for PostgreSQL, an object-relational database management system (ORDBMS) with an emphasis on extensibility and on standards-compliance. +engine: gotpl +home: https://github.com/bitnami/charts/tree/master/bitnami/postgresql +icon: https://bitnami.com/assets/stacks/postgresql/img/postgresql-stack-220x234.png +keywords: + - postgresql + - postgres + - database + - sql + - replication + - cluster +maintainers: + - email: containers@bitnami.com + name: Bitnami + - email: cedric@desaintmartin.fr + name: desaintmartin +name: postgresql +sources: + - https://github.com/bitnami/bitnami-docker-postgresql + - https://www.postgresql.org/ +version: 10.3.5 diff --git a/chart/charts/postgresql/Kptfile b/chart/charts/postgresql/Kptfile new file mode 100644 index 0000000000000000000000000000000000000000..250659e6f75f358b5faee0bd3e0cdc1521afc950 --- /dev/null +++ b/chart/charts/postgresql/Kptfile @@ -0,0 +1,11 @@ +apiVersion: kpt.dev/v1alpha1 +kind: Kptfile +metadata: + name: postgresql +upstream: + type: git + git: + commit: c2ac165a579a8f06dede2b6fede2f4ec2bfea495 + repo: https://github.com/bitnami/charts + directory: /bitnami/postgresql + ref: master diff --git a/chart/charts/postgresql/README.md b/chart/charts/postgresql/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1ccc0c1d44f63ff376d11dbece8d3dc6678f29e7 --- /dev/null +++ b/chart/charts/postgresql/README.md @@ -0,0 +1,770 @@ +# PostgreSQL + +[PostgreSQL](https://www.postgresql.org/) is an object-relational database management system (ORDBMS) with an emphasis on extensibility and on standards-compliance. + +For HA, please see [this repo](https://github.com/bitnami/charts/tree/master/bitnami/postgresql-ha) + +## TL;DR + +```console +$ helm repo add bitnami https://charts.bitnami.com/bitnami +$ helm install my-release bitnami/postgresql +``` + +## Introduction + +This chart bootstraps a [PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This chart has been tested to work with NGINX Ingress, cert-manager, fluentd and Prometheus on top of the [BKPR](https://kubeprod.io/). + +## Prerequisites + +- Kubernetes 1.12+ +- Helm 3.1.0 +- PV provisioner support in the underlying infrastructure + +## Installing the Chart +To install the chart with the release name `my-release`: + +```console +$ helm install my-release bitnami/postgresql +``` + +The command deploys PostgreSQL on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. + +> **Tip**: List all releases using `helm list` + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```console +$ helm delete my-release +``` + +The command removes all the Kubernetes components but PVC's associated with the chart and deletes the release. + +To delete the PVC's associated with `my-release`: + +```console +$ kubectl delete pvc -l release=my-release +``` + +> **Note**: Deleting the PVC's will delete postgresql data as well. Please be cautious before doing it. + +## Parameters + +The following tables lists the configurable parameters of the PostgreSQL chart and their default values. + +| Parameter | Description | Default | +|-----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------| +| `global.imageRegistry` | Global Docker Image registry | `nil` | +| `global.postgresql.postgresqlDatabase` | PostgreSQL database (overrides `postgresqlDatabase`) | `nil` | +| `global.postgresql.postgresqlUsername` | PostgreSQL username (overrides `postgresqlUsername`) | `nil` | +| `global.postgresql.existingSecret` | Name of existing secret to use for PostgreSQL passwords (overrides `existingSecret`) | `nil` | +| `global.postgresql.postgresqlPassword` | PostgreSQL admin password (overrides `postgresqlPassword`) | `nil` | +| `global.postgresql.servicePort` | PostgreSQL port (overrides `service.port`) | `nil` | +| `global.postgresql.replicationPassword` | Replication user password (overrides `replication.password`) | `nil` | +| `global.imagePullSecrets` | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) | +| `global.storageClass` | Global storage class for dynamic provisioning | `nil` | +| `image.registry` | PostgreSQL Image registry | `docker.io` | +| `image.repository` | PostgreSQL Image name | `bitnami/postgresql` | +| `image.tag` | PostgreSQL Image tag | `{TAG_NAME}` | +| `image.pullPolicy` | PostgreSQL Image pull policy | `IfNotPresent` | +| `image.pullSecrets` | Specify Image pull secrets | `nil` (does not add image pull secrets to deployed pods) | +| `image.debug` | Specify if debug values should be set | `false` | +| `nameOverride` | String to partially override common.names.fullname template with a string (will prepend the release name) | `nil` | +| `fullnameOverride` | String to fully override common.names.fullname template with a string | `nil` | +| `volumePermissions.enabled` | Enable init container that changes volume permissions in the data directory (for cases where the default k8s `runAsUser` and `fsUser` values do not work) | `false` | +| `volumePermissions.image.registry` | Init container volume-permissions image registry | `docker.io` | +| `volumePermissions.image.repository` | Init container volume-permissions image name | `bitnami/minideb` | +| `volumePermissions.image.tag` | Init container volume-permissions image tag | `buster` | +| `volumePermissions.image.pullPolicy` | Init container volume-permissions image pull policy | `Always` | +| `volumePermissions.securityContext.*` | Other container security context to be included as-is in the container spec | `{}` | +| `volumePermissions.securityContext.runAsUser` | User ID for the init container (when facing issues in OpenShift or uid unknown, try value "auto") | `0` | +| `usePasswordFile` | Have the secrets mounted as a file instead of env vars | `false` | +| `ldap.enabled` | Enable LDAP support | `false` | +| `ldap.existingSecret` | Name of existing secret to use for LDAP passwords | `nil` | +| `ldap.url` | LDAP URL beginning in the form `ldap[s]://host[:port]/basedn[?[attribute][?[scope][?[filter]]]]` | `nil` | +| `ldap.server` | IP address or name of the LDAP server. | `nil` | +| `ldap.port` | Port number on the LDAP server to connect to | `nil` | +| `ldap.scheme` | Set to `ldaps` to use LDAPS. | `nil` | +| `ldap.tls` | Set to `1` to use TLS encryption | `nil` | +| `ldap.prefix` | String to prepend to the user name when forming the DN to bind | `nil` | +| `ldap.suffix` | String to append to the user name when forming the DN to bind | `nil` | +| `ldap.search_attr` | Attribute to match against the user name in the search | `nil` | +| `ldap.search_filter` | The search filter to use when doing search+bind authentication | `nil` | +| `ldap.baseDN` | Root DN to begin the search for the user in | `nil` | +| `ldap.bindDN` | DN of user to bind to LDAP | `nil` | +| `ldap.bind_password` | Password for the user to bind to LDAP | `nil` | +| `replication.enabled` | Enable replication | `false` | +| `replication.user` | Replication user | `repl_user` | +| `replication.password` | Replication user password | `repl_password` | +| `replication.readReplicas` | Number of read replicas replicas | `1` | +| `replication.synchronousCommit` | Set synchronous commit mode. Allowed values: `on`, `remote_apply`, `remote_write`, `local` and `off` | `off` | +| `replication.numSynchronousReplicas` | Number of replicas that will have synchronous replication. Note: Cannot be greater than `replication.readReplicas`. | `0` | +| `replication.applicationName` | Cluster application name. Useful for advanced replication settings | `my_application` | +| `existingSecret` | Name of existing secret to use for PostgreSQL passwords. The secret has to contain the keys `postgresql-password` which is the password for `postgresqlUsername` when it is different of `postgres`, `postgresql-postgres-password` which will override `postgresqlPassword`, `postgresql-replication-password` which will override `replication.password` and `postgresql-ldap-password` which will be used to authenticate on LDAP. The value is evaluated as a template. | `nil` | +| `postgresqlPostgresPassword` | PostgreSQL admin password (used when `postgresqlUsername` is not `postgres`, in which case`postgres` is the admin username). | _random 10 character alphanumeric string_ | +| `postgresqlUsername` | PostgreSQL user (creates a non-admin user when `postgresqlUsername` is not `postgres`) | `postgres` | +| `postgresqlPassword` | PostgreSQL user password | _random 10 character alphanumeric string_ | +| `postgresqlDatabase` | PostgreSQL database | `nil` | +| `postgresqlDataDir` | PostgreSQL data dir folder | `/bitnami/postgresql` (same value as persistence.mountPath) | +| `extraEnv` | Any extra environment variables you would like to pass on to the pod. The value is evaluated as a template. | `[]` | +| `extraEnvVarsCM` | Name of a Config Map containing extra environment variables you would like to pass on to the pod. The value is evaluated as a template. | `nil` | +| `postgresqlInitdbArgs` | PostgreSQL initdb extra arguments | `nil` | +| `postgresqlInitdbWalDir` | PostgreSQL location for transaction log | `nil` | +| `postgresqlConfiguration` | Runtime Config Parameters | `nil` | +| `postgresqlExtendedConf` | Extended Runtime Config Parameters (appended to main or default configuration) | `nil` | +| `pgHbaConfiguration` | Content of pg_hba.conf | `nil (do not create pg_hba.conf)` | +| `postgresqlSharedPreloadLibraries` | Shared preload libraries (comma-separated list) | `pgaudit` | +| `postgresqlMaxConnections` | Maximum total connections | `nil` | +| `postgresqlPostgresConnectionLimit` | Maximum total connections for the postgres user | `nil` | +| `postgresqlDbUserConnectionLimit` | Maximum total connections for the non-admin user | `nil` | +| `postgresqlTcpKeepalivesInterval` | TCP keepalives interval | `nil` | +| `postgresqlTcpKeepalivesIdle` | TCP keepalives idle | `nil` | +| `postgresqlTcpKeepalivesCount` | TCP keepalives count | `nil` | +| `postgresqlStatementTimeout` | Statement timeout | `nil` | +| `postgresqlPghbaRemoveFilters` | Comma-separated list of patterns to remove from the pg_hba.conf file | `nil` | +| `customStartupProbe` | Override default startup probe | `nil` | +| `customLivenessProbe` | Override default liveness probe | `nil` | +| `customReadinessProbe` | Override default readiness probe | `nil` | +| `audit.logHostname` | Add client hostnames to the log file | `false` | +| `audit.logConnections` | Add client log-in operations to the log file | `false` | +| `audit.logDisconnections` | Add client log-outs operations to the log file | `false` | +| `audit.pgAuditLog` | Add operations to log using the pgAudit extension | `nil` | +| `audit.clientMinMessages` | Message log level to share with the user | `nil` | +| `audit.logLinePrefix` | Template string for the log line prefix | `nil` | +| `audit.logTimezone` | Timezone for the log timestamps | `nil` | +| `configurationConfigMap` | ConfigMap with the PostgreSQL configuration files (Note: Overrides `postgresqlConfiguration` and `pgHbaConfiguration`). The value is evaluated as a template. | `nil` | +| `extendedConfConfigMap` | ConfigMap with the extended PostgreSQL configuration files. The value is evaluated as a template. | `nil` | +| `initdbScripts` | Dictionary of initdb scripts | `nil` | +| `initdbUser` | PostgreSQL user to execute the .sql and sql.gz scripts | `nil` | +| `initdbPassword` | Password for the user specified in `initdbUser` | `nil` | +| `initdbScriptsConfigMap` | ConfigMap with the initdb scripts (Note: Overrides `initdbScripts`). The value is evaluated as a template. | `nil` | +| `initdbScriptsSecret` | Secret with initdb scripts that contain sensitive information (Note: can be used with `initdbScriptsConfigMap` or `initdbScripts`). The value is evaluated as a template. | `nil` | +| `service.type` | Kubernetes Service type | `ClusterIP` | +| `service.port` | PostgreSQL port | `5432` | +| `service.nodePort` | Kubernetes Service nodePort | `nil` | +| `service.annotations` | Annotations for PostgreSQL service | `{}` (evaluated as a template) | +| `service.loadBalancerIP` | loadBalancerIP if service type is `LoadBalancer` | `nil` | +| `service.loadBalancerSourceRanges` | Address that are allowed when svc is LoadBalancer | `[]` (evaluated as a template) | +| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` | +| `shmVolume.enabled` | Enable emptyDir volume for /dev/shm for primary and read replica(s) Pod(s) | `true` | +| `shmVolume.chmod.enabled` | Run at init chmod 777 of the /dev/shm (ignored if `volumePermissions.enabled` is `false`) | `true` | +| `persistence.enabled` | Enable persistence using PVC | `true` | +| `persistence.existingClaim` | Provide an existing `PersistentVolumeClaim`, the value is evaluated as a template. | `nil` | +| `persistence.mountPath` | Path to mount the volume at | `/bitnami/postgresql` | +| `persistence.subPath` | Subdirectory of the volume to mount at | `""` | +| `persistence.storageClass` | PVC Storage Class for PostgreSQL volume | `nil` | +| `persistence.accessModes` | PVC Access Mode for PostgreSQL volume | `[ReadWriteOnce]` | +| `persistence.size` | PVC Storage Request for PostgreSQL volume | `8Gi` | +| `persistence.annotations` | Annotations for the PVC | `{}` | +| `persistence.selector` | Selector to match an existing Persistent Volume (this value is evaluated as a template) | `{}` | +| `commonAnnotations` | Annotations to be added to all deployed resources (rendered as a template) | `{}` | +| `primary.podAffinityPreset` | PostgreSQL primary pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `primary.podAntiAffinityPreset` | PostgreSQL primary pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `primary.nodeAffinityPreset.type` | PostgreSQL primary node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `primary.nodeAffinityPreset.key` | PostgreSQL primary node label key to match Ignored if `primary.affinity` is set. | `""` | +| `primary.nodeAffinityPreset.values` | PostgreSQL primary node label values to match. Ignored if `primary.affinity` is set. | `[]` | +| `primary.affinity` | Affinity for PostgreSQL primary pods assignment | `{}` (evaluated as a template) | +| `primary.nodeSelector` | Node labels for PostgreSQL primary pods assignment | `{}` (evaluated as a template) | +| `primary.tolerations` | Tolerations for PostgreSQL primary pods assignment | `[]` (evaluated as a template) | +| `primary.anotations` | Map of annotations to add to the statefulset (postgresql primary) | `{}` | +| `primary.labels` | Map of labels to add to the statefulset (postgresql primary) | `{}` | +| `primary.podAnnotations` | Map of annotations to add to the pods (postgresql primary) | `{}` | +| `primary.podLabels` | Map of labels to add to the pods (postgresql primary) | `{}` | +| `primary.priorityClassName` | Priority Class to use for each pod (postgresql primary) | `nil` | +| `primary.extraInitContainers` | Additional init containers to add to the pods (postgresql primary) | `[]` | +| `primary.extraVolumeMounts` | Additional volume mounts to add to the pods (postgresql primary) | `[]` | +| `primary.extraVolumes` | Additional volumes to add to the pods (postgresql primary) | `[]` | +| `primary.sidecars` | Add additional containers to the pod | `[]` | +| `primary.service.type` | Allows using a different service type for primary | `nil` | +| `primary.service.nodePort` | Allows using a different nodePort for primary | `nil` | +| `primary.service.clusterIP` | Allows using a different clusterIP for primary | `nil` | +| `primaryAsStandBy.enabled` | Whether to enable current cluster's primary as standby server of another cluster or not. | `false` | +| `primaryAsStandBy.primaryHost` | The Host of replication primary in the other cluster. | `nil` | +| `primaryAsStandBy.primaryPort ` | The Port of replication primary in the other cluster. | `nil` | +| `readReplicas.podAffinityPreset` | PostgreSQL read only pod affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `readReplicas.podAntiAffinityPreset` | PostgreSQL read only pod anti-affinity preset. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `soft` | +| `readReplicas.nodeAffinityPreset.type` | PostgreSQL read only node affinity preset type. Ignored if `primary.affinity` is set. Allowed values: `soft` or `hard` | `""` | +| `readReplicas.nodeAffinityPreset.key` | PostgreSQL read only node label key to match Ignored if `primary.affinity` is set. | `""` | +| `readReplicas.nodeAffinityPreset.values` | PostgreSQL read only node label values to match. Ignored if `primary.affinity` is set. | `[]` | +| `readReplicas.affinity` | Affinity for PostgreSQL read only pods assignment | `{}` (evaluated as a template) | +| `readReplicas.nodeSelector` | Node labels for PostgreSQL read only pods assignment | `{}` (evaluated as a template) | +| `readReplicas.anotations` | Map of annotations to add to the statefulsets (postgresql readReplicas) | `{}` | +| `readReplicas.resources` | CPU/Memory resource requests/limits override for readReplicass. Will fallback to `values.resources` if not defined. | `{}` | +| `readReplicas.labels` | Map of labels to add to the statefulsets (postgresql readReplicas) | `{}` | +| `readReplicas.podAnnotations` | Map of annotations to add to the pods (postgresql readReplicas) | `{}` | +| `readReplicas.podLabels` | Map of labels to add to the pods (postgresql readReplicas) | `{}` | +| `readReplicas.priorityClassName` | Priority Class to use for each pod (postgresql readReplicas) | `nil` | +| `readReplicas.extraInitContainers` | Additional init containers to add to the pods (postgresql readReplicas) | `[]` | +| `readReplicas.extraVolumeMounts` | Additional volume mounts to add to the pods (postgresql readReplicas) | `[]` | +| `readReplicas.extraVolumes` | Additional volumes to add to the pods (postgresql readReplicas) | `[]` | +| `readReplicas.sidecars` | Add additional containers to the pod | `[]` | +| `readReplicas.service.type` | Allows using a different service type for readReplicas | `nil` | +| `readReplicas.service.nodePort` | Allows using a different nodePort for readReplicas | `nil` | +| `readReplicas.service.clusterIP` | Allows using a different clusterIP for readReplicas | `nil` | +| `readReplicas.persistence.enabled` | Whether to enable readReplicas replicas persistence | `true` | +| `terminationGracePeriodSeconds` | Seconds the pod needs to terminate gracefully | `nil` | +| `resources` | CPU/Memory resource requests/limits | Memory: `256Mi`, CPU: `250m` | +| `securityContext.*` | Other pod security context to be included as-is in the pod spec | `{}` | +| `securityContext.enabled` | Enable security context | `true` | +| `securityContext.fsGroup` | Group ID for the pod | `1001` | +| `containerSecurityContext.*` | Other container security context to be included as-is in the container spec | `{}` | +| `containerSecurityContext.enabled` | Enable container security context | `true` | +| `containerSecurityContext.runAsUser` | User ID for the container | `1001` | +| `serviceAccount.enabled` | Enable service account (Note: Service Account will only be automatically created if `serviceAccount.name` is not set) | `false` | +| `serviceAccount.name` | Name of existing service account | `nil` | +| `networkPolicy.enabled` | Enable NetworkPolicy | `false` | +| `networkPolicy.allowExternal` | Don't require client label for connections | `true` | +| `networkPolicy.explicitNamespacesSelector` | A Kubernetes LabelSelector to explicitly select namespaces from which ingress traffic could be allowed | `{}` | +| `startupProbe.enabled` | Enable startupProbe | `false` | +| `startupProbe.initialDelaySeconds` | Delay before liveness probe is initiated | 30 | +| `startupProbe.periodSeconds` | How often to perform the probe | 15 | +| `startupProbe.timeoutSeconds` | When the probe times | 5 | +| `startupProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 10 | +| `startupProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed. | 1 | +| `livenessProbe.enabled` | Enable livenessProbe | `true` | +| `livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | 30 | +| `livenessProbe.periodSeconds` | How often to perform the probe | 10 | +| `livenessProbe.timeoutSeconds` | When the probe times out | 5 | +| `livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | +| `livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | +| `readinessProbe.enabled` | Enable readinessProbe | `true` | +| `readinessProbe.initialDelaySeconds` | Delay before readiness probe is initiated | 5 | +| `readinessProbe.periodSeconds` | How often to perform the probe | 10 | +| `readinessProbe.timeoutSeconds` | When the probe times out | 5 | +| `readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | +| `readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | +| `tls.enabled` | Enable TLS traffic support | `false` | +| `tls.preferServerCiphers` | Whether to use the server's TLS cipher preferences rather than the client's | `true` | +| `tls.certificatesSecret` | Name of an existing secret that contains the certificates | `nil` | +| `tls.certFilename` | Certificate filename | `""` | +| `tls.certKeyFilename` | Certificate key filename | `""` | +| `tls.certCAFilename` | CA Certificate filename. If provided, PostgreSQL will authenticate TLS/SSL clients by requesting them a certificate. | `nil` | +| `tls.crlFilename` | File containing a Certificate Revocation List | `nil` | +| `metrics.enabled` | Start a prometheus exporter | `false` | +| `metrics.service.type` | Kubernetes Service type | `ClusterIP` | +| `service.clusterIP` | Static clusterIP or None for headless services | `nil` | +| `metrics.service.annotations` | Additional annotations for metrics exporter pod | `{ prometheus.io/scrape: "true", prometheus.io/port: "9187"}` | +| `metrics.service.loadBalancerIP` | loadBalancerIP if redis metrics service type is `LoadBalancer` | `nil` | +| `metrics.serviceMonitor.enabled` | Set this to `true` to create ServiceMonitor for Prometheus operator | `false` | +| `metrics.serviceMonitor.additionalLabels` | Additional labels that can be used so ServiceMonitor will be discovered by Prometheus | `{}` | +| `metrics.serviceMonitor.namespace` | Optional namespace in which to create ServiceMonitor | `nil` | +| `metrics.serviceMonitor.interval` | Scrape interval. If not set, the Prometheus default scrape interval is used | `nil` | +| `metrics.serviceMonitor.scrapeTimeout` | Scrape timeout. If not set, the Prometheus default scrape timeout is used | `nil` | +| `metrics.prometheusRule.enabled` | Set this to true to create prometheusRules for Prometheus operator | `false` | +| `metrics.prometheusRule.additionalLabels` | Additional labels that can be used so prometheusRules will be discovered by Prometheus | `{}` | +| `metrics.prometheusRule.namespace` | namespace where prometheusRules resource should be created | the same namespace as postgresql | +| `metrics.prometheusRule.rules` | [rules](https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/) to be created, check values for an example. | `[]` | +| `metrics.image.registry` | PostgreSQL Exporter Image registry | `docker.io` | +| `metrics.image.repository` | PostgreSQL Exporter Image name | `bitnami/postgres-exporter` | +| `metrics.image.tag` | PostgreSQL Exporter Image tag | `{TAG_NAME}` | +| `metrics.image.pullPolicy` | PostgreSQL Exporter Image pull policy | `IfNotPresent` | +| `metrics.image.pullSecrets` | Specify Image pull secrets | `nil` (does not add image pull secrets to deployed pods) | +| `metrics.customMetrics` | Additional custom metrics | `nil` | +| `metrics.extraEnvVars` | Extra environment variables to add to exporter | `{}` (evaluated as a template) | +| `metrics.securityContext.*` | Other container security context to be included as-is in the container spec | `{}` | +| `metrics.securityContext.enabled` | Enable security context for metrics | `false` | +| `metrics.securityContext.runAsUser` | User ID for the container for metrics | `1001` | +| `metrics.livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | 30 | +| `metrics.livenessProbe.periodSeconds` | How often to perform the probe | 10 | +| `metrics.livenessProbe.timeoutSeconds` | When the probe times out | 5 | +| `metrics.livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | +| `metrics.livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | +| `metrics.readinessProbe.enabled` | would you like a readinessProbe to be enabled | `true` | +| `metrics.readinessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | 5 | +| `metrics.readinessProbe.periodSeconds` | How often to perform the probe | 10 | +| `metrics.readinessProbe.timeoutSeconds` | When the probe times out | 5 | +| `metrics.readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | 6 | +| `metrics.readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed | 1 | +| `updateStrategy` | Update strategy policy | `{type: "RollingUpdate"}` | +| `psp.create` | Create Pod Security Policy | `false` | +| `rbac.create` | Create Role and RoleBinding (required for PSP to work) | `false` | +| `extraDeploy` | Array of extra objects to deploy with the release (evaluated as a template). | `nil` | + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +$ helm install my-release \ + --set postgresqlPassword=secretpassword,postgresqlDatabase=my-database \ + bitnami/postgresql +``` + +The above command sets the PostgreSQL `postgres` account password to `secretpassword`. Additionally it creates a database named `my-database`. + +> NOTE: Once this chart is deployed, it is not possible to change the application's access credentials, such as usernames or passwords, using Helm. To change these application credentials after deployment, delete any persistent volumes (PVs) used by the chart and re-deploy it, or use the application's built-in administrative tools if available. + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```console +$ helm install my-release -f values.yaml bitnami/postgresql +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Configuration and installation details + +### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/) + +It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image. + +Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist. + +### Customizing primary and read replica services in a replicated configuration + +At the top level, there is a service object which defines the services for both primary and readReplicas. For deeper customization, there are service objects for both the primary and read types individually. This allows you to override the values in the top level service object so that the primary and read can be of different service types and with different clusterIPs / nodePorts. Also in the case you want the primary and read to be of type nodePort, you will need to set the nodePorts to different values to prevent a collision. The values that are deeper in the primary.service or readReplicas.service objects will take precedence over the top level service object. + +### Change PostgreSQL version + +To modify the PostgreSQL version used in this chart you can specify a [valid image tag](https://hub.docker.com/r/bitnami/postgresql/tags/) using the `image.tag` parameter. For example, `image.tag=X.Y.Z`. This approach is also applicable to other images like exporters. + +### postgresql.conf / pg_hba.conf files as configMap + +This helm chart also supports to customize the whole configuration file. + +Add your custom file to "files/postgresql.conf" in your working directory. This file will be mounted as configMap to the containers and it will be used for configuring the PostgreSQL server. + +Alternatively, you can add additional PostgreSQL configuration parameters using the `postgresqlExtendedConf` parameter as a dict, using camelCase, e.g. {"sharedBuffers": "500MB"}. Alternatively, to replace the entire default configuration use `postgresqlConfiguration`. + +In addition to these options, you can also set an external ConfigMap with all the configuration files. This is done by setting the `configurationConfigMap` parameter. Note that this will override the two previous options. + +### Allow settings to be loaded from files other than the default `postgresql.conf` + +If you don't want to provide the whole PostgreSQL configuration file and only specify certain parameters, you can add your extended `.conf` files to "files/conf.d/" in your working directory. +Those files will be mounted as configMap to the containers adding/overwriting the default configuration using the `include_dir` directive that allows settings to be loaded from files other than the default `postgresql.conf`. + +Alternatively, you can also set an external ConfigMap with all the extra configuration files. This is done by setting the `extendedConfConfigMap` parameter. Note that this will override the previous option. + +### Initialize a fresh instance + +The [Bitnami PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) image allows you to use your custom scripts to initialize a fresh instance. In order to execute the scripts, they must be located inside the chart folder `files/docker-entrypoint-initdb.d` so they can be consumed as a ConfigMap. + +Alternatively, you can specify custom scripts using the `initdbScripts` parameter as dict. + +In addition to these options, you can also set an external ConfigMap with all the initialization scripts. This is done by setting the `initdbScriptsConfigMap` parameter. Note that this will override the two previous options. If your initialization scripts contain sensitive information such as credentials or passwords, you can use the `initdbScriptsSecret` parameter. + +The allowed extensions are `.sh`, `.sql` and `.sql.gz`. + +### Securing traffic using TLS + +TLS support can be enabled in the chart by specifying the `tls.` parameters while creating a release. The following parameters should be configured to properly enable the TLS support in the chart: + +- `tls.enabled`: Enable TLS support. Defaults to `false` +- `tls.certificatesSecret`: Name of an existing secret that contains the certificates. No defaults. +- `tls.certFilename`: Certificate filename. No defaults. +- `tls.certKeyFilename`: Certificate key filename. No defaults. + +For example: + +* First, create the secret with the cetificates files: + + ```console + kubectl create secret generic certificates-tls-secret --from-file=./cert.crt --from-file=./cert.key --from-file=./ca.crt + ``` + +* Then, use the following parameters: + + ```console + volumePermissions.enabled=true + tls.enabled=true + tls.certificatesSecret="certificates-tls-secret" + tls.certFilename="cert.crt" + tls.certKeyFilename="cert.key" + ``` + + > Note TLS and VolumePermissions: PostgreSQL requires certain permissions on sensitive files (such as certificate keys) to start up. Due to an on-going [issue](https://github.com/kubernetes/kubernetes/issues/57923) regarding kubernetes permissions and the use of `containerSecurityContext.runAsUser`, you must enable `volumePermissions` to ensure everything works as expected. + +### Sidecars + +If you need additional containers to run within the same pod as PostgreSQL (e.g. an additional metrics or logging exporter), you can do so via the `sidecars` config parameter. Simply define your container according to the Kubernetes container spec. + +```yaml +# For the PostgreSQL primary +primary: + sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +# For the PostgreSQL replicas +readReplicas: + sidecars: + - name: your-image-name + image: your-image + imagePullPolicy: Always + ports: + - name: portname + containerPort: 1234 +``` + +### Metrics + +The chart optionally can start a metrics exporter for [prometheus](https://prometheus.io). The metrics endpoint (port 9187) is not exposed and it is expected that the metrics are collected from inside the k8s cluster using something similar as the described in the [example Prometheus scrape configuration](https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus-kubernetes.yml). + +The exporter allows to create custom metrics from additional SQL queries. See the Chart's `values.yaml` for an example and consult the [exporters documentation](https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file) for more details. + +### Use of global variables + +In more complex scenarios, we may have the following tree of dependencies + +``` + +--------------+ + | | + +------------+ Chart 1 +-----------+ + | | | | + | --------+------+ | + | | | + | | | + | | | + | | | + v v v ++-------+------+ +--------+------+ +--------+------+ +| | | | | | +| PostgreSQL | | Sub-chart 1 | | Sub-chart 2 | +| | | | | | ++--------------+ +---------------+ +---------------+ +``` + +The three charts below depend on the parent chart Chart 1. However, subcharts 1 and 2 may need to connect to PostgreSQL as well. In order to do so, subcharts 1 and 2 need to know the PostgreSQL credentials, so one option for deploying could be deploy Chart 1 with the following parameters: + +``` +postgresql.postgresqlPassword=testtest +subchart1.postgresql.postgresqlPassword=testtest +subchart2.postgresql.postgresqlPassword=testtest +postgresql.postgresqlDatabase=db1 +subchart1.postgresql.postgresqlDatabase=db1 +subchart2.postgresql.postgresqlDatabase=db1 +``` + +If the number of dependent sub-charts increases, installing the chart with parameters can become increasingly difficult. An alternative would be to set the credentials using global variables as follows: + +``` +global.postgresql.postgresqlPassword=testtest +global.postgresql.postgresqlDatabase=db1 +``` + +This way, the credentials will be available in all of the subcharts. + +## Persistence + +The [Bitnami PostgreSQL](https://github.com/bitnami/bitnami-docker-postgresql) image stores the PostgreSQL data and configurations at the `/bitnami/postgresql` path of the container. + +Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube. +See the [Parameters](#parameters) section to configure the PVC or to disable persistence. + +If you already have data in it, you will fail to sync to standby nodes for all commits, details can refer to [code](https://github.com/bitnami/bitnami-docker-postgresql/blob/8725fe1d7d30ebe8d9a16e9175d05f7ad9260c93/9.6/debian-9/rootfs/libpostgresql.sh#L518-L556). If you need to use those data, please covert them to sql and import after `helm install` finished. + +## NetworkPolicy + +To enable network policy for PostgreSQL, install [a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin), and set `networkPolicy.enabled` to `true`. + +For Kubernetes v1.5 & v1.6, you must also turn on NetworkPolicy by setting the DefaultDeny namespace annotation. Note: this will enforce policy for _all_ pods in the namespace: + +```console +$ kubectl annotate namespace default "net.beta.kubernetes.io/network-policy={\"ingress\":{\"isolation\":\"DefaultDeny\"}}" +``` + +With NetworkPolicy enabled, traffic will be limited to just port 5432. + +For more precise policy, set `networkPolicy.allowExternal=false`. This will only allow pods with the generated client label to connect to PostgreSQL. +This label will be displayed in the output of a successful install. + +## Differences between Bitnami PostgreSQL image and [Docker Official](https://hub.docker.com/_/postgres) image + +- The Docker Official PostgreSQL image does not support replication. If you pass any replication environment variable, this would be ignored. The only environment variables supported by the Docker Official image are POSTGRES_USER, POSTGRES_DB, POSTGRES_PASSWORD, POSTGRES_INITDB_ARGS, POSTGRES_INITDB_WALDIR and PGDATA. All the remaining environment variables are specific to the Bitnami PostgreSQL image. +- The Bitnami PostgreSQL image is non-root by default. This requires that you run the pod with `securityContext` and updates the permissions of the volume with an `initContainer`. A key benefit of this configuration is that the pod follows security best practices and is prepared to run on Kubernetes distributions with hard security constraints like OpenShift. +- For OpenShift, one may either define the runAsUser and fsGroup accordingly, or try this more dynamic option: volumePermissions.securityContext.runAsUser="auto",securityContext.enabled=false,containerSecurityContext.enabled=false,shmVolume.chmod.enabled=false + +### Deploy chart using Docker Official PostgreSQL Image + +From chart version 4.0.0, it is possible to use this chart with the Docker Official PostgreSQL image. +Besides specifying the new Docker repository and tag, it is important to modify the PostgreSQL data directory and volume mount point. Basically, the PostgreSQL data dir cannot be the mount point directly, it has to be a subdirectory. + +``` +image.repository=postgres +image.tag=10.6 +postgresqlDataDir=/data/pgdata +persistence.mountPath=/data/ +``` + +### Setting Pod's affinity + +This chart allows you to set your custom affinity using the `XXX.affinity` paremeter(s). Find more infomation about Pod's affinity in the [kubernetes documentation](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity). + +As an alternative, you can use of the preset configurations for pod affinity, pod anti-affinity, and node affinity available at the [bitnami/common](https://github.com/bitnami/charts/tree/master/bitnami/common#affinities) chart. To do so, set the `XXX.podAffinityPreset`, `XXX.podAntiAffinityPreset`, or `XXX.nodeAffinityPreset` parameters. + +## Troubleshooting + +Find more information about how to deal with common errors related to Bitnami’s Helm charts in [this troubleshooting guide](https://docs.bitnami.com/general/how-to/troubleshoot-helm-chart-issues). + +## Upgrading + +It's necessary to specify the existing passwords while performing an upgrade to ensure the secrets are not updated with invalid randomly generated passwords. Remember to specify the existing values of the `postgresqlPassword` and `replication.password` parameters when upgrading the chart: + +```bash +$ helm upgrade my-release bitnami/postgresql \ + --set postgresqlPassword=[POSTGRESQL_PASSWORD] \ + --set replication.password=[REPLICATION_PASSWORD] +``` + +> Note: you need to substitute the placeholders _[POSTGRESQL_PASSWORD]_, and _[REPLICATION_PASSWORD]_ with the values obtained from instructions in the installation notes. + +### To 10.0.0 + +[On November 13, 2020, Helm v2 support was formally finished](https://github.com/helm/charts#status-of-the-project), this major version is the result of the required changes applied to the Helm Chart to be able to incorporate the different features added in Helm v3 and to be consistent with the Helm project itself regarding the Helm v2 EOL. + +**What changes were introduced in this major version?** + +- Previous versions of this Helm Chart use `apiVersion: v1` (installable by both Helm 2 and 3), this Helm Chart was updated to `apiVersion: v2` (installable by Helm 3 only). [Here](https://helm.sh/docs/topics/charts/#the-apiversion-field) you can find more information about the `apiVersion` field. +- Move dependency information from the *requirements.yaml* to the *Chart.yaml* +- After running `helm dependency update`, a *Chart.lock* file is generated containing the same structure used in the previous *requirements.lock* +- The different fields present in the *Chart.yaml* file has been ordered alphabetically in a homogeneous way for all the Bitnami Helm Chart. + +**Considerations when upgrading to this version** + +- If you want to upgrade to this version using Helm v2, this scenario is not supported as this version doesn't support Helm v2 anymore +- If you installed the previous version with Helm v2 and wants to upgrade to this version with Helm v3, please refer to the [official Helm documentation](https://helm.sh/docs/topics/v2_v3_migration/#migration-use-cases) about migrating from Helm v2 to v3 + +**Useful links** + +- https://docs.bitnami.com/tutorials/resolve-helm2-helm3-post-migration-issues/ +- https://helm.sh/docs/topics/v2_v3_migration/ +- https://helm.sh/blog/migrate-from-helm-v2-to-helm-v3/ + +#### Breaking changes + +- The term `master` has been replaced with `primary` and `slave` with `readReplicas` throughout the chart. Role names have changed from `master` and `slave` to `primary` and `read`. + +To upgrade to `10.0.0`, it should be done reusing the PVCs used to hold the PostgreSQL data on your previous release. To do so, follow the instructions below (the following example assumes that the release name is `postgresql`): + +> NOTE: Please, create a backup of your database before running any of those actions. + +Obtain the credentials and the names of the PVCs used to hold the PostgreSQL data on your current release: + +```console +$ export POSTGRESQL_PASSWORD=$(kubectl get secret --namespace default postgresql -o jsonpath="{.data.postgresql-password}" | base64 --decode) +$ export POSTGRESQL_PVC=$(kubectl get pvc -l app.kubernetes.io/instance=postgresql,role=master -o jsonpath="{.items[0].metadata.name}") +``` + +Delete the PostgreSQL statefulset. Notice the option `--cascade=false`: + +```console +$ kubectl delete statefulsets.apps postgresql-postgresql --cascade=false +``` + +Now the upgrade works: + +```console +$ helm upgrade postgresql bitnami/postgresql --set postgresqlPassword=$POSTGRESQL_PASSWORD --set persistence.existingClaim=$POSTGRESQL_PVC +``` + +You will have to delete the existing PostgreSQL pod and the new statefulset is going to create a new one + +```console +$ kubectl delete pod postgresql-postgresql-0 +``` + +Finally, you should see the lines below in PostgreSQL container logs: + +```console +$ kubectl logs $(kubectl get pods -l app.kubernetes.io/instance=postgresql,app.kubernetes.io/name=postgresql,role=primary -o jsonpath="{.items[0].metadata.name}") +... +postgresql 08:05:12.59 INFO ==> Deploying PostgreSQL with persisted data... +... +``` + +### To 9.0.0 + +In this version the chart was adapted to follow the Helm label best practices, see [PR 3021](https://github.com/bitnami/charts/pull/3021). That means the backward compatibility is not guarantee when upgrading the chart to this major version. + +As a workaround, you can delete the existing statefulset (using the `--cascade=false` flag pods are not deleted) before upgrade the chart. For example, this can be a valid workflow: + +- Deploy an old version (8.X.X) + +```console +$ helm install postgresql bitnami/postgresql --version 8.10.14 +``` + +- Old version is up and running + +```console +$ helm ls +NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION +postgresql default 1 2020-08-04 13:39:54.783480286 +0000 UTC deployed postgresql-8.10.14 11.8.0 + +$ kubectl get pods +NAME READY STATUS RESTARTS AGE +postgresql-postgresql-0 1/1 Running 0 76s +``` + +- The upgrade to the latest one (9.X.X) is going to fail + +```console +$ helm upgrade postgresql bitnami/postgresql +Error: UPGRADE FAILED: cannot patch "postgresql-postgresql" with kind StatefulSet: StatefulSet.apps "postgresql-postgresql" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'template', and 'updateStrategy' are forbidden +``` + +- Delete the statefulset + +```console +$ kubectl delete statefulsets.apps --cascade=false postgresql-postgresql +statefulset.apps "postgresql-postgresql" deleted +``` + +- Now the upgrade works + +```console +$ helm upgrade postgresql bitnami/postgresql +$ helm ls +NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION +postgresql default 3 2020-08-04 13:42:08.020385884 +0000 UTC deployed postgresql-9.1.2 11.8.0 +``` + +- We can kill the existing pod and the new statefulset is going to create a new one: + +```console +$ kubectl delete pod postgresql-postgresql-0 +pod "postgresql-postgresql-0" deleted + +$ kubectl get pods +NAME READY STATUS RESTARTS AGE +postgresql-postgresql-0 1/1 Running 0 19s +``` + +Please, note that without the `--cascade=false` both objects (statefulset and pod) are going to be removed and both objects will be deployed again with the `helm upgrade` command + +### To 8.0.0 + +Prefixes the port names with their protocols to comply with Istio conventions. + +If you depend on the port names in your setup, make sure to update them to reflect this change. + +### To 7.1.0 + +Adds support for LDAP configuration. + +### To 7.0.0 + +Helm performs a lookup for the object based on its group (apps), version (v1), and kind (Deployment). Also known as its GroupVersionKind, or GVK. Changing the GVK is considered a compatibility breaker from Kubernetes' point of view, so you cannot "upgrade" those objects to the new GVK in-place. Earlier versions of Helm 3 did not perform the lookup correctly which has since been fixed to match the spec. + +In https://github.com/helm/charts/pull/17281 the `apiVersion` of the statefulset resources was updated to `apps/v1` in tune with the api's deprecated, resulting in compatibility breakage. + +This major version bump signifies this change. + +### To 6.5.7 + +In this version, the chart will use PostgreSQL with the Postgis extension included. The version used with Postgresql version 10, 11 and 12 is Postgis 2.5. It has been compiled with the following dependencies: + +- protobuf +- protobuf-c +- json-c +- geos +- proj + +### To 5.0.0 + +In this version, the **chart is using PostgreSQL 11 instead of PostgreSQL 10**. You can find the main difference and notable changes in the following links: [https://www.postgresql.org/about/news/1894/](https://www.postgresql.org/about/news/1894/) and [https://www.postgresql.org/about/featurematrix/](https://www.postgresql.org/about/featurematrix/). + +For major releases of PostgreSQL, the internal data storage format is subject to change, thus complicating upgrades, you can see some errors like the following one in the logs: + +```console +Welcome to the Bitnami postgresql container +Subscribe to project updates by watching https://github.com/bitnami/bitnami-docker-postgresql +Submit issues and feature requests at https://github.com/bitnami/bitnami-docker-postgresql/issues +Send us your feedback at containers@bitnami.com + +INFO ==> ** Starting PostgreSQL setup ** +NFO ==> Validating settings in POSTGRESQL_* env vars.. +INFO ==> Initializing PostgreSQL database... +INFO ==> postgresql.conf file not detected. Generating it... +INFO ==> pg_hba.conf file not detected. Generating it... +INFO ==> Deploying PostgreSQL with persisted data... +INFO ==> Configuring replication parameters +INFO ==> Loading custom scripts... +INFO ==> Enabling remote connections +INFO ==> Stopping PostgreSQL... +INFO ==> ** PostgreSQL setup finished! ** + +INFO ==> ** Starting PostgreSQL ** + [1] FATAL: database files are incompatible with server + [1] DETAIL: The data directory was initialized by PostgreSQL version 10, which is not compatible with this version 11.3. +``` + +In this case, you should migrate the data from the old chart to the new one following an approach similar to that described in [this section](https://www.postgresql.org/docs/current/upgrading.html#UPGRADING-VIA-PGDUMPALL) from the official documentation. Basically, create a database dump in the old chart, move and restore it in the new one. + +### To 4.0.0 + +This chart will use by default the Bitnami PostgreSQL container starting from version `10.7.0-r68`. This version moves the initialization logic from node.js to bash. This new version of the chart requires setting the `POSTGRES_PASSWORD` in the slaves as well, in order to properly configure the `pg_hba.conf` file. Users from previous versions of the chart are advised to upgrade immediately. + +IMPORTANT: If you do not want to upgrade the chart version then make sure you use the `10.7.0-r68` version of the container. Otherwise, you will get this error + +``` +The POSTGRESQL_PASSWORD environment variable is empty or not set. Set the environment variable ALLOW_EMPTY_PASSWORD=yes to allow the container to be started with blank passwords. This is recommended only for development +``` + +### To 3.0.0 + +This releases make it possible to specify different nodeSelector, affinity and tolerations for master and slave pods. +It also fixes an issue with `postgresql.master.fullname` helper template not obeying fullnameOverride. + +#### Breaking changes + +- `affinty` has been renamed to `master.affinity` and `slave.affinity`. +- `tolerations` has been renamed to `master.tolerations` and `slave.tolerations`. +- `nodeSelector` has been renamed to `master.nodeSelector` and `slave.nodeSelector`. + +### To 2.0.0 + +In order to upgrade from the `0.X.X` branch to `1.X.X`, you should follow the below steps: + +- Obtain the service name (`SERVICE_NAME`) and password (`OLD_PASSWORD`) of the existing postgresql chart. You can find the instructions to obtain the password in the NOTES.txt, the service name can be obtained by running + +```console +$ kubectl get svc +``` + +- Install (not upgrade) the new version + +```console +$ helm repo update +$ helm install my-release bitnami/postgresql +``` + +- Connect to the new pod (you can obtain the name by running `kubectl get pods`): + +```console +$ kubectl exec -it NAME bash +``` + +- Once logged in, create a dump file from the previous database using `pg_dump`, for that we should connect to the previous postgresql chart: + +```console +$ pg_dump -h SERVICE_NAME -U postgres DATABASE_NAME > /tmp/backup.sql +``` + +After run above command you should be prompted for a password, this password is the previous chart password (`OLD_PASSWORD`). +This operation could take some time depending on the database size. + +- Once you have the backup file, you can restore it with a command like the one below: + +```console +$ psql -U postgres DATABASE_NAME < /tmp/backup.sql +``` + +In this case, you are accessing to the local postgresql, so the password should be the new one (you can find it in NOTES.txt). + +If you want to restore the database and the database schema does not exist, it is necessary to first follow the steps described below. + +```console +$ psql -U postgres +postgres=# drop database DATABASE_NAME; +postgres=# create database DATABASE_NAME; +postgres=# create user USER_NAME; +postgres=# alter role USER_NAME with password 'BITNAMI_USER_PASSWORD'; +postgres=# grant all privileges on database DATABASE_NAME to USER_NAME; +postgres=# alter database DATABASE_NAME owner to USER_NAME; +``` diff --git a/chart/charts/postgresql/ci/commonAnnotations.yaml b/chart/charts/postgresql/ci/commonAnnotations.yaml new file mode 100644 index 0000000000000000000000000000000000000000..97e18a4cc03e89565947d386b8fd30ed56ff6116 --- /dev/null +++ b/chart/charts/postgresql/ci/commonAnnotations.yaml @@ -0,0 +1,3 @@ +commonAnnotations: + helm.sh/hook: "\"pre-install, pre-upgrade\"" + helm.sh/hook-weight: "-1" diff --git a/chart/charts/postgresql/ci/default-values.yaml b/chart/charts/postgresql/ci/default-values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fc2ba605adaef469587377fc0574f0b4b938aa4d --- /dev/null +++ b/chart/charts/postgresql/ci/default-values.yaml @@ -0,0 +1 @@ +# Leave this file empty to ensure that CI runs builds against the default configuration in values.yaml. diff --git a/chart/charts/postgresql/ci/shmvolume-disabled-values.yaml b/chart/charts/postgresql/ci/shmvolume-disabled-values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..347d3b40a8ea67a0d70bfa6b17821426d426c8fb --- /dev/null +++ b/chart/charts/postgresql/ci/shmvolume-disabled-values.yaml @@ -0,0 +1,2 @@ +shmVolume: + enabled: false diff --git a/chart/charts/postgresql/files/README.md b/chart/charts/postgresql/files/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1813a2feaaf1a77b1b7cb37317c47e9b619d3a21 --- /dev/null +++ b/chart/charts/postgresql/files/README.md @@ -0,0 +1 @@ +Copy here your postgresql.conf and/or pg_hba.conf files to use it as a config map. diff --git a/chart/charts/postgresql/files/conf.d/README.md b/chart/charts/postgresql/files/conf.d/README.md new file mode 100644 index 0000000000000000000000000000000000000000..184c1875d575a262710552c0c7f97abbdb56a981 --- /dev/null +++ b/chart/charts/postgresql/files/conf.d/README.md @@ -0,0 +1,4 @@ +If you don't want to provide the whole configuration file and only specify certain parameters, you can copy here your extended `.conf` files. +These files will be injected as a config maps and add/overwrite the default configuration using the `include_dir` directive that allows settings to be loaded from files other than the default `postgresql.conf`. + +More info in the [bitnami-docker-postgresql README](https://github.com/bitnami/bitnami-docker-postgresql#configuration-file). diff --git a/chart/charts/postgresql/files/docker-entrypoint-initdb.d/README.md b/chart/charts/postgresql/files/docker-entrypoint-initdb.d/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cba38091e0f45aac32fdd3bda933f547f95a9ea7 --- /dev/null +++ b/chart/charts/postgresql/files/docker-entrypoint-initdb.d/README.md @@ -0,0 +1,3 @@ +You can copy here your custom `.sh`, `.sql` or `.sql.gz` file so they are executed during the first boot of the image. + +More info in the [bitnami-docker-postgresql](https://github.com/bitnami/bitnami-docker-postgresql#initializing-a-new-instance) repository. \ No newline at end of file diff --git a/chart/charts/postgresql/templates/NOTES.txt b/chart/charts/postgresql/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..4e98958c138e8525b45ed76d8d73bbcb064dd769 --- /dev/null +++ b/chart/charts/postgresql/templates/NOTES.txt @@ -0,0 +1,59 @@ +** Please be patient while the chart is being deployed ** + +PostgreSQL can be accessed via port {{ template "postgresql.port" . }} on the following DNS name from within your cluster: + + {{ template "common.names.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - Read/Write connection +{{- if .Values.replication.enabled }} + {{ template "common.names.fullname" . }}-read.{{ .Release.Namespace }}.svc.cluster.local - Read only connection +{{- end }} + +{{- if not (eq (include "postgresql.username" .) "postgres") }} + +To get the password for "postgres" run: + + export POSTGRES_ADMIN_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "postgresql.secretName" . }} -o jsonpath="{.data.postgresql-postgres-password}" | base64 --decode) +{{- end }} + +To get the password for "{{ template "postgresql.username" . }}" run: + + export POSTGRES_PASSWORD=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "postgresql.secretName" . }} -o jsonpath="{.data.postgresql-password}" | base64 --decode) + +To connect to your database run the following command: + + kubectl run {{ template "common.names.fullname" . }}-client --rm --tty -i --restart='Never' --namespace {{ .Release.Namespace }} --image {{ template "postgresql.image" . }} --env="PGPASSWORD=$POSTGRES_PASSWORD" {{- if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} + --labels="{{ template "common.names.fullname" . }}-client=true" {{- end }} --command -- psql --host {{ template "common.names.fullname" . }} -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} -p {{ template "postgresql.port" . }} + +{{ if and (.Values.networkPolicy.enabled) (not .Values.networkPolicy.allowExternal) }} +Note: Since NetworkPolicy is enabled, only pods with label {{ template "common.names.fullname" . }}-client=true" will be able to connect to this PostgreSQL cluster. +{{- end }} + +To connect to your database from outside the cluster execute the following commands: + +{{- if contains "NodePort" .Values.service.type }} + + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "common.names.fullname" . }}) + {{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host $NODE_IP --port $NODE_PORT -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} + +{{- else if contains "LoadBalancer" .Values.service.type }} + + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "common.names.fullname" . }}' + + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "common.names.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + {{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host $SERVICE_IP --port {{ template "postgresql.port" . }} -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} + +{{- else if contains "ClusterIP" .Values.service.type }} + + kubectl port-forward --namespace {{ .Release.Namespace }} svc/{{ template "common.names.fullname" . }} {{ template "postgresql.port" . }}:{{ template "postgresql.port" . }} & + {{ if (include "postgresql.password" . ) }}PGPASSWORD="$POSTGRES_PASSWORD" {{ end }}psql --host 127.0.0.1 -U {{ .Values.postgresqlUsername }} -d {{- if .Values.postgresqlDatabase }} {{ .Values.postgresqlDatabase }}{{- else }} postgres{{- end }} -p {{ template "postgresql.port" . }} + +{{- end }} + +{{- include "postgresql.validateValues" . -}} + +{{- include "common.warnings.rollingTag" .Values.image -}} + +{{- $passwordValidationErrors := include "common.validations.values.postgresql.passwords" (dict "secret" (include "common.names.fullname" .) "context" $) -}} + +{{- include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $passwordValidationErrors) "context" $) -}} diff --git a/chart/charts/postgresql/templates/_helpers.tpl b/chart/charts/postgresql/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..25d2072d4ea235d7d407e0b967affe4e59291392 --- /dev/null +++ b/chart/charts/postgresql/templates/_helpers.tpl @@ -0,0 +1,919 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "common.names.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "common.names.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Kubernetes standard labels +*/}} +{{- define "common.labels.standard" -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +helm.sh/chart: {{ include "common.names.chart" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} + +{{/* +Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector +*/}} +{{- define "common.labels.matchLabels" -}} +app.kubernetes.io/name: {{ include "common.names.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{/* +Renders a value that contains template. +Usage: +{{ include "common.tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $) }} +*/}} +{{- define "common.tplvalues.render" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{- else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- 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 "common.names.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 -}} + +{{/* +Return the proper image name +{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" $) }} +*/}} +{{- define "common.images.image" -}} +{{- $registryName := .imageRoot.registry -}} +{{- $repositoryName := .imageRoot.repository -}} +{{- $tag := .imageRoot.tag | toString -}} +{{- if .global }} + {{- if .global.imageRegistry }} + {{- $registryName = .global.imageRegistry -}} + {{- end -}} +{{- end -}} +{{- if $registryName }} +{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} +{{- else -}} +{{- printf "%s:%s" $repositoryName $tag -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} +*/}} +{{- define "common.images.pullSecrets" -}} + {{- $pullSecrets := list }} + + {{- if .global }} + {{- range .global.imagePullSecrets -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + + {{- range .images -}} + {{- range .pullSecrets -}} + {{- $pullSecrets = append $pullSecrets . -}} + {{- end -}} + {{- end -}} + + {{- if (not (empty $pullSecrets)) }} +imagePullSecrets: + {{- range $pullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} +{{- end -}} + +{{/* +Return a soft nodeAffinity definition +{{ include "common.affinities.nodes.soft" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.soft" -}} +preferredDuringSchedulingIgnoredDuringExecution: + - preference: + matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . }} + {{- end }} + weight: 1 +{{- end -}} + +{{/* +Return a hard nodeAffinity definition +{{ include "common.affinities.nodes.hard" (dict "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes.hard" -}} +requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: {{ .key }} + operator: In + values: + {{- range .values }} + - {{ . }} + {{- end }} +{{- end -}} + +{{/* +Return a nodeAffinity definition +{{ include "common.affinities.nodes" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.nodes" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.nodes.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.nodes.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Return a soft podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.soft" (dict "component" "FOO" "context" $) -}} +*/}} +{{- define "common.affinities.pods.soft" -}} +{{- $component := default "" .component -}} +preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" .context) | nindent 10 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + namespaces: + - {{ .context.Release.Namespace | quote }} + topologyKey: kubernetes.io/hostname + weight: 1 +{{- end -}} + +{{/* +Return a hard podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods.hard" (dict "component" "FOO" "context" $) -}} +*/}} +{{- define "common.affinities.pods.hard" -}} +{{- $component := default "" .component -}} +requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchLabels: {{- (include "common.labels.matchLabels" .context) | nindent 8 }} + {{- if not (empty $component) }} + {{ printf "app.kubernetes.io/component: %s" $component }} + {{- end }} + namespaces: + - {{ .context.Release.Namespace | quote }} + topologyKey: kubernetes.io/hostname +{{- end -}} + +{{/* +Return the proper Storage Class +{{ include "common.storage.class" ( dict "persistence" .Values.path.to.the.persistence "global" $) }} +*/}} +{{- define "common.storage.class" -}} + +{{- $storageClass := .persistence.storageClass -}} +{{- if .global -}} + {{- if .global.storageClass -}} + {{- $storageClass = .global.storageClass -}} + {{- end -}} +{{- end -}} + +{{- if $storageClass -}} + {{- if (eq "-" $storageClass) -}} + {{- printf "storageClassName: \"\"" -}} + {{- else }} + {{- printf "storageClassName: %s" $storageClass -}} + {{- end -}} +{{- end -}} + +{{- end -}} + +{{/* +Warning about using rolling tag. +Usage: +{{ include "common.warnings.rollingTag" .Values.path.to.the.imageRoot }} +*/}} +{{- define "common.warnings.rollingTag" -}} + +{{- if and (contains "bitnami/" .repository) (not (.tag | toString | regexFind "-r\\d+$|sha256:")) }} +WARNING: Rolling tag detected ({{ .repository }}:{{ .tag }}), please note that it is strongly recommended to avoid using rolling tags in a production environment. ++info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/ +{{- end }} + +{{- end -}} + +{{/* +Return a podAffinity/podAntiAffinity definition +{{ include "common.affinities.pods" (dict "type" "soft" "key" "FOO" "values" (list "BAR" "BAZ")) -}} +*/}} +{{- define "common.affinities.pods" -}} + {{- if eq .type "soft" }} + {{- include "common.affinities.pods.soft" . -}} + {{- else if eq .type "hard" }} + {{- include "common.affinities.pods.hard" . -}} + {{- end -}} +{{- end -}} + +{{/* +Validate PostgreSQL required passwords are not empty. +Usage: +{{ include "common.validations.values.postgresql.passwords" (dict "secret" "secretName" "subchart" false "context" $) }} +Params: + - secret - String - Required. Name of the secret where postgresql values are stored, e.g: "postgresql-passwords-secret" + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.validations.values.postgresql.passwords" -}} + {{- $existingSecret := include "common.postgresql.values.existingSecret" . -}} + {{- $enabled := include "common.postgresql.values.enabled" . -}} + {{- $valueKeyPostgresqlPassword := include "common.postgresql.values.key.postgressPassword" . -}} + {{- $valueKeyPostgresqlReplicationEnabled := include "common.postgresql.values.key.replicationPassword" . -}} + + {{- if and (not $existingSecret) (eq $enabled "true") -}} + {{- $requiredPasswords := list -}} + + {{- $requiredPostgresqlPassword := dict "valueKey" $valueKeyPostgresqlPassword "secret" .secret "field" "postgresql-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlPassword -}} + + {{- $enabledReplication := include "common.postgresql.values.enabled.replication" . -}} + {{- if (eq $enabledReplication "true") -}} + {{- $requiredPostgresqlReplicationPassword := dict "valueKey" $valueKeyPostgresqlReplicationEnabled "secret" .secret "field" "postgresql-replication-password" -}} + {{- $requiredPasswords = append $requiredPasswords $requiredPostgresqlReplicationPassword -}} + {{- end -}} + + {{- include "common.validations.values.multiple.empty" (dict "required" $requiredPasswords "context" .context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate values must not be empty. +Usage: +{{- $validateValueConf00 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-00") -}} +{{- $validateValueConf01 := (dict "valueKey" "path.to.value" "secret" "secretName" "field" "password-01") -}} +{{ include "common.validations.values.empty" (dict "required" (list $validateValueConf00 $validateValueConf01) "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" +*/}} +{{- define "common.validations.values.multiple.empty" -}} + {{- range .required -}} + {{- include "common.validations.values.single.empty" (dict "valueKey" .valueKey "secret" .secret "field" .field "context" $.context) -}} + {{- end -}} +{{- end -}} + +{{/* +Validate a value must not be empty. +Usage: +{{ include "common.validations.value.empty" (dict "valueKey" "mariadb.password" "secret" "secretName" "field" "my-password" "subchart" "subchart" "context" $) }} + +Validate value params: + - valueKey - String - Required. The path to the validating value in the values.yaml, e.g: "mysql.password" + - secret - String - Optional. Name of the secret where the validating value is generated/stored, e.g: "mysql-passwords-secret" + - field - String - Optional. Name of the field in the secret data, e.g: "mysql-password" + - subchart - String - Optional - Name of the subchart that the validated password is part of. +*/}} +{{- define "common.validations.values.single.empty" -}} + {{- $value := include "common.utils.getValueFromKey" (dict "key" .valueKey "context" .context) }} + {{- $subchart := ternary "" (printf "%s." .subchart) (empty .subchart) }} + + {{- if not $value -}} + {{- $varname := "my-value" -}} + {{- $getCurrentValue := "" -}} + {{- if and .secret .field -}} + {{- $varname = include "common.utils.fieldToEnvVar" . -}} + {{- $getCurrentValue = printf " To get the current value:\n\n %s\n" (include "common.utils.secret.getvalue" .) -}} + {{- end -}} + {{- printf "\n '%s' must not be empty, please add '--set %s%s=$%s' to the command.%s" .valueKey $subchart .valueKey $varname $getCurrentValue -}} + {{- end -}} +{{- end -}} + +{{/* +Print instructions to get a secret value. +Usage: +{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} +*/}} +{{- define "common.utils.secret.getvalue" -}} +{{- $varname := include "common.utils.fieldToEnvVar" . -}} +export {{ $varname }}=$(kubectl get secret --namespace {{ .context.Release.Namespace | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 --decode) +{{- end -}} + +{{/* +Build env var name given a field +Usage: +{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} +*/}} +{{- define "common.utils.fieldToEnvVar" -}} + {{- $fieldNameSplit := splitList "-" .field -}} + {{- $upperCaseFieldNameSplit := list -}} + + {{- range $fieldNameSplit -}} + {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} + {{- end -}} + + {{ join "_" $upperCaseFieldNameSplit }} +{{- end -}} + +{{/* +Gets a value from .Values given +Usage: +{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} +*/}} +{{- define "common.utils.getValueFromKey" -}} +{{- $splitKey := splitList "." .key -}} +{{- $value := "" -}} +{{- $latestObj := $.context.Values -}} +{{- range $splitKey -}} + {{- if not $latestObj -}} + {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} + {{- end -}} + {{- $value = ( index $latestObj . ) -}} + {{- $latestObj = $value -}} +{{- end -}} +{{- printf "%v" (default "" $value) -}} +{{- end -}} + +{{/* +Returns first .Values key with a defined value or first of the list if all non-defined +Usage: +{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} +*/}} +{{- define "common.utils.getKeyFromList" -}} +{{- $key := first .keys -}} +{{- $reverseKeys := reverse .keys }} +{{- range $reverseKeys }} + {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} + {{- if $value -}} + {{- $key = . }} + {{- end -}} +{{- end -}} +{{- printf "%s" $key -}} +{{- end -}} + +{{/* +Auxiliary function to decide whether evaluate global values. +Usage: +{{ include "common.postgresql.values.use.global" (dict "key" "key-of-global" "context" $) }} +Params: + - key - String - Required. Field to be evaluated within global, e.g: "existingSecret" +*/}} +{{- define "common.postgresql.values.use.global" -}} + {{- if .context.Values.global -}} + {{- if .context.Values.global.postgresql -}} + {{- index .context.Values.global.postgresql .key | quote -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for existingSecret. +Usage: +{{ include "common.postgresql.values.existingSecret" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.existingSecret" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "existingSecret" "context" .context) -}} + + {{- if .subchart -}} + {{- default (.context.Values.postgresql.existingSecret | quote) $globalValue -}} + {{- else -}} + {{- default (.context.Values.existingSecret | quote) $globalValue -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled postgresql. +Usage: +{{ include "common.postgresql.values.enabled" (dict "context" $) }} +*/}} +{{- define "common.postgresql.values.enabled" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.enabled -}} + {{- else -}} + {{- printf "%v" (not .context.Values.enabled) -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key postgressPassword. +Usage: +{{ include "common.postgresql.values.key.postgressPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.postgressPassword" -}} + {{- $globalValue := include "common.postgresql.values.use.global" (dict "key" "postgresqlUsername" "context" .context) -}} + + {{- if not $globalValue -}} + {{- if .subchart -}} + postgresql.postgresqlPassword + {{- else -}} + postgresqlPassword + {{- end -}} + {{- else -}} + global.postgresql.postgresqlPassword + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for enabled.replication. +Usage: +{{ include "common.postgresql.values.enabled.replication" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.enabled.replication" -}} + {{- if .subchart -}} + {{- printf "%v" .context.Values.postgresql.replication.enabled -}} + {{- else -}} + {{- printf "%v" .context.Values.replication.enabled -}} + {{- end -}} +{{- end -}} + +{{/* +Auxiliary function to get the right value for the key replication.password. +Usage: +{{ include "common.postgresql.values.key.replicationPassword" (dict "subchart" "true" "context" $) }} +Params: + - subchart - Boolean - Optional. Whether postgresql is used as subchart or not. Default: false +*/}} +{{- define "common.postgresql.values.key.replicationPassword" -}} + {{- if .subchart -}} + postgresql.replication.password + {{- else -}} + replication.password + {{- end -}} +{{- end -}} + +{{/* +Through error when upgrading using empty passwords values that must not be empty. +Usage: +{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} +{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} +{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} + +Required password params: + - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. + - context - Context - Required. Parent context. +*/}} +{{- define "common.errors.upgrade.passwords.empty" -}} + {{- $validationErrors := join "" .validationErrors -}} + {{- if and $validationErrors .context.Release.IsUpgrade -}} + {{- $errorString := "\nPASSWORDS ERROR: you must provide your current passwords when upgrade the release%s" -}} + {{- printf $errorString $validationErrors | fail -}} + {{- end -}} +{{- end -}} + +{{/* +Return the target Kubernetes version +*/}} +{{- define "common.capabilities.kubeVersion" -}} +{{- if .Values.global }} + {{- if .Values.global.kubeVersion }} + {{- .Values.global.kubeVersion -}} + {{- else }} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} + {{- end -}} +{{- else }} +{{- default .Capabilities.KubeVersion.Version .Values.kubeVersion -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for deployment. +*/}} +{{- define "common.capabilities.deployment.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for statefulset. +*/}} +{{- define "common.capabilities.statefulset.apiVersion" -}} +{{- if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apps/v1beta1" -}} +{{- else -}} +{{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for ingress. +*/}} +{{- define "common.capabilities.ingress.apiVersion" -}} +{{- if .Values.ingress -}} +{{- if .Values.ingress.apiVersion -}} +{{- .Values.ingress.apiVersion -}} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end }} +{{- else if semverCompare "<1.14-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "extensions/v1beta1" -}} +{{- else if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "networking.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for RBAC resources. +*/}} +{{- define "common.capabilities.rbac.apiVersion" -}} +{{- if semverCompare "<1.17-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "rbac.authorization.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "rbac.authorization.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for CRDs. +*/}} +{{- define "common.capabilities.crd.apiVersion" -}} +{{- if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} +{{- print "apiextensions.k8s.io/v1beta1" -}} +{{- else -}} +{{- print "apiextensions.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Returns true if the used Helm version is 3.3+. +A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. +This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. +**To be removed when the catalog's minimun Helm version is 3.3** +*/}} +{{- define "common.capabilities.supportsHelmVersion" -}} +{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "postgresql.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). +*/}} +{{- define "postgresql.primary.fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- $fullname := default (printf "%s-%s" .Release.Name $name) .Values.fullnameOverride -}} +{{- if .Values.replication.enabled -}} +{{- printf "%s-%s" $fullname "primary" | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s" $fullname | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper PostgreSQL image name +*/}} +{{- define "postgresql.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper PostgreSQL metrics image name +*/}} +{{- define "postgresql.metrics.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.metrics.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper image name (for the init container volume-permissions image) +*/}} +{{- define "postgresql.volumePermissions.image" -}} +{{ include "common.images.image" (dict "imageRoot" .Values.volumePermissions.image "global" .Values.global) }} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "postgresql.imagePullSecrets" -}} +{{ include "common.images.pullSecrets" (dict "images" (list .Values.image .Values.metrics.image .Values.volumePermissions.image) "global" .Values.global) }} +{{- end -}} + +{{/* +Return PostgreSQL postgres user password +*/}} +{{- define "postgresql.postgres.password" -}} +{{- if .Values.global.postgresql.postgresqlPostgresPassword }} + {{- .Values.global.postgresql.postgresqlPostgresPassword -}} +{{- else if .Values.postgresqlPostgresPassword -}} + {{- .Values.postgresqlPostgresPassword -}} +{{- else -}} + {{- randAlphaNum 10 -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL password +*/}} +{{- define "postgresql.password" -}} +{{- if .Values.global.postgresql.postgresqlPassword }} + {{- .Values.global.postgresql.postgresqlPassword -}} +{{- else if .Values.postgresqlPassword -}} + {{- .Values.postgresqlPassword -}} +{{- else -}} + {{- randAlphaNum 10 -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL replication password +*/}} +{{- define "postgresql.replication.password" -}} +{{- if .Values.global.postgresql.replicationPassword }} + {{- .Values.global.postgresql.replicationPassword -}} +{{- else if .Values.replication.password -}} + {{- .Values.replication.password -}} +{{- else -}} + {{- randAlphaNum 10 -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL username +*/}} +{{- define "postgresql.username" -}} +{{- if .Values.global.postgresql.postgresqlUsername }} + {{- .Values.global.postgresql.postgresqlUsername -}} +{{- else -}} + {{- .Values.postgresqlUsername -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL replication username +*/}} +{{- define "postgresql.replication.username" -}} +{{- if .Values.global.postgresql.replicationUser }} + {{- .Values.global.postgresql.replicationUser -}} +{{- else -}} + {{- .Values.replication.user -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL port +*/}} +{{- define "postgresql.port" -}} +{{- if .Values.global.postgresql.servicePort }} + {{- .Values.global.postgresql.servicePort -}} +{{- else -}} + {{- .Values.service.port -}} +{{- end -}} +{{- end -}} + +{{/* +Return PostgreSQL created database +*/}} +{{- define "postgresql.database" -}} +{{- if .Values.global.postgresql.postgresqlDatabase }} + {{- .Values.global.postgresql.postgresqlDatabase -}} +{{- else if .Values.postgresqlDatabase -}} + {{- .Values.postgresqlDatabase -}} +{{- end -}} +{{- end -}} + +{{/* +Get the password secret. +*/}} +{{- define "postgresql.secretName" -}} +{{- if .Values.global.postgresql.existingSecret }} + {{- printf "%s" (tpl .Values.global.postgresql.existingSecret $) -}} +{{- else if .Values.existingSecret -}} + {{- printf "%s" (tpl .Values.existingSecret $) -}} +{{- else -}} + {{- printf "%s" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if we should use an existingSecret. +*/}} +{{- define "postgresql.useExistingSecret" -}} +{{- if or .Values.global.postgresql.existingSecret .Values.existingSecret -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a secret object should be created +*/}} +{{- define "postgresql.createSecret" -}} +{{- if not (include "postgresql.useExistingSecret" .) -}} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Get the configuration ConfigMap name. +*/}} +{{- define "postgresql.configurationCM" -}} +{{- if .Values.configurationConfigMap -}} +{{- printf "%s" (tpl .Values.configurationConfigMap $) -}} +{{- else -}} +{{- printf "%s-configuration" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the extended configuration ConfigMap name. +*/}} +{{- define "postgresql.extendedConfigurationCM" -}} +{{- if .Values.extendedConfConfigMap -}} +{{- printf "%s" (tpl .Values.extendedConfConfigMap $) -}} +{{- else -}} +{{- printf "%s-extended-configuration" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return true if a configmap should be mounted with PostgreSQL configuration +*/}} +{{- define "postgresql.mountConfigurationCM" -}} +{{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap }} + {{- true -}} +{{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts ConfigMap name. +*/}} +{{- define "postgresql.initdbScriptsCM" -}} +{{- if .Values.initdbScriptsConfigMap -}} +{{- printf "%s" (tpl .Values.initdbScriptsConfigMap $) -}} +{{- else -}} +{{- printf "%s-init-scripts" (include "common.names.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Get the initialization scripts Secret name. +*/}} +{{- define "postgresql.initdbScriptsSecret" -}} +{{- printf "%s" (tpl .Values.initdbScriptsSecret $) -}} +{{- end -}} + +{{/* +Get the metrics ConfigMap name. +*/}} +{{- define "postgresql.metricsCM" -}} +{{- printf "%s-metrics" (include "common.names.fullname" .) -}} +{{- end -}} + +{{/* +Get the readiness probe command +*/}} +{{- define "postgresql.readinessProbeCommand" -}} +- | +{{- if (include "postgresql.database" .) }} + exec pg_isready -U {{ include "postgresql.username" . | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ template "postgresql.port" . }} +{{- else }} + exec pg_isready -U {{ include "postgresql.username" . | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} +{{- end }} +{{- if contains "bitnami/" .Values.image.repository }} + [ -f /opt/bitnami/postgresql/tmp/.initialized ] || [ -f /bitnami/postgresql/.initialized ] +{{- end -}} +{{- end -}} + +{{/* +Compile all warnings into a single message, and call fail. +*/}} +{{- define "postgresql.validateValues" -}} +{{- $messages := list -}} +{{- $messages := append $messages (include "postgresql.validateValues.ldapConfigurationMethod" .) -}} +{{- $messages := append $messages (include "postgresql.validateValues.psp" .) -}} +{{- $messages := append $messages (include "postgresql.validateValues.tls" .) -}} +{{- $messages := without $messages "" -}} +{{- $message := join "\n" $messages -}} + +{{- if $message -}} +{{- printf "\nVALUES VALIDATION:\n%s" $message | fail -}} +{{- end -}} +{{- end -}} + +{{/* +Validate values of Postgresql - If ldap.url is used then you don't need the other settings for ldap +*/}} +{{- define "postgresql.validateValues.ldapConfigurationMethod" -}} +{{- if and .Values.ldap.enabled (and (not (empty .Values.ldap.url)) (not (empty .Values.ldap.server))) }} +postgresql: ldap.url, ldap.server + You cannot set both `ldap.url` and `ldap.server` at the same time. + Please provide a unique way to configure LDAP. + More info at https://www.postgresql.org/docs/current/auth-ldap.html +{{- end -}} +{{- end -}} + +{{/* +Validate values of Postgresql - If PSP is enabled RBAC should be enabled too +*/}} +{{- define "postgresql.validateValues.psp" -}} +{{- if and .Values.psp.create (not .Values.rbac.create) }} +postgresql: psp.create, rbac.create + RBAC should be enabled if PSP is enabled in order for PSP to work. + More info at https://kubernetes.io/docs/concepts/policy/pod-security-policy/#authorizing-policies +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for podsecuritypolicy. +*/}} +{{- define "podsecuritypolicy.apiVersion" -}} +{{- if semverCompare "<1.10-0" .Capabilities.KubeVersion.GitVersion -}} +{{- print "extensions/v1beta1" -}} +{{- else -}} +{{- print "policy/v1beta1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for networkpolicy. +*/}} +{{- define "postgresql.networkPolicy.apiVersion" -}} +{{- if semverCompare ">=1.4-0, <1.7-0" .Capabilities.KubeVersion.GitVersion -}} +"extensions/v1beta1" +{{- else if semverCompare "^1.7-0" .Capabilities.KubeVersion.GitVersion -}} +"networking.k8s.io/v1" +{{- end -}} +{{- end -}} + +{{/* +Validate values of Postgresql TLS - When TLS is enabled, so must be VolumePermissions +*/}} +{{- define "postgresql.validateValues.tls" -}} +{{- if and .Values.tls.enabled (not .Values.volumePermissions.enabled) }} +postgresql: tls.enabled, volumePermissions.enabled + When TLS is enabled you must enable volumePermissions as well to ensure certificates files have + the right permissions. +{{- end -}} +{{- end -}} + +{{/* +Return the path to the cert file. +*/}} +{{- define "postgresql.tlsCert" -}} +{{- required "Certificate filename is required when TLS in enabled" .Values.tls.certFilename | printf "/opt/bitnami/postgresql/certs/%s" -}} +{{- end -}} + +{{/* +Return the path to the cert key file. +*/}} +{{- define "postgresql.tlsCertKey" -}} +{{- required "Certificate Key filename is required when TLS in enabled" .Values.tls.certKeyFilename | printf "/opt/bitnami/postgresql/certs/%s" -}} +{{- end -}} + +{{/* +Return the path to the CA cert file. +*/}} +{{- define "postgresql.tlsCACert" -}} +{{- printf "/opt/bitnami/postgresql/certs/%s" .Values.tls.certCAFilename -}} +{{- end -}} + +{{/* +Return the path to the CRL file. +*/}} +{{- define "postgresql.tlsCRL" -}} +{{- if .Values.tls.crlFilename -}} +{{- printf "/opt/bitnami/postgresql/certs/%s" .Values.tls.crlFilename -}} +{{- end -}} +{{- end -}} diff --git a/chart/charts/postgresql/templates/configmap.yaml b/chart/charts/postgresql/templates/configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..627d88027221deeb8b86834a43add18bf72b44e9 --- /dev/null +++ b/chart/charts/postgresql/templates/configmap.yaml @@ -0,0 +1,27 @@ +{{ if and (or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration) (not .Values.configurationConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "common.names.fullname" . }}-configuration + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +data: +{{- if (.Files.Glob "files/postgresql.conf") }} +{{ (.Files.Glob "files/postgresql.conf").AsConfig | indent 2 }} +{{- else if .Values.postgresqlConfiguration }} + postgresql.conf: | +{{- range $key, $value := default dict .Values.postgresqlConfiguration }} + {{ $key | snakecase }}={{ $value }} +{{- end }} +{{- end }} +{{- if (.Files.Glob "files/pg_hba.conf") }} +{{ (.Files.Glob "files/pg_hba.conf").AsConfig | indent 2 }} +{{- else if .Values.pgHbaConfiguration }} + pg_hba.conf: | +{{ .Values.pgHbaConfiguration | indent 4 }} +{{- end }} +{{ end }} diff --git a/chart/charts/postgresql/templates/extended-config-configmap.yaml b/chart/charts/postgresql/templates/extended-config-configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bd477e44c106e22a361d6a9142c980c1e45301a7 --- /dev/null +++ b/chart/charts/postgresql/templates/extended-config-configmap.yaml @@ -0,0 +1,22 @@ +{{- if and (or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf) (not .Values.extendedConfConfigMap)}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "common.names.fullname" . }}-extended-configuration + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +data: +{{- with .Files.Glob "files/conf.d/*.conf" }} +{{ .AsConfig | indent 2 }} +{{- end }} +{{ with .Values.postgresqlExtendedConf }} + override.conf: | +{{- range $key, $value := . }} + {{ $key | snakecase }}={{ $value }} +{{- end }} +{{- end }} +{{- end }} diff --git a/chart/charts/postgresql/templates/extra-list.yaml b/chart/charts/postgresql/templates/extra-list.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9ac65f9e16f4bfda4a21649ad5f33e4e9a683143 --- /dev/null +++ b/chart/charts/postgresql/templates/extra-list.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraDeploy }} +--- +{{ include "common.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/chart/charts/postgresql/templates/initialization-configmap.yaml b/chart/charts/postgresql/templates/initialization-configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7796c67a93decf78bb011cbdb94a9215f88a75ea --- /dev/null +++ b/chart/charts/postgresql/templates/initialization-configmap.yaml @@ -0,0 +1,25 @@ +{{- if and (or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScripts) (not .Values.initdbScriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "common.names.fullname" . }}-init-scripts + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +{{- with .Files.Glob "files/docker-entrypoint-initdb.d/*.sql.gz" }} +binaryData: +{{- range $path, $bytes := . }} + {{ base $path }}: {{ $.Files.Get $path | b64enc | quote }} +{{- end }} +{{- end }} +data: +{{- with .Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql}" }} +{{ .AsConfig | indent 2 }} +{{- end }} +{{- with .Values.initdbScripts }} +{{ toYaml . | indent 2 }} +{{- end }} +{{- end }} diff --git a/chart/charts/postgresql/templates/metrics-configmap.yaml b/chart/charts/postgresql/templates/metrics-configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fa539582bb54715078ff5689bda8eb74cdff82f6 --- /dev/null +++ b/chart/charts/postgresql/templates/metrics-configmap.yaml @@ -0,0 +1,14 @@ +{{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "postgresql.metricsCM" . }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +data: + custom-metrics.yaml: {{ toYaml .Values.metrics.customMetrics | quote }} +{{- end }} diff --git a/chart/charts/postgresql/templates/metrics-svc.yaml b/chart/charts/postgresql/templates/metrics-svc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..af8b67e2ff8c93eaea3d345f8971dd136890be69 --- /dev/null +++ b/chart/charts/postgresql/templates/metrics-svc.yaml @@ -0,0 +1,26 @@ +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }}-metrics + labels: + {{- include "common.labels.standard" . | nindent 4 }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- toYaml .Values.metrics.service.annotations | nindent 4 }} + namespace: {{ .Release.Namespace }} +spec: + type: {{ .Values.metrics.service.type }} + {{- if and (eq .Values.metrics.service.type "LoadBalancer") .Values.metrics.service.loadBalancerIP }} + loadBalancerIP: {{ .Values.metrics.service.loadBalancerIP }} + {{- end }} + ports: + - name: http-metrics + port: 9187 + targetPort: http-metrics + selector: + {{- include "common.labels.matchLabels" . | nindent 4 }} + role: primary +{{- end }} diff --git a/chart/charts/postgresql/templates/networkpolicy.yaml b/chart/charts/postgresql/templates/networkpolicy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4f2740ea0ccb6af1125c38db609f7afd21172b23 --- /dev/null +++ b/chart/charts/postgresql/templates/networkpolicy.yaml @@ -0,0 +1,39 @@ +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ template "postgresql.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +spec: + podSelector: + matchLabels: + {{- include "common.labels.matchLabels" . | nindent 6 }} + ingress: + # Allow inbound connections + - ports: + - port: {{ template "postgresql.port" . }} + {{- if not .Values.networkPolicy.allowExternal }} + from: + - podSelector: + matchLabels: + {{ template "common.names.fullname" . }}-client: "true" + {{- if .Values.networkPolicy.explicitNamespacesSelector }} + namespaceSelector: +{{ toYaml .Values.networkPolicy.explicitNamespacesSelector | indent 12 }} + {{- end }} + - podSelector: + matchLabels: + {{- include "common.labels.matchLabels" . | nindent 14 }} + role: read + {{- end }} + {{- if .Values.metrics.enabled }} + # Allow prometheus scrapes + - ports: + - port: 9187 + {{- end }} +{{- end }} diff --git a/chart/charts/postgresql/templates/podsecuritypolicy.yaml b/chart/charts/postgresql/templates/podsecuritypolicy.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0c49694fad591862f8fa7e3c6e4f5f06b87040c1 --- /dev/null +++ b/chart/charts/postgresql/templates/podsecuritypolicy.yaml @@ -0,0 +1,38 @@ +{{- if .Values.psp.create }} +apiVersion: {{ include "podsecuritypolicy.apiVersion" . }} +kind: PodSecurityPolicy +metadata: + name: {{ template "common.names.fullname" . }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +spec: + privileged: false + volumes: + - 'configMap' + - 'secret' + - 'persistentVolumeClaim' + - 'emptyDir' + - 'projected' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + fsGroup: + rule: 'MustRunAs' + ranges: + - min: 1 + max: 65535 + readOnlyRootFilesystem: false +{{- end }} diff --git a/chart/charts/postgresql/templates/prometheusrule.yaml b/chart/charts/postgresql/templates/prometheusrule.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d0f408c78f330f7b044ffe3c66fc910904e816bc --- /dev/null +++ b/chart/charts/postgresql/templates/prometheusrule.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.metrics.enabled .Values.metrics.prometheusRule.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: PrometheusRule +metadata: + name: {{ template "common.names.fullname" . }} +{{- with .Values.metrics.prometheusRule.namespace }} + namespace: {{ . }} +{{- end }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- with .Values.metrics.prometheusRule.additionalLabels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: +{{- with .Values.metrics.prometheusRule.rules }} + groups: + - name: {{ template "postgresql.name" $ }} + rules: {{ tpl (toYaml .) $ | nindent 8 }} +{{- end }} +{{- end }} diff --git a/chart/charts/postgresql/templates/role.yaml b/chart/charts/postgresql/templates/role.yaml new file mode 100644 index 0000000000000000000000000000000000000000..017a5716b11675ba67d824014290f340f6dbc9f5 --- /dev/null +++ b/chart/charts/postgresql/templates/role.yaml @@ -0,0 +1,20 @@ +{{- if .Values.rbac.create }} +kind: Role +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +rules: + {{- if .Values.psp.create }} + - apiGroups: ["extensions"] + resources: ["podsecuritypolicies"] + verbs: ["use"] + resourceNames: + - {{ template "common.names.fullname" . }} + {{- end }} +{{- end }} diff --git a/chart/charts/postgresql/templates/rolebinding.yaml b/chart/charts/postgresql/templates/rolebinding.yaml new file mode 100644 index 0000000000000000000000000000000000000000..189775a15a3f7568f9bca989daeb921046d3c44d --- /dev/null +++ b/chart/charts/postgresql/templates/rolebinding.yaml @@ -0,0 +1,20 @@ +{{- if .Values.rbac.create }} +kind: RoleBinding +apiVersion: {{ include "common.capabilities.rbac.apiVersion" . }} +metadata: + name: {{ template "common.names.fullname" . }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: {{ template "common.names.fullname" . }} + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: {{ default (include "common.names.fullname" . ) .Values.serviceAccount.name }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/chart/charts/postgresql/templates/secrets.yaml b/chart/charts/postgresql/templates/secrets.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dc301daba81dfa1084401cbaa58e49f492358992 --- /dev/null +++ b/chart/charts/postgresql/templates/secrets.yaml @@ -0,0 +1,22 @@ +{{- if (include "postgresql.createSecret" .) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "common.names.fullname" . }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +type: Opaque +data: + postgresql-postgres-password: {{ include "postgresql.postgres.password" . | b64enc | quote }} + postgresql-password: {{ include "postgresql.password" . | b64enc | quote }} + {{- if .Values.replication.enabled }} + postgresql-replication-password: {{ include "postgresql.replication.password" . | b64enc | quote }} + {{- end }} + {{- if (and .Values.ldap.enabled .Values.ldap.bind_password)}} + postgresql-ldap-password: {{ .Values.ldap.bind_password | b64enc | quote }} + {{- end }} +{{- end -}} diff --git a/chart/charts/postgresql/templates/serviceaccount.yaml b/chart/charts/postgresql/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..03f0f50e7dfbff25b166c45b915b4c27b8966de9 --- /dev/null +++ b/chart/charts/postgresql/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if and (.Values.serviceAccount.enabled) (not .Values.serviceAccount.name) }} +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + {{- include "common.labels.standard" . | nindent 4 }} + name: {{ template "common.names.fullname" . }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/chart/charts/postgresql/templates/servicemonitor.yaml b/chart/charts/postgresql/templates/servicemonitor.yaml new file mode 100644 index 0000000000000000000000000000000000000000..587ce85b872586da4b1a9a1b094e15561725ed48 --- /dev/null +++ b/chart/charts/postgresql/templates/servicemonitor.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "common.names.fullname" . }} + {{- if .Values.metrics.serviceMonitor.namespace }} + namespace: {{ .Values.metrics.serviceMonitor.namespace }} + {{- end }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.metrics.serviceMonitor.additionalLabels }} + {{- toYaml .Values.metrics.serviceMonitor.additionalLabels | nindent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + +spec: + endpoints: + - port: http-metrics + {{- if .Values.metrics.serviceMonitor.interval }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + {{- end }} + {{- if .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- end }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + selector: + matchLabels: + {{- include "common.labels.matchLabels" . | nindent 6 }} +{{- end }} diff --git a/chart/charts/postgresql/templates/statefulset-readreplicas.yaml b/chart/charts/postgresql/templates/statefulset-readreplicas.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7e93d6568344034e8cf55e12431098220aef8712 --- /dev/null +++ b/chart/charts/postgresql/templates/statefulset-readreplicas.yaml @@ -0,0 +1,411 @@ +{{- if .Values.replication.enabled }} +{{- $readReplicasResources := coalesce .Values.readReplicas.resources .Values.resources -}} +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: "{{ template "common.names.fullname" . }}-read" + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: read +{{- with .Values.readReplicas.labels }} +{{ toYaml . | indent 4 }} +{{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- with .Values.readReplicas.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +spec: + serviceName: {{ template "common.names.fullname" . }}-headless + replicas: {{ .Values.replication.readReplicas }} + selector: + matchLabels: + {{- include "common.labels.matchLabels" . | nindent 6 }} + role: read + template: + metadata: + name: {{ template "common.names.fullname" . }} + labels: + {{- include "common.labels.standard" . | nindent 8 }} + app.kubernetes.io/component: read + role: read +{{- with .Values.readReplicas.podLabels }} +{{ toYaml . | indent 8 }} +{{- end }} +{{- with .Values.readReplicas.podAnnotations }} + annotations: +{{ toYaml . | indent 8 }} +{{- end }} + spec: + {{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" + {{- end }} +{{- include "postgresql.imagePullSecrets" . | indent 6 }} + {{- if .Values.readReplicas.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.readReplicas.podAffinityPreset "component" "read" "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.readReplicas.podAntiAffinityPreset "component" "read" "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.readReplicas.nodeAffinityPreset.type "key" .Values.readReplicas.nodeAffinityPreset.key "values" .Values.readReplicas.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.readReplicas.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.readReplicas.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.readReplicas.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.securityContext.enabled }} + securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.serviceAccount.enabled }} + serviceAccountName: {{ default (include "common.names.fullname" . ) .Values.serviceAccount.name}} + {{- end }} + {{- if or .Values.readReplicas.extraInitContainers (and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled))) }} + initContainers: + {{- if and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled) .Values.tls.enabled) }} + - name: init-chmod-data + image: {{ template "postgresql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -cx + - | + {{- if .Values.persistence.enabled }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.persistence.mountPath }} + {{- else }} + chown {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} {{ .Values.persistence.mountPath }} + {{- end }} + mkdir -p {{ .Values.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.persistence.mountPath }}/conf {{- end }} + chmod 700 {{ .Values.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.persistence.mountPath }}/conf {{- end }} + find {{ .Values.persistence.mountPath }} -mindepth 1 -maxdepth 1 {{- if not (include "postgresql.mountConfigurationCM" .) }} -not -name "conf" {{- end }} -not -name ".snapshot" -not -name "lost+found" | \ + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + xargs chown -R `id -u`:`id -G | cut -d " " -f2` + {{- else }} + xargs chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} + {{- end }} + {{- end }} + {{- if and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled }} + chmod -R 777 /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/ + {{- else }} + chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} /opt/bitnami/postgresql/certs/ + {{- end }} + chmod 600 {{ template "postgresql.tlsCertKey" . }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + {{ if .Values.persistence.enabled }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- end }} + {{- end }} + {{- if .Values.readReplicas.extraInitContainers }} + {{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.extraInitContainers "context" $ ) | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.readReplicas.priorityClassName }} + priorityClassName: {{ .Values.readReplicas.priorityClassName }} + {{- end }} + containers: + - name: {{ template "common.names.fullname" . }} + image: {{ template "postgresql.image" . }} + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + {{- if $readReplicasResources }} + resources: {{- toYaml $readReplicasResources | nindent 12 }} + {{- end }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + - name: POSTGRESQL_VOLUME_DIR + value: "{{ .Values.persistence.mountPath }}" + - name: POSTGRESQL_PORT_NUMBER + value: "{{ template "postgresql.port" . }}" + {{- if .Values.persistence.mountPath }} + - name: PGDATA + value: {{ .Values.postgresqlDataDir | quote }} + {{- end }} + - name: POSTGRES_REPLICATION_MODE + value: "slave" + - name: POSTGRES_REPLICATION_USER + value: {{ include "postgresql.replication.username" . | quote }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_REPLICATION_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-replication-password" + {{- else }} + - name: POSTGRES_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-replication-password + {{- end }} + - name: POSTGRES_CLUSTER_APP_NAME + value: {{ .Values.replication.applicationName }} + - name: POSTGRES_MASTER_HOST + value: {{ template "common.names.fullname" . }} + - name: POSTGRES_MASTER_PORT_NUMBER + value: {{ include "postgresql.port" . | quote }} + {{- if and (not (eq .Values.postgresqlUsername "postgres")) (or .Values.postgresqlPostgresPassword (include "postgresql.useExistingSecret" .)) }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-postgres-password" + {{- else }} + - name: POSTGRES_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-postgres-password + {{- end }} + {{- end }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-password" + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-password + {{- end }} + - name: POSTGRESQL_ENABLE_TLS + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS + value: {{ ternary "yes" "no" .Values.tls.preferServerCiphers | quote }} + - name: POSTGRESQL_TLS_CERT_FILE + value: {{ template "postgresql.tlsCert" . }} + - name: POSTGRESQL_TLS_KEY_FILE + value: {{ template "postgresql.tlsCertKey" . }} + {{- if .Values.tls.certCAFilename }} + - name: POSTGRESQL_TLS_CA_FILE + value: {{ template "postgresql.tlsCACert" . }} + {{- end }} + {{- if .Values.tls.crlFilename }} + - name: POSTGRESQL_TLS_CRL_FILE + value: {{ template "postgresql.tlsCRL" . }} + {{- end }} + {{- end }} + - name: POSTGRESQL_LOG_HOSTNAME + value: {{ .Values.audit.logHostname | quote }} + - name: POSTGRESQL_LOG_CONNECTIONS + value: {{ .Values.audit.logConnections | quote }} + - name: POSTGRESQL_LOG_DISCONNECTIONS + value: {{ .Values.audit.logDisconnections | quote }} + {{- if .Values.audit.logLinePrefix }} + - name: POSTGRESQL_LOG_LINE_PREFIX + value: {{ .Values.audit.logLinePrefix | quote }} + {{- end }} + {{- if .Values.audit.logTimezone }} + - name: POSTGRESQL_LOG_TIMEZONE + value: {{ .Values.audit.logTimezone | quote }} + {{- end }} + {{- if .Values.audit.pgAuditLog }} + - name: POSTGRESQL_PGAUDIT_LOG + value: {{ .Values.audit.pgAuditLog | quote }} + {{- end }} + - name: POSTGRESQL_PGAUDIT_LOG_CATALOG + value: {{ .Values.audit.pgAuditLogCatalog | quote }} + - name: POSTGRESQL_CLIENT_MIN_MESSAGES + value: {{ .Values.audit.clientMinMessages | quote }} + - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES + value: {{ .Values.postgresqlSharedPreloadLibraries | quote }} + {{- if .Values.postgresqlMaxConnections }} + - name: POSTGRESQL_MAX_CONNECTIONS + value: {{ .Values.postgresqlMaxConnections | quote }} + {{- end }} + {{- if .Values.postgresqlPostgresConnectionLimit }} + - name: POSTGRESQL_POSTGRES_CONNECTION_LIMIT + value: {{ .Values.postgresqlPostgresConnectionLimit | quote }} + {{- end }} + {{- if .Values.postgresqlDbUserConnectionLimit }} + - name: POSTGRESQL_USERNAME_CONNECTION_LIMIT + value: {{ .Values.postgresqlDbUserConnectionLimit | quote }} + {{- end }} + {{- if .Values.postgresqlTcpKeepalivesInterval }} + - name: POSTGRESQL_TCP_KEEPALIVES_INTERVAL + value: {{ .Values.postgresqlTcpKeepalivesInterval | quote }} + {{- end }} + {{- if .Values.postgresqlTcpKeepalivesIdle }} + - name: POSTGRESQL_TCP_KEEPALIVES_IDLE + value: {{ .Values.postgresqlTcpKeepalivesIdle | quote }} + {{- end }} + {{- if .Values.postgresqlStatementTimeout }} + - name: POSTGRESQL_STATEMENT_TIMEOUT + value: {{ .Values.postgresqlStatementTimeout | quote }} + {{- end }} + {{- if .Values.postgresqlTcpKeepalivesCount }} + - name: POSTGRESQL_TCP_KEEPALIVES_COUNT + value: {{ .Values.postgresqlTcpKeepalivesCount | quote }} + {{- end }} + {{- if .Values.postgresqlPghbaRemoveFilters }} + - name: POSTGRESQL_PGHBA_REMOVE_FILTERS + value: {{ .Values.postgresqlPghbaRemoveFilters | quote }} + {{- end }} + ports: + - name: tcp-postgresql + containerPort: {{ template "postgresql.port" . }} + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.database" .) }} + - exec pg_isready -U {{ include "postgresql.username" . | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ template "postgresql.port" . }} + {{- else }} + - exec pg_isready -U {{ include "postgresql.username" . | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} + {{- end }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + {{- else if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + exec: + command: + - /bin/sh + - -c + - -e + {{- include "postgresql.readinessProbeCommand" . | nindent 16 }} + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + {{- else if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.usePasswordFile }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.persistence.enabled }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + {{ end }} + {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} + - name: postgresql-extended-config + mountPath: /bitnami/postgresql/conf/conf.d/ + {{- end }} + {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap }} + - name: postgresql-config + mountPath: /bitnami/postgresql/conf + {{- end }} + {{- if .Values.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + readOnly: true + {{- end }} + {{- if .Values.readReplicas.extraVolumeMounts }} + {{- toYaml .Values.readReplicas.extraVolumeMounts | nindent 12 }} + {{- end }} +{{- if .Values.readReplicas.sidecars }} +{{- include "common.tplvalues.render" ( dict "value" .Values.readReplicas.sidecars "context" $ ) | nindent 8 }} +{{- end }} + volumes: + {{- if .Values.usePasswordFile }} + - name: postgresql-password + secret: + secretName: {{ template "postgresql.secretName" . }} + {{- end }} + {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap}} + - name: postgresql-config + configMap: + name: {{ template "postgresql.configurationCM" . }} + {{- end }} + {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} + - name: postgresql-extended-config + configMap: + name: {{ template "postgresql.extendedConfigurationCM" . }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + secret: + secretName: {{ required "A secret containing TLS certificates is required when TLS is enabled" .Values.tls.certificatesSecret }} + - name: postgresql-certificates + emptyDir: {} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + emptyDir: + medium: Memory + sizeLimit: 1Gi + {{- end }} + {{- if or (not .Values.persistence.enabled) (not .Values.readReplicas.persistence.enabled) }} + - name: data + emptyDir: {} + {{- end }} + {{- if .Values.readReplicas.extraVolumes }} + {{- toYaml .Values.readReplicas.extraVolumes | nindent 8 }} + {{- end }} + updateStrategy: + type: {{ .Values.updateStrategy.type }} + {{- if (eq "Recreate" .Values.updateStrategy.type) }} + rollingUpdate: null + {{- end }} +{{- if and .Values.persistence.enabled .Values.readReplicas.persistence.enabled }} + volumeClaimTemplates: + - metadata: + name: data + {{- with .Values.persistence.annotations }} + annotations: + {{- range $key, $value := . }} + {{ $key }}: {{ $value }} + {{- end }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} + + {{- if .Values.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.selector "context" $) | nindent 10 }} + {{- end -}} +{{- end }} +{{- end }} diff --git a/chart/charts/postgresql/templates/statefulset.yaml b/chart/charts/postgresql/templates/statefulset.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4d7c5468f67bb3880f281084cbc168fdae630c79 --- /dev/null +++ b/chart/charts/postgresql/templates/statefulset.yaml @@ -0,0 +1,618 @@ +apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +kind: StatefulSet +metadata: + name: {{ template "postgresql.primary.fullname" . }} + labels: {{- include "common.labels.standard" . | nindent 4 }} + app.kubernetes.io/component: primary + {{- with .Values.primary.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- with .Values.primary.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +spec: + serviceName: {{ template "common.names.fullname" . }}-headless + replicas: 1 + updateStrategy: + type: {{ .Values.updateStrategy.type }} + {{- if (eq "Recreate" .Values.updateStrategy.type) }} + rollingUpdate: null + {{- end }} + selector: + matchLabels: + {{- include "common.labels.matchLabels" . | nindent 6 }} + role: primary + template: + metadata: + name: {{ template "common.names.fullname" . }} + labels: + {{- include "common.labels.standard" . | nindent 8 }} + role: primary + app.kubernetes.io/component: primary + {{- with .Values.primary.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.primary.podAnnotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if .Values.schedulerName }} + schedulerName: "{{ .Values.schedulerName }}" + {{- end }} +{{- include "postgresql.imagePullSecrets" . | indent 6 }} + {{- if .Values.primary.affinity }} + affinity: {{- include "common.tplvalues.render" (dict "value" .Values.primary.affinity "context" $) | nindent 8 }} + {{- else }} + affinity: + podAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAffinityPreset "component" "primary" "context" $) | nindent 10 }} + podAntiAffinity: {{- include "common.affinities.pods" (dict "type" .Values.primary.podAntiAffinityPreset "component" "primary" "context" $) | nindent 10 }} + nodeAffinity: {{- include "common.affinities.nodes" (dict "type" .Values.primary.nodeAffinityPreset.type "key" .Values.primary.nodeAffinityPreset.key "values" .Values.primary.nodeAffinityPreset.values) | nindent 10 }} + {{- end }} + {{- if .Values.primary.nodeSelector }} + nodeSelector: {{- include "common.tplvalues.render" (dict "value" .Values.primary.nodeSelector "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.primary.tolerations }} + tolerations: {{- include "common.tplvalues.render" (dict "value" .Values.primary.tolerations "context" $) | nindent 8 }} + {{- end }} + {{- if .Values.terminationGracePeriodSeconds }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + {{- end }} + {{- if .Values.securityContext.enabled }} + securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 8 }} + {{- end }} + {{- if .Values.serviceAccount.enabled }} + serviceAccountName: {{ default (include "common.names.fullname" . ) .Values.serviceAccount.name }} + {{- end }} + {{- if or .Values.primary.extraInitContainers (and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled))) }} + initContainers: + {{- if and .Values.volumePermissions.enabled (or .Values.persistence.enabled (and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled) .Values.tls.enabled) }} + - name: init-chmod-data + image: {{ template "postgresql.volumePermissions.image" . }} + imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + command: + - /bin/sh + - -cx + - | + {{- if .Values.persistence.enabled }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + chown `id -u`:`id -G | cut -d " " -f2` {{ .Values.persistence.mountPath }} + {{- else }} + chown {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} {{ .Values.persistence.mountPath }} + {{- end }} + mkdir -p {{ .Values.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.persistence.mountPath }}/conf {{- end }} + chmod 700 {{ .Values.persistence.mountPath }}/data {{- if (include "postgresql.mountConfigurationCM" .) }} {{ .Values.persistence.mountPath }}/conf {{- end }} + find {{ .Values.persistence.mountPath }} -mindepth 1 -maxdepth 1 {{- if not (include "postgresql.mountConfigurationCM" .) }} -not -name "conf" {{- end }} -not -name ".snapshot" -not -name "lost+found" | \ + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + xargs chown -R `id -u`:`id -G | cut -d " " -f2` + {{- else }} + xargs chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} + {{- end }} + {{- end }} + {{- if and .Values.shmVolume.enabled .Values.shmVolume.chmod.enabled }} + chmod -R 777 /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + cp /tmp/certs/* /opt/bitnami/postgresql/certs/ + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + chown -R `id -u`:`id -G | cut -d " " -f2` /opt/bitnami/postgresql/certs/ + {{- else }} + chown -R {{ .Values.containerSecurityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} /opt/bitnami/postgresql/certs/ + {{- end }} + chmod 600 {{ template "postgresql.tlsCertKey" . }} + {{- end }} + {{- if eq ( toString ( .Values.volumePermissions.securityContext.runAsUser )) "auto" }} + securityContext: {{- omit .Values.volumePermissions.securityContext "runAsUser" | toYaml | nindent 12 }} + {{- else }} + securityContext: {{- .Values.volumePermissions.securityContext | toYaml | nindent 12 }} + {{- end }} + volumeMounts: + {{- if .Values.persistence.enabled }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + mountPath: /tmp/certs + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + {{- end }} + {{- end }} + {{- if .Values.primary.extraInitContainers }} + {{- include "common.tplvalues.render" ( dict "value" .Values.primary.extraInitContainers "context" $ ) | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.primary.priorityClassName }} + priorityClassName: {{ .Values.primary.priorityClassName }} + {{- end }} + containers: + - name: {{ template "common.names.fullname" . }} + image: {{ template "postgresql.image" . }} + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + {{- if .Values.resources }} + resources: {{- toYaml .Values.resources | nindent 12 }} + {{- end }} + {{- if .Values.containerSecurityContext.enabled }} + securityContext: {{- omit .Values.containerSecurityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + args: + {{- range $key, $value := default dict .Values.postgresqlConfiguration }} + - -c + - '{{ $key | snakecase }}={{ $value }}' + {{- end }} + {{- if .Values.pgHbaConfiguration }} + - -c + - hba_file=/bitnami/postgresql/conf/pg_hba.conf + {{- end }} + env: + - name: BITNAMI_DEBUG + value: {{ ternary "true" "false" .Values.image.debug | quote }} + - name: POSTGRESQL_PORT_NUMBER + value: "{{ template "postgresql.port" . }}" + - name: POSTGRESQL_VOLUME_DIR + value: "{{ .Values.persistence.mountPath }}" + {{- if .Values.postgresqlInitdbArgs }} + - name: POSTGRES_INITDB_ARGS + value: {{ .Values.postgresqlInitdbArgs | quote }} + {{- end }} + {{- if .Values.postgresqlInitdbWalDir }} + - name: POSTGRES_INITDB_WALDIR + value: {{ .Values.postgresqlInitdbWalDir | quote }} + {{- end }} + {{- if .Values.initdbUser }} + - name: POSTGRESQL_INITSCRIPTS_USERNAME + value: {{ .Values.initdbUser }} + {{- end }} + {{- if .Values.initdbPassword }} + - name: POSTGRESQL_INITSCRIPTS_PASSWORD + value: {{ .Values.initdbPassword }} + {{- end }} + {{- if .Values.persistence.mountPath }} + - name: PGDATA + value: {{ .Values.postgresqlDataDir | quote }} + {{- end }} + {{- if .Values.primaryAsStandBy.enabled }} + - name: POSTGRES_MASTER_HOST + value: {{ .Values.primaryAsStandBy.primaryHost }} + - name: POSTGRES_MASTER_PORT_NUMBER + value: {{ .Values.primaryAsStandBy.primaryPort | quote }} + {{- end }} + {{- if or .Values.replication.enabled .Values.primaryAsStandBy.enabled }} + - name: POSTGRES_REPLICATION_MODE + {{- if .Values.primaryAsStandBy.enabled }} + value: "slave" + {{- else }} + value: "master" + {{- end }} + - name: POSTGRES_REPLICATION_USER + value: {{ include "postgresql.replication.username" . | quote }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_REPLICATION_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-replication-password" + {{- else }} + - name: POSTGRES_REPLICATION_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-replication-password + {{- end }} + {{- if not (eq .Values.replication.synchronousCommit "off")}} + - name: POSTGRES_SYNCHRONOUS_COMMIT_MODE + value: {{ .Values.replication.synchronousCommit | quote }} + - name: POSTGRES_NUM_SYNCHRONOUS_REPLICAS + value: {{ .Values.replication.numSynchronousReplicas | quote }} + {{- end }} + - name: POSTGRES_CLUSTER_APP_NAME + value: {{ .Values.replication.applicationName }} + {{- end }} + {{- if not (eq (include "postgresql.username" .) "postgres") }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-postgres-password" + {{- else }} + - name: POSTGRES_POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-postgres-password + {{- end }} + {{- end }} + - name: POSTGRES_USER + value: {{ include "postgresql.username" . | quote }} + {{- if .Values.usePasswordFile }} + - name: POSTGRES_PASSWORD_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-password" + {{- else }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-password + {{- end }} + {{- if (include "postgresql.database" .) }} + - name: POSTGRES_DB + value: {{ (include "postgresql.database" .) | quote }} + {{- end }} + {{- if .Values.extraEnv }} + {{- include "common.tplvalues.render" (dict "value" .Values.extraEnv "context" $) | nindent 12 }} + {{- end }} + - name: POSTGRESQL_ENABLE_LDAP + value: {{ ternary "yes" "no" .Values.ldap.enabled | quote }} + {{- if .Values.ldap.enabled }} + - name: POSTGRESQL_LDAP_SERVER + value: {{ .Values.ldap.server }} + - name: POSTGRESQL_LDAP_PORT + value: {{ .Values.ldap.port | quote }} + - name: POSTGRESQL_LDAP_SCHEME + value: {{ .Values.ldap.scheme }} + {{- if .Values.ldap.tls }} + - name: POSTGRESQL_LDAP_TLS + value: "1" + {{- end }} + - name: POSTGRESQL_LDAP_PREFIX + value: {{ .Values.ldap.prefix | quote }} + - name: POSTGRESQL_LDAP_SUFFIX + value: {{ .Values.ldap.suffix | quote }} + - name: POSTGRESQL_LDAP_BASE_DN + value: {{ .Values.ldap.baseDN }} + - name: POSTGRESQL_LDAP_BIND_DN + value: {{ .Values.ldap.bindDN }} + {{- if (not (empty .Values.ldap.bind_password)) }} + - name: POSTGRESQL_LDAP_BIND_PASSWORD + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-ldap-password + {{- end}} + - name: POSTGRESQL_LDAP_SEARCH_ATTR + value: {{ .Values.ldap.search_attr }} + - name: POSTGRESQL_LDAP_SEARCH_FILTER + value: {{ .Values.ldap.search_filter }} + - name: POSTGRESQL_LDAP_URL + value: {{ .Values.ldap.url }} + {{- end}} + - name: POSTGRESQL_ENABLE_TLS + value: {{ ternary "yes" "no" .Values.tls.enabled | quote }} + {{- if .Values.tls.enabled }} + - name: POSTGRESQL_TLS_PREFER_SERVER_CIPHERS + value: {{ ternary "yes" "no" .Values.tls.preferServerCiphers | quote }} + - name: POSTGRESQL_TLS_CERT_FILE + value: {{ template "postgresql.tlsCert" . }} + - name: POSTGRESQL_TLS_KEY_FILE + value: {{ template "postgresql.tlsCertKey" . }} + {{- if .Values.tls.certCAFilename }} + - name: POSTGRESQL_TLS_CA_FILE + value: {{ template "postgresql.tlsCACert" . }} + {{- end }} + {{- if .Values.tls.crlFilename }} + - name: POSTGRESQL_TLS_CRL_FILE + value: {{ template "postgresql.tlsCRL" . }} + {{- end }} + {{- end }} + - name: POSTGRESQL_LOG_HOSTNAME + value: {{ .Values.audit.logHostname | quote }} + - name: POSTGRESQL_LOG_CONNECTIONS + value: {{ .Values.audit.logConnections | quote }} + - name: POSTGRESQL_LOG_DISCONNECTIONS + value: {{ .Values.audit.logDisconnections | quote }} + {{- if .Values.audit.logLinePrefix }} + - name: POSTGRESQL_LOG_LINE_PREFIX + value: {{ .Values.audit.logLinePrefix | quote }} + {{- end }} + {{- if .Values.audit.logTimezone }} + - name: POSTGRESQL_LOG_TIMEZONE + value: {{ .Values.audit.logTimezone | quote }} + {{- end }} + {{- if .Values.audit.pgAuditLog }} + - name: POSTGRESQL_PGAUDIT_LOG + value: {{ .Values.audit.pgAuditLog | quote }} + {{- end }} + - name: POSTGRESQL_PGAUDIT_LOG_CATALOG + value: {{ .Values.audit.pgAuditLogCatalog | quote }} + - name: POSTGRESQL_CLIENT_MIN_MESSAGES + value: {{ .Values.audit.clientMinMessages | quote }} + - name: POSTGRESQL_SHARED_PRELOAD_LIBRARIES + value: {{ .Values.postgresqlSharedPreloadLibraries | quote }} + {{- if .Values.postgresqlMaxConnections }} + - name: POSTGRESQL_MAX_CONNECTIONS + value: {{ .Values.postgresqlMaxConnections | quote }} + {{- end }} + {{- if .Values.postgresqlPostgresConnectionLimit }} + - name: POSTGRESQL_POSTGRES_CONNECTION_LIMIT + value: {{ .Values.postgresqlPostgresConnectionLimit | quote }} + {{- end }} + {{- if .Values.postgresqlDbUserConnectionLimit }} + - name: POSTGRESQL_USERNAME_CONNECTION_LIMIT + value: {{ .Values.postgresqlDbUserConnectionLimit | quote }} + {{- end }} + {{- if .Values.postgresqlTcpKeepalivesInterval }} + - name: POSTGRESQL_TCP_KEEPALIVES_INTERVAL + value: {{ .Values.postgresqlTcpKeepalivesInterval | quote }} + {{- end }} + {{- if .Values.postgresqlTcpKeepalivesIdle }} + - name: POSTGRESQL_TCP_KEEPALIVES_IDLE + value: {{ .Values.postgresqlTcpKeepalivesIdle | quote }} + {{- end }} + {{- if .Values.postgresqlStatementTimeout }} + - name: POSTGRESQL_STATEMENT_TIMEOUT + value: {{ .Values.postgresqlStatementTimeout | quote }} + {{- end }} + {{- if .Values.postgresqlTcpKeepalivesCount }} + - name: POSTGRESQL_TCP_KEEPALIVES_COUNT + value: {{ .Values.postgresqlTcpKeepalivesCount | quote }} + {{- end }} + {{- if .Values.postgresqlPghbaRemoveFilters }} + - name: POSTGRESQL_PGHBA_REMOVE_FILTERS + value: {{ .Values.postgresqlPghbaRemoveFilters | quote }} + {{- end }} + {{- if .Values.extraEnvVarsCM }} + envFrom: + - configMapRef: + name: {{ tpl .Values.extraEnvVarsCM . }} + {{- end }} + ports: + - name: tcp-postgresql + containerPort: {{ template "postgresql.port" . }} + {{- if .Values.startupProbe.enabled }} + startupProbe: + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.database" .) }} + - exec pg_isready -U {{ include "postgresql.username" . | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ template "postgresql.port" . }} + {{- else }} + - exec pg_isready -U {{ include "postgresql.username" . | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} + {{- end }} + initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} + successThreshold: {{ .Values.startupProbe.successThreshold }} + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + {{- else if .Values.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customStartupProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + exec: + command: + - /bin/sh + - -c + {{- if (include "postgresql.database" .) }} + - exec pg_isready -U {{ include "postgresql.username" . | quote }} -d "dbname={{ include "postgresql.database" . }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}{{- end }}" -h 127.0.0.1 -p {{ template "postgresql.port" . }} + {{- else }} + - exec pg_isready -U {{ include "postgresql.username" . | quote }} {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} -d "sslcert={{ include "postgresql.tlsCert" . }} sslkey={{ include "postgresql.tlsCertKey" . }}"{{- end }} -h 127.0.0.1 -p {{ template "postgresql.port" . }} + {{- end }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + {{- else if .Values.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customLivenessProbe "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + exec: + command: + - /bin/sh + - -c + - -e + {{- include "postgresql.readinessProbeCommand" . | nindent 16 }} + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + {{- else if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- end }} + volumeMounts: + {{- if or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + mountPath: /docker-entrypoint-initdb.d/ + {{- end }} + {{- if .Values.initdbScriptsSecret }} + - name: custom-init-scripts-secret + mountPath: /docker-entrypoint-initdb.d/secret + {{- end }} + {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} + - name: postgresql-extended-config + mountPath: /bitnami/postgresql/conf/conf.d/ + {{- end }} + {{- if .Values.usePasswordFile }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + readOnly: true + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + mountPath: /dev/shm + {{- end }} + {{- if .Values.persistence.enabled }} + - name: data + mountPath: {{ .Values.persistence.mountPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap }} + - name: postgresql-config + mountPath: /bitnami/postgresql/conf + {{- end }} + {{- if .Values.primary.extraVolumeMounts }} + {{- toYaml .Values.primary.extraVolumeMounts | nindent 12 }} + {{- end }} +{{- if .Values.primary.sidecars }} +{{- include "common.tplvalues.render" ( dict "value" .Values.primary.sidecars "context" $ ) | nindent 8 }} +{{- end }} +{{- if .Values.metrics.enabled }} + - name: metrics + image: {{ template "postgresql.metrics.image" . }} + imagePullPolicy: {{ .Values.metrics.image.pullPolicy | quote }} + {{- if .Values.metrics.securityContext.enabled }} + securityContext: {{- omit .Values.metrics.securityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + env: + {{- $database := required "In order to enable metrics you need to specify a database (.Values.postgresqlDatabase or .Values.global.postgresql.postgresqlDatabase)" (include "postgresql.database" .) }} + {{- $sslmode := ternary "require" "disable" .Values.tls.enabled }} + {{- if and .Values.tls.enabled .Values.tls.certCAFilename }} + - name: DATA_SOURCE_NAME + value: {{ printf "host=127.0.0.1 port=%d user=%s sslmode=%s sslcert=%s sslkey=%s" (int (include "postgresql.port" .)) (include "postgresql.username" .) $sslmode (include "postgresql.tlsCert" .) (include "postgresql.tlsCertKey" .) }} + {{- else }} + - name: DATA_SOURCE_URI + value: {{ printf "127.0.0.1:%d/%s?sslmode=%s" (int (include "postgresql.port" .)) $database $sslmode }} + {{- end }} + {{- if .Values.usePasswordFile }} + - name: DATA_SOURCE_PASS_FILE + value: "/opt/bitnami/postgresql/secrets/postgresql-password" + {{- else }} + - name: DATA_SOURCE_PASS + valueFrom: + secretKeyRef: + name: {{ template "postgresql.secretName" . }} + key: postgresql-password + {{- end }} + - name: DATA_SOURCE_USER + value: {{ template "postgresql.username" . }} + {{- if .Values.metrics.extraEnvVars }} + {{- include "common.tplvalues.render" (dict "value" .Values.metrics.extraEnvVars "context" $) | nindent 12 }} + {{- end }} + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: / + port: http-metrics + initialDelaySeconds: {{ .Values.metrics.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.metrics.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.metrics.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.metrics.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.metrics.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: / + port: http-metrics + initialDelaySeconds: {{ .Values.metrics.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.metrics.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.metrics.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.metrics.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.metrics.readinessProbe.failureThreshold }} + {{- end }} + volumeMounts: + {{- if .Values.usePasswordFile }} + - name: postgresql-password + mountPath: /opt/bitnami/postgresql/secrets/ + {{- end }} + {{- if .Values.tls.enabled }} + - name: postgresql-certificates + mountPath: /opt/bitnami/postgresql/certs + readOnly: true + {{- end }} + {{- if .Values.metrics.customMetrics }} + - name: custom-metrics + mountPath: /conf + readOnly: true + args: ["--extend.query-path", "/conf/custom-metrics.yaml"] + {{- end }} + ports: + - name: http-metrics + containerPort: 9187 + {{- if .Values.metrics.resources }} + resources: {{- toYaml .Values.metrics.resources | nindent 12 }} + {{- end }} +{{- end }} + volumes: + {{- if or (.Files.Glob "files/postgresql.conf") (.Files.Glob "files/pg_hba.conf") .Values.postgresqlConfiguration .Values.pgHbaConfiguration .Values.configurationConfigMap}} + - name: postgresql-config + configMap: + name: {{ template "postgresql.configurationCM" . }} + {{- end }} + {{- if or (.Files.Glob "files/conf.d/*.conf") .Values.postgresqlExtendedConf .Values.extendedConfConfigMap }} + - name: postgresql-extended-config + configMap: + name: {{ template "postgresql.extendedConfigurationCM" . }} + {{- end }} + {{- if .Values.usePasswordFile }} + - name: postgresql-password + secret: + secretName: {{ template "postgresql.secretName" . }} + {{- end }} + {{- if or (.Files.Glob "files/docker-entrypoint-initdb.d/*.{sh,sql,sql.gz}") .Values.initdbScriptsConfigMap .Values.initdbScripts }} + - name: custom-init-scripts + configMap: + name: {{ template "postgresql.initdbScriptsCM" . }} + {{- end }} + {{- if .Values.initdbScriptsSecret }} + - name: custom-init-scripts-secret + secret: + secretName: {{ template "postgresql.initdbScriptsSecret" . }} + {{- end }} + {{- if .Values.tls.enabled }} + - name: raw-certificates + secret: + secretName: {{ required "A secret containing TLS certificates is required when TLS is enabled" .Values.tls.certificatesSecret }} + - name: postgresql-certificates + emptyDir: {} + {{- end }} + {{- if .Values.primary.extraVolumes }} + {{- toYaml .Values.primary.extraVolumes | nindent 8 }} + {{- end }} + {{- if and .Values.metrics.enabled .Values.metrics.customMetrics }} + - name: custom-metrics + configMap: + name: {{ template "postgresql.metricsCM" . }} + {{- end }} + {{- if .Values.shmVolume.enabled }} + - name: dshm + emptyDir: + medium: Memory + sizeLimit: 1Gi + {{- end }} +{{- if and .Values.persistence.enabled .Values.persistence.existingClaim }} + - name: data + persistentVolumeClaim: +{{- with .Values.persistence.existingClaim }} + claimName: {{ tpl . $ }} +{{- end }} +{{- else if not .Values.persistence.enabled }} + - name: data + emptyDir: {} +{{- else if and .Values.persistence.enabled (not .Values.persistence.existingClaim) }} + volumeClaimTemplates: + - metadata: + name: data + {{- with .Values.persistence.annotations }} + annotations: + {{- range $key, $value := . }} + {{ $key }}: {{ $value }} + {{- end }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{ include "common.storage.class" (dict "persistence" .Values.persistence "global" .Values.global) }} + {{- if .Values.persistence.selector }} + selector: {{- include "common.tplvalues.render" (dict "value" .Values.persistence.selector "context" $) | nindent 10 }} + {{- end -}} +{{- end }} diff --git a/chart/charts/postgresql/templates/svc-headless.yaml b/chart/charts/postgresql/templates/svc-headless.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6f5f3b9ee4b843273ad49f1628ea27495c828942 --- /dev/null +++ b/chart/charts/postgresql/templates/svc-headless.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }}-headless + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + # Use this annotation in addition to the actual publishNotReadyAddresses + # field below because the annotation will stop being respected soon but the + # field is broken in some versions of Kubernetes: + # https://github.com/kubernetes/kubernetes/issues/58662 + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" + namespace: {{ .Release.Namespace }} +spec: + type: ClusterIP + clusterIP: None + # We want all pods in the StatefulSet to have their addresses published for + # the sake of the other Postgresql pods even before they're ready, since they + # have to be able to talk to each other in order to become ready. + publishNotReadyAddresses: true + ports: + - name: tcp-postgresql + port: {{ template "postgresql.port" . }} + targetPort: tcp-postgresql + selector: + {{- include "common.labels.matchLabels" . | nindent 4 }} diff --git a/chart/charts/postgresql/templates/svc-read.yaml b/chart/charts/postgresql/templates/svc-read.yaml new file mode 100644 index 0000000000000000000000000000000000000000..56195ea1e6d930da6bb2f6342a479fde419271eb --- /dev/null +++ b/chart/charts/postgresql/templates/svc-read.yaml @@ -0,0 +1,43 @@ +{{- if .Values.replication.enabled }} +{{- $serviceAnnotations := coalesce .Values.readReplicas.service.annotations .Values.service.annotations -}} +{{- $serviceType := coalesce .Values.readReplicas.service.type .Values.service.type -}} +{{- $serviceLoadBalancerIP := coalesce .Values.readReplicas.service.loadBalancerIP .Values.service.loadBalancerIP -}} +{{- $serviceLoadBalancerSourceRanges := coalesce .Values.readReplicas.service.loadBalancerSourceRanges .Values.service.loadBalancerSourceRanges -}} +{{- $serviceClusterIP := coalesce .Values.readReplicas.service.clusterIP .Values.service.clusterIP -}} +{{- $serviceNodePort := coalesce .Values.readReplicas.service.nodePort .Values.service.nodePort -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }}-read + labels: + {{- include "common.labels.standard" . | nindent 4 }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if $serviceAnnotations }} + {{- include "common.tplvalues.render" (dict "value" $serviceAnnotations "context" $) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +spec: + type: {{ $serviceType }} + {{- if and $serviceLoadBalancerIP (eq $serviceType "LoadBalancer") }} + loadBalancerIP: {{ $serviceLoadBalancerIP }} + {{- end }} + {{- if and (eq $serviceType "LoadBalancer") $serviceLoadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- include "common.tplvalues.render" (dict "value" $serviceLoadBalancerSourceRanges "context" $) | nindent 4 }} + {{- end }} + {{- if and (eq $serviceType "ClusterIP") $serviceClusterIP }} + clusterIP: {{ $serviceClusterIP }} + {{- end }} + ports: + - name: tcp-postgresql + port: {{ template "postgresql.port" . }} + targetPort: tcp-postgresql + {{- if $serviceNodePort }} + nodePort: {{ $serviceNodePort }} + {{- end }} + selector: + {{- include "common.labels.matchLabels" . | nindent 4 }} + role: read +{{- end }} diff --git a/chart/charts/postgresql/templates/svc.yaml b/chart/charts/postgresql/templates/svc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a29431b6a472429c1b3d206d6e6a1ab648803811 --- /dev/null +++ b/chart/charts/postgresql/templates/svc.yaml @@ -0,0 +1,41 @@ +{{- $serviceAnnotations := coalesce .Values.primary.service.annotations .Values.service.annotations -}} +{{- $serviceType := coalesce .Values.primary.service.type .Values.service.type -}} +{{- $serviceLoadBalancerIP := coalesce .Values.primary.service.loadBalancerIP .Values.service.loadBalancerIP -}} +{{- $serviceLoadBalancerSourceRanges := coalesce .Values.primary.service.loadBalancerSourceRanges .Values.service.loadBalancerSourceRanges -}} +{{- $serviceClusterIP := coalesce .Values.primary.service.clusterIP .Values.service.clusterIP -}} +{{- $serviceNodePort := coalesce .Values.primary.service.nodePort .Values.service.nodePort -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "common.names.fullname" . }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + annotations: + {{- if .Values.commonAnnotations }} + {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if $serviceAnnotations }} + {{- include "common.tplvalues.render" (dict "value" $serviceAnnotations "context" $) | nindent 4 }} + {{- end }} + namespace: {{ .Release.Namespace }} +spec: + type: {{ $serviceType }} + {{- if and $serviceLoadBalancerIP (eq $serviceType "LoadBalancer") }} + loadBalancerIP: {{ $serviceLoadBalancerIP }} + {{- end }} + {{- if and (eq $serviceType "LoadBalancer") $serviceLoadBalancerSourceRanges }} + loadBalancerSourceRanges: {{- include "common.tplvalues.render" (dict "value" $serviceLoadBalancerSourceRanges "context" $) | nindent 4 }} + {{- end }} + {{- if and (eq $serviceType "ClusterIP") $serviceClusterIP }} + clusterIP: {{ $serviceClusterIP }} + {{- end }} + ports: + - name: tcp-postgresql + port: {{ template "postgresql.port" . }} + targetPort: tcp-postgresql + {{- if $serviceNodePort }} + nodePort: {{ $serviceNodePort }} + {{- end }} + selector: + {{- include "common.labels.matchLabels" . | nindent 4 }} + role: primary diff --git a/chart/charts/postgresql/values.schema.json b/chart/charts/postgresql/values.schema.json new file mode 100644 index 0000000000000000000000000000000000000000..66a2a9dd06e454e3d0f523392a2bde336c76c04a --- /dev/null +++ b/chart/charts/postgresql/values.schema.json @@ -0,0 +1,103 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "postgresqlUsername": { + "type": "string", + "title": "Admin user", + "form": true + }, + "postgresqlPassword": { + "type": "string", + "title": "Password", + "form": true + }, + "persistence": { + "type": "object", + "properties": { + "size": { + "type": "string", + "title": "Persistent Volume Size", + "form": true, + "render": "slider", + "sliderMin": 1, + "sliderMax": 100, + "sliderUnit": "Gi" + } + } + }, + "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" + } + } + } + } + }, + "replication": { + "type": "object", + "form": true, + "title": "Replication Details", + "properties": { + "enabled": { + "type": "boolean", + "title": "Enable Replication", + "form": true + }, + "readReplicas": { + "type": "integer", + "title": "read Replicas", + "form": true, + "hidden": { + "value": false, + "path": "replication/enabled" + } + } + } + }, + "volumePermissions": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "form": true, + "title": "Enable Init Containers", + "description": "Change the owner of the persist volume mountpoint to RunAsUser:fsGroup" + } + } + }, + "metrics": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "title": "Configure metrics exporter", + "form": true + } + } + } + } +} diff --git a/chart/charts/postgresql/values.yaml b/chart/charts/postgresql/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..324670ac24ca68f90403cd53c71495fb34855e1f --- /dev/null +++ b/chart/charts/postgresql/values.yaml @@ -0,0 +1,825 @@ +## 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 and imagePullSecrets +## +global: + postgresql: {} +# imageRegistry: myRegistryName +# imagePullSecrets: +# - myRegistryKeySecretName +# storageClass: myStorageClass + +## Bitnami PostgreSQL image version +## ref: https://hub.docker.com/r/bitnami/postgresql/tags/ +## +image: + registry: docker.io + repository: bitnami/postgresql + tag: 11.11.0-debian-10-r9 + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## 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/ + ## + # pullSecrets: + # - myRegistryKeySecretName + + ## Set to true if you would like to see extra information on logs + ## It turns BASH and NAMI debugging in minideb + ## ref: https://github.com/bitnami/minideb-extras/#turn-on-bash-debugging + ## + debug: false + +## String to partially override common.names.fullname template (will maintain the release name) +## +# nameOverride: + +## String to fully override common.names.fullname template +## +# fullnameOverride: + +## +## Init containers parameters: +## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup +## +volumePermissions: + enabled: false + image: + registry: docker.io + repository: bitnami/minideb + tag: buster + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: http://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/ + ## + # pullSecrets: + # - myRegistryKeySecretName + ## Init container Security Context + ## Note: the chown of the data folder is done to securityContext.runAsUser + ## and not the below volumePermissions.securityContext.runAsUser + ## When runAsUser is set to special value "auto", init container will try to chwon the + ## data folder to autodetermined user&group, using commands: `id -u`:`id -G | cut -d" " -f2` + ## "auto" is especially useful for OpenShift which has scc with dynamic userids (and 0 is not allowed). + ## You may want to use this volumePermissions.securityContext.runAsUser="auto" in combination with + ## pod securityContext.enabled=false and shmVolume.chmod.enabled=false + ## + securityContext: + runAsUser: 0 + +## Use an alternate scheduler, e.g. "stork". +## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/ +## +# schedulerName: + +## Pod Security Context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +## +securityContext: + enabled: true + fsGroup: 1001 + +## Container Security Context +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +## +containerSecurityContext: + enabled: true + runAsUser: 1001 + +## Pod Service Account +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ +## +serviceAccount: + enabled: false + ## Name of an already existing service account. Setting this value disables the automatic service account creation. + # name: + +## Pod Security Policy +## ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/ +## +psp: + create: false + +## Creates role for ServiceAccount +## Required for PSP +## +rbac: + create: false + +replication: + enabled: false + user: repl_user + password: repl_password + readReplicas: 1 + ## Set synchronous commit mode: on, off, remote_apply, remote_write and local + ## ref: https://www.postgresql.org/docs/9.6/runtime-config-wal.html#GUC-WAL-LEVEL + synchronousCommit: 'off' + ## From the number of `readReplicas` defined above, set the number of those that will have synchronous replication + ## NOTE: It cannot be > readReplicas + numSynchronousReplicas: 0 + ## Replication Cluster application name. Useful for defining multiple replication policies + ## + applicationName: my_application + +## PostgreSQL admin password (used when `postgresqlUsername` is not `postgres`) +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-user-on-first-run (see note!) +# postgresqlPostgresPassword: + +## PostgreSQL user (has superuser privileges if username is `postgres`) +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run +## +postgresqlUsername: postgres + +## PostgreSQL password +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#setting-the-root-password-on-first-run +## +# postgresqlPassword: + +## PostgreSQL password using existing secret +## existingSecret: secret +## + +## Mount PostgreSQL secret as a file instead of passing environment variable +# usePasswordFile: false + +## Create a database +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md#creating-a-database-on-first-run +## +# postgresqlDatabase: + +## PostgreSQL data dir +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md +## +postgresqlDataDir: /bitnami/postgresql/data + +## An array to add extra environment variables +## For example: +## extraEnv: +## - name: FOO +## value: "bar" +## +# extraEnv: +extraEnv: [] + +## Name of a ConfigMap containing extra env vars +## +# extraEnvVarsCM: + +## Specify extra initdb args +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md +## +# postgresqlInitdbArgs: + +## Specify a custom location for the PostgreSQL transaction log +## ref: https://github.com/bitnami/bitnami-docker-postgresql/blob/master/README.md +## +# postgresqlInitdbWalDir: + +## PostgreSQL configuration +## Specify runtime configuration parameters as a dict, using camelCase, e.g. +## {"sharedBuffers": "500MB"} +## Alternatively, you can put your postgresql.conf under the files/ directory +## ref: https://www.postgresql.org/docs/current/static/runtime-config.html +## +# postgresqlConfiguration: + +## PostgreSQL extended configuration +## As above, but _appended_ to the main configuration +## Alternatively, you can put your *.conf under the files/conf.d/ directory +## https://github.com/bitnami/bitnami-docker-postgresql#allow-settings-to-be-loaded-from-files-other-than-the-default-postgresqlconf +## +# postgresqlExtendedConf: + +## Configure current cluster's primary server to be the standby server in other cluster. +## This will allow cross cluster replication and provide cross cluster high availability. +## You will need to configure pgHbaConfiguration if you want to enable this feature with local cluster replication enabled. +## +primaryAsStandBy: + enabled: false + # primaryHost: + # primaryPort: + +## PostgreSQL client authentication configuration +## Specify content for pg_hba.conf +## Default: do not create pg_hba.conf +## Alternatively, you can put your pg_hba.conf under the files/ directory +# pgHbaConfiguration: |- +# local all all trust +# host all all localhost trust +# host mydatabase mysuser 192.168.0.0/24 md5 + +## ConfigMap with PostgreSQL configuration +## NOTE: This will override postgresqlConfiguration and pgHbaConfiguration +# configurationConfigMap: + +## ConfigMap with PostgreSQL extended configuration +# extendedConfConfigMap: + +## initdb scripts +## Specify dictionary of scripts to be run at first boot +## Alternatively, you can put your scripts under the files/docker-entrypoint-initdb.d directory +## +# initdbScripts: +# my_init_script.sh: | +# #!/bin/sh +# echo "Do something." + +## ConfigMap with scripts to be run at first boot +## NOTE: This will override initdbScripts +# initdbScriptsConfigMap: + +## Secret with scripts to be run at first boot (in case it contains sensitive information) +## NOTE: This can work along initdbScripts or initdbScriptsConfigMap +# initdbScriptsSecret: + +## Specify the PostgreSQL username and password to execute the initdb scripts +# initdbUser: +# initdbPassword: + +## Audit settings +## https://github.com/bitnami/bitnami-docker-postgresql#auditing +## +audit: + ## Log client hostnames + ## + logHostname: false + ## Log connections to the server + ## + logConnections: false + ## Log disconnections + ## + logDisconnections: false + ## Operation to audit using pgAudit (default if not set) + ## + pgAuditLog: "" + ## Log catalog using pgAudit + ## + pgAuditLogCatalog: "off" + ## Log level for clients + ## + clientMinMessages: error + ## Template for log line prefix (default if not set) + ## + logLinePrefix: "" + ## Log timezone + ## + logTimezone: "" + +## Shared preload libraries +## +postgresqlSharedPreloadLibraries: "pgaudit" + +## Maximum total connections +## +postgresqlMaxConnections: + +## Maximum connections for the postgres user +## +postgresqlPostgresConnectionLimit: + +## Maximum connections for the created user +## +postgresqlDbUserConnectionLimit: + +## TCP keepalives interval +## +postgresqlTcpKeepalivesInterval: + +## TCP keepalives idle +## +postgresqlTcpKeepalivesIdle: + +## TCP keepalives count +## +postgresqlTcpKeepalivesCount: + +## Statement timeout +## +postgresqlStatementTimeout: + +## Remove pg_hba.conf lines with the following comma-separated patterns +## (cannot be used with custom pg_hba.conf) +## +postgresqlPghbaRemoveFilters: + +## Optional duration in seconds the pod needs to terminate gracefully. +## ref: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods +## +# terminationGracePeriodSeconds: 30 + +## LDAP configuration +## +ldap: + enabled: false + url: '' + server: '' + port: '' + prefix: '' + suffix: '' + baseDN: '' + bindDN: '' + bind_password: + search_attr: '' + search_filter: '' + scheme: '' + tls: {} + +## PostgreSQL service configuration +## +service: + ## PosgresSQL service type + ## + type: ClusterIP + # clusterIP: None + port: 5432 + + ## Specify the nodePort value for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + # nodePort: + + ## Provide any additional annotations which may be required. Evaluated as a template. + ## + annotations: {} + ## Set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + # loadBalancerIP: + ## Load Balancer sources. Evaluated as a template. + ## https://kubernetes.io/docs/tasks/access-application-cluster/configure-cloud-provider-firewall/#restrict-access-for-loadbalancer-service + ## + # loadBalancerSourceRanges: + # - 10.10.10.0/24 + +## Start primary and read(s) pod(s) without limitations on shm memory. +## By default docker and containerd (and possibly other container runtimes) +## limit `/dev/shm` to `64M` (see e.g. the +## [docker issue](https://github.com/docker-library/postgres/issues/416) and the +## [containerd issue](https://github.com/containerd/containerd/issues/3654), +## which could be not enough if PostgreSQL uses parallel workers heavily. +## +shmVolume: + ## Set `shmVolume.enabled` to `true` to mount a new tmpfs volume to remove + ## this limitation. + ## + enabled: true + ## Set to `true` to `chmod 777 /dev/shm` on a initContainer. + ## This option is ignored if `volumePermissions.enabled` is `false` + ## + chmod: + enabled: true + +## PostgreSQL data Persistent Volume Storage Class +## If defined, storageClassName: +## If set to "-", storageClassName: "", which disables dynamic provisioning +## If undefined (the default) or set to null, no storageClassName spec is +## set, choosing the default provisioner. (gp2 on AWS, standard on +## GKE, AWS & OpenStack) +## +persistence: + enabled: true + ## A manually managed Persistent Volume and Claim + ## If defined, PVC must be created manually before volume will be bound + ## The value is evaluated as a template, so, for example, the name can depend on .Release or .Chart + ## + # existingClaim: + + ## The path the volume will be mounted at, useful when using different + ## PostgreSQL images. + ## + mountPath: /bitnami/postgresql + + ## The subdirectory of the volume to mount to, useful in dev environments + ## and one PV for multiple services. + ## + subPath: '' + + # storageClass: "-" + accessModes: + - ReadWriteOnce + size: 8Gi + annotations: {} + ## selector can be used to match an existing PersistentVolume + ## selector: + ## matchLabels: + ## app: my-app + selector: {} + +## updateStrategy for PostgreSQL StatefulSet and its reads StatefulSets +## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies +## +updateStrategy: + type: RollingUpdate + +## +## PostgreSQL Primary parameters +## +primary: + ## PostgreSQL Primary pod affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## Allowed values: soft, hard + ## + podAffinityPreset: "" + + ## PostgreSQL Primary pod anti-affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## Allowed values: soft, hard + ## + podAntiAffinityPreset: soft + + ## PostgreSQL Primary node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## Allowed values: soft, hard + ## + nodeAffinityPreset: + ## Node affinity type + ## Allowed values: soft, hard + type: "" + ## Node label key to match + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## Node label values to match + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + + ## Affinity for PostgreSQL primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: primary.podAffinityPreset, primary.podAntiAffinityPreset, and primary.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + + ## Node labels for PostgreSQL primary pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Tolerations for PostgreSQL primary pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + priorityClassName: '' + ## Extra init containers + ## Example + ## + ## extraInitContainers: + ## - name: do-something + ## image: busybox + ## command: ['do', 'something'] + ## + extraInitContainers: [] + + ## Additional PostgreSQL primary Volume mounts + ## + extraVolumeMounts: [] + ## Additional PostgreSQL primary Volumes + ## + extraVolumes: [] + ## Add sidecars to the pod + ## + ## For example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + + ## Override the service configuration for primary + ## + service: {} + # type: + # nodePort: + # clusterIP: + +## +## PostgreSQL read only replica parameters +## +readReplicas: + ## PostgreSQL read only pod affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## Allowed values: soft, hard + ## + podAffinityPreset: "" + + ## PostgreSQL read only pod anti-affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity + ## Allowed values: soft, hard + ## + podAntiAffinityPreset: soft + + ## PostgreSQL read only node affinity preset + ## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity + ## Allowed values: soft, hard + ## + nodeAffinityPreset: + ## Node affinity type + ## Allowed values: soft, hard + type: "" + ## Node label key to match + ## E.g. + ## key: "kubernetes.io/e2e-az-name" + ## + key: "" + ## Node label values to match + ## E.g. + ## values: + ## - e2e-az1 + ## - e2e-az2 + ## + values: [] + + ## Affinity for PostgreSQL read only pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + ## Note: readReplicas.podAffinityPreset, readReplicas.podAntiAffinityPreset, and readReplicas.nodeAffinityPreset will be ignored when it's set + ## + affinity: {} + + ## Node labels for PostgreSQL read only pods assignment + ## ref: https://kubernetes.io/docs/user-guide/node-selection/ + ## + nodeSelector: {} + + ## Tolerations for PostgreSQL read only pods assignment + ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + ## + tolerations: [] + labels: {} + annotations: {} + podLabels: {} + podAnnotations: {} + priorityClassName: '' + + ## Extra init containers + ## Example + ## + ## extraInitContainers: + ## - name: do-something + ## image: busybox + ## command: ['do', 'something'] + ## + extraInitContainers: [] + + ## Additional PostgreSQL read replicas Volume mounts + ## + extraVolumeMounts: [] + + ## Additional PostgreSQL read replicas Volumes + ## + extraVolumes: [] + + ## Add sidecars to the pod + ## + ## For example: + ## sidecars: + ## - name: your-image-name + ## image: your-image + ## imagePullPolicy: Always + ## ports: + ## - name: portname + ## containerPort: 1234 + ## + sidecars: [] + + ## Override the service configuration for read + ## + service: {} + # type: + # nodePort: + # clusterIP: + + ## Whether to enable PostgreSQL read replicas data Persistent + ## + persistence: + enabled: true + + # Override the resource configuration for read replicas + resources: {} + # requests: + # memory: 256Mi + # cpu: 250m + +## Configure resource requests and limits +## ref: http://kubernetes.io/docs/user-guide/compute-resources/ +## +resources: + requests: + memory: 256Mi + cpu: 250m + +## Add annotations to all the deployed resources +## +commonAnnotations: {} + +networkPolicy: + ## Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now. + ## + enabled: false + + ## The Policy model to apply. When set to false, only pods with the correct + ## client label will have network access to the port PostgreSQL is listening + ## on. When true, PostgreSQL will accept connections from any source + ## (with the correct destination port). + ## + allowExternal: true + + ## if explicitNamespacesSelector is missing or set to {}, only client Pods that are in the networkPolicy's namespace + ## and that match other criteria, the ones that have the good label, can reach the DB. + ## But sometimes, we want the DB to be accessible to clients from other namespaces, in this case, we can use this + ## LabelSelector to select these namespaces, note that the networkPolicy's namespace should also be explicitly added. + ## + ## Example: + ## explicitNamespacesSelector: + ## matchLabels: + ## role: frontend + ## matchExpressions: + ## - {key: role, operator: In, values: [frontend]} + ## + explicitNamespacesSelector: {} + +## Configure extra options for startup, liveness and readiness probes +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#configure-probes +## +startupProbe: + enabled: false + initialDelaySeconds: 30 + periodSeconds: 15 + timeoutSeconds: 5 + failureThreshold: 10 + successThreshold: 1 + +livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + +readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + +## Custom Startup probe +## +customStartupProbe: {} + +## Custom Liveness probe +## +customLivenessProbe: {} + +## Custom Rediness probe +## +customReadinessProbe: {} + +## +## TLS configuration +## +tls: + # Enable TLS traffic + enabled: false + # + # Whether to use the server's TLS cipher preferences rather than the client's. + preferServerCiphers: true + # + # Name of the Secret that contains the certificates + certificatesSecret: '' + # + # Certificate filename + certFilename: '' + # + # Certificate Key filename + certKeyFilename: '' + # + # CA Certificate filename + # If provided, PostgreSQL will authenticate TLS/SSL clients by requesting them a certificate + # ref: https://www.postgresql.org/docs/9.6/auth-methods.html + certCAFilename: + # + # File containing a Certificate Revocation List + crlFilename: + +## Configure metrics exporter +## +metrics: + enabled: false + # resources: {} + service: + type: ClusterIP + annotations: + prometheus.io/scrape: 'true' + prometheus.io/port: '9187' + loadBalancerIP: + serviceMonitor: + enabled: false + additionalLabels: {} + # namespace: monitoring + # interval: 30s + # scrapeTimeout: 10s + ## Custom PrometheusRule to be defined + ## The value is evaluated as a template, so, for example, the value can depend on .Release or .Chart + ## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions + ## + prometheusRule: + enabled: false + additionalLabels: {} + namespace: '' + ## These are just examples rules, please adapt them to your needs. + ## Make sure to constraint the rules to the current postgresql service. + ## rules: + ## - alert: HugeReplicationLag + ## expr: pg_replication_lag{service="{{ template "common.names.fullname" . }}-metrics"} / 3600 > 1 + ## for: 1m + ## labels: + ## severity: critical + ## annotations: + ## description: replication for {{ template "common.names.fullname" . }} PostgreSQL is lagging by {{ "{{ $value }}" }} hour(s). + ## summary: PostgreSQL replication is lagging by {{ "{{ $value }}" }} hour(s). + ## + rules: [] + + image: + registry: docker.io + repository: bitnami/postgres-exporter + tag: 0.8.0-debian-10-r362 + pullPolicy: IfNotPresent + ## 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/ + ## + # pullSecrets: + # - myRegistryKeySecretName + ## Define additional custom metrics + ## ref: https://github.com/wrouesnel/postgres_exporter#adding-new-metrics-via-a-config-file + # customMetrics: + # pg_database: + # query: "SELECT d.datname AS name, CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT') THEN pg_catalog.pg_database_size(d.datname) ELSE 0 END AS size_bytes FROM pg_catalog.pg_database d where datname not in ('template0', 'template1', 'postgres')" + # metrics: + # - name: + # usage: "LABEL" + # description: "Name of the database" + # - size_bytes: + # usage: "GAUGE" + # description: "Size of the database in bytes" + # + ## An array to add extra env vars to configure postgres-exporter + ## see: https://github.com/wrouesnel/postgres_exporter#environment-variables + ## For example: + # extraEnvVars: + # - name: PG_EXPORTER_DISABLE_DEFAULT_METRICS + # value: "true" + extraEnvVars: {} + + ## Pod Security Context + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + ## + securityContext: + enabled: false + runAsUser: 1001 + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#configure-probes) + ## Configure extra options for liveness and readiness probes + ## + livenessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + + readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 6 + successThreshold: 1 + +## Array with extra yaml to deploy with the chart. Evaluated as a template +## +extraDeploy: [] diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..5a1108e9a3c2a23c1284556f379d34880bb03da4 --- /dev/null +++ b/chart/templates/_helpers.tpl @@ -0,0 +1,61 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "mattermost.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 "mattermost.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 "mattermost.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mattermost.labels" -}} +helm.sh/chart: {{ include "mattermost.chart" . }} +{{ include "mattermost.selectorLabels" . }} +app.kubernetes.io/version: {{ .Chart.Version | quote }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mattermost.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mattermost.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/part-of: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "mattermost.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "mattermost.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/chart/templates/db-credentials.yaml b/chart/templates/db-credentials.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6c0b5ebd6a6d5792b3cacf98ae52fc3f3b92d08a --- /dev/null +++ b/chart/templates/db-credentials.yaml @@ -0,0 +1,16 @@ +{{- if and (not .Values.database.secret) .Values.postgresql.install }} +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: {{ include "mattermost.fullname" . }}-dbcreds + namespace: {{ .Release.Namespace }} + labels: + {{ include "mattermost.labels" . | nindent 4 }} + app.kubernetes.io/component: "database" +stringData: + {{- with .Values.postgresql }} + DB_CONNECTION_CHECK_URL: "postgres://{{ .postgresqlUsername }}:{{ .postgresqlPassword }}@{{ .fullnameOverride }}:5432/{{ .postgresqlDatabase }}?connect_timeout=10&sslmode=disable" + DB_CONNECTION_STRING: "postgres://{{ .postgresqlUsername }}:{{ .postgresqlPassword }}@{{ .fullnameOverride }}:5432/{{ .postgresqlDatabase }}?connect_timeout=10&sslmode=disable" + {{- end }} +{{- end }} diff --git a/chart/templates/license.yaml b/chart/templates/license.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7e559ac6cdc8d59e68f60beca2ff7b0ce2004bcb --- /dev/null +++ b/chart/templates/license.yaml @@ -0,0 +1,15 @@ +{{- if and .Values.enterprise.enabled .Values.enterprise.license }} +apiVersion: v1 +kind: Secret +metadata: + name: mattermost-license + namespace: {{ .Release.Namespace }} + labels: + {{ include "mattermost.labels" . | nindent 4 }} + app.kubernetes.io/component: "license" + annotations: + "helm.sh/hook": "pre-install,pre-upgrade" +type: Opaque +data: + license: {{ .Values.enterprise.license | b64enc }} +{{- end }} diff --git a/chart/templates/mattermost-instance.yaml b/chart/templates/mattermost-instance.yaml deleted file mode 100644 index 485e14829b1e97611e864610bd983bc2d4ff8feb..0000000000000000000000000000000000000000 --- a/chart/templates/mattermost-instance.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: mattermost.com/v1alpha1 -kind: ClusterInstallation -metadata: - name: chat -spec: - version: 5.27.0 - size: 100users - ingressName: chat.kube.dev - image: registry1.dsop.io/ironbank/opensource/mattermost/mattermost \ No newline at end of file diff --git a/chart/templates/mattermost.yaml b/chart/templates/mattermost.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8dda86a336cc7c5901c29a31aeb09e4e549734e5 --- /dev/null +++ b/chart/templates/mattermost.yaml @@ -0,0 +1,96 @@ +apiVersion: installation.mattermost.com/v1beta1 +kind: Mattermost +metadata: + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} + labels: + {{ include "mattermost.labels" . | nindent 4 }} + app.kubernetes.io/component: "instance" +spec: + image: {{ .Values.image.name }} + imagePullPolicy: {{ .Values.image.imagePullPolicy }} + + size: {{ .Values.users }}users + version: {{ .Values.image.tag }} + replicas: {{ .Values.replicaCount }} + + {{- if .Values.istio.chat.hosts }} + ingressName: {{ tpl (index .Values.istio.chat.hosts 0) $ }} + {{- else }} + ingressName: "chat.bigbang.dev" + {{- end }} + + {{- if and .Values.enterprise.enabled .Values.enterprise.license }} + licenseSecret: "mattermost-license" + {{- end }} + + {{- if or .Values.mattermostEnvs .Values.sso.enabled }} + mattermostEnv: + {{- range $k, $v := .Values.mattermostEnvs }} + - name: {{ $k }} + value: {{ $v | quote }} + {{- end }} + {{- if .Values.sso.enabled }} + - name: MM_GITLABSETTINGS_ENABLE + value: "{{ .Values.sso.enabled }}" + - name: MM_GITLABSETTINGS_ID + value: "{{ .Values.sso.client_id }}" + - name: MM_GITLABSETTINGS_SECRET + value: "{{ .Values.sso.client_secret }}" + - name: MM_GITLABSETTINGS_AUTHENDPOINT + value: "{{ .Values.sso.auth_endpoint }}" + - name: MM_GITLABSETTINGS_TOKENENDPOINT + value: "{{ .Values.sso.token_endpoint }}" + - name: MM_GITLABSETTINGS_USERAPIENDPOINT + value: "{{ .Values.sso.user_api_endpoint }}" + {{- end }} + {{- end }} + + # Give MM enough time to keel over if needed + probes: + livenessProbe: + initialDelaySeconds: 120 + periodSeconds: 120 + + scheduling: + resources: + {{- toYaml .Values.resources | nindent 6 }} + + {{- if or .Values.antiAffinity .Values.nodeAffinity }} + affinity: + {{- if eq .Values.antiAffinity "hard" }} + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: "kubernetes.io/hostname" + labelSelector: + matchLabels: + app: mattermost + installation.mattermost.com/installation: mattermost + installation.mattermost.com/resource: mattermost + {{- else if eq .Values.antiAffinity "soft" }} + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + app: mattermost + installation.mattermost.com/installation: mattermost + installation.mattermost.com/resource: mattermost + {{- end }} + {{- with .Values.nodeAffinity }} + nodeAffinity: + {{ toYaml . | nindent 8 }} + {{- end }} + {{- end }} + + database: + external: + secret: {{ .Values.database.secret | default (printf "%s-dbcreds" (include "mattermost.fullname" .)) }} + + fileStore: + external: + url: {{ .Values.fileStore.url | default "minio-service:9000" }} + bucket: {{ .Values.fileStore.bucket | default "mattermost" }} + secret: {{ .Values.fileStore.secret | default "minio-creds-secret" }} diff --git a/chart/templates/objectstorage-credentials.yaml b/chart/templates/objectstorage-credentials.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fc2ca134da6bdaab36709ce447fcf6443743a173 --- /dev/null +++ b/chart/templates/objectstorage-credentials.yaml @@ -0,0 +1,14 @@ +{{- if and (not .Values.fileStore.secret) .Values.minio.install }} +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: {{ include "mattermost.fullname" . }}-objstore-creds + namespace: {{ .Release.Namespace }} + labels: + {{ include "mattermost.labels" . | nindent 4 }} + app.kubernetes.io/component: "objectstorage" +data: + accesskey: {{ .Values.minio.accessKey | b64enc }} + secretkey: {{ .Values.minio.secretKey | b64enc }} +{{- end }} diff --git a/chart/templates/role-binding.yaml b/chart/templates/role-binding.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a095e860e8d35b50303080ffac0c213d33e72a26 --- /dev/null +++ b/chart/templates/role-binding.yaml @@ -0,0 +1,21 @@ +{{- if .Values.monitoring.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBindingList +items: +- apiVersion: rbac.authorization.k8s.io/v1 + kind: RoleBinding + metadata: + name: prometheus-k8s + namespace: {{ .Release.Namespace }} + labels: + {{ include "mattermost.labels" . | nindent 6 }} + app.kubernetes.io/component: "monitoring" + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: prometheus-k8s + subjects: + - kind: ServiceAccount + name: prometheus-k8s + namespace: {{ .Values.monitoring.namespace }} +{{- end }} diff --git a/chart/templates/role.yaml b/chart/templates/role.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ea79ecc7478fb8e8aba432ba9b950d0f2b565593 --- /dev/null +++ b/chart/templates/role.yaml @@ -0,0 +1,24 @@ +{{- if .Values.monitoring.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleList +items: +- apiVersion: rbac.authorization.k8s.io/v1 + kind: Role + metadata: + name: prometheus-k8s + namespace: {{ .Release.Namespace }} + labels: + {{ include "mattermost.labels" . | nindent 6 }} + app.kubernetes.io/component: "monitoring" + rules: + - apiGroups: + - "" + resources: + - services + - endpoints + - pods + verbs: + - get + - list + - watch +{{- end }} diff --git a/chart/templates/service-monitor.yaml b/chart/templates/service-monitor.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3db3a6f44cb05fc49fee8149d5f866da3dabb40b --- /dev/null +++ b/chart/templates/service-monitor.yaml @@ -0,0 +1,24 @@ +{{- if and .Values.monitoring.enabled .Values.enterprise.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + prometheus: k8s + release: monitoring + {{ include "mattermost.labels" . | nindent 4 }} + app.kubernetes.io/component: "monitoring" + name: mattermost-enterprise-metrics + namespace: {{ .Release.Namespace }} +spec: + selector: + matchLabels: + app: {{ .Release.Name }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - interval: 30s + port: metrics + scheme: http + jobLabel: mattermost +{{- end }} diff --git a/chart/templates/virtualservice.yaml b/chart/templates/virtualservice.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f47b867ab7e1c3fb5d8f04ec49861f7329d61bb2 --- /dev/null +++ b/chart/templates/virtualservice.yaml @@ -0,0 +1,32 @@ +{{- if and .Values.istio.enabled .Values.istio.chat.enabled -}} +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: {{ template "mattermost.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{ include "mattermost.labels" . | nindent 4 }} + app.kubernetes.io/component: "chat" + {{- if .Values.istio.chat.labels }} + {{ toYaml .Values.istio.chat.labels | indent 4 }} + {{- end }} + {{- if .Values.istio.chat.annotations }} + annotations: + {{ toYaml .Values.istio.chat.annotations | indent 4 }} + {{- end }} +spec: + gateways: + {{- range .Values.istio.chat.gateways }} + - {{ . }} + {{- end }} + hosts: + {{- range .Values.istio.chat.hosts }} + - {{ tpl . $ }} + {{- end }} + http: + - route: + - destination: + host: {{ .Release.Name }}.{{ .Release.Namespace }}.svc.cluster.local + port: + number: 8065 # hardcode this because the operator does +{{- end }} diff --git a/chart/values.yaml b/chart/values.yaml index d6e4d6c6fff74ca94d3e7e1d064f315bdaedecb0..26d59a9546df79faace7be743d142af199ba6bef 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -1,11 +1,120 @@ +hostname: bigbang.dev + +istio: + # Toggle istio integration + enabled: false + chat: + # Toggle vs creation + enabled: true + annotations: {} + labels: {} + gateways: + - istio-system/main + hosts: + - chat.{{ .Values.hostname }} + +# NOTE: Requires enterprise.enabled to have any effect +monitoring: + enabled: false + namespace: monitoring + +sso: + enabled: false + client_id: platform1_a8604cc9-f5e9-4656-802d-d05624370245_bb8-mattermost + client_secret: nothing # Change to your Keycloak client secret + auth_endpoint: https://login.dso.mil/oauth/authorize + token_endpoint: https://login.dso.mil/oauth/token + user_api_endpoint: https://login.dso.mil/api/v4/user + # Repo and image tag -image: +image: + name: registry.dso.mil/platform-one/big-bang/apps/collaboration-tools/mattermost/mattermost + tag: 5.31.0 imagePullPolicy: IfNotPresent - name: "registry1.dsop.io/ironbank/opensource/mattermost/mattermost-operator:v1.5.0" -#Mattermost operator desired replicas -replicas: - count: 1 +global: + imagePullSecrets: [] + # - name: private-registry + +# Mattermost instance desired replicas +replicaCount: 3 + +users: 100 # Allowable: 100, 1000, 5000, 10000, 25000 + +enterprise: + enabled: false + license: "" + # Example: + # license: | + # LICENSE HERE + +nameOverride: "" + +resources: {} + # limits: + # cpu: 500m + # memory: 512Mi + # requests: + # cpu: 250m + # memory: 256Mi + +# Available options are "soft" and "hard" +antiAffinity: "" + +nodeAffinity: {} + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: type + # operator: In + # values: + # - "mattermost-optimized" + +mattermostEnvs: {} + +minio: + install: false + + accessKey: minio + secretKey: minio#123 # default key, change this! + +postgresql: + install: false + + image: + registry: "registry1.dso.mil/ironbank" + repository: "opensource/postgres/postgresql11" + tag: "11.10" + + pullSecrets: [] + # - private-registry + + postgresqlUsername: "mattermost" + postgresqlPassword: "bigbang" # default password, change this! + postgresqlDatabase: "mattermost" + + fullnameOverride: "mattermost-postgresql" # Overrides the name used for resource creation + + securityContext: + fsGroup: 26 + containerSecurityContext: + runAsUser: 26 + + # Set the configs to allow listening and connecting from other pods + postgresqlConfiguration: {"listen_addresses": "*"} + pgHbaConfiguration: |- + local all all md5 + host all all all md5 + +database: + # Name of an existing secret to pull credentials from, leave empty for chart created database + # Must at minimum contain DB_CONNECTION_STRING + secret: "" -# Watched namespace, blank for all namspaces -watchedNamespace: +fileStore: + # Name of an existing secret to pull credentials from, leave empty for chart created minio + secret: "" + # URL for existing file store, leave empty for chart created minio + url: "" + # Bucket for existing file store, leave empty for chart created minio + bucket: "" diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md deleted file mode 100644 index 3eaee7ded0b00c266a1bd2a33dd1763e3913a418..0000000000000000000000000000000000000000 --- a/docs/CHANGELOG.md +++ /dev/null @@ -1,6 +0,0 @@ -# Mattermost Change log - -October 1, 2020 Update oprator to 1.8 and MM to 5.27, use direct IB images from Harbor - -July 20,2020 Added ECK instructions to README.md -October 8, 2020 Switched thei images being pulled to the registr1 repo (harbor) diff --git a/docs/keycloak.md b/docs/keycloak.md index 4feabad9e5330e6dfb0e059b100a67a498758346..a2423ae55d7ddd7f36e81201481c9d4aca046a16 100644 --- a/docs/keycloak.md +++ b/docs/keycloak.md @@ -1,117 +1,70 @@ -# Keycloak SSO helm config +# Keycloak SSO Mattermost Config -Modify your values.yaml to enable sso: +## Keycloak Client Setup + +The Keycloak client can be set up by following [this tutorial](https://medium.com/@mrtcve/mattermost-teams-edition-replacing-gitlab-sso-with-keycloak-dabf13ebb99e). A summary is provided below, but if there are any issues refer to the source linked. + +Create client: +- client id - you pick, "mattermost" +- enabled - on +- client protocol - openid-connect +- access type - confidential +- standard flow enabled - on +- valid redirect URIs - "{mattermosturl}/signup/gitlab/complete" + +Under the mappers tab, create a new mapper: +- name - mattermostId +- mapper type - user attribute +- user attribute - mattermostId +- token claim name - id +- claim JSON type - long +- add to userinfo - on + +Create another mapper: +- name - username +- mapper type - user property +- property - username +- token claim name - username +- claim JSON type - string +- add to userinfo - on +- all other sliders off + +Add mattermostid to existing user: +- Login to keycloak Admin Console with the master realm user +- Go to your realm +- Go to the users section and edit the user +- Go to the Attributes tab +- In the bottom row type `mattermostId` in the key and a random number in the `value` field. +- Click Add. + +This mattermostid needs to be unique per user, so it's a bad idea to generate these by hand. This process is just a way to edit test/existing users. + +## Helm Values + +First get the values you need for your Keycloak: +- client_id: This is the client id you created and picked earlier +- client_secret: This is under the credential tab for your client, you can click regenerate and then copy it +- endpoints: Go to your realm settings and then open the "OpenID Endpoint Configuration". There should be values for authorization_endpoint, token_endpoint, and userinfo_endpoint which correspond to the auth, token, and user_api endpoints in the values. + +Modify your values.yaml with these to enable sso (provided below are examples for using the P1 Keycloak for dev): ``` # SSO Additions sso: enabled: true - secret: secret - id: platform1_a8604cc9-f5e9-4656-802d-d05624370245_bb8-mattermost - authendpoint: https://login.dso.mil/oauth/authorize - tokenendpoint: https://login.dso.mil/oauth/token - userapiendpoint: https://login.dso.mil/api/v4/user + client_id: platform1_a8604cc9-f5e9-4656-802d-d05624370245_bb8-mattermost + client_secret: nothing # Change to your Keycloak client secret + auth_endpoint: https://login.dso.mil/oauth/authorize + token_endpoint: https://login.dso.mil/oauth/token + user_api_endpoint: https://login.dso.mil/api/v4/user ``` + Example install: ``` -helm upgrade -i mattermost chart -n mattermost --create-namespace -f tests/test-values.yml +helm upgrade -i mattermost chart -n mattermost --create-namespace -f my-values.yml ``` -# Keycloak SSO Kustomize config - -Generate secret for client: -Go to Baby-Yoda realm - 1. Click on Clients - 2. Click on il2_00eb8904-5b88-4c68-ad67-cec0d2e07aa6_mattermost - 3. Click the credentials tab - 4. Press Regenerate Secret and copy it to clipboard - -Create Mattermost secret - 1. Create sso-creds.env - 2. Edit sso-creds.env - ``` - MM_GITLABSETTINGS_ENABLE="true" - MM_GITLABSETTINGS_SECRET=OID_SECRET - MM_GITLABSETTINGS_ID=OID_ID - MM_GITLABSETTINGS_AUTHENDPOINT=OID_AUTH_ENDPOINT - MM_GITLABSETTINGS_TOKENENDPOINT=OID_TOKEN_ENDPOINT - MM_GITLABSETTINGS_USERAPIENDPOINT=OID_USERAPI_ENDPOINT - ``` - 3. Encrypt the variables. This can be done with `sops -e sso-creds.env > sso-creds.enc.env` - 4. Remove the unecrypted `sso-creds.env` file. - 5. Add `sso-creds.enc.env` as kubernetes secret `sso-creds-generator.yaml`: - ``` - --- - # SSO configuration - - apiVersion: goabout.com/v1beta1 - kind: SopsSecretGenerator - metadata: - name: sso-secret - disableNameSuffixHash: true - envs: - - sso-creds.enc.env - ``` - 6. Kustomize patch clusterinstallation.yaml with keyloak settings: - ``` - apiVersion: mattermost.com/v1alpha1 - kind: ClusterInstallation - metadata: - name: chat - spec: - mattermostEnv: - # Keycloak Settings - - name: MM_GITLABSETTINGS_ENABLE - valueFrom: - secretKeyRef: - name: sso-secret - key: MM_GITLABSETTINGS_ENABLE - - name: MM_GITLABSETTINGS_SECRET - valueFrom: - secretKeyRef: - name: sso-secret - key: MM_GITLABSETTINGS_SECRET - - name: MM_GITLABSETTINGS_ID - valueFrom: - secretKeyRef: - name: sso-secret - key: MM_GITLABSETTINGS_ID - - name: MM_GITLABSETTINGS_ID - valueFrom: - secretKeyRef: - name: sso-secret - key: MM_GITLABSETTINGS_ID - - name: MM_GITLABSETTINGS_AUTHENDPOINT - valueFrom: - secretKeyRef: - name: sso-secret - key: MM_GITLABSETTINGS_AUTHENDPOINT - - name: MM_GITLABSETTINGS_TOKENENDPOINT - valueFrom: - secretKeyRef: - name: sso-secret - key: MM_GITLABSETTINGS_TOKENENDPOINT - - name: MM_GITLABSETTINGS_USERAPIENDPOINT - valueFrom: - secretKeyRef: - name: sso-secret - key: MM_GITLABSETTINGS_USERAPIENDPOINT - ``` - In Kustomization.yaml - ``` - patchesStrategicMerge: - - clusterinstallation.yaml - ``` -Mattermost is now configured to use keycloak for SSO. Any baby-yoda realm users created from the keycloak Admin Console will need -a mattermostid attribute added to their user. Users who register throuh an invite link or with a CAC will automatically had this -id generated. +## Role Based Authentication -Add mattermostid to user - 1. Login to keycloak Admin Console with the master realm user created above - 1. Go to the baby-yoda realm - 1. Go to the users section and edit the user you created in the baby-yoda realm - 1. Go to the Attributes tab - 1. In the bottom row type `mattermostid` in the key and a random number in the `value` field. - 1. Click Add. +Role based authentication can be configured as long as you are on an enterprise version. -This mattermostid needs to be unique per user, so it's a bad idea to generate these by hand. The registration process will -automatically generate these for users, but in the case that you generated a test user it can be handy to add a mattermostid. \ No newline at end of file +Follow the steps in [this tutorial](https://docs.mattermost.com/deployment/advanced-permissions.html) to customize the permissions given to users. In general permissions can be edited under the "System Console -> User Management -> Permissions". Users should be created by default under the "Member" group, except for the first user to sign up or login. diff --git a/docs/readme.md b/docs/readme.md deleted file mode 100644 index f2b00f0f1381cec8abffd5e80d9c1acd2bb88059..0000000000000000000000000000000000000000 --- a/docs/readme.md +++ /dev/null @@ -1,119 +0,0 @@ -# Mattermost - -Mattermost is the primary collaboration tool used in the DSOP pipeline. More information on the application can be found [here.](https://mattermost.org/) - -## Application Pre-requisites - -* kubectl - -## Getting Started - -To deploy Mattermost, clone the repository and run: - -`` -git clone https://repo1.dsop.io/platform-one/apps/mattermost.git -`` - -`` -cd app/monitoring/prometheus -`` - -``` -kubectl apply -k . -``` -## The image repo has been changed to Iron Bamk - -You will need to patch the mattermost-operator to support your Iron Bank secrets. - -Put your Iron bank secrets under apps/common/dev. You will need generators for both registry and repo secrets. - -Patch the matermost operator: - -```yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: mattermost-operator -# Adding common secrets for harbor images -imagePullSecrets: - - name: your-repo-creds - - name: your-registry-read-creds - ``` - -## Metrics in Mattermost - -### Prometheus Metrics - -The list of metrics collected by prometheus for mattermost: - -() - -NOTE: Current implementation provides only standard GO metrics - -To enable prometheus metrics in Mattermost: -`` -cd app/monitoring/prometheus -`` -`` -kubectl apply -k . -`` - -## Logging - -### Pre-requisites - -mattermost is deployed - -ECK/Fluentd is deployed - -### Kibana - -1. Login to Kibana - username: elastic - Password : -
Password can be obtained by querying -`kubectl get secret elasticsearch-es-elastic-user -n elastic -o yaml ` -
-2. Create Index by selecting Management icon from the left menu and clicking Index patterns under Kibana.
-In the Create Index patterns and click create index pattern. - - In the the next step Click on the dropdown and select "@timestamp" -
-3. For Search click on Discovery from the side menu. -
- -4. In KQL textbox enter the field of interest for eg: "kubernets.namespace.name : mattermost*" -
- -5. Click Refresh/Update - -NOTE: Default indexpattern is "mattermost*" and this may change in future. Check the available index name - -## Applicaiton specific logging - -1. Create a mattermost user (if SSO isn't configured) - -The sysadmin has to be created. The following steps will create a user and prompte the user to sys-admin. - -``kubectl get pods -n mattermost`` - -2. Pick one of the chat pods. - -``chat-68755f7ffb-``*xxxx*``1/1 Running 0 3h12m`` - -3. Create a user. The e-mail address needs to be one of the approved domains. - -``fbi.gov, dc3.mil, mail.mil, us.af.mil, afwerx.af.mil, diu.mil, usmc.mil, us.army.mil, us.navy.mil, navy.mil, kr.af.mil, niwc.navy.mil, spawar.navy.mil, afit.edu, sco.mil, nsa.gov, darpa.mil, pacom.mil, socom.mil, mitre.org, aero.org, mda.mil, nrl.navy.mil, auab.afcent.af.mil, adab.afcent.af.mil, dau.edu, AZAB.AFCENT.AF.MIL, afcent.af.mil, deployed.af.mil, sd.mil, whmo.mil, hpc.mil, dren.mil, jhuapl.edu, diux.mil, jsf.mi`` - -To create a user: -``kubectl exec chat-68755f7ffb-xxxx -n mattermost -- mattermost user create --email randomadmin@us.af.mil --username randomguy --password P@ssw0rdclear`` - -Remember to change the password when logging into ``https://chat.fenses.dsop.io`` . - -4. Promote the user to system admin: - -``kubectl exec chat-68755f7ffb-xxxx -n mattermost -- mattermost roles system_admin randomguy`` - -Using the userid from the admin user, verify events in the kibana mattermost query. User IC can be found under User Management -> Users - -In kibana, query "log : userId" to track all user activities. diff --git a/image/Dockerfile b/image/Dockerfile deleted file mode 100644 index f53f3e55b33ec2fd3f4a38dc9d565bcc26454696..0000000000000000000000000000000000000000 --- a/image/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM registry1.dsop.io/ironbank/opensource/mattermost/mattermost:5.27.0 - -COPY --chown=mattermost:mattermost en.json /mattermost/client/i18n/en.json -COPY --chown=mattermost:mattermost root.html /mattermost/client/root.html -COPY --chown=mattermost:mattermost p1-bg.jpg /mattermost/client/images/p1-bg.jpg diff --git a/image/en.json b/image/en.json deleted file mode 100644 index a53437e1af980fcb88079128eb0e0cf369ccd6d3..0000000000000000000000000000000000000000 --- a/image/en.json +++ /dev/null @@ -1,3890 +0,0 @@ -{ - "about.buildnumber": "Build Number:", - "about.copyright": "Copyright 2015 - {currentYear} Mattermost, Inc. All rights reserved", - "about.database": "Database:", - "about.date": "Build Date:", - "about.dbversion": "Database Schema Version:", - "about.enterpriseEditione1": "Enterprise Edition", - "about.enterpriseEditionLearn": "Learn more about Enterprise Edition at ", - "about.enterpriseEditionSt": "Modern communication from behind your firewall.", - "about.hash": "Build Hash:", - "about.hashee": "EE Build Hash:", - "about.hashwebapp": "Webapp Build Hash:", - "about.licensed": "Licensed to:", - "about.notice": "Mattermost is made possible by the open source software used in our [server](!https://about.mattermost.com/platform-notice-txt/), [desktop](!https://about.mattermost.com/desktop-notice-txt/) and [mobile](!https://about.mattermost.com/mobile-notice-txt/) apps.", - "about.privacy": "Privacy Policy", - "about.teamEditionLearn": "Join the Mattermost community at ", - "about.teamEditionSt": "All your team communication in one place, instantly searchable and accessible anywhere.", - "about.teamEditiont0": "Team Edition", - "about.teamEditiont1": "Enterprise Edition", - "about.title": "About {appTitle}", - "about.tos": "Terms of Service", - "about.version": "Mattermost Version:", - "access_history.title": "Access History", - "accessibility.button.attachment": "attachment", - "accessibility.button.dialog": "{dialogName} dialog", - "accessibility.button.Info": "Info", - "accessibility.button.Search": "Search", - "accessibility.sections.centerContent": "message list main region", - "accessibility.sections.centerFooter": "message input complimentary region", - "accessibility.sections.channelHeader": "channel header region", - "accessibility.sections.lhsHeader": "team menu region", - "accessibility.sections.lhsList": "channel sidebar region", - "accessibility.sections.rhs": "{regionTitle} complimentary region", - "accessibility.sections.rhsContent": "message details complimentary region", - "accessibility.sections.rhsFooter": "reply input region", - "accessibility.sidebar.types.mention": "mention", - "accessibility.sidebar.types.mentions": "mentions", - "accessibility.sidebar.types.private": "private channel", - "accessibility.sidebar.types.public": "public channel", - "accessibility.sidebar.types.unread": "unread", - "activity_log_modal.android": "Android", - "activity_log_modal.androidNativeApp": "Android Native App", - "activity_log_modal.androidNativeClassicApp": "Android Native Classic App", - "activity_log_modal.desktop": "Native Desktop App", - "activity_log_modal.iphoneNativeApp": "iPhone Native App", - "activity_log_modal.iphoneNativeClassicApp": "iPhone Native Classic App", - "activity_log.activeSessions": "Active Sessions", - "activity_log.browser": "Browser: {browser}", - "activity_log.firstTime": "First time active: {date}, {time}", - "activity_log.lastActivity": "Last activity: {date}, {time}", - "activity_log.logout": "Log Out", - "activity_log.moreInfo": "More info", - "activity_log.os": "OS: {os}", - "activity_log.sessionId": "Session ID: {id}", - "activity_log.sessionsDescription": "Sessions are created when you log in through a new browser on a device. Sessions let you use Mattermost without having to log in again for a time period specified by the System Admin. To end the session sooner, use the 'Log Out' button.", - "add_channels_to_scheme.title": "Add Channels to **Channel Selection** List", - "add_command.autocomplete": "Autocomplete", - "add_command.autocomplete.help": "(Optional) Show your slash command on the autocomplete list when someone types / in the input box.", - "add_command.autocompleteDescription": "Autocomplete Description", - "add_command.autocompleteDescription.help": "(Optional) Describe your slash command for the autocomplete list.", - "add_command.autocompleteDescription.placeholder": "Example: \"Returns search results for patient records\"", - "add_command.autocompleteHint": "Autocomplete Hint", - "add_command.autocompleteHint.help": "(Optional) Specify the arguments associated with your slash command.", - "add_command.autocompleteHint.placeholder": "Example: [Patient Name]", - "add_command.cancel": "Cancel", - "add_command.description": "Description", - "add_command.description.help": "Describe your incoming webhook.", - "add_command.displayName": "Title", - "add_command.displayName.help": "Specify a title, of up to 64 characters, for the slash command settings page.", - "add_command.doneHelp": "Your slash command is set up. The following token will be sent in the outgoing payload. Please use it to verify the request came from your Mattermost team (details at [Slash Commands](!https://docs.mattermost.com/developer/slash-commands.html)).", - "add_command.iconUrl": "Response Icon", - "add_command.iconUrl.help": "(Optional) Enter the URL of a .png or .jpg file to use as the icon when posting responses to this slash command. The file must be at least 128 pixels by 128 pixels. If left blank, your profile picture is used.", - "add_command.iconUrl.placeholder": "https://www.example.com/myicon.png", - "add_command.method": "Request Method", - "add_command.method.get": "GET", - "add_command.method.help": "Specify the type of request, either POST or GET, sent to the endpoint that Mattermost hits to reach your application.", - "add_command.method.post": "POST", - "add_command.save": "Save", - "add_command.saving": "Saving...", - "add_command.token": "**Token**: {token}", - "add_command.trigger": "Command Trigger Word", - "add_command.trigger.help": "Specify a trigger word that is not a built-in command, does not contain spaces, and does not begin with the slash character.", - "add_command.trigger.helpExamples": "Examples: client, employee, patient, weather", - "add_command.trigger.helpReserved": "Reserved: {link}", - "add_command.trigger.helpReservedLinkText": "See built-in slash commands", - "add_command.trigger.placeholder": "Command trigger e.g. \"hello\" not including the slash", - "add_command.triggerInvalidLength": "A trigger word must contain between {min} and {max} characters", - "add_command.triggerInvalidSlash": "A trigger word cannot begin with a /", - "add_command.triggerInvalidSpace": "A trigger word must not contain spaces", - "add_command.triggerRequired": "A trigger word is required", - "add_command.url": "Request URL", - "add_command.url.help": "Specify the callback URL to receive the HTTP POST or GET event request when the slash command is run.", - "add_command.url.placeholder": "Must start with http:// or https://", - "add_command.urlRequired": "A request URL is required", - "add_command.username": "Response Username", - "add_command.username.help": "(Optional) Specify the name to use when posting responses for this slash command. Usernames can be up to 22 characters, and contain lowercase letters, numbers, and the symbols \"-\", \"_\", and \".\". If left blank, your Mattermost username is used.", - "add_command.username.placeholder": "Username", - "add_emoji.cancel": "Cancel", - "add_emoji.header": "Add", - "add_emoji.image": "Image", - "add_emoji.image.button": "Select", - "add_emoji.image.help": "Specify a .gif, .png, or .jpg file for your emoji. The file can be up to 1 MB. The dimensions are resized automatically to 128 pixels by 128 pixels while maintaining the aspect ratio.", - "add_emoji.imageRequired": "An image is required for the emoji", - "add_emoji.name": "Name", - "add_emoji.name.help": "Specify an emoji name that's up to 64 characters. It can contain lowercase letters, numbers, and the symbols '-' and '_'.", - "add_emoji.nameInvalid": "An emoji's name can only contain numbers, letters, and the symbols '-' and '_'.", - "add_emoji.nameRequired": "A name is required for the emoji", - "add_emoji.nameTaken": "This name is already in use by a system emoji. Please choose another name.", - "add_emoji.preview": "Preview", - "add_emoji.preview.sentence": "This is a sentence with {image} in it.", - "add_emoji.save": "Save", - "add_emoji.saving": "Saving...", - "add_groups_to_channel.title": "Add New Groups to {channelName} Channel", - "add_groups_to_team.title": "Add New Groups to {teamName} Team", - "add_incoming_webhook.cancel": "Cancel", - "add_incoming_webhook.channel": "Channel", - "add_incoming_webhook.channel.help": "This is the default public or private channel that receives the webhook payloads. When setting up the webhook, you must belong to the private channel.", - "add_incoming_webhook.channelLocked": "Lock to this channel", - "add_incoming_webhook.channelLocked.help": "If set, the incoming webhook can post only to the selected channel.", - "add_incoming_webhook.channelRequired": "A valid channel is required", - "add_incoming_webhook.description": "Description", - "add_incoming_webhook.description.help": "Describe your incoming webhook.", - "add_incoming_webhook.displayName": "Title", - "add_incoming_webhook.displayName.help": "Specify a title, of up to 64 characters, for the webhook settings page.", - "add_incoming_webhook.doneHelp": "Your incoming webhook is set up. Please send data to the following URL (details at [Incoming Webhooks](!https://docs.mattermost.com/developer/webhooks-incoming.html)).", - "add_incoming_webhook.icon_url": "Profile Picture", - "add_incoming_webhook.icon_url.help": "Enter the URL of a .png or .jpg file for the profile picture of this integration when posting. The file should be at least 128 pixels by 128 pixels. If left blank, the profile picture specified by the webhook creator is used.", - "add_incoming_webhook.save": "Save", - "add_incoming_webhook.saving": "Saving...", - "add_incoming_webhook.url": "**URL**: {url}", - "add_incoming_webhook.username": "Username", - "add_incoming_webhook.username.help": "Specify the username this integration will post as. Usernames must be in lowercase, be up to 22 characters, and can contain numbers and the symbols \"-\", \"_\", and \".\" . If left blank, the name specified by the webhook creator is used.", - "add_oauth_app.callbackUrls.help": "Specify the URIs to which the service redirects users after accepting or denying them authorization to your application, and handles authorization codes or access tokens. It must start with http:// or https://.", - "add_oauth_app.callbackUrlsRequired": "One or more callback URLs are required", - "add_oauth_app.clientId": "**Client ID**: {id}", - "add_oauth_app.clientSecret": "**Client Secret**: {secret}", - "add_oauth_app.description.help": "Describe your OAuth 2.0 application.", - "add_oauth_app.descriptionRequired": "Description for the OAuth 2.0 application is required.", - "add_oauth_app.doneHelp": "Your OAuth 2.0 application is set up. Please use the following Client ID and Client Secret when requesting authorization for your application (details at [oAuth 2.0 Applications](!https://docs.mattermost.com/developer/oauth-2-0-applications.html)).", - "add_oauth_app.doneUrlHelp": "Here are your authorized redirect URLs.", - "add_oauth_app.header": "Add", - "add_oauth_app.homepage.help": "This is the URL for the homepage of the OAuth 2.0 application. Depending on your server configuration, use HTTP or HTTPS in your URL.", - "add_oauth_app.homepageRequired": "Homepage for the OAuth 2.0 application is required.", - "add_oauth_app.icon.help": "(Optional) Specify the URL of the image for your OAuth 2.0 application. Use either HTTP or HTTPS in the URL.", - "add_oauth_app.name.help": "Specify the display name of your OAuth 2.0 application. You can use up to 64 characters.", - "add_oauth_app.nameRequired": "Name for the OAuth 2.0 application is required.", - "add_oauth_app.trusted.help": "If true, the OAuth 2.0 application is considered trusted by the Mattermost server and does not require the user to accept authorization. If false, a window opens to ask the user to accept or deny the authorization.", - "add_oauth_app.url": "**URL(s)**: {url}", - "add_outgoing_webhook.callbackUrls": "Callback URLs (One Per Line)", - "add_outgoing_webhook.callbackUrls.help": "Specify the URL that messages will be sent to. If the URL is private, add it as a {link}.", - "add_outgoing_webhook.callbackUrls.helpLinkText": "trusted internal connection", - "add_outgoing_webhook.callbackUrlsRequired": "One or more callback URLs are required", - "add_outgoing_webhook.cancel": "Cancel", - "add_outgoing_webhook.channel": "Channel", - "add_outgoing_webhook.channel.help": "This field is optional if you specify at least one trigger word. Specify the public channel that delivers the payload to the webhook.", - "add_outgoing_webhook.content_Type": "Content Type", - "add_outgoing_webhook.contentType.help1": "Specify the content type by which to send the request.", - "add_outgoing_webhook.contentType.help2": "For the server to encode the parameters in a URL format in the request body, select application/x-www-form-urlencoded.", - "add_outgoing_webhook.contentType.help3": "For the server to format the request body as JSON, select application/json.", - "add_outgoing_webhook.description": "Description", - "add_outgoing_webhook.description.help": "Describe your outgoing webhook.", - "add_outgoing_webhook.displayName": "Title", - "add_outgoing_webhook.displayName.help": "Specify a title for the webhook settings page. The title can contain up to 64 characters.", - "add_outgoing_webhook.doneHelp": "Your outgoing webhook is set up. The following token will be sent in the outgoing payload. Please use it to verify the request came from your Mattermost team (details at [Outgoing Webhooks](!https://docs.mattermost.com/developer/webhooks-outgoing.html)).", - "add_outgoing_webhook.icon_url": "Profile Picture", - "add_outgoing_webhook.icon_url.help": "Enter the URL of a .png or .jpg file for this integration to use as the profile picture when posting. The file should be at least 128 pixels by 128 pixels. If left blank, the profile picture specified by the webhook creator is used.", - "add_outgoing_webhook.save": "Save", - "add_outgoing_webhook.saving": "Saving...", - "add_outgoing_webhook.token": "**Token**: {token}", - "add_outgoing_webhook.token.message": "Make sure to add this bot account to teams and channels you want it to interact in. See [documentation](https://mattermost.com/pl/default-bot-accounts) to learn more.", - "add_outgoing_webhook.triggerWords": "Trigger Words (One Per Line)", - "add_outgoing_webhook.triggerWords.help": "Specify the trigger words that send an HTTP POST request to your application. If you select only channel, this is optional. The trigger can be for the channel, the outgoing webhook, or both but when you set it for both, the message must match both values.", - "add_outgoing_webhook.triggerWordsOrChannelRequired": "A valid channel or a list of trigger words is required", - "add_outgoing_webhook.triggerWordsTriggerWhen": "Trigger When", - "add_outgoing_webhook.triggerWordsTriggerWhen.help": "Specify when to trigger the outgoing webhook.", - "add_outgoing_webhook.triggerWordsTriggerWhenFullWord": "First word matches a trigger word exactly", - "add_outgoing_webhook.triggerWordsTriggerWhenStartsWith": "First word starts with a trigger word", - "add_outgoing_webhook.username": "Username", - "add_outgoing_webhook.username.help": "Specify the username this integration will post as. Usernames can be up to 22 characters, and contain lowercase letters, numbers and the symbols \"-\", \"_\", and \".\". If left blank, the name specified by the webhook creator is used.", - "add_teams_to_scheme.confirmation.accept": "Yes, Move Team", - "add_teams_to_scheme.confirmation.message": "This team is already selected in another team scheme, are you sure you want to move it to this team scheme?", - "add_teams_to_scheme.confirmation.title": "Team Override Scheme Change?", - "add_teams_to_scheme.title": "Add Teams to **Team Selection** List", - "add_user_to_channel_modal.add": "Add", - "add_user_to_channel_modal.cancel": "Cancel", - "add_user_to_channel_modal.help": "Type to find a channel. Use ↑↓ to browse, ↵ to select, ESC to dismiss.", - "add_user_to_channel_modal.membershipExistsError": "{name} is already a member of that channel", - "add_user_to_channel_modal.title": "Add {name} to a Channel", - "add_users_to_team.title": "Add New Members to {teamName} Team", - "admin.advance.cluster": "High Availability", - "admin.advance.metrics": "Performance Monitoring", - "admin.audits.reload": "Reload User Activity Logs", - "admin.authentication.email": "Email Authentication", - "admin.authentication.gitlab": "P1 SSO", - "admin.authentication.guest_access": "Guest Access (Beta)", - "admin.authentication.ldap": "AD/LDAP", - "admin.authentication.mfa": "Multi-factor Authentication", - "admin.authentication.oauth": "OAuth 2.0", - "admin.authentication.saml": "SAML 2.0", - "admin.authentication.signup": "Signup", - "admin.banner.heading": "Note:", - "admin.bleve.bulkIndexingTitle": "Bulk Indexing:", - "admin.bleve.createJob.help": "All users, channels and posts in the database will be indexed from oldest to newest. Bleve is available during indexing but search results may be incomplete until the indexing job is complete.", - "admin.bleve.createJob.title": "Index Now", - "admin.bleve.enableAutocompleteDescription": "Requires a successful connection to the Bleve server. When true, Bleve will be used for all autocompletion queries on users and channels using the latest index. Autocompletion results may be incomplete until a bulk index of the existing users and channels database is finished. When false, database autocomplete is used.", - "admin.bleve.enableAutocompleteTitle": "Enable Bleve for autocomplete queries:", - "admin.bleve.enableIndexingDescription": "When true, indexing of new posts occurs automatically. Search queries will use database search until \"Enable Bleve for search queries\" is enabled. {documentationLink}", - "admin.bleve.enableIndexingDescription.documentationLinkText": "Learn more about Bleve in our documentation.", - "admin.bleve.enableIndexingTitle": "Enable Bleve Indexing:", - "admin.bleve.enableSearchingDescription": "Requires a successful connection to the Bleve server. When true, Bleve will be used for all search queries using the latest index. Search results may be incomplete until a bulk index of the existing post database is finished. When false, database search is used.", - "admin.bleve.enableSearchingTitle": "Enable Bleve for search queries:", - "admin.bleve.indexDirDescription": "Directory path to use for store bleve indexes.", - "admin.bleve.indexDirTitle": "IndexDir:", - "admin.bleve.percentComplete": "{percent}% Complete", - "admin.bleve.purgeIndexesButton": "Purge Index", - "admin.bleve.purgeIndexesButton.error": "Failed to purge indexes: {error}", - "admin.bleve.purgeIndexesButton.label": "Purge Indexes:", - "admin.bleve.purgeIndexesButton.success": "Indexes purged successfully.", - "admin.bleve.purgeIndexesHelpText": "Purging will entirely remove the indexes on the Bleve server. Search results may be incomplete until a bulk index of the existing database is rebuilt.", - "admin.bleve.title": "Bleve", - "admin.channel_settings.channel_detail.channel_configuration": "Channel Configuration", - "admin.channel_settings.channel_detail.channelName": "**Name**", - "admin.channel_settings.channel_detail.channelTeam": "**Team**", - "admin.channel_settings.channel_detail.groupsDescription": "Select groups to be added to this channel.", - "admin.channel_settings.channel_detail.groupsTitle": "Groups", - "admin.channel_settings.channel_detail.manageDescription": "Choose between inviting members manually or syncing members automatically from groups.", - "admin.channel_settings.channel_detail.manageTitle": "Channel Management", - "admin.channel_settings.channel_detail.membersDescription": "A list of users who are currently in the channel right now", - "admin.channel_settings.channel_detail.membersTitle": "Members", - "admin.channel_settings.channel_detail.profileDescription": "Summary of the channel, including the channel name.", - "admin.channel_settings.channel_detail.profileTitle": "Channel Profile", - "admin.channel_settings.channel_detail.syncedGroupsDescription": "Add and remove channel members based on their group membership.", - "admin.channel_settings.channel_detail.syncedGroupsTitle": "Synced Groups", - "admin.channel_settings.channel_details.add_group": "Add Group", - "admin.channel_settings.channel_details.isDefaultDescr": "This default channel cannot be converted into a private channel.", - "admin.channel_settings.channel_details.isPublic": "Public channel or private channel", - "admin.channel_settings.channel_details.isPublicDescr": "If `public` the channel is discoverable and any user can join, or if `private` invitations are required. Toggle to convert public channels to private. When Group Sync is enabled, private channels cannot be converted to public.", - "admin.channel_settings.channel_details.syncGroupMembers": "Sync Group Members", - "admin.channel_settings.channel_details.syncGroupMembersDescr": "When enabled, adding and removing users from groups will add or remove them from this channel. The only way of inviting members to this channel is by adding the groups they belong to. [Learn More](!https://www.mattermost.com/pl/default-ldap-group-constrained-team-channel.html)", - "admin.channel_settings.channel_list.managementHeader": "Management", - "admin.channel_settings.channel_list.nameHeader": "Name", - "admin.channel_settings.channel_list.no_channels_found": "No channels found", - "admin.channel_settings.channel_list.teamHeader": "Team", - "admin.channel_settings.channel_moderation.channelMentions": "Channel Mentions", - "admin.channel_settings.channel_moderation.channelMentions.disabledBoth": "Channel mentions for members and guests are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.channelMentions.disabledBothDueToCreatePosts": "Guests and members can not use channel mentions without the ability to create posts.", - "admin.channel_settings.channel_moderation.channelMentions.disabledGuest": "Channel mentions for guests are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.channelMentions.disabledGuestsDueToCreatePosts": "Guests can not use channel mentions without the ability to create posts.", - "admin.channel_settings.channel_moderation.channelMentions.disabledMember": "Channel mentions for members are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.channelMentions.disabledMemberDueToCreatePosts": "Members can not use channel mentions without the ability to create posts.", - "admin.channel_settings.channel_moderation.channelMentionsDesc": "The ability for members and guests to use @all, @here and @channel.", - "admin.channel_settings.channel_moderation.channelMentionsDescMembers": "The ability for members to use @all, @here and @channel.", - "admin.channel_settings.channel_moderation.createPosts": "Create Posts", - "admin.channel_settings.channel_moderation.createPosts.disabledBoth": "Create posts for members and guests are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.createPosts.disabledGuest": "Create posts for guests are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.createPosts.disabledMember": "Create posts for members are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.createPostsDesc": "The ability for members and guests to create posts in the channel.", - "admin.channel_settings.channel_moderation.createPostsDescMembers": "The ability for members to create posts in the channel.", - "admin.channel_settings.channel_moderation.guests": "Guests", - "admin.channel_settings.channel_moderation.manageMembers": "Manage Members", - "admin.channel_settings.channel_moderation.manageMembers.disabledBoth": "Manage members for members and guests are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.manageMembers.disabledGuest": "Manage members for guests are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.manageMembers.disabledMember": "Manage members for members are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.manageMembersDesc": "The ability for members to add and remove people.", - "admin.channel_settings.channel_moderation.members": "Members", - "admin.channel_settings.channel_moderation.permissions": "Permissions", - "admin.channel_settings.channel_moderation.postReactions": "Post Reactions", - "admin.channel_settings.channel_moderation.postReactions.disabledBoth": "Post reactions for members and guests are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.postReactions.disabledGuest": "Post reactions for guests are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.postReactions.disabledMember": "Post reactions for members are disabled in [{scheme_name}](../permissions/{scheme_link}).", - "admin.channel_settings.channel_moderation.postReactionsDesc": "The ability for members and guests to post reactions.", - "admin.channel_settings.channel_moderation.postReactionsDescMembers": "The ability for members to post reactions.", - "admin.channel_settings.channel_moderation.subtitle": "Manage the actions available to channel members and guests.", - "admin.channel_settings.channel_moderation.subtitleMembers": "Manage the actions available to channel members.", - "admin.channel_settings.channel_moderation.title": "Channel Moderation (Beta)", - "admin.channel_settings.channel_row.configure": "Edit", - "admin.channel_settings.description": "Manage channel settings.", - "admin.channel_settings.groupsPageTitle": "{siteName} Channels", - "admin.channel_settings.title": "Channels", - "admin.cluster.ClusterName": "Cluster Name:", - "admin.cluster.ClusterNameDesc": "The cluster to join by name. Only nodes with the same cluster name will join together. This is to support Blue-Green deployments or staging pointing to the same database.", - "admin.cluster.ClusterNameEx": "E.g.: \"Production\" or \"Staging\"", - "admin.cluster.enableDescription": "When true, Mattermost will run in High Availability mode. Please see [documentation](!http://docs.mattermost.com/deployment/cluster.html) to learn more about configuring High Availability for Mattermost.", - "admin.cluster.enableTitle": "Enable High Availability Mode:", - "admin.cluster.GossipPort": "Gossip Port:", - "admin.cluster.GossipPortDesc": "The port used for the gossip protocol. Both UDP and TCP should be allowed on this port.", - "admin.cluster.GossipPortEx": "E.g.: \"8074\"", - "admin.cluster.loadedFrom": "This configuration file was loaded from Node ID {clusterId}. Please see the Troubleshooting Guide in our [documentation](!http://docs.mattermost.com/deployment/cluster.html) if you are accessing the System Console through a load balancer and experiencing issues.", - "admin.cluster.noteDescription": "Changing properties in this section will require a server restart before taking effect.", - "admin.cluster.OverrideHostname": "Override Hostname:", - "admin.cluster.OverrideHostnameDesc": "The default value of will attempt to get the Hostname from the OS or use the IP Address. You can override the hostname of this server with this property. It is not recommended to override the Hostname unless needed. This property can also be set to a specific IP Address if needed.", - "admin.cluster.OverrideHostnameEx": "E.g.: \"app-server-01\"", - "admin.cluster.should_not_change": "WARNING: These settings may not sync with the other servers in the cluster. High Availability inter-node communication will not start until you modify the config.json to be identical on all servers and restart Mattermost. Please see the [documentation](!http://docs.mattermost.com/deployment/cluster.html) on how to add or remove a server from the cluster. If you are accessing the System Console through a load balancer and experiencing issues, please see the Troubleshooting Guide in our [documentation](!http://docs.mattermost.com/deployment/cluster.html).", - "admin.cluster.status_table.config_hash": "Config File MD5", - "admin.cluster.status_table.hostname": "Hostname", - "admin.cluster.status_table.reload": " Reload Cluster Status", - "admin.cluster.status_table.status": "Status", - "admin.cluster.status_table.url": "Gossip Address", - "admin.cluster.status_table.version": "Version", - "admin.cluster.StreamingPort": "Streaming Port:", - "admin.cluster.StreamingPortDesc": "The port used for streaming data between servers.", - "admin.cluster.StreamingPortEx": "E.g.: \"8075\"", - "admin.cluster.unknown": "unknown", - "admin.cluster.UseExperimentalGossip": "Use Experimental Gossip:", - "admin.cluster.UseExperimentalGossipDesc": "When true, the server will attempt to communicate via the gossip protocol over the gossip port. When false the server will attempt to communicate over the streaming port. When false the gossip port and protocol are still used to determine cluster health.", - "admin.cluster.UseIpAddress": "Use IP Address:", - "admin.cluster.UseIpAddressDesc": "When true, the cluster will attempt to communicate via IP Address vs using the hostname.", - "admin.compliance_reports.desc": "Job Name:", - "admin.compliance_reports.desc_placeholder": "E.g. \"Audit 445 for HR\"", - "admin.compliance_reports.emails": "Emails:", - "admin.compliance_reports.emails_placeholder": "E.g. \"bill@example.com, bob@example.com\"", - "admin.compliance_reports.from": "From:", - "admin.compliance_reports.from_placeholder": "E.g. \"2016-03-11\"", - "admin.compliance_reports.keywords": "Keywords:", - "admin.compliance_reports.keywords_placeholder": "E.g. \"shorting stock\"", - "admin.compliance_reports.reload": "Reload Completed Compliance Reports", - "admin.compliance_reports.run": "Run Compliance Report", - "admin.compliance_reports.title": "Compliance Reports", - "admin.compliance_reports.to": "To:", - "admin.compliance_reports.to_placeholder": "E.g. \"2016-03-15\"", - "admin.compliance_table.desc": "Description", - "admin.compliance_table.download": "Download", - "admin.compliance_table.failed": "Failed", - "admin.compliance_table.files": "Files", - "admin.compliance_table.params": "Params", - "admin.compliance_table.pending": "Pending", - "admin.compliance_table.records": "Records", - "admin.compliance_table.status": "Status", - "admin.compliance_table.success": "Success", - "admin.compliance_table.timestamp": "Timestamp", - "admin.compliance_table.type": "Type", - "admin.compliance_table.userId": "Requested By", - "admin.compliance.complianceMonitoring": "Compliance Monitoring", - "admin.compliance.directoryDescription": "Directory to which compliance reports are written. If blank, will be set to ./data/.", - "admin.compliance.directoryExample": "E.g.: \"./data/\"", - "admin.compliance.directoryTitle": "Compliance Report Directory:", - "admin.compliance.enableDailyDesc": "When true, Mattermost will generate a daily compliance report.", - "admin.compliance.enableDailyTitle": "Enable Daily Report:", - "admin.compliance.enableDesc": "When true, Mattermost allows compliance reporting from the **Compliance and Auditing** tab. See [documentation](!https://docs.mattermost.com/administration/compliance.html) to learn more.", - "admin.compliance.enableTitle": "Enable Compliance Reporting:", - "admin.compliance.newComplianceExportBanner": "This feature is replaced by a new [Compliance Export]({siteURL}/admin_console/compliance/export) feature, and will be removed in a future release. We recommend migrating to the new system.", - "admin.complianceExport.createJob.help": "Initiates a Compliance Export job immediately.", - "admin.complianceExport.createJob.title": "Run Compliance Export Job Now", - "admin.complianceExport.exportFormat.actiance": "Actiance XML", - "admin.complianceExport.exportFormat.csv": "CSV", - "admin.complianceExport.exportFormat.description": "Format of the compliance export. Corresponds to the system that you want to import the data into.\n \nFor Actiance XML, compliance export files are written to the \"exports\" subdirectory of the configured [Local Storage Directory]({siteURL}/admin_console/environment/file_storage). For Global Relay EML, they are emailed to the configured email address.", - "admin.complianceExport.exportFormat.globalrelay": "Global Relay EML", - "admin.complianceExport.exportFormat.title": "Export Format:", - "admin.complianceExport.exportJobStartTime.description": "Set the start time of the daily scheduled compliance export job. Choose a time when fewer people are using your system. Must be a 24-hour time stamp in the form HH:MM.", - "admin.complianceExport.exportJobStartTime.example": "E.g.: \"02:00\"", - "admin.complianceExport.exportJobStartTime.title": "Compliance Export time:", - "admin.complianceExport.globalRelayCustomerType.a10.description": "A10/Type 10", - "admin.complianceExport.globalRelayCustomerType.a9.description": "A9/Type 9", - "admin.complianceExport.globalRelayCustomerType.description": "Type of Global Relay customer account your organization has.", - "admin.complianceExport.globalRelayCustomerType.title": "Global Relay Customer Account:", - "admin.complianceExport.globalRelayEmailAddress.description": "The email address your Global Relay server monitors for incoming compliance exports.", - "admin.complianceExport.globalRelayEmailAddress.example": "E.g.: \"globalrelay@mattermost.com\"", - "admin.complianceExport.globalRelayEmailAddress.title": "Global Relay Email Address:", - "admin.complianceExport.globalRelaySmtpPassword.description": "The password associated with the SMTP username.", - "admin.complianceExport.globalRelaySmtpPassword.example": "E.g.: \"globalRelayPassword\"", - "admin.complianceExport.globalRelaySmtpPassword.title": "Global Relay SMTP Password:", - "admin.complianceExport.globalRelaySmtpUsername.description": "The username for authenticating to the Global Relay SMTP server.", - "admin.complianceExport.globalRelaySmtpUsername.example": "E.g.: \"globalRelayUser\"", - "admin.complianceExport.globalRelaySmtpUsername.title": "Global Relay SMTP Username:", - "admin.complianceExport.messagesExportedCount": "{count} messages exported.", - "admin.complianceExport.title": "Compliance Export (Beta)", - "admin.complianceExport.warningCount": "{count} warning(s) encountered, see warning.txt for details", - "admin.complianceMonitoring.userActivityLogsTitle": "User Activity Logs", - "admin.connectionSecurityNone": "None", - "admin.connectionSecurityNoneDescription": "Mattermost will connect over an insecure connection.", - "admin.connectionSecurityStart": "STARTTLS", - "admin.connectionSecurityStartDescription": "Takes an existing insecure connection and attempts to upgrade it to a secure connection using TLS.", - "admin.connectionSecurityTitle": "Connection Security:", - "admin.connectionSecurityTls": "TLS", - "admin.connectionSecurityTlsDescription": "Encrypts the communication between Mattermost and your server.", - "admin.customization.androidAppDownloadLinkDesc": "Add a link to download the Android app. Users who access the site on a mobile web browser will be prompted with a page giving them the option to download the app. Leave this field blank to prevent the page from appearing.", - "admin.customization.androidAppDownloadLinkTitle": "Android App Download Link:", - "admin.customization.announcement.allowBannerDismissalDesc": "When true, users can dismiss the banner until its next update. When false, the banner is permanently visible until it is turned off by the System Admin.", - "admin.customization.announcement.allowBannerDismissalTitle": "Allow Banner Dismissal:", - "admin.customization.announcement.bannerColorTitle": "Banner Color:", - "admin.customization.announcement.bannerTextColorTitle": "Banner Text Color:", - "admin.customization.announcement.bannerTextDesc": "Text that will appear in the announcement banner.", - "admin.customization.announcement.bannerTextTitle": "Banner Text:", - "admin.customization.announcement.enableBannerDesc": "Enable an announcement banner across all teams.", - "admin.customization.announcement.enableBannerTitle": "Enable Announcement Banner:", - "admin.customization.appDownloadLinkDesc": "Add a link to a download page for the Mattermost apps. When a link is present, an option to \"Download Mattermost Apps\" will be added in the Main Menu so users can find the download page. Leave this field blank to hide the option from the Main Menu.", - "admin.customization.appDownloadLinkTitle": "Mattermost Apps Download Page Link:", - "admin.customization.customUrlSchemes": "Custom URL Schemes:", - "admin.customization.customUrlSchemesDesc": "Allows message text to link if it begins with any of the comma-separated URL schemes listed. By default, the following schemes will create links: \"http\", \"https\", \"ftp\", \"tel\", and \"mailto\".", - "admin.customization.customUrlSchemesPlaceholder": "E.g.: \"git,smtp\"", - "admin.customization.enableCustomEmojiDesc": "Enable users to create custom emoji for use in messages. When enabled, Custom Emoji settings can be accessed by switching to a team and clicking the three dots above the channel sidebar, and selecting \"Custom Emoji\".", - "admin.customization.enableCustomEmojiTitle": "Enable Custom Emoji:", - "admin.customization.enableEmojiPickerDesc": "The emoji picker allows users to select emoji to add as reactions or use in messages. Enabling the emoji picker with a large number of custom emoji may slow down performance.", - "admin.customization.enableEmojiPickerTitle": "Enable Emoji Picker:", - "admin.customization.enableGifPickerDesc": "Allow users to select GIFs from the emoji picker via a Gfycat integration.", - "admin.customization.enableGifPickerTitle": "Enable GIF Picker:", - "admin.customization.enableLatexDesc": "Enable rendering of Latex code. If false, Latex code will be highlighted only.", - "admin.customization.enableLatexTitle": "Enable Latex Rendering:", - "admin.customization.enableLinkPreviewsDesc": "Display a preview of website content, image links and YouTube links below the message when available. The server must be connected to the internet and have access through the firewall (if applicable) to the websites from which previews are expected. Users can disable these previews from Account Settings > Display > Website Link Previews.", - "admin.customization.enableLinkPreviewsTitle": "Enable Link Previews:", - "admin.customization.enableSVGsDesc": "Enable previews for SVG file attachments and allow them to appear in messages.", - "admin.customization.enableSVGsTitle": "Enable SVGs:", - "admin.customization.gfycatApiKey": "Gfycat API Key:", - "admin.customization.gfycatApiKeyDescription": "Request an API key at [https://developers.gfycat.com/signup/#](!https://developers.gfycat.com/signup/#). Enter the client ID you receive via email to this field. When blank, uses the default API key provided by Gfycat.", - "admin.customization.gfycatApiSecret": "Gfycat API Secret:", - "admin.customization.gfycatApiSecretDescription": "The API secret generated by Gfycat for your API key. When blank, uses the default API secret provided by Gfycat.", - "admin.customization.iosAppDownloadLinkDesc": "Add a link to download the iOS app. Users who access the site on a mobile web browser will be prompted with a page giving them the option to download the app. Leave this field blank to prevent the page from appearing.", - "admin.customization.iosAppDownloadLinkTitle": "iOS App Download Link:", - "admin.data_grid.empty": "No items found", - "admin.data_grid.loading": "Loading", - "admin.data_grid.paginatorCount": "{startCount, number} - {endCount, number} of {total, number}", - "admin.data_retention.confirmChangesModal.clarification": "Once deleted, messages and files cannot be retrieved.", - "admin.data_retention.confirmChangesModal.confirm": "Confirm Settings", - "admin.data_retention.confirmChangesModal.description": "Are you sure you want to apply the following data retention policy:", - "admin.data_retention.confirmChangesModal.description.itemFileDeletion": "All files will be permanently deleted after {days} days.", - "admin.data_retention.confirmChangesModal.description.itemFileIndefinite": "All files will be retained indefinitely.", - "admin.data_retention.confirmChangesModal.description.itemMessageDeletion": "All messages will be permanently deleted after {days} days.", - "admin.data_retention.confirmChangesModal.description.itemMessageIndefinite": "All messages will be retained indefinitely.", - "admin.data_retention.confirmChangesModal.title": "Confirm data retention policy", - "admin.data_retention.createJob.help": "Initiates a Data Retention deletion job immediately.", - "admin.data_retention.createJob.title": "Run Deletion Job Now", - "admin.data_retention.deletionJobStartTime.description": "Set the start time of the daily scheduled data retention job. Choose a time when fewer people are using your system. Must be a 24-hour time stamp in the form HH:MM.", - "admin.data_retention.deletionJobStartTime.example": "E.g.: \"02:00\"", - "admin.data_retention.deletionJobStartTime.title": "Data Deletion Time:", - "admin.data_retention.enableFileDeletion.description": "Set how long Mattermost keeps file uploads in channels and direct messages.", - "admin.data_retention.enableFileDeletion.title": "File Retention:", - "admin.data_retention.enableMessageDeletion.description": "Set how long Mattermost keeps messages in channels and direct messages.", - "admin.data_retention.enableMessageDeletion.title": "Message Retention:", - "admin.data_retention.fileRetentionDays.description": "Set how many days file uploads are kept in Mattermost. Files older than the duration you set will be deleted nightly. The minimum time is one day.", - "admin.data_retention.fileRetentionDays.example": "E.g.: \"60\"", - "admin.data_retention.keepFilesForTime": "Keep files for a set amount of time", - "admin.data_retention.keepFilesIndefinitely": "Keep all files indefinitely", - "admin.data_retention.keepMessageForTime": "Keep messages for a set amount of time", - "admin.data_retention.keepMessagesIndefinitely": "Keep all messages indefinitely", - "admin.data_retention.messageRetentionDays.description": "Set how many days messages are kept in Mattermost. Messages, including file attachments older than the duration you set will be deleted nightly. The minimum time is one day.", - "admin.data_retention.messageRetentionDays.example": "E.g.: \"60\"", - "admin.data_retention.note.description": "Caution: Once a message or a file is deleted, the action is irreversible. Please be careful when setting up a custom data retention policy. See {documentationLink} to learn more.", - "admin.data_retention.note.description.documentationLinkText": "documentation", - "admin.data_retention.title": "Data Retention Policy", - "admin.database.title": "Database", - "admin.developer.title": "Developer Settings", - "admin.elasticsearch.bulkIndexingTitle": "Bulk Indexing:", - "admin.elasticsearch.connectionUrlDescription": "The address of the Elasticsearch server. {documentationLink}", - "admin.elasticsearch.connectionUrlExample": "E.g.: \"https://elasticsearch.example.org:9200\"", - "admin.elasticsearch.connectionUrlExample.documentationLinkText": "Please see documentation with server setup instructions.", - "admin.elasticsearch.connectionUrlTitle": "Server Connection Address:", - "admin.elasticsearch.createJob.help": "All users, channels and posts in the database will be indexed from oldest to newest. Elasticsearch is available during indexing but search results may be incomplete until the indexing job is complete.", - "admin.elasticsearch.createJob.title": "Index Now", - "admin.elasticsearch.elasticsearch_test_button": "Test Connection", - "admin.elasticsearch.enableAutocompleteDescription": "Requires a successful connection to the Elasticsearch server. When true, Elasticsearch will be used for all autocompletion queries on users and channels using the latest index. Autocompletion results may be incomplete until a bulk index of the existing users and channels database is finished. When false, database autocomplete is used.", - "admin.elasticsearch.enableAutocompleteTitle": "Enable Elasticsearch for autocomplete queries:", - "admin.elasticsearch.enableIndexingDescription": "When true, indexing of new posts occurs automatically. Search queries will use database search until \"Enable Elasticsearch for search queries\" is enabled. {documentationLink}", - "admin.elasticsearch.enableIndexingDescription.documentationLinkText": "Learn more about Elasticsearch in our documentation.", - "admin.elasticsearch.enableIndexingTitle": "Enable Elasticsearch Indexing:", - "admin.elasticsearch.enableSearchingDescription": "Requires a successful connection to the Elasticsearch server. When true, Elasticsearch will be used for all search queries using the latest index. Search results may be incomplete until a bulk index of the existing post database is finished. When false, database search is used.", - "admin.elasticsearch.enableSearchingTitle": "Enable Elasticsearch for search queries:", - "admin.elasticsearch.password": "E.g.: \"yourpassword\"", - "admin.elasticsearch.passwordDescription": "(Optional) The password to authenticate to the Elasticsearch server.", - "admin.elasticsearch.passwordTitle": "Server Password:", - "admin.elasticsearch.percentComplete": "{percent}% Complete", - "admin.elasticsearch.purgeIndexesButton": "Purge Indexes", - "admin.elasticsearch.purgeIndexesButton.error": "Failed to purge indexes: {error}", - "admin.elasticsearch.purgeIndexesButton.label": "Purge Indexes:", - "admin.elasticsearch.purgeIndexesButton.success": "Indexes purged successfully.", - "admin.elasticsearch.purgeIndexesHelpText": "Purging will entirely remove the indexes on the Elasticsearch server. Search results may be incomplete until a bulk index of the existing database is rebuilt.", - "admin.elasticsearch.skipTLSVerificationDescription": "When true, Mattermost will not require the Elasticsearch certificate to be signed by a trusted Certificate Authority.", - "admin.elasticsearch.skipTLSVerificationTitle": "Skip TLS Verification:", - "admin.elasticsearch.sniffDescription": "When true, sniffing finds and connects to all data nodes in your cluster automatically.", - "admin.elasticsearch.sniffTitle": "Enable Cluster Sniffing:", - "admin.elasticsearch.testConfigSuccess": "Test successful. Configuration saved.", - "admin.elasticsearch.testHelpText": "Tests if the Mattermost server can connect to the Elasticsearch server specified. Testing the connection only saves the configuration if the test is successful. See log file for more detailed error messages.", - "admin.elasticsearch.title": "Elasticsearch", - "admin.elasticsearch.usernameDescription": "(Optional) The username to authenticate to the Elasticsearch server.", - "admin.elasticsearch.usernameExample": "E.g.: \"elastic\"", - "admin.elasticsearch.usernameTitle": "Server Username:", - "admin.email.agreeHPNS": " I understand and accept the Mattermost Hosted Push Notification Service [Terms of Service](!https://about.mattermost.com/hpns-terms/) and [Privacy Policy](!https://about.mattermost.com/hpns-privacy/).", - "admin.email.allowEmailSignInDescription": "When true, Mattermost allows users to sign in using their email and password.", - "admin.email.allowEmailSignInTitle": "Enable sign-in with email: ", - "admin.email.allowSignupDescription": "When true, Mattermost allows account creation using email and password. This value should be false only when you want to limit sign up to a single sign-on service like AD/LDAP, SAML or P1 SSO.", - "admin.email.allowSignupTitle": "Enable account creation with email: ", - "admin.email.allowUsernameSignInDescription": "When true, users with email login can sign in using their username and password. This setting does not affect AD/LDAP login.", - "admin.email.allowUsernameSignInTitle": "Enable sign-in with username: ", - "admin.email.easHelp": "Learn more about compiling and deploying your own mobile apps from an [Enterprise App Store](!https://about.mattermost.com/default-enterprise-app-store).", - "admin.email.mhpns": "Use HPNS connection with uptime SLA to send notifications to iOS and Android apps", - "admin.email.mhpnsHelp": "Download [Mattermost iOS app](!https://about.mattermost.com/mattermost-ios-app/) from iTunes. Download [Mattermost Android app](!https://about.mattermost.com/mattermost-android-app/) from Google Play. Learn more about [HPNS](!https://about.mattermost.com/default-hpns/).", - "admin.email.mtpns": "Use TPNS connection to send notifications to iOS and Android apps", - "admin.email.mtpnsHelp": "Download [Mattermost iOS app](!https://about.mattermost.com/mattermost-ios-app/) from iTunes. Download [Mattermost Android app](!https://about.mattermost.com/mattermost-android-app/) from Google Play. Learn more about [TPNS](!https://about.mattermost.com/default-tpns/).", - "admin.email.pushOff": "Do not send push notifications", - "admin.email.pushOffHelp": "Please see [documentation on push notifications](!https://about.mattermost.com/default-mobile-push-notifications/) to learn more about setup options.", - "admin.email.pushServerEx": "E.g.: \"https://push-test.mattermost.com\"", - "admin.email.pushServerTitle": "Push Notification Server:", - "admin.email.pushTitle": "Enable Push Notifications: ", - "admin.email.requireVerificationDescription": "Typically set to true in production. When true, Mattermost requires email verification after account creation prior to allowing login. Developers may set this field to false to skip sending verification emails for faster development.", - "admin.email.requireVerificationTitle": "Require Email Verification: ", - "admin.email.selfPush": "Manually enter Push Notification Service location", - "admin.environment.fileStorage": "File Storage", - "admin.environment.imageProxy": "Image Proxy", - "admin.environment.notifications": "Notifications", - "admin.environment.notifications.contents.full": "Send full message contents", - "admin.environment.notifications.contents.generic": "Send generic description with only sender name", - "admin.environment.notifications.contents.help": "**Send full message contents** - Sender name and channel are included in email notifications. Typically used for compliance reasons if Mattermost contains confidential information and policy dictates it cannot be stored in email.\n **Send generic description with only sender name** - Only the name of the person who sent the message, with no information about channel name or message contents are included in email notifications. Typically used for compliance reasons if Mattermost contains confidential information and policy dictates it cannot be stored in email.", - "admin.environment.notifications.contents.label": "Email Notification Contents:", - "admin.environment.notifications.enable.help": "Typically set to true in production. When true, Mattermost attempts to send email notifications. When false, email invitations and user account setting change emails are still sent as long as the SMTP server is configured. Developers may set this field to false to skip email setup for faster development.", - "admin.environment.notifications.enable.label": "Enable Email Notifications:", - "admin.environment.notifications.enableConfirmNotificationsToChannel.help": "When true, users will be prompted to confirm when posting @channel, @all and group mentions in channels with over five members. When false, no confirmation is required.", - "admin.environment.notifications.enableConfirmNotificationsToChannel.label": "Show @channel and @all and group mention confirmation dialog:", - "admin.environment.notifications.enableEmailBatching.help": "When true, users will have email notifications for multiple direct messages and mentions combined into a single email. Batching will occur at a default interval of 15 minutes, configurable in Account Settings > Notifications.", - "admin.environment.notifications.enableEmailBatching.label": "Enable Email Batching:", - "admin.environment.notifications.enablePreviewModeBanner.help": "When true, the Preview Mode banner is displayed so users are aware that email notifications are disabled. When false, the Preview Mode banner is not displayed to users.", - "admin.environment.notifications.enablePreviewModeBanner.label": "Enable Preview Mode Banner:", - "admin.environment.notifications.feedbackEmail.help": "Email address displayed on email account used when sending notification emails from Mattermost.", - "admin.environment.notifications.feedbackEmail.label": "Notification From Address:", - "admin.environment.notifications.feedbackEmail.placeholder": "Ex: \"mattermost@yourcompany.com\", \"admin@yourcompany.com\"", - "admin.environment.notifications.feedbackOrganization.help": "Organization name and address displayed on email notifications from Mattermost, such as \"© ABC Corporation, 565 Knight Way, Palo Alto, California, 94305, USA\". If the field is left empty, the organization name and address will not be displayed.", - "admin.environment.notifications.feedbackOrganization.label": "Notification Footer Mailing Address:", - "admin.environment.notifications.feedbackOrganization.placeholder": "Ex: \"© ABC Corporation, 565 Knight Way, Palo Alto, California, 94305, USA\"", - "admin.environment.notifications.notificationDisplay.help": "Display name on email account used when sending notification emails from Mattermost.", - "admin.environment.notifications.notificationDisplay.label": "Notification Display Name:", - "admin.environment.notifications.notificationDisplay.placeholder": "Ex: \"Mattermost Notification\", \"System\", \"No-Reply\"", - "admin.environment.notifications.pushContents.full": "Full message content sent in the notification payload", - "admin.environment.notifications.pushContents.generic": "Generic description with sender and channel names", - "admin.environment.notifications.pushContents.genericNoChannel": "Generic description with only sender name", - "admin.environment.notifications.pushContents.help": "**Generic description with only sender name** - Includes only the name of the person who sent the message in push notifications, with no information about channel name or message contents.\n **Generic description with sender and channel names** - Includes the name of the person who sent the message and the channel it was sent in, but not the message contents.\n **Full message content sent in the notification payload** - Includes the message contents in the push notification payload that is relayed through Apple's Push Notification Service (APNS) or Google's Firebase Cloud Messaging (FCM). It is **highly recommended** this option only be used with an \"https\" protocol to encrypt the connection and protect confidential information sent in messages.", - "admin.environment.notifications.pushContents.idLoaded": "Full message content fetched from the server on receipt", - "admin.environment.notifications.pushContents.label": "Push Notification Contents:", - "admin.environment.notifications.pushContents.withIdLoaded.help": "**Generic description with only sender name** - Includes only the name of the person who sent the message in push notifications, with no information about channel name or message contents.\n **Generic description with sender and channel names** - Includes the name of the person who sent the message and the channel it was sent in, but not the message contents.\n **Full message content sent in the notification payload** - Includes the message contents in the push notification payload that is relayed through Apple's Push Notification Service (APNS) or Google's Firebase Cloud Messaging (FCM). It is **highly recommended** this option only be used with an \"https\" protocol to encrypt the connection and protect confidential information sent in messages.\n**Full message content fetched from the server on receipt** - The notification payload relayed through APNS or FCM contains no message content, instead it contains a unique message ID used to fetch message content from the server when a push notification is received by a device. If the server cannot be reached, a generic notification will be displayed.", - "admin.environment.notifications.replyToAddress.help": "Email address used in the Reply-To header when sending notification emails from Mattermost.", - "admin.environment.notifications.replyToAddress.label": "Notification Reply-To Address:", - "admin.environment.notifications.replyToAddress.placeholder": "Ex: \"mattermost@yourcompany.com\", \"admin@yourcompany.com\"", - "admin.environment.pushNotificationServer": "Push Notification Server", - "admin.environment.smtp": "SMTP", - "admin.environment.smtp.connectionSecurity.option.none": "None", - "admin.environment.smtp.connectionSecurity.option.starttls": "STARTTLS", - "admin.environment.smtp.connectionSecurity.option.tls": "TLS (Recommended)", - "admin.environment.smtp.connectionSecurity.title": "Connection Security:", - "admin.environment.smtp.connectionSmtpTest": "Test Connection", - "admin.environment.smtp.enableSecurityFixAlert.description": "When true, System Administrators are notified by email if a relevant security fix alert has been announced in the last 12 hours. Requires email to be enabled.", - "admin.environment.smtp.enableSecurityFixAlert.title": "Enable Security Alerts:", - "admin.environment.smtp.skipServerCertificateVerification.description": "When true, Mattermost will not verify the email server certificate.", - "admin.environment.smtp.skipServerCertificateVerification.title": "Skip Server Certificate Verification:", - "admin.environment.smtp.smtpAuth.description": "When true, SMTP Authentication is enabled.", - "admin.environment.smtp.smtpAuth.title": "Enable SMTP Authentication:", - "admin.environment.smtp.smtpFail": "Connection unsuccessful: {error}", - "admin.environment.smtp.smtpPassword.description": "Obtain this credential from administrator setting up your email server.", - "admin.environment.smtp.smtpPassword.placeholder": "Ex: \"yourpassword\", \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"", - "admin.environment.smtp.smtpPassword.title": "SMTP Server Password:", - "admin.environment.smtp.smtpPort.description": "Port of SMTP email server.", - "admin.environment.smtp.smtpPort.placeholder": "Ex: \"25\", \"465\", \"587\"", - "admin.environment.smtp.smtpPort.title": "SMTP Server Port:", - "admin.environment.smtp.smtpServer.description": "Location of SMTP email server.", - "admin.environment.smtp.smtpServer.placeholder": "Ex: \"smtp.yourcompany.com\", \"email-smtp.us-east-1.amazonaws.com\"", - "admin.environment.smtp.smtpServer.title": "SMTP Server:", - "admin.environment.smtp.smtpSuccess": "No errors were reported while sending an email. Please check your inbox to make sure.", - "admin.environment.smtp.smtpUsername.description": "Obtain this credential from administrator setting up your email server.", - "admin.environment.smtp.smtpUsername.placeholder": "Ex: \"admin@yourcompany.com\", \"AKIADTOVBGERKLCBV\"", - "admin.environment.smtp.smtpUsername.title": "SMTP Server Username:", - "admin.environment.smtp.testing": "Testing...", - "admin.environment.webServer": "Web Server", - "admin.experimental.allowCustomThemes.desc": "Enables the **Display > Theme > Custom Theme** section in Account Settings.", - "admin.experimental.allowCustomThemes.title": "Allow Custom Themes:", - "admin.experimental.clientSideCertCheck.desc": "When **primary**, after the client side certificate is verified, user’s email is retrieved from the certificate and is used to log in without a password. When **secondary**, after the client side certificate is verified, user’s email is retrieved from the certificate and matched against the one supplied by the user. If they match, the user logs in with regular email/password credentials.", - "admin.experimental.clientSideCertCheck.title": "Client-Side Certification Login Method:", - "admin.experimental.clientSideCertEnable.desc": "Enables client-side certification for your Mattermost server. See [documentation](!https://docs.mattermost.com/deployment/certificate-based-authentication.html) to learn more.", - "admin.experimental.clientSideCertEnable.title": "Enable Client-Side Certification:", - "admin.experimental.closeUnusedDirectMessages.desc": "When true, direct message conversations with no activity for 7 days will be hidden from the sidebar. When false, conversations remain in the sidebar until they are manually closed.", - "admin.experimental.closeUnusedDirectMessages.title": "Autoclose Direct Messages in Sidebar:", - "admin.experimental.defaultTheme.desc": "Set a default theme that applies to all new users on the system.", - "admin.experimental.defaultTheme.title": "Default Theme:", - "admin.experimental.emailBatchingBufferSize.desc": "Specify the maximum number of notifications batched into a single email.", - "admin.experimental.emailBatchingBufferSize.example": "E.g.: \"256\"", - "admin.experimental.emailBatchingBufferSize.title": "Email Batching Buffer Size:", - "admin.experimental.emailBatchingInterval.desc": "Specify the maximum frequency, in seconds, which the batching job checks for new notifications. Longer batching intervals will increase performance.", - "admin.experimental.emailBatchingInterval.example": "E.g.: \"30\"", - "admin.experimental.emailBatchingInterval.title": "Email Batching Interval:", - "admin.experimental.emailSettingsLoginButtonBorderColor.desc": "Specify the color of the email login button border for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.", - "admin.experimental.emailSettingsLoginButtonBorderColor.title": "Email Login Button Border Color:", - "admin.experimental.emailSettingsLoginButtonColor.desc": "Specify the color of the email login button for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.", - "admin.experimental.emailSettingsLoginButtonColor.title": "Email Login Button Color:", - "admin.experimental.emailSettingsLoginButtonTextColor.desc": "Specify the color of the email login button text for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.", - "admin.experimental.emailSettingsLoginButtonTextColor.title": "Email Login Button Text Color:", - "admin.experimental.enableChannelViewedMessages.desc": "This setting determines whether `channel_viewed` WebSocket events are sent, which synchronize unread notifications across clients and devices. Disabling the setting in larger deployments may improve server performance.", - "admin.experimental.enableChannelViewedMessages.title": "Enable Channel Viewed WebSocket Messages:", - "admin.experimental.enablePreviewFeatures.desc": "When true, preview features can be enabled from **Account Settings > Advanced > Preview pre-release features**. When false, disables and hides preview features from **Account Settings > Advanced > Preview pre-release features**.", - "admin.experimental.enablePreviewFeatures.title": "Enable Preview Features:", - "admin.experimental.enableThemeSelection.desc": "Enables the **Display > Theme** tab in Account Settings so users can select their theme.", - "admin.experimental.enableThemeSelection.title": "Enable Theme Selection:", - "admin.experimental.enableTutorial.desc": "When true, users are prompted with a tutorial when they open Mattermost for the first time after account creation. When false, the tutorial is disabled, and users are placed in Town Square when they open Mattermost for the first time after account creation.", - "admin.experimental.enableTutorial.title": "Enable Tutorial:", - "admin.experimental.enableUserDeactivation.desc": "When true, users may deactivate their own account from **Account Settings > Advanced**. If a user deactivates their own account, they will get an email notification confirming they were deactivated. When false, users may not deactivate their own account.", - "admin.experimental.enableUserDeactivation.title": "Enable Account Deactivation:", - "admin.experimental.enableUserTypingMessages.desc": "This setting determines whether \"user is typing...\" messages are displayed below the message box. Disabling the setting in larger deployments may improve server performance.", - "admin.experimental.enableUserTypingMessages.title": "Enable User Typing Messages:", - "admin.experimental.enableXToLeaveChannelsFromLHS.desc": "When true, users can leave Public and Private Channels by clicking the “x” beside the channel name. When false, users must use the **Leave Channel** option from the channel menu to leave channels.", - "admin.experimental.enableXToLeaveChannelsFromLHS.title": "Enable X to Leave Channels from Left-Hand Sidebar:", - "admin.experimental.experimentalChannelOrganization.desc": "Enables channel sidebar organization options in **Account Settings > Sidebar > Channel grouping and sorting** including options for grouping unread channels, sorting channels by most recent post and combining all channel types into a single list. These settings are not available if **Account Settings > Sidebar > Experimental Sidebar Features** are enabled.", - "admin.experimental.experimentalChannelOrganization.title": "Channel Grouping and Sorting", - "admin.experimental.experimentalChannelSidebarOrganization.default_off": "Enabled (Default Off)", - "admin.experimental.experimentalChannelSidebarOrganization.default_on": "Enabled (Default On)", - "admin.experimental.experimentalChannelSidebarOrganization.desc": "When enabled, users can access experimental channel sidebar features, including collapsible sections and unreads filtering. If default on, this enabled the new sidebar features by default for all users on this server. Users can disable the features in **Account Settings > Sidebar > Experimental Sidebar Features**. If default off, users must enable the experimental sidebar features in Account Settings. [Learn more](!https://about.mattermost.com/default-sidebar/) or [give us feedback](!https://about.mattermost.com/default-sidebar-survey/)", - "admin.experimental.experimentalChannelSidebarOrganization.disabled": "Disabled", - "admin.experimental.experimentalChannelSidebarOrganization.title": "Experimental Sidebar Features", - "admin.experimental.experimentalEnableAuthenticationTransfer.desc": "When true, users can change their sign-in method to any that is enabled on the server, either via Account Settings or the APIs. When false, Users cannot change their sign-in method, regardless of which authentication options are enabled.", - "admin.experimental.experimentalEnableAuthenticationTransfer.title": "Allow Authentication Transfer:", - "admin.experimental.experimentalEnableAutomaticReplies.desc": "When true, users can enable Automatic Replies in **Account Settings > Notifications**. Users set a custom message that will be automatically sent in response to Direct Messages. When false, disables the Automatic Direct Message Replies feature and hides it from Account Settings.", - "admin.experimental.experimentalEnableAutomaticReplies.title": "Enable Automatic Replies:", - "admin.experimental.experimentalEnableDefaultChannelLeaveJoinMessages.desc": "This setting determines whether team leave/join system messages are posted in the default town-square channel.", - "admin.experimental.experimentalEnableDefaultChannelLeaveJoinMessages.title": "Enable Default Channel Leave/Join System Messages:", - "admin.experimental.experimentalEnableHardenedMode.desc": "Enables a hardened mode for Mattermost that makes user experience trade-offs in the interest of security. See [documentation](!https://docs.mattermost.com/administration/config-settings.html#enable-hardened-mode-experimental) to learn more.", - "admin.experimental.experimentalEnableHardenedMode.title": "Enable Hardened Mode:", - "admin.experimental.experimentalFeatures": "Experimental Features", - "admin.experimental.experimentalHideTownSquareinLHS.desc": "When true, hides Town Square in the left-hand sidebar if there are no unread messages in the channel. When false, Town Square is always visible in the left-hand sidebar even if all messages have been read.", - "admin.experimental.experimentalHideTownSquareinLHS.title": "Town Square is Hidden in Left-Hand Sidebar:", - "admin.experimental.experimentalPrimaryTeam.desc": "The primary team of which users on the server are members. When a primary team is set, the options to join other teams or leave the primary team are disabled.", - "admin.experimental.experimentalPrimaryTeam.example": "E.g.: \"teamname\"", - "admin.experimental.experimentalPrimaryTeam.title": "Primary Team:", - "admin.experimental.experimentalTimezone.desc": "Select the timezone used for timestamps in the user interface and email notifications. When true, the Timezone setting is visible in the Account Settings and a time zone is automatically assigned in the next active session. When false, the Timezone setting is hidden in the Account Settings.", - "admin.experimental.experimentalTimezone.title": "Timezone:", - "admin.experimental.experimentalTownSquareIsReadOnly.desc": "When true, only System Admins can post in Town Square. Other members are not able to post, reply, upload files, emoji react or pin messages to Town Square, nor are they able to change the channel name, header or purpose. When false, anyone can post in Town Square.", - "admin.experimental.experimentalTownSquareIsReadOnly.title": "Town Square is Read-Only:", - "admin.experimental.experimentalUseNewSAMLLibrary.desc": "Enable an updated SAML Library, which does not require the XML Security Library (xmlsec1) to be installed. Warning: Not all providers have been tested. If you experience issues, please contact support: [https://about.mattermost.com/support/](!https://about.mattermost.com/support/). Changing this setting requires a server restart before taking effect.", - "admin.experimental.experimentalUseNewSAMLLibrary.title": "Use Improved SAML Library (Beta):", - "admin.experimental.ldapSettingsLoginButtonBorderColor.desc": "Specify the color of the AD/LDAP login button border for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.", - "admin.experimental.ldapSettingsLoginButtonBorderColor.title": "AD/LDAP Login Button Border Color:", - "admin.experimental.ldapSettingsLoginButtonColor.desc": "Specify the color of the AD/LDAP login button for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.", - "admin.experimental.ldapSettingsLoginButtonColor.title": "AD/LDAP Login Button Color:", - "admin.experimental.ldapSettingsLoginButtonTextColor.desc": "Specify the color of the AD/LDAP login button text for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.", - "admin.experimental.ldapSettingsLoginButtonTextColor.title": "AD/LDAP Login Button Text Color:", - "admin.experimental.linkMetadataTimeoutMilliseconds.desc": "The number of milliseconds to wait for metadata from a third-party link. Used with Post Metadata.", - "admin.experimental.linkMetadataTimeoutMilliseconds.example": "E.g.: \"5000\"", - "admin.experimental.linkMetadataTimeoutMilliseconds.title": "Link Metadata Timeout:", - "admin.experimental.samlSettingsLoginButtonBorderColor.desc": "Specify the color of the SAML login button border for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.", - "admin.experimental.samlSettingsLoginButtonBorderColor.title": "SAML login Button Border Color:", - "admin.experimental.samlSettingsLoginButtonColor.desc": "Specify the color of the SAML login button for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.", - "admin.experimental.samlSettingsLoginButtonColor.title": "SAML Login Button Color:", - "admin.experimental.samlSettingsLoginButtonTextColor.desc": "Specify the color of the SAML login button text for white labeling purposes. Use a hex code with a #-sign before the code. This setting only applies to the mobile apps.", - "admin.experimental.samlSettingsLoginButtonTextColor.title": "SAML login Button Text Color:", - "admin.experimental.timeBetweenUserTypingUpdatesMilliseconds.desc": "The number of milliseconds to wait between emitting user typing websocket events.", - "admin.experimental.timeBetweenUserTypingUpdatesMilliseconds.example": "E.g.: \"5000\"", - "admin.experimental.timeBetweenUserTypingUpdatesMilliseconds.title": "User Typing Timeout:", - "admin.experimental.useChannelInEmailNotifications.desc": "When true, channel and team name appears in email notification subject lines. Useful for servers using only one team. When false, only team name appears in email notification subject line.", - "admin.experimental.useChannelInEmailNotifications.title": "Use Channel Name in Email Notifications:", - "admin.experimental.userStatusAwayTimeout.desc": "This setting defines the number of seconds after which the user’s status indicator changes to \"Away\", when they are away from Mattermost.", - "admin.experimental.userStatusAwayTimeout.example": "E.g.: \"300\"", - "admin.experimental.userStatusAwayTimeout.title": "User Status Away Timeout:", - "admin.false": "false", - "admin.field_names.allowBannerDismissal": "Allow banner dismissal", - "admin.field_names.bannerColor": "Banner color", - "admin.field_names.bannerText": "Banner text", - "admin.field_names.bannerTextColor": "Banner text color", - "admin.field_names.enableBanner": "Enable Announcement banner", - "admin.field_names.enableCommands": "Enable Custom Slash Commands", - "admin.field_names.enableConfirmNotificationsToChannel": "Show @channel and @all confirmation dialog", - "admin.field_names.enableIncomingWebhooks": "Enable Incoming Webhooks", - "admin.field_names.enableOAuthServiceProvider": "Enable OAuth 2.0 Service Provider", - "admin.field_names.enableOutgoingWebhooks": "Enable Outgoing Webhooks", - "admin.field_names.enablePostIconOverride": "Enable integrations to override profile picture icons", - "admin.field_names.enablePostUsernameOverride": "Enable integrations to override usernames", - "admin.field_names.enableUserAccessTokens": "Enable Personal Access Tokens", - "admin.field_names.enableUserCreation": "Enable Account Creation", - "admin.field_names.maxChannelsPerTeam": "Max Channels Per Team", - "admin.field_names.maxNotificationsPerChannel": "Max Notifications Per Channel", - "admin.field_names.maxUsersPerTeam": "Max Users Per Team", - "admin.field_names.postEditTimeLimit": "Edit post time limit", - "admin.field_names.restrictCreationToDomains": "Restrict account creation to specified email domains", - "admin.field_names.restrictDirectMessage": "Enable users to open Direct Message channels with", - "admin.field_names.teammateNameDisplay": "Teammate Name Display", - "admin.file_upload.chooseFile": "Choose File", - "admin.file_upload.noFile": "No file uploaded", - "admin.file_upload.uploadFile": "Upload", - "admin.file.enableFileAttachments": "Allow File Sharing:", - "admin.file.enableFileAttachmentsDesc": "When false, disables file sharing on the server. All file and image uploads on messages are forbidden across clients and devices, including mobile.", - "admin.file.enableMobileDownloadDesc": "When false, disables file downloads on mobile apps. Users can still download files from a mobile web browser.", - "admin.file.enableMobileDownloadTitle": "Allow File Downloads on Mobile:", - "admin.file.enableMobileUploadDesc": "When false, disables file uploads on mobile apps. If Allow File Sharing is set to true, users can still upload files from a mobile web browser.", - "admin.file.enableMobileUploadTitle": "Allow File Uploads on Mobile:", - "admin.general.localization.availableLocalesDescription": "Set which languages are available for users in Account Settings (leave this field blank to have all supported languages available). If you're manually adding new languages, the **Default Client Language** must be added before saving this setting.\n \nWould like to help with translations? Join the [Mattermost Translation Server](!http://translate.mattermost.com/) to contribute.", - "admin.general.localization.availableLocalesNoResults": "No results found", - "admin.general.localization.availableLocalesNotPresent": "The default client language must be included in the available list", - "admin.general.localization.availableLocalesTitle": "Available Languages:", - "admin.general.localization.clientLocaleDescription": "Default language for newly created users and pages where the user hasn't logged in.", - "admin.general.localization.clientLocaleTitle": "Default Client Language:", - "admin.general.localization.serverLocaleDescription": "Default language for system messages. Changing this will require a server restart before taking effect.", - "admin.general.localization.serverLocaleTitle": "Default Server Language:", - "admin.general.log": "Logging", - "admin.gitlab.authTitle": "Auth Endpoint:", - "admin.gitlab.clientIdDescription": "Obtain this value via the instructions above for logging into P1 SSO.", - "admin.gitlab.clientIdExample": "E.g.: \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"", - "admin.gitlab.clientIdTitle": "Application ID:", - "admin.gitlab.clientSecretDescription": "Obtain this value via the instructions above for logging into P1 SSO.", - "admin.gitlab.clientSecretExample": "E.g.: \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"", - "admin.gitlab.clientSecretTitle": "Application Secret Key:", - "admin.gitlab.enableDescription": "When true, Mattermost allows team creation and account signup using P1 SSO.\n", - "admin.gitlab.EnableMarkdownDesc": "N/A", - "admin.gitlab.enableTitle": "Enable authentication with P1 SSO: ", - "admin.gitlab.siteUrl": "P1 SSO Site URL: ", - "admin.gitlab.siteUrlDescription": "Enter the URL of your P1 SSO instance, e.g. https://example.com:3000. If your P1 SSO instance is not set up with SSL, start the URL with http:// instead of https://.", - "admin.gitlab.siteUrlExample": "E.g.: https://", - "admin.gitlab.tokenTitle": "Token Endpoint:", - "admin.gitlab.userTitle": "User API Endpoint:", - "admin.google.authTitle": "Auth Endpoint:", - "admin.google.clientIdDescription": "The Client ID you received when registering your application with Google.", - "admin.google.clientIdExample": "E.g.: \"7602141235235-url0fhs1mayfasbmop5qlfns8dh4.apps.googleusercontent.com\"", - "admin.google.clientIdTitle": "Client ID:", - "admin.google.clientSecretDescription": "The Client Secret you received when registering your application with Google.", - "admin.google.clientSecretExample": "E.g.: \"H8sz0Az-dDs2p15-7QzD231\"", - "admin.google.clientSecretTitle": "Client Secret:", - "admin.google.EnableMarkdownDesc": "1. [Log in](!https://accounts.google.com/login) to your Google account.\n2. Go to [https://console.developers.google.com](!https://console.developers.google.com), click **Credentials** in the left hand sidebar and enter \"Mattermost - your-company-name\" as the **Project Name**, then click **Create**.\n3. Click the **OAuth consent screen** header and enter \"Mattermost\" as the **Product name shown to users**, then click **Save**.\n4. Under the **Credentials** header, click **Create credentials**, choose **OAuth client ID** and select **Web Application**.\n5. Under **Restrictions** and **Authorized redirect URIs** enter **your-mattermost-url/signup/google/complete** (example: http://localhost:8065/signup/google/complete). Click **Create**.\n6. Paste the **Client ID** and **Client Secret** to the fields below, then click **Save**.\n7. Go to the [Google People API](!https://console.developers.google.com/apis/library/people.googleapis.com) and click *Enable*.", - "admin.google.tokenTitle": "Token Endpoint:", - "admin.google.userTitle": "User API Endpoint:", - "admin.group_settings.filters.isConfigured": "Is Configured", - "admin.group_settings.filters.isLinked": "Is Linked", - "admin.group_settings.filters.isUnconfigured": "Is Not Configured", - "admin.group_settings.filters.isUnlinked": "Is Not Linked", - "admin.group_settings.group_detail.duplicateMentionNameError": "Group mention is already taken.", - "admin.group_settings.group_detail.group_configuration": "Group Configuration", - "admin.group_settings.group_detail.groupProfileDescription": "The name for this group.", - "admin.group_settings.group_detail.groupProfileTitle": "Group Profile", - "admin.group_settings.group_detail.groupTeamsAndChannelsDescription": "Set default teams and channels for group members. Teams added will include default channels, town-square, and off-topic. Adding a channel without setting the team will add the implied team to the listing below.", - "admin.group_settings.group_detail.groupTeamsAndChannelsTitle": "Team and Channel Membership", - "admin.group_settings.group_detail.groupUsersDescription": "Listing of users in Mattermost associated with this group.", - "admin.group_settings.group_detail.groupUsersTitle": "Users", - "admin.group_settings.group_detail.introBanner": "Configure default teams and channels and view users belonging to this group.", - "admin.group_settings.group_detail.invalidOrReservedMentionNameError": "Only letters (a-z), numbers(0-9), periods, dashes and underscores are allowed.", - "admin.group_settings.group_details.add_channel": "Add Channel", - "admin.group_settings.group_details.add_team": "Add Team", - "admin.group_settings.group_details.add_team_or_channel": "Add Team or Channel", - "admin.group_settings.group_details.group_mention.name": "Group Mention:", - "admin.group_settings.group_details.group_profile.name": "Name:", - "admin.group_settings.group_details.group_teams_and_channels_row.privateChannel": "Channel (Private)", - "admin.group_settings.group_details.group_teams_and_channels_row.privateTeam": "Team (Private)", - "admin.group_settings.group_details.group_teams_and_channels_row.publicChannel": "Channel", - "admin.group_settings.group_details.group_teams_and_channels_row.publicTeam": "Team", - "admin.group_settings.group_details.group_teams_and_channels_row.remove": "Remove", - "admin.group_settings.group_details.group_teams_and_channels_row.remove.confirm_body": "Removing this membership will prevent future users in this group from being added to the {name} {displayType}.", - "admin.group_settings.group_details.group_teams_and_channels_row.remove.confirm_button": "Yes, Remove", - "admin.group_settings.group_details.group_teams_and_channels_row.remove.confirm_header": "Remove Membership from the {name} {displayType}?", - "admin.group_settings.group_details.group_teams_and_channels.no-teams-or-channels-speicified": "No teams or channels specified yet", - "admin.group_settings.group_details.group_users.email": "Email:", - "admin.group_settings.group_details.group_users.no-users-found": "No users found", - "admin.group_settings.group_details.menuAriaLabel": "Add Team or Channel Menu", - "admin.group_settings.group_profile.group_teams_and_channels.assignedRoles": "Assigned Roles", - "admin.group_settings.group_profile.group_teams_and_channels.name": "Name", - "admin.group_settings.group_profile.group_teams_and_channels.type": "Type", - "admin.group_settings.group_profile.group_users.ldapConnector": "AD/LDAP Connector is configured to sync and manage this group and its users. [Click here to view]({siteURL}/admin_console/authentication/ldap)", - "admin.group_settings.group_row.configure": "Configure", - "admin.group_settings.group_row.edit": "Edit", - "admin.group_settings.group_row.link_failed": "Link failed", - "admin.group_settings.group_row.linked": "Linked", - "admin.group_settings.group_row.linking": "Linking", - "admin.group_settings.group_row.not_linked": "Not Linked", - "admin.group_settings.group_row.unlink_failed": "Unlink failed", - "admin.group_settings.group_row.unlinking": "Unlinking", - "admin.group_settings.groups_list.link_selected": "Link Selected Groups", - "admin.group_settings.groups_list.mappingHeader": "Mattermost Linking", - "admin.group_settings.groups_list.nameHeader": "Name", - "admin.group_settings.groups_list.no_groups_found": "No groups found", - "admin.group_settings.groups_list.paginatorCount": "{startCount, number} - {endCount, number} of {total, number}", - "admin.group_settings.groups_list.unlink_selected": "Unlink Selected Groups", - "admin.group_settings.groupsPageTitle": "Groups (Beta)", - "admin.group_settings.introBanner": "Groups are a way to organize users and apply actions to all users within that group.\nFor more information on Groups, please see [documentation](!https://www.mattermost.com/default-ad-ldap-groups).", - "admin.group_settings.ldapGroupsDescription": "Connect AD/LDAP and create groups in Mattermost. To get started, configure group attributes on the [AD/LDAP]({siteURL}/admin_console/authentication/ldap) configuration page.", - "admin.group_settings.ldapGroupsTitle": "AD/LDAP Groups", - "admin.group_settings.need_groupname": "You must specify a group mention.", - "admin.group_teams_and_channels_row.channelAdmin": "Channel Admin", - "admin.group_teams_and_channels_row.member": "Member", - "admin.group_teams_and_channels_row.teamAdmin": "Team Admin", - "admin.guest_access.disableConfirmButton": "Save and Disable Guest Access", - "admin.guest_access.disableConfirmMessage": "Disabling guest access will revoke all current Guest Account sessions. Guests will no longer be able to login and new guests cannot be invited into Mattermost. Guest users will be marked as inactive in user lists. Enabling this feature will not reinstate previous guest accounts. Are you sure you wish to remove these users?", - "admin.guest_access.disableConfirmTitle": "Save and Disable Guest Access?", - "admin.guest_access.disableConfirmWarning": "All current guest account sessions will be revoked, and marked as inactive", - "admin.guest_access.enableDescription": "When true, external guest can be invited to channels within teams. Please see [Permissions Schemes](../user_management/permissions/system_scheme) for which roles can invite guests.", - "admin.guest_access.enableTitle": "Enable Guest Access: ", - "admin.guest_access.mfaDescription": "When true, [multi-factor authentication](!https://docs.mattermost.com/deployment/auth.html) for guests is required for login. New guest users will be required to configure MFA on signup. Logged in guest users without MFA configured are redirected to the MFA setup page until configuration is complete.\n \nIf your system has guest users with login methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost.", - "admin.guest_access.mfaDescriptionMFANotEnabled": "[Multi-factor authentication](./mfa) is currently not enabled.", - "admin.guest_access.mfaDescriptionMFANotEnforced": "[Multi-factor authentication](./mfa) is currently not enforced.", - "admin.guest_access.mfaTitle": "Enforce Multi-factor Authentication: ", - "admin.guest_access.whitelistedDomainsDescription": "(Optional) Guest accounts can be created at the system level from this list of allowed guest domains.", - "admin.guest_access.whitelistedDomainsExample": "E.g.: \"company.com, othercorp.org\"", - "admin.guest_access.whitelistedDomainsTitle": "Whitelisted Guest Domains:", - "admin.image.amazonS3BucketDescription": "Name you selected for your S3 bucket in AWS.", - "admin.image.amazonS3BucketExample": "E.g.: \"mattermost-media\"", - "admin.image.amazonS3BucketTitle": "Amazon S3 Bucket:", - "admin.image.amazonS3EndpointDescription": "Hostname of your S3 Compatible Storage provider. Defaults to \"s3.amazonaws.com\".", - "admin.image.amazonS3EndpointExample": "E.g.: \"s3.amazonaws.com\"", - "admin.image.amazonS3EndpointTitle": "Amazon S3 Endpoint:", - "admin.image.amazonS3IdDescription": "(Optional) Only required if you do not want to authenticate to S3 using an [IAM role](!https://about.mattermost.com/default-iam-role). Enter the Access Key ID provided by your Amazon EC2 administrator.", - "admin.image.amazonS3IdExample": "E.g.: \"AKIADTOVBGERKLCBV\"", - "admin.image.amazonS3IdTitle": "Amazon S3 Access Key ID:", - "admin.image.amazonS3RegionDescription": "AWS region you selected when creating your S3 bucket. If no region is set, Mattermost attempts to get the appropriate region from AWS, or sets it to 'us-east-1' if none found.", - "admin.image.amazonS3RegionExample": "E.g.: \"us-east-1\"", - "admin.image.amazonS3RegionTitle": "Amazon S3 Region:", - "admin.image.amazonS3SecretDescription": "(Optional) The secret access key associated with your Amazon S3 Access Key ID.", - "admin.image.amazonS3SecretExample": "E.g.: \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"", - "admin.image.amazonS3SecretTitle": "Amazon S3 Secret Access Key:", - "admin.image.amazonS3SSEDescription": "When true, encrypt files in Amazon S3 using server-side encryption with Amazon S3-managed keys. See [documentation](!https://about.mattermost.com/default-server-side-encryption) to learn more.", - "admin.image.amazonS3SSETitle": "Enable Server-Side Encryption for Amazon S3:", - "admin.image.amazonS3SSLDescription": "When false, allow insecure connections to Amazon S3. Defaults to secure connections only.", - "admin.image.amazonS3SSLTitle": "Enable Secure Amazon S3 Connections:", - "admin.image.amazonS3TraceDescription": "(Development Mode) When true, log additional debugging information to the system logs.", - "admin.image.amazonS3TraceTitle": "Enable Amazon S3 Debugging:", - "admin.image.enableProxy": "Enable Image Proxy:", - "admin.image.enableProxyDescription": "When true, enables an image proxy for loading all Markdown images.", - "admin.image.localDescription": "Directory to which files and images are written. If blank, defaults to ./data/.", - "admin.image.localExample": "E.g.: \"./data/\"", - "admin.image.localTitle": "Local Storage Directory:", - "admin.image.maxFileSizeDescription": "Maximum file size for message attachments in megabytes. Caution: Verify server memory can support your setting choice. Large file sizes increase the risk of server crashes and failed uploads due to network interruptions.", - "admin.image.maxFileSizeExample": "50", - "admin.image.maxFileSizeTitle": "Maximum File Size:", - "admin.image.proxyOptions": "Remote Image Proxy Options:", - "admin.image.proxyOptionsDescription": "Additional options such as the URL signing key. Refer to your image proxy documentation to learn more about what options are supported.", - "admin.image.proxyType": "Image Proxy Type:", - "admin.image.proxyTypeDescription": "Configure an image proxy to load all Markdown images through a proxy. The image proxy prevents users from making insecure image requests, provides caching for increased performance, and automates image adjustments such as resizing. See [documentation](!https://about.mattermost.com/default-image-proxy-documentation) to learn more.", - "admin.image.proxyURL": "Remote Image Proxy URL:", - "admin.image.proxyURLDescription": "URL of your remote image proxy server.", - "admin.image.publicLinkDescription": "32-character salt added to signing of public image links. Randomly generated on install. Click \"Regenerate\" to create new salt.", - "admin.image.publicLinkTitle": "Public Link Salt:", - "admin.image.shareDescription": "Allow users to share public links to files and images.", - "admin.image.shareTitle": "Enable Public File Links: ", - "admin.image.storeAmazonS3": "Amazon S3", - "admin.image.storeDescription": "Storage system where files and image attachments are saved.\n \nSelecting \"Amazon S3\" enables fields to enter your Amazon credentials and bucket details.\n \nSelecting \"Local File System\" enables the field to specify a local file directory.", - "admin.image.storeLocal": "Local File System", - "admin.image.storeTitle": "File Storage System:", - "admin.integrations.botAccounts": "Bot Accounts", - "admin.integrations.botAccounts.title": "Bot Accounts", - "admin.integrations.cors": "CORS", - "admin.integrations.gif": "GIF (Beta)", - "admin.integrations.integrationManagement": "Integration Management", - "admin.integrations.integrationManagement.title": "Integration Management", - "admin.jobTable.cancelButton": "Cancel", - "admin.jobTable.headerExtraInfo": "Details", - "admin.jobTable.headerFinishAt": "Finish Time", - "admin.jobTable.headerRunTime": "Run Time", - "admin.jobTable.headerStatus": "Status", - "admin.jobTable.jobId": "Job ID: ", - "admin.jobTable.lastActivityAt": "Last Activity: ", - "admin.jobTable.runLengthMinutes": " minutes", - "admin.jobTable.runLengthSeconds": " seconds", - "admin.jobTable.statusCanceled": "Canceled", - "admin.jobTable.statusCanceling": "Canceling...", - "admin.jobTable.statusError": "Error", - "admin.jobTable.statusInProgress": "In Progress", - "admin.jobTable.statusPending": "Pending", - "admin.jobTable.statusSuccess": "Success", - "admin.jobTable.statusWarning": "Warning", - "admin.ldap_feature_discovery.call_to_action.primary": "Request trial", - "admin.ldap_feature_discovery.call_to_action.secondary": "Learn more", - "admin.ldap_feature_discovery.copy": "When you connect Mattermost with your organization's Active Directory / LDAP, users can log in without having to create new usernames and passwords.", - "admin.ldap_feature_discovery.title": "Integrate Active Directory / LDAP with Mattermost Enterprise E10", - "admin.ldap.adminFilterEx": "E.g.: \"(objectClass=user)\"", - "admin.ldap.adminFilterFilterDesc": "(Optional) Enter an AD/LDAP filter to use for designating System Admins. The users selected by the query will have access to your Mattermost server as System Admins. By default, System Admins have complete access to the Mattermost System Console.\n \nExisting members that are identified by this attribute will be promoted from member to System Admin upon next login. The next login is based upon Session lengths set in **System Console > Session Lengths**. It is highly recommend to manually demote users to members in **System Console > User Management** to ensure access is restricted immediately.\n \nNote: If this filter is removed/changed, System Admins that were promoted via this filter will be demoted to members and will not retain access to the System Console. When this filter is not in use, System Admins can be manually promoted/demoted in **System Console > User Management**.", - "admin.ldap.adminFilterTitle": "Admin Filter:", - "admin.ldap.baseDesc": "The Base DN is the Distinguished Name of the location where Mattermost should start its search for user and group objects in the AD/LDAP tree.", - "admin.ldap.baseEx": "E.g.: \"ou=Unit Name,dc=corp,dc=example,dc=com\"", - "admin.ldap.baseTitle": "BaseDN:", - "admin.ldap.bindPwdDesc": "Password of the user given in \"Bind Username\".", - "admin.ldap.bindPwdTitle": "Bind Password:", - "admin.ldap.bindUserDesc": "The username used to perform the AD/LDAP search. This should typically be an account created specifically for use with Mattermost. It should have access limited to read the portion of the AD/LDAP tree specified in the BaseDN field.", - "admin.ldap.bindUserTitle": "Bind Username:", - "admin.ldap.emailAttrDesc": "The attribute in the AD/LDAP server used to populate the email address field in Mattermost.", - "admin.ldap.emailAttrEx": "E.g.: \"mail\" or \"userPrincipalName\"", - "admin.ldap.emailAttrTitle": "Email Attribute:", - "admin.ldap.enableAdminFilterTitle": "Enable Admin Filter", - "admin.ldap.enableDesc": "When true, Mattermost allows login using AD/LDAP", - "admin.ldap.enableSyncDesc": "When true, Mattermost periodically synchronizes users from AD/LDAP. When false, user attributes are updated from AD/LDAP during user login only.", - "admin.ldap.enableSyncTitle": "Enable Synchronization with AD/LDAP:", - "admin.ldap.enableTitle": "Enable sign-in with AD/LDAP:", - "admin.ldap.firstnameAttrDesc": "(Optional) The attribute in the AD/LDAP server used to populate the first name of users in Mattermost. When set, users cannot edit their first name, since it is synchronized with the LDAP server. When left blank, users can set their first name in Account Settings.", - "admin.ldap.firstnameAttrEx": "E.g.: \"givenName\"", - "admin.ldap.firstnameAttrTitle": "First Name Attribute:", - "admin.ldap.groupDisplayNameAttributeDesc": "The attribute in the AD/LDAP server used to populate the group display names.", - "admin.ldap.groupDisplayNameAttributeEx": "E.g.: \"cn\"", - "admin.ldap.groupDisplayNameAttributeTitle": "Group Display Name Attribute:", - "admin.ldap.groupFilterEx": "E.g.: \"(objectClass=group)\"", - "admin.ldap.groupFilterFilterDesc": "(Optional) Enter an AD/LDAP filter to use when searching for group objects. Only the groups selected by the query will be available to Mattermost. From [User Management > Groups]({siteURL}/admin_console/user_management/groups), select which AD/LDAP groups should be linked and configured.", - "admin.ldap.groupFilterTitle": "Group Filter:", - "admin.ldap.groupIdAttributeDesc": "The attribute in the AD/LDAP server used as a unique identifier for Groups. This should be a AD/LDAP attribute with a value that does not change such as `entryUUID` for LDAP or `objectGUID` for Active Directory.", - "admin.ldap.groupIdAttributeEx": "E.g.: \"objectGUID\" or \"entryUUID\"", - "admin.ldap.groupIdAttributeTitle": "Group ID Attribute:", - "admin.ldap.guestFilterEx": "E.g.: \"(objectClass=user)\"", - "admin.ldap.guestFilterFilterDesc": "(Optional) Requires Guest Access to be enabled before being applied. Enter an AD/LDAP filter to use when searching for guest objects. Only the users selected by the query will be able to access Mattermost as Guests. Guests are prevented from accessing teams or channels upon logging in until they are assigned a team and at least one channel.\n \nNote: If this filter is removed/changed, active guests will not be promoted to a member and will retain their Guest role. Guests can be promoted in **System Console > User Management**.\n \n \nExisting members that are identified by this attribute as a guest will be demoted from a member to a guest when they are asked to login next. The next login is based upon Session lengths set in **System Console > Session Lengths**. It is highly recommend to manually demote users to guests in **System Console > User Management ** to ensure access is restricted immediately.", - "admin.ldap.guestFilterTitle": "Guest Filter:", - "admin.ldap.idAttrDesc": "The attribute in the AD/LDAP server used as a unique identifier in Mattermost. It should be an AD/LDAP attribute with a value that does not change such as `uid` for LDAP or `objectGUID` for Active Directory. If a user's ID Attribute changes, it will create a new Mattermost account unassociated with their old one.\n \nIf you need to change this field after users have already logged in, use the [mattermost ldap idmigrate](!https://about.mattermost.com/default-mattermost-ldap-idmigrate) CLI tool.", - "admin.ldap.idAttrEx": "E.g.: \"objectGUID\" or \"uid\"", - "admin.ldap.idAttrTitle": "ID Attribute: ", - "admin.ldap.jobExtraInfo.addedGroupMembers": "Added {groupMemberAddCount, number} group members.", - "admin.ldap.jobExtraInfo.deactivatedUsers": "Deactivated {deleteCount, number} users.", - "admin.ldap.jobExtraInfo.deletedGroupMembers": "Deleted {groupMemberDeleteCount, number} group members.", - "admin.ldap.jobExtraInfo.deletedGroups": "Deleted {groupDeleteCount, number} groups.", - "admin.ldap.jobExtraInfo.updatedUsers": "Updated {updateCount, number} users.", - "admin.ldap.lastnameAttrDesc": "(Optional) The attribute in the AD/LDAP server used to populate the last name of users in Mattermost. When set, users cannot edit their last name, since it is synchronized with the LDAP server. When left blank, users can set their last name in Account Settings.", - "admin.ldap.lastnameAttrEx": "E.g.: \"sn\"", - "admin.ldap.lastnameAttrTitle": "Last Name Attribute:", - "admin.ldap.ldap_test_button": "AD/LDAP Test", - "admin.ldap.loginAttrDesc": "The attribute in the AD/LDAP server used to log in to Mattermost. Normally this attribute is the same as the \"Username Attribute\" field above.\n \nIf your team typically uses domain/username to log in to other services with AD/LDAP, you may enter domain/username in this field to maintain consistency between sites.", - "admin.ldap.loginAttrTitle": "Login ID Attribute: ", - "admin.ldap.loginIdAttrEx": "E.g.: \"sAMAccountName\"", - "admin.ldap.loginNameDesc": "The placeholder text that appears in the login field on the login page. Defaults to \"AD/LDAP Username\".", - "admin.ldap.loginNameEx": "E.g.: \"AD/LDAP Username\"", - "admin.ldap.loginNameTitle": "Login Field Name:", - "admin.ldap.maxPageSizeEx": "E.g.: \"2000\"", - "admin.ldap.maxPageSizeHelpText": "The maximum number of users the Mattermost server will request from the AD/LDAP server at one time. 0 is unlimited.", - "admin.ldap.maxPageSizeTitle": "Maximum Page Size:", - "admin.ldap.nicknameAttrDesc": "(Optional) The attribute in the AD/LDAP server used to populate the nickname of users in Mattermost. When set, users cannot edit their nickname, since it is synchronized with the LDAP server. When left blank, users can set their nickname in Account Settings.", - "admin.ldap.nicknameAttrEx": "E.g.: \"nickname\"", - "admin.ldap.nicknameAttrTitle": "Nickname Attribute:", - "admin.ldap.pictureAttrDesc": "The attribute in the AD/LDAP server used to populate the profile picture in Mattermost.", - "admin.ldap.pictureAttrEx": "E.g.: \"thumbnailPhoto\" or \"jpegPhoto\"", - "admin.ldap.pictureAttrTitle": "Profile Picture Attribute:", - "admin.ldap.portDesc": "The port Mattermost will use to connect to the AD/LDAP server. Default is 389.", - "admin.ldap.portEx": "E.g.: \"389\"", - "admin.ldap.portTitle": "AD/LDAP Port:", - "admin.ldap.positionAttrDesc": "(Optional) The attribute in the AD/LDAP server used to populate the position field in Mattermost. When set, users cannot edit their position, since it is synchronized with the LDAP server. When left blank, users can set their position in Account Settings.", - "admin.ldap.positionAttrEx": "E.g.: \"title\"", - "admin.ldap.positionAttrTitle": "Position Attribute:", - "admin.ldap.queryDesc": "The timeout value for queries to the AD/LDAP server. Increase if you are getting timeout errors caused by a slow AD/LDAP server.", - "admin.ldap.queryEx": "E.g.: \"60\"", - "admin.ldap.queryTitle": "Query Timeout (seconds):", - "admin.ldap.serverDesc": "The domain or IP address of AD/LDAP server.", - "admin.ldap.serverEx": "E.g.: \"10.0.0.23\"", - "admin.ldap.serverTitle": "AD/LDAP Server:", - "admin.ldap.skipCertificateVerification": "Skip Certificate Verification:", - "admin.ldap.skipCertificateVerificationDesc": "Skips the certificate verification step for TLS or STARTTLS connections. Skipping certificate verification is not recommended for production environments where TLS is required.", - "admin.ldap.sync_button": "AD/LDAP Synchronize Now", - "admin.ldap.syncIntervalHelpText": "AD/LDAP Synchronization updates Mattermost user information to reflect updates on the AD/LDAP server. For example, when a user's name changes on the AD/LDAP server, the change updates in Mattermost when synchronization is performed. Accounts removed from or disabled in the AD/LDAP server have their Mattermost accounts set to \"Inactive\" and have their account sessions revoked. Mattermost performs synchronization on the interval entered. For example, if 60 is entered, Mattermost synchronizes every 60 minutes.", - "admin.ldap.syncIntervalTitle": "Synchronization Interval (minutes):", - "admin.ldap.syncNowHelpText": "Initiates an AD/LDAP synchronization immediately. See the table below for status of each synchronization. Please review \"System Console > Logs\" and [documentation](!https://mattermost.com/default-ldap-docs) to troubleshoot errors.", - "admin.ldap.testFailure": "AD/LDAP Test Failure: {error}", - "admin.ldap.testHelpText": "Tests if the Mattermost server can connect to the AD/LDAP server specified. Please review \"System Console > Logs\" and [documentation](!https://mattermost.com/default-ldap-docs) to troubleshoot errors.", - "admin.ldap.testSuccess": "AD/LDAP Test Successful", - "admin.ldap.userFilterDisc": "(Optional) Enter an AD/LDAP filter to use when searching for user objects. Only the users selected by the query will be able to access Mattermost. For Active Directory, the query to filter out disabled users is (&(objectCategory=Person)(!(UserAccountControl:1.2.840.113556.1.4.803:=2))).", - "admin.ldap.userFilterEx": "E.g.: \"(objectClass=user)\"", - "admin.ldap.userFilterTitle": "User Filter:", - "admin.ldap.usernameAttrDesc": "The attribute in the AD/LDAP server used to populate the username field in Mattermost. This may be the same as the Login ID Attribute.", - "admin.ldap.usernameAttrEx": "E.g.: \"sAMAccountName\"", - "admin.ldap.usernameAttrTitle": "Username Attribute:", - "admin.license.choose": "Choose File", - "admin.license.edition": "Edition: ", - "admin.license.key": "License Key: ", - "admin.license.keyRemove": "Remove Enterprise License and Downgrade Server", - "admin.license.noFile": "No file uploaded", - "admin.license.removing": "Removing License...", - "admin.license.title": "Edition and License", - "admin.license.type": "License: ", - "admin.license.upload": "Upload", - "admin.license.uploadDesc": "Upload a license key for Mattermost Enterprise Edition to upgrade this server. [Visit us online](!http://mattermost.com) to learn more about the benefits of Enterprise Edition or to purchase a key.", - "admin.license.uploading": "Uploading License...", - "admin.lockTeammateNameDisplay": "Lock Teammate Name Display for all users: ", - "admin.lockTeammateNameDisplayHelpText": "When true, disables users' ability to change settings under Main Menu > Account Settings > Display > Teammate Name Display.", - "admin.log.consoleDescription": "Typically set to false in production. Developers may set this field to true to output log messages to console based on the console level option. If true, server writes messages to the standard output stream (stdout). Changing this setting requires a server restart before taking effect.", - "admin.log.consoleJsonTitle": "Output console logs as JSON:", - "admin.log.consoleTitle": "Output logs to console: ", - "admin.log.enableDiagnostics": "Enable Diagnostics and Error Reporting:", - "admin.log.enableDiagnosticsDescription": "Enable this feature to improve the quality and performance of Mattermost by sending error reporting and diagnostic information to Mattermost, Inc. Read our [privacy policy](!https://about.mattermost.com/default-privacy-policy/) to learn more.", - "admin.log.enableWebhookDebugging": "Enable Webhook Debugging:", - "admin.log.enableWebhookDebuggingDescription": "When true, sends webhook debug messages to the server logs. To also output the request body of incoming webhooks, set {boldedLogLevel} to 'DEBUG'.", - "admin.log.fileDescription": "Typically set to true in production. When true, logged events are written to the mattermost.log file in the directory specified in the File Log Directory field. The logs are rotated at 10,000 lines and archived to a file in the same directory, and given a name with a datestamp and serial number. For example, mattermost.2017-03-31.001. Changing this setting requires a server restart before taking effect.", - "admin.log.fileJsonTitle": "Output file logs as JSON:", - "admin.log.fileLevelDescription": "This setting determines the level of detail at which log events are written to the log file. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.", - "admin.log.fileLevelTitle": "File Log Level:", - "admin.log.fileTitle": "Output logs to file: ", - "admin.log.jsonDescription": "When true, logged events are written in a machine readable JSON format. Otherwise they are printed as plain text. Changing this setting requires a server restart before taking effect.", - "admin.log.levelDescription": "This setting determines the level of detail at which log events are written to the console. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.", - "admin.log.levelTitle": "Console Log Level:", - "admin.log.locationDescription": "The location of the log files. If blank, they are stored in the ./logs directory. The path that you set must exist and Mattermost must have write permissions in it. Changing this setting requires a server restart before taking effect.", - "admin.log.locationPlaceholder": "Enter your file location", - "admin.log.locationTitle": "File Log Directory:", - "admin.log.logLevel": "Log Level", - "admin.logs.bannerDesc": "To look up users by User ID or Token ID, go to Reporting > Users and paste the ID into the search filter.", - "admin.logs.next": "Next", - "admin.logs.prev": "Previous", - "admin.logs.reload": "Reload", - "admin.logs.title": "Server Logs", - "admin.manage_roles.additionalRoles": "Select additional permissions for the account. [Read more about roles and permissions](!https://about.mattermost.com/default-permissions).", - "admin.manage_roles.allowUserAccessTokens": "Allow this account to generate [personal access tokens](!https://about.mattermost.com/default-user-access-tokens).", - "admin.manage_roles.allowUserAccessTokensDesc": "Removing this permission doesn't delete existing tokens. To delete them, go to the user's Manage Tokens menu.", - "admin.manage_roles.cancel": "Cancel", - "admin.manage_roles.manageRolesTitle": "Manage Roles", - "admin.manage_roles.postAllPublicRole": "Access to post to all Mattermost public channels.", - "admin.manage_roles.postAllPublicRoleTitle": "post:channels", - "admin.manage_roles.postAllRole": "Access to post to all Mattermost channels including direct messages.", - "admin.manage_roles.postAllRoleTitle": "post:all", - "admin.manage_roles.save": "Save", - "admin.manage_roles.saveError": "Unable to save roles.", - "admin.manage_roles.systemAdmin": "System Admin", - "admin.manage_roles.systemMember": "Member", - "admin.manage_tokens.manageTokensTitle": "Manage Personal Access Tokens", - "admin.manage_tokens.userAccessTokensDescription": "Personal access tokens function similarly to session tokens and can be used by integrations to [interact with this Mattermost server](!https://about.mattermost.com/default-api-authentication). Tokens are disabled if the user is deactivated. Learn more about [personal access tokens](!https://about.mattermost.com/default-user-access-tokens).", - "admin.manage_tokens.userAccessTokensIdLabel": "Token ID: ", - "admin.manage_tokens.userAccessTokensNameLabel": "Token Description: ", - "admin.manage_tokens.userAccessTokensNone": "No personal access tokens.", - "admin.metrics.enableDescription": "When true, Mattermost will enable performance monitoring collection and profiling. Please see [documentation](!http://docs.mattermost.com/deployment/metrics.html) to learn more about configuring performance monitoring for Mattermost.", - "admin.metrics.enableTitle": "Enable Performance Monitoring:", - "admin.metrics.listenAddressDesc": "The address the server will listen on to expose performance metrics.", - "admin.metrics.listenAddressEx": "E.g.: \":8067\"", - "admin.metrics.listenAddressTitle": "Listen Address:", - "admin.mfa.bannerDesc": "[Multi-factor authentication](!https://docs.mattermost.com/deployment/auth.html) is available for accounts with AD/LDAP or email login. If other login methods are used, MFA should be configured with the authentication provider.", - "admin.nav.administratorsGuide": "Administrator's Guide", - "admin.nav.commercialSupport": "Commercial Support", - "admin.nav.menuAriaLabel": "Admin Console Menu", - "admin.nav.switch": "Team Selection", - "admin.nav.troubleshootingForum": "Troubleshooting Forum", - "admin.oauth.gitlab": "P1 SSO", - "admin.oauth.google": "Google Apps", - "admin.oauth.off": "Do not allow sign-in via an OAuth 2.0 provider", - "admin.oauth.office365": "Office 365", - "admin.oauth.providerDescription": "When true, Mattermost can act as an OAuth 2.0 service provider allowing Mattermost to authorize API requests from external applications. See [documentation](!https://docs.mattermost.com/developer/oauth-2-0-applications.html) to learn more.", - "admin.oauth.providerTitle": "Enable OAuth 2.0 Service Provider: ", - "admin.oauth.select": "Select OAuth 2.0 service provider:", - "admin.office365.authTitle": "Auth Endpoint:", - "admin.office365.clientIdDescription": "The Application/Client ID you received when registering your application with Microsoft.", - "admin.office365.clientIdExample": "E.g.: \"adf3sfa2-ag3f-sn4n-ids0-sh1hdax192qq\"", - "admin.office365.clientIdTitle": "Application ID:", - "admin.office365.clientSecretDescription": "The Application Secret Password you generated when registering your application with Microsoft.", - "admin.office365.clientSecretExample": "E.g.: \"shAieM47sNBfgl20f8ci294\"", - "admin.office365.clientSecretTitle": "Application Secret Password:", - "admin.office365.directoryIdDescription": "The Directory (tenant) ID you received when registering your application with Microsoft.", - "admin.office365.directoryIdExample": "E.g.: \"adf3sfa2-ag3f-sn4n-ids0-sh1hdax192qq\"", - "admin.office365.directoryIdTitle": "Directory (tenant) ID:", - "admin.office365.EnableMarkdownDesc": "1. [Log in](!https://login.microsoftonline.com/) to your Microsoft or Office 365 account. Make sure it`s the account on the same [tenant](!https://msdn.microsoft.com/en-us/library/azure/jj573650.aspx#Anchor_0) that you would like users to log in with.\n2. Go to [https://apps.dev.microsoft.com](!https://apps.dev.microsoft.com), click **Go to app list** > **Add an app** and use \"Mattermost - your-company-name\" as the **Application Name**.\n3. Under **Application Secrets**, click **Generate New Password** and paste it to the **Application Secret Password** field below.\n4. Under **Platforms**, click **Add Platform**, choose **Web** and enter **your-mattermost-url/signup/office365/complete** (example: http://localhost:8065/signup/office365/complete) under **Redirect URIs**. Also uncheck **Allow Implicit Flow**.\n5. Finally, click **Save** and then paste the **Application ID** below.", - "admin.office365.tokenTitle": "Token Endpoint:", - "admin.office365.userTitle": "User API Endpoint:", - "admin.password.lowercase": "At least one lowercase letter", - "admin.password.minimumLength": "Minimum Password Length:", - "admin.password.minimumLengthDescription": "Minimum number of characters required for a valid password. Must be a whole number greater than or equal to {min} and less than or equal to {max}.", - "admin.password.minimumLengthExample": "E.g.: \"5\"", - "admin.password.number": "At least one number", - "admin.password.preview": "Error message preview", - "admin.password.symbol": "At least one symbol (e.g. \"~!@#$%^&*()\")", - "admin.password.uppercase": "At least one uppercase letter", - "admin.permissions.documentationLinkText": "documentation", - "admin.permissions.group.delete_posts.description": "Delete own and others' posts.", - "admin.permissions.group.delete_posts.name": "Delete Posts", - "admin.permissions.group.edit_posts.description": "Edit own and others' posts.", - "admin.permissions.group.edit_posts.name": "Edit Posts", - "admin.permissions.group.integrations.description": "Manage OAuth 2.0, slash commands, webhooks and emoji.", - "admin.permissions.group.integrations.name": "Integrations & Customizations", - "admin.permissions.group.posts.description": "Write, edit and delete posts.", - "admin.permissions.group.posts.name": "Manage Posts", - "admin.permissions.group.private_channel.description": "Create and archive channels, manage settings and members.", - "admin.permissions.group.private_channel.name": "Manage Private Channels", - "admin.permissions.group.public_channel.description": "Join, create and archive channels, manage settings and members.", - "admin.permissions.group.public_channel.name": "Manage Public Channels", - "admin.permissions.group.reactions.description": "Add and delete reactions on posts.", - "admin.permissions.group.reactions.name": "Post Reactions", - "admin.permissions.group.send_invites.description": "Add team members, send email invites and share team invite link.", - "admin.permissions.group.send_invites.name": "Add Team Members", - "admin.permissions.group.teams_team_scope.description": "Manage team members.", - "admin.permissions.group.teams_team_scope.name": "Teams", - "admin.permissions.group.teams.description": "Create teams and manage members.", - "admin.permissions.group.teams.name": "Teams", - "admin.permissions.inherited_from": "Inherited from {name}.", - "admin.permissions.introBanner": "Permission Schemes set the default permissions for Team Admins, Channel Admins and everyone else. Learn more about permission schemes in our [documentation](!https://about.mattermost.com/default-advanced-permissions).", - "admin.permissions.loadingMoreSchemes": "Loading...", - "admin.permissions.loadMoreSchemes": "Load more schemes", - "admin.permissions.permission.assign_system_admin_role.description": "Assign system admin role", - "admin.permissions.permission.assign_system_admin_role.name": "Assign system admin role", - "admin.permissions.permission.create_direct_channel.description": "Create direct channel", - "admin.permissions.permission.create_direct_channel.name": "Create direct channel", - "admin.permissions.permission.create_emojis.description": "Allow users to create custom emoji.", - "admin.permissions.permission.create_emojis.name": "Create Custom Emoji", - "admin.permissions.permission.create_group_channel.description": "Create group channel", - "admin.permissions.permission.create_group_channel.name": "Create group channel", - "admin.permissions.permission.create_post.description": "Allow users to create posts.", - "admin.permissions.permission.create_post.name": "Create Posts", - "admin.permissions.permission.create_private_channel.description": "Create new private channels.", - "admin.permissions.permission.create_private_channel.name": "Create Channels", - "admin.permissions.permission.create_public_channel.description": "Create new public channels.", - "admin.permissions.permission.create_public_channel.name": "Create Channels", - "admin.permissions.permission.create_team.description": "Create new teams.", - "admin.permissions.permission.create_team.name": "Create Teams", - "admin.permissions.permission.create_user_access_token.description": "Create user access token", - "admin.permissions.permission.create_user_access_token.name": "Create user access token", - "admin.permissions.permission.delete_emojis.description": "Allow users to delete custom emoji that they created.", - "admin.permissions.permission.delete_emojis.name": "Delete Own Custom Emoji", - "admin.permissions.permission.delete_others_emojis.description": "Allow users to delete custom emoji that were created by other users.", - "admin.permissions.permission.delete_others_emojis.name": "Delete Others' Custom Emoji", - "admin.permissions.permission.delete_others_posts.description": "Posts made by other users can be deleted.", - "admin.permissions.permission.delete_others_posts.name": "Delete Others' Posts", - "admin.permissions.permission.delete_post.description": "Author's own posts can be deleted.", - "admin.permissions.permission.delete_post.name": "Delete Own Posts", - "admin.permissions.permission.delete_private_channel.description": "Archive private channels.", - "admin.permissions.permission.delete_private_channel.name": "Archive Channels", - "admin.permissions.permission.delete_public_channel.description": "Archive public channels.", - "admin.permissions.permission.delete_public_channel.name": "Archive Channels", - "admin.permissions.permission.edit_other_users.description": "Edit other users", - "admin.permissions.permission.edit_other_users.name": "Edit other users", - "admin.permissions.permission.edit_others_posts.description": "Allow users to edit others' posts.", - "admin.permissions.permission.edit_others_posts.name": "Edit Others' Posts", - "admin.permissions.permission.edit_post.description": "{editTimeLimitButton} after posting, allow users to edit their own posts.", - "admin.permissions.permission.edit_post.name": "Edit Own Posts", - "admin.permissions.permission.import_team.description": "Import team", - "admin.permissions.permission.import_team.name": "Import team", - "admin.permissions.permission.invite_guest.description": "Invite guests to channels and send guest email invites.", - "admin.permissions.permission.invite_guest.name": "Invite guests", - "admin.permissions.permission.list_team_channels.description": "List team channels", - "admin.permissions.permission.list_team_channels.name": "List team channels", - "admin.permissions.permission.list_users_without_team.description": "List users without team", - "admin.permissions.permission.list_users_without_team.name": "List users without team", - "admin.permissions.permission.manage_channel_roles.description": "Manage channel roles", - "admin.permissions.permission.manage_channel_roles.name": "Manage channel roles", - "admin.permissions.permission.manage_incoming_webhooks.description": "Create, edit, and delete incoming webhooks.", - "admin.permissions.permission.manage_incoming_webhooks.name": "Manage Incoming Webhooks", - "admin.permissions.permission.manage_jobs.description": "Manage jobs", - "admin.permissions.permission.manage_jobs.name": "Manage jobs", - "admin.permissions.permission.manage_oauth.description": "Create, edit and delete OAuth 2.0 application tokens.", - "admin.permissions.permission.manage_oauth.name": "Manage OAuth Applications", - "admin.permissions.permission.manage_outgoing_webhooks.description": "Create, edit, and delete outgoing webhooks.", - "admin.permissions.permission.manage_outgoing_webhooks.name": "Manage Outgoing Webhooks", - "admin.permissions.permission.manage_private_channel_members.description": "Add and remove private channel members.", - "admin.permissions.permission.manage_private_channel_members.name": "Manage Channel Members", - "admin.permissions.permission.manage_private_channel_properties.description": "Update private channel names, headers and purposes.", - "admin.permissions.permission.manage_private_channel_properties.name": "Manage Channel Settings", - "admin.permissions.permission.manage_public_channel_members.description": "Add and remove public channel members.", - "admin.permissions.permission.manage_public_channel_members.name": "Manage Channel Members", - "admin.permissions.permission.manage_public_channel_properties.description": "Update public channel names, headers and purposes.", - "admin.permissions.permission.manage_public_channel_properties.name": "Manage Channel Settings", - "admin.permissions.permission.manage_roles.description": "Manage roles", - "admin.permissions.permission.manage_roles.name": "Manage roles", - "admin.permissions.permission.manage_slash_commands.description": "Create, edit and delete custom slash commands.", - "admin.permissions.permission.manage_slash_commands.name": "Manage Slash Commands", - "admin.permissions.permission.manage_system.description": "Manage system", - "admin.permissions.permission.manage_system.name": "Manage system", - "admin.permissions.permission.manage_team_roles.description": "Manage team roles", - "admin.permissions.permission.manage_team_roles.name": "Manage team roles", - "admin.permissions.permission.manage_team.description": "Manage team", - "admin.permissions.permission.manage_team.name": "Manage team", - "admin.permissions.permission.permanent_delete_user.description": "Permanent delete user", - "admin.permissions.permission.permanent_delete_user.name": "Permanent delete user", - "admin.permissions.permission.read_channel.description": "Read channel", - "admin.permissions.permission.read_channel.name": "Read channel", - "admin.permissions.permission.read_user_access_token.description": "Read user access token", - "admin.permissions.permission.read_user_access_token.name": "Read user access token", - "admin.permissions.permission.remove_user_from_team.description": "Remove user from team", - "admin.permissions.permission.remove_user_from_team.name": "Remove user from team", - "admin.permissions.permission.revoke_user_access_token.description": "Revoke user access token", - "admin.permissions.permission.revoke_user_access_token.name": "Revoke user access token", - "admin.permissions.permission.upload_file.description": "Upload file", - "admin.permissions.permission.upload_file.name": "Upload file", - "admin.permissions.permission.use_channel_mentions.description": "Notify channel members with @all, @channel and @here", - "admin.permissions.permission.use_channel_mentions.name": "Channel Mentions", - "admin.permissions.permission.use_group_mentions.description": "Notify group members with a group mention", - "admin.permissions.permission.use_group_mentions.name": "Group Mentions", - "admin.permissions.permission.view_team.description": "View team", - "admin.permissions.permission.view_team.name": "View team", - "admin.permissions.permissionSchemes": "Permission Schemes", - "admin.permissions.permissionSchemes.cancel": "Cancel", - "admin.permissions.permissionsSchemeSummary.delete": "Delete", - "admin.permissions.permissionsSchemeSummary.deleteConfirmButton": "Yes, Delete", - "admin.permissions.permissionsSchemeSummary.deleteConfirmQuestion": "The permissions in the teams using this scheme will reset to the defaults in the System Scheme. Are you sure you want to delete the {schemeName} scheme?", - "admin.permissions.permissionsSchemeSummary.deleteSchemeTitle": "Delete {scheme} scheme?", - "admin.permissions.permissionsSchemeSummary.deleting": "Deleting...", - "admin.permissions.permissionsSchemeSummary.edit": "Edit", - "admin.permissions.permissionsSchemeSummary.moreTeams": "+{number} more", - "admin.permissions.permissionsTree.description": "Description", - "admin.permissions.permissionsTree.permission": "Permission", - "admin.permissions.roles.all_users.name": "All Members", - "admin.permissions.roles.channel_admin.name": "Channel Admin", - "admin.permissions.roles.channel_user.name": "Channel User", - "admin.permissions.roles.system_admin.name": "System Admin", - "admin.permissions.roles.system_user.name": "System User", - "admin.permissions.roles.team_admin.name": "Team Admin", - "admin.permissions.roles.team_user.name": "Team User", - "admin.permissions.systemScheme": "System Scheme", - "admin.permissions.systemScheme.allMembersDescription": "Permissions granted to all members, including administrators and newly created users.", - "admin.permissions.systemScheme.allMembersTitle": "All Members", - "admin.permissions.systemScheme.channelAdminsDescription": "Permissions granted to channel creators and any users promoted to Channel Administrator.", - "admin.permissions.systemScheme.channelAdminsTitle": "Channel Administrators", - "admin.permissions.systemScheme.GuestsDescription": "Permissions granted to guest users.", - "admin.permissions.systemScheme.GuestsTitle": "Guests", - "admin.permissions.systemScheme.introBanner": "Configure the default permissions for Team Admins, Channel Admins and other members. This scheme is inherited by all teams unless a [Team Override Scheme](!https://about.mattermost.com/default-team-override-scheme) is applied in specific teams.", - "admin.permissions.systemScheme.resetDefaultsButton": "Reset to Defaults", - "admin.permissions.systemScheme.resetDefaultsButtonModalBody": "This will reset all selections on this page to their default settings. Are you sure you want to reset?", - "admin.permissions.systemScheme.resetDefaultsButtonModalTitle": "Reset to Default?", - "admin.permissions.systemScheme.resetDefaultsConfirmationButton": "Yes, Reset", - "admin.permissions.systemScheme.systemAdminsDescription": "Full permissions granted to System Administrators.", - "admin.permissions.systemScheme.systemAdminsTitle": "System Administrators", - "admin.permissions.systemScheme.teamAdminsDescription": "Permissions granted to team creators and any users promoted to Team Administrator.", - "admin.permissions.systemScheme.teamAdminsTitle": "Team Administrators", - "admin.permissions.systemSchemeBannerButton": "Edit Scheme", - "admin.permissions.systemSchemeBannerText": "Set the default permissions inherited by all teams unless a [Team Override Scheme](!https://about.mattermost.com/default-team-override-scheme) is applied.", - "admin.permissions.systemSchemeBannerTitle": "System Scheme", - "admin.permissions.teamOverrideSchemesBannerText": "Use when specific teams need permission exceptions to the [System Scheme](!https://about.mattermost.com/default-system-scheme).", - "admin.permissions.teamOverrideSchemesInProgress": "Migration job in progress: Team Override Schemes are not available until the job server completes the permissions migration. Learn more in the {documentationLink}.", - "admin.permissions.teamOverrideSchemesNewButton": "New Team Override Scheme", - "admin.permissions.teamOverrideSchemesNoJobsEnabled": "Migration job on hold: Team Override Schemes are not available until the job server can execute the permissions migration. The job will be automatically started when the job server is enabled. Learn more in the {documentationLink}.", - "admin.permissions.teamOverrideSchemesNoSchemes": "No team override schemes created.", - "admin.permissions.teamOverrideSchemesTitle": "Team Override Schemes", - "admin.permissions.teamScheme": "Team Scheme", - "admin.permissions.teamScheme.addTeams": "Add Teams", - "admin.permissions.teamScheme.introBanner": "[Team Override Schemes](!https://about.mattermost.com/default-team-override-scheme) set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the [System Scheme](!https://about.mattermost.com/default-system-scheme).", - "admin.permissions.teamScheme.noTeams": "No team selected. Please add teams to this list.", - "admin.permissions.teamScheme.removeTeam": "Remove", - "admin.permissions.teamScheme.schemeDescriptionLabel": "Scheme Description:", - "admin.permissions.teamScheme.schemeDescriptionPlaceholder": "Scheme Description", - "admin.permissions.teamScheme.schemeDetailsDescription": "Set the name and description for this scheme.", - "admin.permissions.teamScheme.schemeDetailsTitle": "Scheme Details", - "admin.permissions.teamScheme.schemeNameLabel": "Scheme Name:", - "admin.permissions.teamScheme.schemeNamePlaceholder": "Scheme Name", - "admin.permissions.teamScheme.selectTeamsDescription": "Select teams where permission exceptions are required.", - "admin.permissions.teamScheme.selectTeamsTitle": "Select teams to override permissions", - "admin.plugin.backToPlugins": "Go back to the Plugins", - "admin.plugin.choose": "Choose File", - "admin.plugin.cluster_instance": "Cluster Instance", - "admin.plugin.customSetting.pluginDisabledWarning": "In order to view this setting, enable the plugin and click Save.", - "admin.plugin.disable": "Disable", - "admin.plugin.disabling": "Disabling...", - "admin.plugin.enable": "Enable", - "admin.plugin.enable_plugin": "Enable Plugin: ", - "admin.plugin.enable_plugin.help": "When true, this plugin is enabled.", - "admin.plugin.enabling": "Enabling...", - "admin.plugin.error.activate": "Unable to upload the plugin. It may conflict with another plugin on your server.", - "admin.plugin.error.extract": "Encountered an error when extracting the plugin. Review your plugin file content and try again.", - "admin.plugin.installedDesc": "Installed plugins on your Mattermost server.", - "admin.plugin.installedTitle": "Installed Plugins: ", - "admin.plugin.management.title": "Plugin Management", - "admin.plugin.multiple_versions_warning": "There are multiple versions of this plugin installed across your cluster. Re-install this plugin to ensure it works consistently.", - "admin.plugin.no_plugins": "No installed plugins.", - "admin.plugin.remove": "Remove", - "admin.plugin.remove_modal.desc": "Are you sure you would like to remove the plugin?", - "admin.plugin.remove_modal.overwrite": "Remove", - "admin.plugin.remove_modal.title": "Remove plugin?", - "admin.plugin.removing": "Removing...", - "admin.plugin.settingsButton": "Settings", - "admin.plugin.state": "State", - "admin.plugin.state.failed_to_start": "Failed to start", - "admin.plugin.state.failed_to_start.description": "This plugin failed to start. Check your system logs for errors.", - "admin.plugin.state.failed_to_stay_running": "Crashing", - "admin.plugin.state.failed_to_stay_running.description": "This plugin crashed multiple times and is no longer running. Check your system logs for errors.", - "admin.plugin.state.not_running": "Not running", - "admin.plugin.state.not_running.description": "This plugin is not enabled.", - "admin.plugin.state.running": "Running", - "admin.plugin.state.running.description": "This plugin is running.", - "admin.plugin.state.starting": "Starting", - "admin.plugin.state.starting.description": "This plugin is starting.", - "admin.plugin.state.stopping": "Stopping", - "admin.plugin.state.stopping.description": "This plugin is stopping.", - "admin.plugin.state.unknown": "Unknown", - "admin.plugin.upload": "Upload", - "admin.plugin.upload.overwrite_modal.desc": "A plugin with this ID already exists. Would you like to overwrite it?", - "admin.plugin.upload.overwrite_modal.overwrite": "Overwrite", - "admin.plugin.upload.overwrite_modal.title": "Overwrite existing plugin?", - "admin.plugin.uploadAndPluginDisabledDesc": "To enable plugins, set **Enable Plugins** to true. See [documentation](!https://about.mattermost.com/default-plugin-uploads) to learn more.", - "admin.plugin.uploadDesc": "Upload a plugin for your Mattermost server. See [documentation](!https://about.mattermost.com/default-plugin-uploads) to learn more.", - "admin.plugin.uploadDisabledDesc": "Enable plugin uploads in config.json. See [documentation](!https://about.mattermost.com/default-plugin-uploads) to learn more.", - "admin.plugin.uploading": "Uploading...", - "admin.plugin.uploadTitle": "Upload Plugin: ", - "admin.plugin.version_title": "Version", - "admin.plugins.pluginManagement": "Plugin Management", - "admin.plugins.settings.automaticPrepackagedPlugins": "Enable Automatic Prepackaged Plugins:", - "admin.plugins.settings.automaticPrepackagedPluginsDesc": "When true, the server will detect previously enabled plugins on the server and will automatically install them.", - "admin.plugins.settings.enable": "Enable Plugins: ", - "admin.plugins.settings.enableDesc": "When true, enables plugins on your Mattermost server. Use plugins to integrate with third-party systems, extend functionality, or customize the user interface of your Mattermost server. See [documentation](!https://about.mattermost.com/default-plugins) to learn more.", - "admin.plugins.settings.enableMarketplace": "Enable Marketplace:", - "admin.plugins.settings.enableMarketplaceDesc": "When true, enables System Administrators to install plugins from the [marketplace](!https://mattermost.com/pl/default-mattermost-marketplace.html).", - "admin.plugins.settings.enableRemoteMarketplace": "Enable Remote Marketplace:", - "admin.plugins.settings.enableRemoteMarketplaceDesc": "When true, marketplace fetches latest plugins from the configured Marketplace URL.", - "admin.plugins.settings.marketplaceUrl": "Marketplace URL:", - "admin.plugins.settings.marketplaceUrlDesc": "URL of the marketplace server.", - "admin.plugins.settings.marketplaceUrlDesc.empty": " Marketplace URL is a required field.", - "admin.plugins.settings.requirePluginSignature": "Require Plugin Signature:", - "admin.plugins.settings.requirePluginSignatureDesc": "When true, uploading plugins is disabled and may only be installed through the Marketplace. Plugins are always verified during Mattermost server startup and initialization. See [documentation](!https://mattermost.com/pl/default-plugin-signing) to learn more.", - "admin.privacy.showEmailDescription": "When false, hides the email address of members from everyone except System Administrators.", - "admin.privacy.showEmailTitle": "Show Email Address: ", - "admin.privacy.showFullNameDescription": "When false, hides the full name of members from everyone except System Administrators. Username is shown in place of full name.", - "admin.privacy.showFullNameTitle": "Show Full Name: ", - "admin.purge.button": "Purge All Caches", - "admin.purge.purgeDescription": "This will purge all the in-memory caches for things like sessions, accounts, channels, etc. Deployments using High Availability will attempt to purge all the servers in the cluster. Purging the caches may adversely impact performance.", - "admin.purge.purgeFail": "Purging unsuccessful: {error}", - "admin.rate.enableLimiterDescription": "When true, APIs are throttled at rates specified below.", - "admin.rate.enableLimiterTitle": "Enable Rate Limiting: ", - "admin.rate.httpHeaderDescription": "When filled in, vary rate limiting by HTTP header field specified (e.g. when configuring NGINX set to \"X-Real-IP\", when configuring AmazonELB set to \"X-Forwarded-For\").", - "admin.rate.httpHeaderExample": "E.g.: \"X-Real-IP\", \"X-Forwarded-For\"", - "admin.rate.httpHeaderTitle": "Vary rate limit by HTTP header:", - "admin.rate.maxBurst": "Maximum Burst Size:", - "admin.rate.maxBurstDescription": "Maximum number of requests allowed beyond the per second query limit.", - "admin.rate.maxBurstExample": "E.g.: \"100\"", - "admin.rate.memoryDescription": "Maximum number of users sessions connected to the system as determined by \"Vary rate limit by remote address\" and \"Vary rate limit by HTTP header\" settings below.", - "admin.rate.memoryExample": "E.g.: \"10000\"", - "admin.rate.memoryTitle": "Memory Store Size:", - "admin.rate.noteDescription": "Changing properties in this section will require a server restart before taking effect.", - "admin.rate.queriesDescription": "Throttles API at this number of requests per second.", - "admin.rate.queriesExample": "E.g.: \"10\"", - "admin.rate.queriesTitle": "Maximum Queries per Second:", - "admin.rate.remoteDescription": "When true, rate limit API access by IP address.", - "admin.rate.remoteTitle": "Vary rate limit by remote address: ", - "admin.rate.title": "Rate Limiting", - "admin.rate.varyByUser": "Vary rate limit by user: ", - "admin.rate.varyByUserDescription": "When true, rate limit API access by user authentication token.", - "admin.recycle.button": "Recycle Database Connections", - "admin.recycle.recycleDescription": "Deployments using multiple databases can switch from one master database to another without restarting the Mattermost server by updating \"config.json\" to the new desired configuration and using the {reloadConfiguration} feature to load the new settings while the server is running. The administrator should then use {featureName} feature to recycle the database connections based on the new settings.", - "admin.recycle.recycleDescription.featureName": "Recycle Database Connections", - "admin.recycle.recycleDescription.reloadConfiguration": "Environment > Web Server > Reload Configuration from Disk", - "admin.recycle.reloadFail": "Recycling unsuccessful: {error}", - "admin.regenerate": "Regenerate", - "admin.reload.button": "Reload Configuration From Disk", - "admin.reload.reloadDescription": "Deployments using multiple databases can switch from one master database to another without restarting the Mattermost server by updating \"config.json\" to the new desired configuration and using the {featureName} feature to load the new settings while the server is running. The administrator should then use the {recycleDatabaseConnections} feature to recycle the database connections based on the new settings.", - "admin.reload.reloadDescription.featureName": "Reload Configuration from Disk", - "admin.reload.reloadDescription.recycleDatabaseConnections": "Environment > Database > Recycle Database Connections", - "admin.reload.reloadFail": "Reloading unsuccessful: {error}", - "admin.requestButton.loading": " Loading...", - "admin.requestButton.requestFailure": "Test Failure: {error}", - "admin.requestButton.requestSuccess": "Test Successful", - "admin.reset_email.cancel": "Cancel", - "admin.reset_email.newEmail": "New Email", - "admin.reset_email.reset": "Reset", - "admin.reset_email.titleReset": "Update Email", - "admin.reset_password.cancel": "Cancel", - "admin.reset_password.curentPassword": "Current Password", - "admin.reset_password.missing_current": "Please enter your current password.", - "admin.reset_password.newPassword": "New Password", - "admin.reset_password.reset": "Reset", - "admin.reset_password.titleReset": "Reset Password", - "admin.reset_password.titleSwitch": "Switch Account to Email/Password", - "admin.revoke_token_button.delete": "Delete", - "admin.s3.connectionS3Test": "Test Connection", - "admin.s3.s3Fail": "Connection unsuccessful: {error}", - "admin.s3.s3Success": "Connection was successful", - "admin.s3.testing": "Testing...", - "admin.saml_feature_discovery.copy": "When you connect Mattermost with your organization's single sign-on provider, users can access Mattermost without having to re-enter their credentials.", - "admin.saml_feature_discovery.title": "Integrate SAML 2.0 with Mattermost Enterprise E20", - "admin.saml.adminAttrDesc": "(Optional) The attribute in the SAML Assertion for designating System Admins. The users selected by the query will have access to your Mattermost server as System Admins. By default, System Admins have complete access to the Mattermost System Console.\n \nExisting members that are identified by this attribute will be promoted from member to System Admin upon next login. The next login is based upon Session lengths set in **System Console > Session Lengths**. It is highly recommend to manually demote users to members in **System Console > User Management** to ensure access is restricted immediately.\n \nNote: If this filter is removed/changed, System Admins that were promoted via this filter will be demoted to members and will not retain access to the System Console. When this filter is not in use, System Admins can be manually promoted/demoted in **System Console > User Management**.", - "admin.saml.adminAttrEx": "E.g.: \"usertype=Admin\" or \"isAdmin=true\"", - "admin.saml.adminAttrTitle": "Admin Attribute:", - "admin.saml.assertionConsumerServiceURLEx": "E.g.: \"https:///login/sso/saml\"", - "admin.saml.assertionConsumerServiceURLPopulatedDesc": "This field is also known as the Assertion Consumer Service URL.", - "admin.saml.assertionConsumerServiceURLTitle": "Service Provider Login URL:", - "admin.saml.canonicalAlgorithmDescription.c14": "Specify the Canonicalization algorithm (Canonical XML 1.1). Please see more information provided at http://www.w3.org/2006/12/xml-c14n11", - "admin.saml.canonicalAlgorithmDescription.exc": "Specify the Canonicalization algorithm (Exclusive XML Canonicalization 1.0). Please see more information provided at http://www.w3.org/2001/10/xml-exc-c14n#", - "admin.saml.canonicalAlgorithmDisplay.n10": "Exclusive XML Canonicalization 1.0 (omit comments)", - "admin.saml.canonicalAlgorithmDisplay.n11": "Canonical XML 1.1 (omit comments)", - "admin.saml.canonicalAlgorithmTitle": "Canonicalization Algorithm", - "admin.saml.emailAttrDesc": "The attribute in the SAML Assertion that will be used to populate the email addresses of users in Mattermost.", - "admin.saml.emailAttrEx": "E.g.: \"Email\" or \"PrimaryEmail\"", - "admin.saml.emailAttrTitle": "Email Attribute:", - "admin.saml.enableAdminAttrTitle": "Enable Admin Attribute:", - "admin.saml.enableDescription": "When true, Mattermost allows login using SAML 2.0. Please see [documentation](!http://docs.mattermost.com/deployment/sso-saml.html) to learn more about configuring SAML for Mattermost.", - "admin.saml.enableSyncWithLdapDescription": "When true, Mattermost periodically synchronizes SAML user attributes, including user deactivation and removal, from AD/LDAP. Enable and configure synchronization settings at **Authentication > AD/LDAP**. When false, user attributes are updated from SAML during user login. See [documentation](!https://about.mattermost.com/default-saml-ldap-sync) to learn more.", - "admin.saml.enableSyncWithLdapIncludeAuthDescription": "When true, Mattermost will override the SAML ID attribute with the AD/LDAP ID attribute if configured or override the SAML Email attribute with the AD/LDAP Email attribute if SAML ID attribute is not present. This will allow you automatically migrate users from Email binding to ID binding to prevent creation of new users when an email address changes for a user. Moving from true to false, will remove the override from happening.\n \n**Note:** SAML IDs must match the LDAP IDs to prevent disabling of user accounts. Please review [documentation](!https://docs.mattermost.com/deployment/sso-saml-ldapsync.html) for more information.", - "admin.saml.enableSyncWithLdapIncludeAuthTitle": "Override SAML bind data with AD/LDAP information:", - "admin.saml.enableSyncWithLdapTitle": "Enable Synchronizing SAML Accounts With AD/LDAP:", - "admin.saml.enableTitle": "Enable Login With SAML 2.0:", - "admin.saml.encryptDescription": "When false, Mattermost will not decrypt SAML Assertions encrypted with your Service Provider Public Certificate. Disabling encryption is not recommended for production environments.", - "admin.saml.encryptTitle": "Enable Encryption:", - "admin.saml.firstnameAttrDesc": "(Optional) The attribute in the SAML Assertion that will be used to populate the first name of users in Mattermost.", - "admin.saml.firstnameAttrEx": "E.g.: \"FirstName\"", - "admin.saml.firstnameAttrTitle": "First Name Attribute:", - "admin.saml.getSamlMetadataFromIDPFail": "SAML Metadata URL did not connect and pull data successfully", - "admin.saml.getSamlMetadataFromIDPFetching": "Fetching...", - "admin.saml.getSamlMetadataFromIDPSuccess": "SAML Metadata retrieved successfully. Two fields and one certificate have been updated", - "admin.saml.getSamlMetadataFromIDPUrl": "Get SAML Metadata From IdP", - "admin.saml.guestAttrDesc": "(Optional) Requires Guest Access to be enabled before being applied. The attribute in the SAML Assertion that will be used to apply a guest role to users in Mattermost. Guests are prevented from accessing teams or channels upon logging in until they are assigned a team and at least one channel.\n \nNote: If this attribute is removed/changed from your guest user in SAML and the user is still active, they will not be promoted to a member and will retain their Guest role. Guests can be promoted in **System Console > User Management**.\n \n \nExisting members that are identified by this attribute as a guest will be demoted from a member to a guest when they are asked to login next. The next login is based upon Session lengths set in **System Console > Session Lengths**. It is highly recommend to manually demote users to guests in **System Console > User Management ** to ensure access is restricted immediately.", - "admin.saml.guestAttrEx": "E.g.: \"usertype=Guest\" or \"isGuest=true\"", - "admin.saml.guestAttrTitle": "Guest Attribute:", - "admin.saml.idAttrDesc": "(Optional) The attribute in the SAML Assertion that will be used to bind users from SAML to users in Mattermost.", - "admin.saml.idAttrEx": "E.g.: \"Id\"", - "admin.saml.idAttrTitle": "Id Attribute:", - "admin.saml.idpCertificateFileDesc": "The public authentication certificate issued by your Identity Provider.", - "admin.saml.idpCertificateFileRemoveDesc": "Remove the public authentication certificate issued by your Identity Provider.", - "admin.saml.idpCertificateFileTitle": "Identity Provider Public Certificate:", - "admin.saml.idpDescriptorUrlDesc": "The issuer URL for the Identity Provider you use for SAML requests.", - "admin.saml.idpDescriptorUrlEx": "E.g.: \"https://idp.example.org/SAML2/issuer\"", - "admin.saml.idpDescriptorUrlTitle": "Identity Provider Issuer URL:", - "admin.saml.idpMetadataUrlDesc": "The URL where Mattermost sends a request to obtain metadata", - "admin.saml.idpMetadataUrlEx": "E.g.: \"https://idp.example.org/SAML2/saml/metadata\"", - "admin.saml.idpMetadataUrlTitle": "Identity Provider Metadata URL:", - "admin.saml.idpUrlDesc": "The URL where Mattermost sends a SAML request to start login sequence.", - "admin.saml.idpUrlEx": "E.g.: \"https://idp.example.org/SAML2/SSO/Login\"", - "admin.saml.idpUrlTitle": "SAML SSO URL:", - "admin.saml.lastnameAttrDesc": "(Optional) The attribute in the SAML Assertion that will be used to populate the last name of users in Mattermost.", - "admin.saml.lastnameAttrEx": "E.g.: \"LastName\"", - "admin.saml.lastnameAttrTitle": "Last Name Attribute:", - "admin.saml.localeAttrDesc": "(Optional) The attribute in the SAML Assertion that will be used to populate the language of users in Mattermost.", - "admin.saml.localeAttrEx": "E.g.: \"Locale\" or \"PrimaryLanguage\"", - "admin.saml.localeAttrTitle": "Preferred Language Attribute:", - "admin.saml.loginButtonTextDesc": "(Optional) The text that appears in the login button on the login page. Defaults to \"SAML\".", - "admin.saml.loginButtonTextEx": "E.g.: \"OKTA\"", - "admin.saml.loginButtonTextTitle": "Login Button Text:", - "admin.saml.nicknameAttrDesc": "(Optional) The attribute in the SAML Assertion that will be used to populate the nickname of users in Mattermost.", - "admin.saml.nicknameAttrEx": "E.g.: \"Nickname\"", - "admin.saml.nicknameAttrTitle": "Nickname Attribute:", - "admin.saml.positionAttrDesc": "(Optional) The attribute in the SAML Assertion that will be used to populate the position of users in Mattermost.", - "admin.saml.positionAttrEx": "E.g.: \"Role\"", - "admin.saml.positionAttrTitle": "Position Attribute:", - "admin.saml.privateKeyFileFileDesc": "The private key used to decrypt SAML Assertions from the Identity Provider.", - "admin.saml.privateKeyFileFileRemoveDesc": "Remove the private key used to decrypt SAML Assertions from the Identity Provider.", - "admin.saml.privateKeyFileTitle": "Service Provider Private Key:", - "admin.saml.publicCertificateFileDesc": "The certificate used to generate the signature on a SAML request to the Identity Provider for a service provider initiated SAML login, when Mattermost is the Service Provider.", - "admin.saml.publicCertificateFileRemoveDesc": "Remove the certificate used to generate the signature on a SAML request to the Identity Provider for a service provider initiated SAML login, when Mattermost is the Service Provider.", - "admin.saml.publicCertificateFileTitle": "Service Provider Public Certificate:", - "admin.saml.remove.idp_certificate": "Remove Identity Provider Certificate", - "admin.saml.remove.privKey": "Remove Service Provider Private Key", - "admin.saml.remove.sp_certificate": "Remove Service Provider Certificate", - "admin.saml.removing.certificate": "Removing Certificate...", - "admin.saml.removing.privKey": "Removing Private Key...", - "admin.saml.signatureAlgorithmDescription.sha1": "Specify the Signature algorithm used to sign the request (RSAwithSHA1). Please see more information provided at http://www.w3.org/2000/09/xmldsig#rsa-sha1", - "admin.saml.signatureAlgorithmDescription.sha256": "Specify the Signature algorithm used to sign the request (RSAwithSHA256). Please see more information provided at http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 [section 6.4.2 RSA (PKCS#1 v1.5)]", - "admin.saml.signatureAlgorithmDescription.sha512": "Specify the Signature algorithm used to sign the request (RSAwithSHA512). Please see more information provided at http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", - "admin.saml.signatureAlgorithmDisplay.sha1": "RSAwithSHA1", - "admin.saml.signatureAlgorithmDisplay.sha256": "RSAwithSHA256", - "admin.saml.signatureAlgorithmDisplay.sha512": "RSAwithSHA512", - "admin.saml.signatureAlgorithmTitle": "Signature Algorithm", - "admin.saml.signRequestDescription": "When true, Mattermost will sign the SAML request using your private key. When false, Mattermost will not sign the SAML request.", - "admin.saml.signRequestTitle": "Sign Request:", - "admin.saml.uploading.certificate": "Uploading Certificate...", - "admin.saml.uploading.privateKey": "Uploading Private Key...", - "admin.saml.usernameAttrDesc": "The attribute in the SAML Assertion that will be used to populate the username field in Mattermost.", - "admin.saml.usernameAttrEx": "E.g.: \"Username\"", - "admin.saml.usernameAttrTitle": "Username Attribute:", - "admin.saml.verifyDescription": "When false, Mattermost will not verify that the signature sent from a SAML Response matches the Service Provider Login URL. Disabling verification is not recommended for production environments.", - "admin.saml.verifyTitle": "Verify Signature:", - "admin.saving": "Saving Config...", - "admin.security.password": "Password", - "admin.service.attemptDescription": "Number of login attempts allowed before a user is locked out and required to reset their password via email.", - "admin.service.attemptExample": "E.g.: \"10\"", - "admin.service.attemptTitle": "Maximum Login Attempts:", - "admin.service.cmdsDesc": "When true, custom slash commands will be allowed. See [documentation](!http://docs.mattermost.com/developer/slash-commands.html) to learn more.", - "admin.service.cmdsTitle": "Enable Custom Slash Commands: ", - "admin.service.complianceExportDesc": "When true, Mattermost will export all messages that were posted in the last 24 hours. The export task is scheduled to run once per day. See [the documentation](!https://about.mattermost.com/default-compliance-export-documentation) to learn more.", - "admin.service.complianceExportTitle": "Enable Compliance Export:", - "admin.service.corsAllowCredentialsDescription": "When true, requests that pass validation will include the Access-Control-Allow-Credentials header.", - "admin.service.corsAllowCredentialsLabel": "CORS Allow Credentials:", - "admin.service.corsDebugDescription": "When true, prints messages to the logs to help when developing an integration that uses CORS. These messages will include the structured key value pair \"source\":\"cors\".", - "admin.service.CorsDebugLabel": "CORS Debug:", - "admin.service.corsDescription": "Enable HTTP Cross origin request from a specific domain. Use \"*\" if you want to allow CORS from any domain or leave it blank to disable it. Should not be set to \"*\" in production.", - "admin.service.corsEx": "http://example.com", - "admin.service.corsExposedHeadersDescription": "Whitelist of headers that will be accessible to the requester.", - "admin.service.corsExposedHeadersTitle": "CORS Exposed Headers:", - "admin.service.corsHeadersEx": "X-My-Header", - "admin.service.corsTitle": "Enable cross-origin requests from:", - "admin.service.developerDesc": "When true, JavaScript errors are shown in a purple bar at the top of the user interface. Not recommended for use in production. ", - "admin.service.developerTitle": "Enable Developer Mode: ", - "admin.service.disableBotOwnerDeactivatedTitle": "Disable bot accounts when owner is deactivated:", - "admin.service.disableBotWhenOwnerIsDeactivated": "When a user is deactivated, disables all bot accounts managed by the user. To re-enable bot accounts, go to [Integrations > Bot Accounts]({siteURL}/_redirect/integrations/bots).", - "admin.service.enableBotAccountCreation": "When true, System Admins can create bot accounts for integrations in [Integrations > Bot Accounts]({siteURL}/_redirect/integrations/bots). Bot accounts are similar to user accounts except they cannot be used to log in. See [documentation](https://mattermost.com/pl/default-bot-accounts) to learn more.", - "admin.service.enableBotTitle": "Enable Bot Account Creation: ", - "admin.service.enforceMfaDesc": "When true, [multi-factor authentication](!https://docs.mattermost.com/deployment/auth.html) is required for login. New users will be required to configure MFA on signup. Logged in users without MFA configured are redirected to the MFA setup page until configuration is complete.\n \nIf your system has users with login methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost.", - "admin.service.enforceMfaTitle": "Enforce Multi-factor Authentication:", - "admin.service.extendSessionLengthActivity.helpText": "When true, sessions will be automatically extended when the user is active in their Mattermost client. Users sessions will only expire if they are not active in their Mattermost client for the entire duration of the session lengths defined in the fields below. When false, sessions will not extend with activity in Mattermost. User sessions will immediately expire at the end of the session length or idle timeouts defined below. ", - "admin.service.extendSessionLengthActivity.label": "Extend session length with activity: ", - "admin.service.forward80To443": "Forward port 80 to 443:", - "admin.service.forward80To443Description": "Forwards all insecure traffic from port 80 to secure port 443. Not recommended when using a proxy server.", - "admin.service.forward80To443Description.disabled": "Forwards all insecure traffic from port 80 to secure port 443. Not recommended when using a proxy server.\n \nThis setting cannot be enabled until your server is [listening](#ListenAddress) on port 443.", - "admin.service.googleDescription": "Set this key to enable the display of titles for embedded YouTube video previews. Without the key, YouTube previews will still be created based on hyperlinks appearing in messages or comments but they will not show the video title. View a [Google Developers Tutorial](!https://www.youtube.com/watch?v=Im69kzhpR3I) for instructions on how to obtain a key and add YouTube Data API v3 as a service to your key.", - "admin.service.googleExample": "E.g.: \"7rAh6iwQCkV4cA1Gsg3fgGOXJAQ43QV\"", - "admin.service.googleTitle": "Google API Key:", - "admin.service.iconDescription": "When true, webhooks, slash commands and other integrations, such as [Zapier](!https://docs.mattermost.com/integrations/zapier.html), will be allowed to change the profile picture they post with. Note: Combined with allowing integrations to override usernames, users may be able to perform phishing attacks by attempting to impersonate other users.", - "admin.service.iconTitle": "Enable integrations to override profile picture icons:", - "admin.service.insecureTlsDesc": "When true, any outgoing HTTPS requests will accept unverified, self-signed certificates. For example, outgoing webhooks to a server with a self-signed TLS certificate, using any domain, will be allowed. Note that this makes these connections susceptible to man-in-the-middle attacks.", - "admin.service.insecureTlsTitle": "Enable Insecure Outgoing Connections: ", - "admin.service.integrationAdmin": "Restrict managing integrations to Admins:", - "admin.service.integrationAdminDesc": "When true, webhooks and slash commands can only be created, edited and viewed by Team and System Admins, and OAuth 2.0 applications by System Admins. Integrations are available to all users after they have been created by the Admin.", - "admin.service.internalConnectionsDesc": "A whitelist of local network addresses that can be requested by the Mattermost server on behalf of a client. Care should be used when configuring this setting to prevent unintended access to your local network. See [documentation](!https://mattermost.com/pl/default-allow-untrusted-internal-connections) to learn more.", - "admin.service.internalConnectionsEx": "webhooks.internal.example.com 127.0.0.1 10.0.16.0/28", - "admin.service.internalConnectionsTitle": "Allow untrusted internal connections to: ", - "admin.service.letsEncryptCertificateCacheFile": "Let's Encrypt Certificate Cache File:", - "admin.service.letsEncryptCertificateCacheFileDescription": "Certificates retrieved and other data about the Let's Encrypt service will be stored in this file.", - "admin.service.listenAddress": "Listen Address:", - "admin.service.listenDescription": "The address and port to which to bind and listen. Specifying \":8065\" will bind to all network interfaces. Specifying \"127.0.0.1:8065\" will only bind to the network interface having that IP address. If you choose a port of a lower level (called \"system ports\" or \"well-known ports\", in the range of 0-1023), you must have permissions to bind to that port. On Linux you can use: \"sudo setcap cap_net_bind_service=+ep ./bin/mattermost\" to allow Mattermost to bind to well-known ports.", - "admin.service.listenExample": "E.g.: \":8065\"", - "admin.service.mfaDesc": "When true, users with AD/LDAP or email login can add multi-factor authentication to their account using Google Authenticator.", - "admin.service.mfaTitle": "Enable Multi-factor Authentication:", - "admin.service.minimumHashtagLengthDescription": "Minimum number of characters in a hashtag. This must be greater than or equal to 2. MySQL databases must be configured to support searching strings shorter than three characters, [see documentation](!https://dev.mysql.com/doc/refman/8.0/en/fulltext-fine-tuning.html).", - "admin.service.minimumHashtagLengthExample": "E.g.: \"3\"", - "admin.service.minimumHashtagLengthTitle": "Minimum Hashtag Length:", - "admin.service.mobileSessionDays": "Session Length Mobile (days):", - "admin.service.mobileSessionDaysDesc": "The number of days from the last time a user entered their credentials to the expiry of the user's session. After changing this setting, the new session length will take effect after the next time the user enters their credentials.", - "admin.service.mobileSessionDaysDesc.extendLength": "Set the number of days from the last activity in Mattermost to the expiry of the user’s session on mobile. After changing this setting, the new session length will take effect after the next time the user enters their credentials.", - "admin.service.outWebhooksDesc": "When true, outgoing webhooks will be allowed. See [documentation](!http://docs.mattermost.com/developer/webhooks-outgoing.html) to learn more.", - "admin.service.outWebhooksTitle": "Enable Outgoing Webhooks: ", - "admin.service.overrideDescription": "When true, webhooks, slash commands and other integrations, such as [Zapier](!https://docs.mattermost.com/integrations/zapier.html), will be allowed to change the username they are posting as. Note: Combined with allowing integrations to override profile picture icons, users may be able to perform phishing attacks by attempting to impersonate other users.", - "admin.service.overrideTitle": "Enable integrations to override usernames:", - "admin.service.readTimeout": "Read Timeout:", - "admin.service.readTimeoutDescription": "Maximum time allowed from when the connection is accepted to when the request body is fully read.", - "admin.service.sessionCache": "Session Cache (minutes):", - "admin.service.sessionCacheDesc": "The number of minutes to cache a session in memory.", - "admin.service.sessionDaysEx": "E.g.: \"30\"", - "admin.service.sessionIdleTimeout": "Session Idle Timeout (minutes):", - "admin.service.sessionIdleTimeoutDesc": "The number of minutes from the last time a user was active on the system to the expiry of the user's session. Once expired, the user will need to log in to continue. Minimum is 5 minutes, and 0 is unlimited.\n \nApplies to the desktop app and browsers. For mobile apps, use an EMM provider to lock the app when not in use. In High Availability mode, enable IP hash load balancing for reliable timeout measurement.", - "admin.service.sessionIdleTimeoutEx": "E.g.: \"60\"", - "admin.service.sessionMinutesEx": "E.g.: \"10\"", - "admin.service.siteURL": "Site URL:", - "admin.service.siteURLDescription": "The URL that users will use to access Mattermost. Standard ports, such as 80 and 443, can be omitted, but non-standard ports are required. For example: http://example.com:8065. This setting is required.\n \nMattermost may be hosted at a subpath. For example: http://example.com:8065/company/mattermost. A restart is required before the server will work correctly.", - "admin.service.siteURLExample": "E.g.: \"http://example.com:8065\"", - "admin.service.ssoSessionDays": "Session Length SSO (days):", - "admin.service.ssoSessionDaysDesc": "The number of days from the last time a user entered their credentials to the expiry of the user's session. If the authentication method is SAML or P1 SSO, the user may automatically be logged back in to Mattermost if they are already logged in to SAML or P1 SSO. After changing this setting, the setting will take effect after the next time the user enters their credentials.", - "admin.service.ssoSessionDaysDesc.extendLength": "Set the number of days from the last activity in Mattermost to the expiry of the user’s session for SSO authentication, such as SAML, P1 SSO and OAuth 2.0. If the authentication method is SAML or P1 SSO, the user may automatically be logged back in to Mattermost if they are already logged in to SAML or P1 SSO. After changing this setting, the setting will take effect after the next time the user enters their credentials.", - "admin.service.testingDescription": "When true, /test slash command is enabled to load test accounts, data and text formatting. Changing this requires a server restart before taking effect.", - "admin.service.testingTitle": "Enable Testing Commands: ", - "admin.service.testSiteURL": "Test Live URL", - "admin.service.testSiteURLFail": "Test unsuccessful: {error}", - "admin.service.testSiteURLSuccess": "Test successful. This is a valid URL.", - "admin.service.testSiteURLTesting": "Testing...", - "admin.service.tlsCertFile": "TLS Certificate File:", - "admin.service.tlsCertFileDescription": "The certificate file to use.", - "admin.service.tlsKeyFile": "TLS Key File:", - "admin.service.tlsKeyFileDescription": "The private key file to use.", - "admin.service.useLetsEncrypt": "Use Let's Encrypt:", - "admin.service.useLetsEncryptDescription": "Enable the automatic retrieval of certificates from Let's Encrypt. The certificate will be retrieved when a client attempts to connect from a new domain. This will work with multiple domains.", - "admin.service.useLetsEncryptDescription.disabled": "Enable the automatic retrieval of certificates from Let's Encrypt. The certificate will be retrieved when a client attempts to connect from a new domain. This will work with multiple domains.\n \nThis setting cannot be enabled unless the [Forward port 80 to 443](#Forward80To443) setting is set to true.", - "admin.service.userAccessTokensDescription": "When true, users can create [user access tokens](!https://about.mattermost.com/default-user-access-tokens) for integrations in **Account Settings > Security**. They can be used to authenticate against the API and give full access to the account.\n\n To manage who can create personal access tokens or to search users by token ID, go to the **User Management > Users** page.", - "admin.service.userAccessTokensTitle": "Enable Personal Access Tokens: ", - "admin.service.webhooksDescription": "When true, incoming webhooks will be allowed. To help combat phishing attacks, all posts from webhooks will be labelled by a BOT tag. See [documentation](!http://docs.mattermost.com/developer/webhooks-incoming.html) to learn more.", - "admin.service.webhooksTitle": "Enable Incoming Webhooks: ", - "admin.service.webSessionDays": "Session Length AD/LDAP and Email (days):", - "admin.service.webSessionDaysDesc": "The number of days from the last time a user entered their credentials to the expiry of the user's session. After changing this setting, the new session length will take effect after the next time the user enters their credentials.", - "admin.service.webSessionDaysDesc.extendLength": "Set the number of days from the last activity in Mattermost to the expiry of the user’s session when using email and AD/LDAP authentication. After changing this setting, the new session length will take effect after the next time the user enters their credentials.", - "admin.service.writeTimeout": "Write Timeout:", - "admin.service.writeTimeoutDescription": "If using HTTP (insecure), this is the maximum time allowed from the end of reading the request headers until the response is written. If using HTTPS, it is the total time from when the connection is accepted until the response is written.", - "admin.sessionLengths.title": "Session Lengths", - "admin.set_by_env": "This setting has been set through an environment variable. It cannot be changed through the System Console.", - "admin.sidebar.about": "About", - "admin.sidebar.announcement": "Announcement Banner", - "admin.sidebar.authentication": "Authentication", - "admin.sidebar.blevesearch": "Bleve", - "admin.sidebar.channels": "Channels", - "admin.sidebar.compliance": "Compliance", - "admin.sidebar.complianceExport": "Compliance Export (Beta)", - "admin.sidebar.complianceMonitoring": "Compliance Monitoring", - "admin.sidebar.cors": "CORS", - "admin.sidebar.customization": "Customization", - "admin.sidebar.customTermsOfService": "Custom Terms of Service (Beta)", - "admin.sidebar.database": "Database", - "admin.sidebar.dataRetentionPolicy": "Data Retention Policy", - "admin.sidebar.developer": "Developer", - "admin.sidebar.elasticsearch": "Elasticsearch", - "admin.sidebar.email": "Email", - "admin.sidebar.emoji": "Emoji", - "admin.sidebar.environment": "Environment", - "admin.sidebar.experimental": "Experimental", - "admin.sidebar.experimentalFeatures": "Features", - "admin.sidebar.fileSharingDownloads": "File Sharing and Downloads", - "admin.sidebar.fileStorage": "File Storage", - "admin.sidebar.filter": "Find settings", - "admin.sidebar.gif": "GIF (Beta)", - "admin.sidebar.gitlab": "P1 SSO", - "admin.sidebar.groups": "Groups (Beta)", - "admin.sidebar.guest_access": "Guest Access (Beta)", - "admin.sidebar.highAvailability": "High Availability", - "admin.sidebar.imageProxy": "Image Proxy", - "admin.sidebar.integrations": "Integrations", - "admin.sidebar.ldap": "AD/LDAP", - "admin.sidebar.license": "Edition and License", - "admin.sidebar.localization": "Localization", - "admin.sidebar.logging": "Logging", - "admin.sidebar.logs": "Server Logs", - "admin.sidebar.metrics": "Performance Monitoring", - "admin.sidebar.mfa": "MFA", - "admin.sidebar.notifications": "Notifications", - "admin.sidebar.oauth": "OAuth 2.0", - "admin.sidebar.password": "Password", - "admin.sidebar.permissions": "Permissions", - "admin.sidebar.plugins": "Plugins (Beta)", - "admin.sidebar.posts": "Posts", - "admin.sidebar.publicLinks": "Public Links", - "admin.sidebar.pushNotificationServer": "Push Notification Server", - "admin.sidebar.rateLimiting": "Rate Limiting", - "admin.sidebar.reporting": "Reporting", - "admin.sidebar.saml": "SAML 2.0", - "admin.sidebar.sessionLengths": "Session Lengths", - "admin.sidebar.signup": "Signup", - "admin.sidebar.site": "Site Configuration", - "admin.sidebar.siteStatistics": "Site Statistics", - "admin.sidebar.smtp": "SMTP", - "admin.sidebar.teams": "Teams", - "admin.sidebar.teamStatistics": "Team Statistics", - "admin.sidebar.userManagement": "User Management", - "admin.sidebar.users": "Users", - "admin.sidebar.usersAndTeams": "Users and Teams", - "admin.sidebar.webServer": "Web Server", - "admin.sidebarHeader.systemConsole": "System Console", - "admin.site.announcementBanner": "Announcement Banner", - "admin.site.customization": "Customization", - "admin.site.emoji": "Emoji", - "admin.site.fileSharingDownloads": "File Sharing and Downloads", - "admin.site.localization": "Localization", - "admin.site.posts": "Posts", - "admin.site.public_links": "Public Links", - "admin.site.usersAndTeams": "Users and Teams", - "admin.sql.connMaxLifetimeDescription": "Maximum lifetime (in milliseconds) for a connection to the database.", - "admin.sql.connMaxLifetimeExample": "E.g.: \"3600000\"", - "admin.sql.connMaxLifetimeTitle": "Maximum Connection Lifetime:", - "admin.sql.dataSource": "Data Source:", - "admin.sql.dataSourceDescription": "Set the database source in the config.json file.", - "admin.sql.disableDatabaseSearchDescription": "Disables the use of the database to perform searches. Should only be used when other [search engines](!https://mattermost.com/pl/default-search-engine) are configured.", - "admin.sql.disableDatabaseSearchTitle": "Disable database search: ", - "admin.sql.driverName": "Driver Name:", - "admin.sql.driverNameDescription": "Set the database driver in the config.json file.", - "admin.sql.maxConnectionsDescription": "Maximum number of idle connections held open to the database.", - "admin.sql.maxConnectionsExample": "E.g.: \"10\"", - "admin.sql.maxConnectionsTitle": "Maximum Idle Connections:", - "admin.sql.maxOpenDescription": "Maximum number of open connections held open to the database.", - "admin.sql.maxOpenExample": "E.g.: \"10\"", - "admin.sql.maxOpenTitle": "Maximum Open Connections:", - "admin.sql.noteDescription": "Changing properties in this section will require a server restart before taking effect.", - "admin.sql.queryTimeoutDescription": "The number of seconds to wait for a response from the database after opening a connection and sending the query. Errors that you see in the UI or in the logs as a result of a query timeout can vary depending on the type of query.", - "admin.sql.queryTimeoutExample": "E.g.: \"30\"", - "admin.sql.queryTimeoutTitle": "Query Timeout:", - "admin.sql.traceDescription": "(Development Mode) When true, executing SQL statements are written to the log.", - "admin.sql.traceTitle": "SQL Statement Logging: ", - "admin.support.aboutDesc": "The URL for the About link on the Mattermost login and sign-up pages. If this field is empty, the About link is hidden from users.", - "admin.support.aboutTitle": "About Link:", - "admin.support.emailHelp": "Email address displayed on email notifications and during tutorial for end users to ask support questions.", - "admin.support.emailTitle": "Support Email:", - "admin.support.enableTermsOfServiceHelp": "When true, new users must accept the terms of service before accessing any Mattermost teams on desktop, web or mobile. Existing users must accept them after login or a page refresh.\n \nTo update terms of service link displayed in account creation and login pages, go to [Site Configuration > Customization](../site_config/customization).", - "admin.support.enableTermsOfServiceTitle": "Enable Custom Terms of Service:", - "admin.support.helpDesc": "The URL for the Help link on the Mattermost login page, sign-up pages, and Main Menu. If this field is empty, the Help link is hidden from users.", - "admin.support.helpTitle": "Help Link:", - "admin.support.privacyDesc": "The URL for the Privacy link on the login and sign-up pages. If this field is empty, the Privacy link is hidden from users.", - "admin.support.privacyTitle": "Privacy Policy Link:", - "admin.support.problemDesc": "The URL for the Report a Problem link in the Main Menu. If this field is empty, the link is removed from the Main Menu.", - "admin.support.problemTitle": "Report a Problem Link:", - "admin.support.termsDesc": "Link to the terms under which users may use your online service. By default, this includes the \"Mattermost Conditions of Use (End Users)\" explaining the terms under which Mattermost software is provided to end users. If you change the default link to add your own terms for using the service you provide, your new terms must include a link to the default terms so end users are aware of the Mattermost Conditions of Use (End User) for Mattermost software.", - "admin.support.termsOfServiceReAcceptanceHelp": "The number of days before Terms of Service acceptance expires, and the terms must be re-accepted.", - "admin.support.termsOfServiceReAcceptanceTitle": "Re-Acceptance Period:", - "admin.support.termsOfServiceTextHelp": "Text that will appear in your custom Terms of Service. Supports Markdown-formatted text.", - "admin.support.termsOfServiceTextTitle": "Custom Terms of Service Text:", - "admin.support.termsOfServiceTitle": "Custom Terms of Service (Beta)", - "admin.support.termsTitle": "Terms of Service Link:", - "admin.system_users.allUsers": "All Users", - "admin.system_users.guest": "Guest", - "admin.system_users.inactive": "Inactive", - "admin.system_users.noTeams": "No Teams", - "admin.system_users.revoke_all_sessions_button": "Revoke All Sessions", - "admin.system_users.revoke_all_sessions_modal_message": "This action revokes all sessions in the system. All users will be logged out from all devices. Are you sure you want to revoke all sessions?", - "admin.system_users.revoke_all_sessions_modal_title": "Revoke all sessions in the system", - "admin.system_users.revokeAllSessions": "Revoke All Sessions", - "admin.system_users.system_admin": "System Admin", - "admin.system_users.title": "{siteName} Users", - "admin.systemUserDetail.teamList.header.name": "Name", - "admin.systemUserDetail.teamList.header.role": "Role", - "admin.systemUserDetail.teamList.header.type": "Type", - "admin.systemUserDetail.teamList.teamRole.admin": "Team Admin", - "admin.systemUserDetail.teamList.teamRole.guest": "Guest", - "admin.systemUserDetail.teamList.teamRole.member": "Team Member", - "admin.systemUserDetail.teamList.teamType.anyoneCanJoin": "Anyone Can Join", - "admin.systemUserDetail.teamList.teamType.groupSync": "Group Sync", - "admin.systemUserDetail.teamList.teamType.inviteOnly": "Invite Only", - "admin.systemUserDetail.title": "User Configuration", - "admin.team_channel_settings.cancel": "Cancel", - "admin.team_channel_settings.convertAndRemoveConfirmModal.cancel": "No, cancel", - "admin.team_channel_settings.convertAndRemoveConfirmModal.toPrivateConfirm": "Yes, convert channel to private and remove {amount, number} {amount, plural, one {user} other {users}}", - "admin.team_channel_settings.convertAndRemoveConfirmModal.toPrivateTitle": "Convert channel to a private and remove {amount, number} {amount, plural, one {user} other {users}}?", - "admin.team_channel_settings.convertAndRemoveConfirmModal.toPublicConfirm": "Yes, convert channel to public and remove {amount, number} {amount, plural, one {user} other {users}}", - "admin.team_channel_settings.convertAndRemoveConfirmModal.toPublicTitle": "Convert channel to public and remove {amount, number} {amount, plural, one {user} other {users}}", - "admin.team_channel_settings.convertConfirmModal.cancel": "No, cancel", - "admin.team_channel_settings.convertConfirmModal.toPrivateConfirm": "Yes, convert to private channel", - "admin.team_channel_settings.convertConfirmModal.toPrivateMessage": "When you convert **{displayName}** to a private channel, history and membership are preserved. Publicly shared files remain accessible to anyone with the link. Membership in a private channel is by invitation only. \n \nAre you sure you want to convert **{displayName}** to a private channel?", - "admin.team_channel_settings.convertConfirmModal.toPrivateTitle": "Convert {displayName} to a private channel?", - "admin.team_channel_settings.convertConfirmModal.toPublicConfirm": "Yes, convert to public channel", - "admin.team_channel_settings.convertConfirmModal.toPublicMessage": "When you convert **{displayName}** to a public channel, history and membership are preserved. Public channels are discoverable and can by joined by users on the system without invitation. \n \nAre you sure you want to convert **{displayName}** to a public channel?", - "admin.team_channel_settings.convertConfirmModal.toPublicTitle": "Convert {displayName} to a public channel?", - "admin.team_channel_settings.group_list.membersHeader": "Member Count", - "admin.team_channel_settings.group_list.nameHeader": "Group Name", - "admin.team_channel_settings.group_list.no-groups": "No groups specified yet", - "admin.team_channel_settings.group_list.no-synced-groups": "At least one group must be specified", - "admin.team_channel_settings.group_list.rolesHeader": "Roles", - "admin.team_channel_settings.group_row.channelAdmin": "Channel Admin", - "admin.team_channel_settings.group_row.member": "Member", - "admin.team_channel_settings.group_row.memberRole": "Member Role", - "admin.team_channel_settings.group_row.members": "{memberCount, number} {memberCount, plural, one {member} other {members}}", - "admin.team_channel_settings.group_row.remove": "Remove", - "admin.team_channel_settings.group_row.teamAdmin": "Team Admin", - "admin.team_channel_settings.list.paginatorCount": "{startCount, number} - {endCount, number} of {total, number}", - "admin.team_channel_settings.need_domains": "Please specify allowed email domains.", - "admin.team_channel_settings.need_groups": "You must add at least one group to manage this team by sync group members.", - "admin.team_channel_settings.need_groups_channel": "You must add at least one group to manage this channel by sync group members.", - "admin.team_channel_settings.removeConfirmModal.messageChannel": "{amount, number} {amount, plural, one {user} other {users}} will be removed. They are not in groups linked to this channel. Are you sure you wish to remove {amount, plural, one {this user} other {these users}}?", - "admin.team_channel_settings.removeConfirmModal.messageTeam": "{amount, number} {amount, plural, one {user} other {users}} will be removed. They are not in groups linked to this team. Are you sure you wish to remove {amount, plural, one {this user} other {these users}}?", - "admin.team_channel_settings.removeConfirmModal.remove": "Save and remove {amount, plural, one {user} other {users}}", - "admin.team_channel_settings.removeConfirmModal.title": "Save and remove {amount, number} {amount, plural, one {user} other {users}}?", - "admin.team_channel_settings.saving": "Saving Config...", - "admin.team_channel_settings.user_list.groupsHeader": "Groups", - "admin.team_channel_settings.user_list.nameHeader": "Name", - "admin.team_channel_settings.user_list.roleHeader": "Role", - "admin.team_channel_settings.users_will_be_removed": "{amount, number} {amount, plural, one {user} other {users}} will be removed from this team. They are not in groups linked to this team.", - "admin.team_channel_settings.usersToBeRemovedModal.close": "Close", - "admin.team_channel_settings.usersToBeRemovedModal.message": "The members listed below are not in any of the groups currently linked to this team. Because this team is set to be managed by group sync they will all be removed once saved.", - "admin.team_channel_settings.usersToBeRemovedModal.title": "**{total, number} {total, plural, one {User} other {Users}}** To Be Removed", - "admin.team_channel_settings.view_removed_users": "View These Users", - "admin.team_settings.description": "Manage team settings.", - "admin.team_settings.groupsPageTitle": "{siteName} Teams", - "admin.team_settings.team_detail.group_configuration": "Team Configuration", - "admin.team_settings.team_detail.groupsDescription": "Group members will be added to the team.", - "admin.team_settings.team_detail.groupsTitle": "Groups", - "admin.team_settings.team_detail.manageDescription": "Choose between inviting members manually or syncing members automatically from groups.", - "admin.team_settings.team_detail.manageTitle": "Team Management", - "admin.team_settings.team_detail.membersDescription": "A list of users who are currently in the team right now", - "admin.team_settings.team_detail.membersTitle": "Members", - "admin.team_settings.team_detail.profileDescription": "Summary of the team, including team name and description.", - "admin.team_settings.team_detail.profileNoDescription": "No team description added.", - "admin.team_settings.team_detail.profileTitle": "Team Profile", - "admin.team_settings.team_detail.syncedGroupsDescription": "Add and remove team members based on their group membership.", - "admin.team_settings.team_detail.syncedGroupsTitle": "Synced Groups", - "admin.team_settings.team_detail.teamDescription": "**Team Description**:", - "admin.team_settings.team_detail.teamName": "**Team Name**:", - "admin.team_settings.team_details.add_group": "Add Group", - "admin.team_settings.team_details.add_members": "Add Members", - "admin.team_settings.team_details.anyoneCanJoin": "Anyone can join this team", - "admin.team_settings.team_details.anyoneCanJoinDescr": "This team can be discovered allowing anyone with an account to join this team.", - "admin.team_settings.team_details.csvDomains": "Comma Separated Email Domain List", - "admin.team_settings.team_details.groupDetailsToggle": "Enable Group Mentions (Beta)", - "admin.team_settings.team_details.groupDetailsToggleDescr": "When enabled, this group can be mentioned in other channels and teams. This may result in the group member list being visible to all users.", - "admin.team_settings.team_details.specificDomains": "Only specific email domains can join this team", - "admin.team_settings.team_details.specificDomainsDescr": "Users can only join the team if their email matches one of the specified domains", - "admin.team_settings.team_details.syncGroupMembers": "Sync Group Members", - "admin.team_settings.team_details.syncGroupMembersDescr": "When enabled, adding and removing users from groups will add or remove them from this team. The only way of inviting members to this team is by adding the groups they belong to. [Learn More](!https://www.mattermost.com/pl/default-ldap-group-constrained-team-channel.html)", - "admin.team_settings.team_list.mappingHeader": "Management", - "admin.team_settings.team_list.nameHeader": "Name", - "admin.team_settings.team_list.no_teams_found": "No teams found", - "admin.team_settings.team_row.configure": "Edit", - "admin.team_settings.team_row.managementMethod.anyoneCanJoin": "Anyone Can Join", - "admin.team_settings.team_row.managementMethod.groupSync": "Group Sync", - "admin.team_settings.team_row.managementMethod.inviteOnly": "Invite Only", - "admin.team_settings.title": "Teams", - "admin.team.brandDesc": "Enable custom branding to show an image of your choice, uploaded below, and some help text, written below, on the login page.", - "admin.team.brandDescriptionHelp": "Description of service shown in login screens and UI. When not specified, \"All team communication in one place, searchable and accessible anywhere\" is displayed.", - "admin.team.brandDescriptionTitle": "Site Description: ", - "admin.team.brandImageTitle": "Custom Brand Image:", - "admin.team.brandTextDescription": "Text that will appear below your custom brand image on your login screen. Supports Markdown-formatted text. Maximum 500 characters allowed.", - "admin.team.brandTextTitle": "Custom Brand Text:", - "admin.team.brandTitle": "Enable Custom Branding: ", - "admin.team.chooseImage": "Select Image", - "admin.team.editOthersPostsDesc": "When true, Team Administrators and System Administrators can edit other user's posts. When false, only System Administrators can edit other user's posts.", - "admin.team.editOthersPostsTitle": "Allow Team Administrators to edit others posts:", - "admin.team.emailInvitationsDescription": "When true users can invite others to the system using email.", - "admin.team.emailInvitationsTitle": "Enable Email Invitations: ", - "admin.team.invalidateEmailInvitesDescription": "This will invalidate active email invitations that have not been accepted by the user. By default email invitations expire after 48 hours.", - "admin.team.invalidateEmailInvitesFail": "Unable to invalidate pending email invites: {error}", - "admin.team.invalidateEmailInvitesSuccess": "Pending email invitations invalidated successfully", - "admin.team.invalidateEmailInvitesTitle": "Invalidate pending email invites", - "admin.team.maxChannelsDescription": "Maximum total number of channels per team, including both active and archived channels.", - "admin.team.maxChannelsExample": "E.g.: \"100\"", - "admin.team.maxChannelsTitle": "Max Channels Per Team:", - "admin.team.maxNotificationsPerChannelDescription": "Maximum total number of users in a channel before users typing messages, @all, @here, and @channel no longer send notifications because of performance.", - "admin.team.maxNotificationsPerChannelExample": "E.g.: \"1000\"", - "admin.team.maxNotificationsPerChannelTitle": "Max Notifications Per Channel:", - "admin.team.maxUsersDescription": "Maximum total number of users per team, including both active and inactive users.", - "admin.team.maxUsersExample": "E.g.: \"25\"", - "admin.team.maxUsersTitle": "Max Users Per Team:", - "admin.team.noBrandImage": "No brand image uploaded", - "admin.team.openServerDescription": "When true, anyone can signup for a user account on this server without the need to be invited.", - "admin.team.openServerTitle": "Enable Open Server: ", - "admin.team.removeBrandImage": "Remove brand image", - "admin.team.restrict_direct_message_any": "Any user on the Mattermost server", - "admin.team.restrict_direct_message_team": "Any member of the team", - "admin.team.restrictDescription": "New user accounts are restricted to the above specified email domain (e.g. \"mattermost.org\") or list of comma-separated domains (e.g. \"corp.mattermost.com, mattermost.org\"). New teams can only be created by users from the above domain(s). This setting affects email login for users.", - "admin.team.restrictDirectMessage": "Enable users to open Direct Message channels with:", - "admin.team.restrictDirectMessageDesc": "'Any user on the Mattermost server' enables users to open a Direct Message channel with any user on the server, even if they are not on any teams together. 'Any member of the team' limits the ability in the Direct Messages 'More' menu to only open Direct Message channels with users who are in the same team.\n \nNote: This setting only affects the UI, not permissions on the server.", - "admin.team.restrictExample": "E.g.: \"corp.mattermost.com, mattermost.org\"", - "admin.team.restrictGuestDescription": "New user accounts are restricted to the above specified email domain (e.g. \"mattermost.org\") or list of comma-separated domains (e.g. \"corp.mattermost.com, mattermost.org\"). New teams can only be created by users from the above domain(s). This setting affects email login for users. For Guest users, please add domains under Signup > Guest Access.", - "admin.team.restrictTitle": "Restrict new system and team members to specified email domains:", - "admin.team.showFullname": "Show first and last name", - "admin.team.showNickname": "Show nickname if one exists, otherwise show first and last name", - "admin.team.showUsername": "Show username (default)", - "admin.team.siteNameDescription": "Name of service shown in login screens and UI. When not specified, it defaults to \"Mattermost\".", - "admin.team.siteNameExample": "E.g.: \"Mattermost\"", - "admin.team.siteNameTitle": "Site Name:", - "admin.team.teamCreationDescription": "When false, only System Administrators can create teams.", - "admin.team.teamCreationTitle": "Enable Team Creation: ", - "admin.team.teammateNameDisplay": "Teammate Name Display:", - "admin.team.teammateNameDisplayDesc": "Set how to display users' names in posts and the Direct Messages list.", - "admin.team.upload": "Upload", - "admin.team.uploadDesc": "Customize your user experience by adding a custom image to your login screen. Recommended maximum image size is less than 2 MB.", - "admin.team.uploaded": "Uploaded!", - "admin.team.uploading": "Uploading...", - "admin.team.userCreationDescription": "When false, the ability to create accounts is disabled. The create account button displays error when pressed.", - "admin.team.userCreationTitle": "Enable Account Creation: ", - "admin.true": "true", - "admin.user_grid.channel_admin": "Channel Admin", - "admin.user_grid.channel_member": "Channel Member", - "admin.user_grid.guest": "Guest", - "admin.user_grid.name": "Name", - "admin.user_grid.new": "New", - "admin.user_grid.notFound": "No users found", - "admin.user_grid.remove": "Remove", - "admin.user_grid.role": "Role", - "admin.user_grid.system_admin": "System Admin", - "admin.user_grid.team_admin": "Team Admin", - "admin.user_grid.team_member": "Team Member", - "admin.user_item.authServiceEmail": "**Sign-in Method:** Email", - "admin.user_item.authServiceNotEmail": "**Sign-in Method:** {service}", - "admin.user_item.demoteToGuest": "Demote to Guest", - "admin.user_item.emailTitle": "**Email:** {email}", - "admin.user_item.guest": "Guest", - "admin.user_item.inactive": "Inactive", - "admin.user_item.makeActive": "Activate", - "admin.user_item.makeInactive": "Deactivate", - "admin.user_item.makeMember": "Make Team Member", - "admin.user_item.makeTeamAdmin": "Make Team Admin", - "admin.user_item.manageRoles": "Manage Roles", - "admin.user_item.manageTeams": "Manage Teams", - "admin.user_item.manageTokens": "Manage Tokens", - "admin.user_item.member": "Member", - "admin.user_item.menuAriaLabel": "User Actions Menu", - "admin.user_item.mfaNo": "**MFA**: No", - "admin.user_item.mfaYes": "**MFA**: Yes", - "admin.user_item.promoteToUser": "Promote to User", - "admin.user_item.resetEmail": "Update Email", - "admin.user_item.resetMfa": "Remove MFA", - "admin.user_item.resetPwd": "Reset Password", - "admin.user_item.revokeSessions": "Revoke Sessions", - "admin.user_item.switchToEmail": "Switch to Email/Password", - "admin.user_item.sysAdmin": "System Admin", - "admin.user_item.teamAdmin": "Team Admin", - "admin.user_item.teamMember": "Team Member", - "admin.user_item.user_id": "**User ID:** {userID}", - "admin.user_item.userAccessTokenPostAll": "(can create post:all personal access tokens)", - "admin.user_item.userAccessTokenPostAllPublic": "(can create post:channels personal access tokens)", - "admin.user_item.userAccessTokenYes": "(can create personal access tokens)", - "admin.userManagement.userDetail.addTeam": "Add Team", - "admin.userManagement.userDetail.authenticationMethod": "Authentication Method", - "admin.userManagement.userDetail.email": "Email", - "admin.userManagement.userDetail.mfa": "MFA", - "admin.userManagement.userDetail.role": "Role", - "admin.userManagement.userDetail.teamsSubtitle": "Teams to which this user belongs", - "admin.userManagement.userDetail.teamsTitle": "Team Membership", - "admin.userManagement.userDetail.userId": "User ID:", - "admin.userManagement.userDetail.username": "Username", - "admin.viewArchivedChannelsHelpText": "(Beta) When true, allows users to view, share and search for content of channels that have been archived. Users can only view the content in channels of which they were a member before the channel was archived.", - "admin.viewArchivedChannelsTitle": "Allow users to view archived channels:", - "admin.webserverModeDisabled": "Disabled", - "admin.webserverModeDisabledDescription": "The Mattermost server will not serve static files.", - "admin.webserverModeGzip": "gzip", - "admin.webserverModeGzipDescription": "The Mattermost server will serve static files compressed with gzip.", - "admin.webserverModeHelpText": "gzip compression applies to static content files. It is recommended to enable gzip to improve performance unless your environment has specific restrictions, such as a web proxy that distributes gzip files poorly.", - "admin.webserverModeTitle": "Webserver Mode:", - "admin.webserverModeUncompressed": "Uncompressed", - "admin.webserverModeUncompressedDescription": "The Mattermost server will serve static files uncompressed.", - "analytics.chart.loading": "Loading...", - "analytics.chart.meaningful": "Not enough data for a meaningful representation.", - "analytics.system.activeUsers": "Active Users With Posts", - "analytics.system.channelTypes": "Channel Types", - "analytics.system.dailyActiveUsers": "Daily Active Users", - "analytics.system.info": "Use data for only the chosen team. Exclude posts in direct message channels that are not tied to a team.", - "analytics.system.infoAndSkippedIntensiveQueries": "Use data for only the chosen team. Exclude posts in direct message channels that are not tied to a team. \n \n To maximize performance, some statistics are disabled. You can [re-enable them in config.json](!https://docs.mattermost.com/administration/statistics.html).", - "analytics.system.monthlyActiveUsers": "Monthly Active Users", - "analytics.system.postTypes": "Posts, Files and Hashtags", - "analytics.system.privateGroups": "Private Channels", - "analytics.system.publicChannels": "Public Channels", - "analytics.system.skippedIntensiveQueries": "To maximize performance, some statistics are disabled. You can [re-enable them in config.json](!https://docs.mattermost.com/administration/statistics.html).", - "analytics.system.textPosts": "Posts with Text-only", - "analytics.system.title": "System Statistics", - "analytics.system.totalBotPosts": "Total Posts from Bots", - "analytics.system.totalChannels": "Total Channels", - "analytics.system.totalCommands": "Total Commands", - "analytics.system.totalFilePosts": "Posts with Files", - "analytics.system.totalHashtagPosts": "Posts with Hashtags", - "analytics.system.totalIncomingWebhooks": "Incoming Webhooks", - "analytics.system.totalMasterDbConnections": "Master DB Conns", - "analytics.system.totalOutgoingWebhooks": "Outgoing Webhooks", - "analytics.system.totalPosts": "Total Posts", - "analytics.system.totalReadDbConnections": "Replica DB Conns", - "analytics.system.totalSessions": "Total Sessions", - "analytics.system.totalTeams": "Total Teams", - "analytics.system.totalUsers": "Total Active Users", - "analytics.system.totalWebsockets": "WebSocket Conns", - "analytics.team.activeUsers": "Active Users With Posts", - "analytics.team.newlyCreated": "Newly Created Users", - "analytics.team.noTeams": "This server has no teams for which to view statistics.", - "analytics.team.privateGroups": "Private Channels", - "analytics.team.publicChannels": "Public Channels", - "analytics.team.recentUsers": "Recent Active Users", - "analytics.team.title": "Team Statistics for {team}", - "analytics.team.totalPosts": "Total Posts", - "analytics.team.totalUsers": "Total Active Users", - "announcement_bar.error.email_verification_required": "Check your email inbox to verify the address.", - "announcement_bar.error.license_expired": "Enterprise license is expired and some features may be disabled. [Please renew](!{link}).", - "announcement_bar.error.license_expiring": "Enterprise license expires on {date, date, long}. [Please renew](!{link}).", - "announcement_bar.error.past_grace": "Enterprise license is expired and some features may be disabled. Please contact your System Administrator for details.", - "announcement_bar.error.preview_mode": "Preview Mode: Email notifications have not been configured.", - "announcement_bar.error.site_url_gitlab.full": "Please configure your [site URL](https://docs.mattermost.com/administration/config-settings.html#site-url) on the [System Console](/admin_console/environment/web_server).", - "announcement_bar.error.site_url.full": "Please configure your [site URL](https://docs.mattermost.com/administration/config-settings.html#site-url) on the [System Console](/admin_console/environment/web_server).", - "announcement_bar.notification.email_verified": "Email verified", - "api.channel.add_guest.added": "{addedUsername} added to the channel as a guest by {username}.", - "api.channel.add_member.added": "{addedUsername} added to the channel by {username}.", - "api.channel.delete_channel.archived": "{username} archived the channel.", - "api.channel.guest_join_channel.post_and_forget": "{username} joined the channel as a guest.", - "api.channel.join_channel.post_and_forget": "{username} joined the channel.", - "api.channel.leave.left": "{username} left the channel.", - "api.channel.post_convert_channel_to_private.updated_from": "{username} converted the channel from public to private", - "api.channel.post_update_channel_displayname_message_and_forget.updated_from": "{username} updated the channel display name from: {old} to: {new}", - "api.channel.post_update_channel_header_message_and_forget.removed": "{username} removed the channel header (was: {old})", - "api.channel.post_update_channel_header_message_and_forget.updated_from": "{username} updated the channel header from: {old} to: {new}", - "api.channel.post_update_channel_header_message_and_forget.updated_to": "{username} updated the channel header to: {new}", - "api.channel.remove_member.removed": "{removedUsername} was removed from the channel", - "api.channel.restore_channel.unarchived": "{username} unarchived the channel.", - "api.team.add_member.added": "{addedUsername} added to the team by {username}", - "api.team.join_team.post_and_forget": "{username} joined the team.", - "api.team.leave.left": "{username} left the team.", - "api.team.remove_user_from_team.removed": "{removedUsername} was removed from the team.", - "app.channel.post_update_channel_purpose_message.removed": "{username} removed the channel purpose (was: {old})", - "app.channel.post_update_channel_purpose_message.updated_from": "{username} updated the channel purpose from: {old} to: {new}", - "app.channel.post_update_channel_purpose_message.updated_to": "{username} updated the channel purpose to: {new}", - "app.plugin.marketplace_plugins.app_error": "Error connecting to the marketplace server. Please check your settings in the [System Console]({siteURL}/admin_console/plugins/plugin_management).", - "archivedChannelMessage": "You are viewing an **archived channel**. New messages cannot be posted.", - "atmos/camo": "atmos/camo", - "audit_table.accountActive": "Account activated", - "audit_table.accountInactive": "Account deactivated", - "audit_table.action": "Action", - "audit_table.attemptedAllowOAuthAccess": "Attempted to allow a new OAuth service access", - "audit_table.attemptedLicenseAdd": "Attempted to add new license", - "audit_table.attemptedLogin": "Attempted to login", - "audit_table.attemptedOAuthToken": "Attempted to get an OAuth access token", - "audit_table.attemptedPassword": "Attempted to change password", - "audit_table.attemptedRegisterApp": "Attempted to register a new OAuth Application with ID {id}", - "audit_table.attemptedReset": "Attempted to reset password", - "audit_table.attemptedWebhookCreate": "Attempted to create a webhook", - "audit_table.attemptedWebhookDelete": "Attempted to delete a webhook", - "audit_table.authenticated": "Successfully authenticated", - "audit_table.by": " by {username}", - "audit_table.byAdmin": " by an admin", - "audit_table.channelCreated": "Created the {channelName} channel", - "audit_table.channelDeleted": "Archived the channel with the URL {url}", - "audit_table.establishedDM": "Established a direct message channel with {username}", - "audit_table.failedExpiredLicenseAdd": "Failed to add a new license as it has either expired or not yet been started", - "audit_table.failedInvalidLicenseAdd": "Failed to add an invalid license", - "audit_table.failedLogin": "FAILED login attempt", - "audit_table.failedOAuthAccess": "Failed to allow a new OAuth service access - the redirect URI did not match the previously registered callback", - "audit_table.failedPassword": "Failed to change password - tried to update user password who was logged in through OAuth", - "audit_table.failedWebhookCreate": "Failed to create a webhook - bad channel permissions", - "audit_table.failedWebhookDelete": "Failed to delete a webhook - inappropriate conditions", - "audit_table.headerUpdated": "Updated the {channelName} channel header", - "audit_table.ip": "IP Address", - "audit_table.licenseRemoved": "Successfully removed a license", - "audit_table.loginAttempt": " (Login attempt)", - "audit_table.loginFailure": " (Login failure)", - "audit_table.logout": "Logged out of your account", - "audit_table.member": "member", - "audit_table.nameUpdated": "Updated the {channelName} channel name", - "audit_table.oauthTokenFailed": "Failed to get an OAuth access token - {token}", - "audit_table.revokedAll": "Revoked all current sessions for the team", - "audit_table.sentEmail": "Sent an email to {email} to reset your password", - "audit_table.session": "Session ID", - "audit_table.sessionRevoked": "The session with id {sessionId} was revoked", - "audit_table.successfullLicenseAdd": "Successfully added new license", - "audit_table.successfullLogin": "Successfully logged in", - "audit_table.successfullOAuthAccess": "Successfully gave a new OAuth service access", - "audit_table.successfullOAuthToken": "Successfully added a new OAuth service", - "audit_table.successfullPassword": "Successfully changed password", - "audit_table.successfullReset": "Successfully reset password", - "audit_table.successfullWebhookCreate": "Successfully created a webhook", - "audit_table.successfullWebhookDelete": "Successfully deleted a webhook", - "audit_table.timestamp": "Timestamp", - "audit_table.updatedRol": "Updated user role(s) to ", - "audit_table.updateGeneral": "Updated the general settings of your account", - "audit_table.updateGlobalNotifications": "Updated your global notification settings", - "audit_table.updatePicture": "Updated your profile picture", - "audit_table.userAdded": "Added {username} to the {channelName} channel", - "audit_table.userId": "User ID", - "audit_table.userRemoved": "Removed {username} to the {channelName} channel", - "audit_table.verified": "Successfully verified your email address", - "authorize.access": "Allow **{appName}** access?", - "authorize.allow": "Allow", - "authorize.app": "The app **{appName}** would like the ability to access and modify your basic information.", - "authorize.deny": "Deny", - "authorize.title": "Authorize **{appName}** to Connect to Your **Mattermost** User Account", - "backstage_list.search": "Search", - "backstage_navbar.backToMattermost": "Back to {siteName}", - "backstage_sidebar.bots": "Bot Accounts", - "backstage_sidebar.emoji": "Custom Emoji", - "backstage_sidebar.integrations": "Integrations", - "backstage_sidebar.integrations.commands": "Slash Commands", - "backstage_sidebar.integrations.incoming_webhooks": "Incoming Webhooks", - "backstage_sidebar.integrations.oauthApps": "OAuth 2.0 Applications", - "backstage_sidebar.integrations.outgoing_webhooks": "Outgoing Webhooks", - "bot.add.description": "Description", - "bot.add.description.help": "(Optional) Let others know what this bot does.", - "bot.add.display_name.help": "(Optional) You can choose to display your bot's full name rather than its username.", - "bot.add.post_all": "post:all", - "bot.add.post_all.enabled": "Enabled", - "bot.add.post_all.help": "Bot will have access to post to all Mattermost channels including direct messages.", - "bot.add.post_channels": "post:channels", - "bot.add.post_channels.enabled": "Enabled", - "bot.add.post_channels.help": "Bot will have access to post to all Mattermost public channels.", - "bot.add.role": "Role", - "bot.add.role.admin": "System Admin", - "bot.add.role.help": "Choose what role the bot should have.", - "bot.add.role.member": "Member", - "bot.add.username.help": "You can use lowercase letters, numbers, periods, dashes, and underscores.", - "bot.create_failed": "Failed to create bot", - "bot.create_token.close": "Close", - "bot.edit_failed": "Failed to edit bot", - "bot.manage.create_token": "Create New Token", - "bot.manage.disable": "Disable", - "bot.manage.enable": "Enable", - "bot.remove_profile_picture": "Remove Bot Icon", - "bot.token.default.description": "Default Token", - "bot.token.error.description": "Please enter a description.", - "bots.add.displayName": "Display Name", - "bots.add.icon": "Bot Icon", - "bots.add.username": "Username", - "bots.disabled": "Disabled", - "bots.image.upload": "Upload Image", - "bots.is_bot": "BOT", - "bots.manage.add": "Add Bot Account", - "bots.manage.add.cancel": "Cancel", - "bots.manage.add.create": "Create Bot Account", - "bots.manage.add.creating": "Creating...", - "bots.manage.add.invalid_username": "Usernames have to begin with a lowercase letter and be 3-22 characters long. You can use lowercase letters, numbers, periods, dashes, and underscores.", - "bots.manage.bot_accounts": "Bot Accounts", - "bots.manage.created.text": "Your bot account **{botname}** has been created successfully. Please use the following access token to connect to the bot (see [documentation](https://mattermost.com/pl/default-bot-accounts) for further details).", - "bots.manage.description": "Use bot accounts to integrate with Mattermost through plugins or the API", - "bots.manage.edit": "Edit", - "bots.manage.edit.editing": "Updating...", - "bots.manage.edit.title": "Update", - "bots.manage.empty": "No bot accounts found", - "bots.manage.emptySearch": "No bot accounts match **{searchTerm}**", - "bots.manage.header": "Bot Accounts", - "bots.manage.help1": "Use {botAccounts} to integrate with Mattermost through plugins or the API. Bot accounts are available to everyone on your server. ", - "bots.manage.help2": "Enable bot account creation in the [System Console]({siteURL}/admin_console/integrations/bot_accounts).", - "bots.manage.search": "Search Bot Accounts", - "bots.managed_by": "Managed by ", - "bots.token.confirm": "Delete", - "bots.token.confirm_text": "Are you sure you want to delete the token?", - "bots.token.delete": "Delete Token", - "center_panel.archived.closeChannel": "Close Channel", - "center_panel.direct.closeDirectMessage": "Close Direct Message", - "center_panel.direct.closeGroupMessage": "Close Group Message", - "change_url.close": "Close", - "change_url.endWithLetter": "URLs must end with a lowercase letter or number.", - "change_url.helpText": "You can use lowercase letters, numbers, dashes, and underscores.", - "change_url.invalidDirectMessage": "User IDs are not allowed in channel URLs.", - "change_url.invalidUrl": "Invalid URL", - "change_url.longer": "URLs must have at least 2 characters.", - "change_url.startAndEndWithLetter": "URLs must start and end with a lowercase letter or number.", - "change_url.startWithLetter": "URLs must start with a lowercase letter or number.", - "change_url.urlLabel": "Channel URL", - "channel_flow.alreadyExist": "A channel with that URL already exists", - "channel_flow.changeUrlTitle": "Change Channel URL", - "channel_flow.create": "Create Channel", - "channel_flow.handleTooShort": "Channel URL must be 2 or more lowercase alphanumeric characters", - "channel_flow.invalidName": "Invalid Channel Name", - "channel_flow.set_url_title": "Set Channel URL", - "channel_header.addChannelHeader": "Add a channel description", - "channel_header.channelHasGuests": "This channel has guests", - "channel_header.channelMembers": "Members", - "channel_header.convert": "Convert to Private Channel", - "channel_header.delete": "Archive Channel", - "channel_header.directchannel.you": "{displayname} (you) ", - "channel_header.editLink": "(Edit)", - "channel_header.flagged": "Flagged posts", - "channel_header.groupConstrained": "Members managed by linked groups.", - "channel_header.groupMessageHasGuests": "This group message has guests", - "channel_header.leave": "Leave Channel", - "channel_header.manageMembers": "Manage Members", - "channel_header.menuAriaLabel": "Channel Menu", - "channel_header.mute": "Mute Channel", - "channel_header.pinnedPosts": "Pinned posts", - "channel_header.recentMentions": "Recent mentions", - "channel_header.rename": "Rename Channel", - "channel_header.search": "Search", - "channel_header.setHeader": "Edit Channel Header", - "channel_header.setPurpose": "Edit Channel Purpose", - "channel_header.unarchive": "Unarchive Channel", - "channel_header.unmute": "Unmute Channel", - "channel_header.viewMembers": "View Members", - "channel_info.about": "About", - "channel_info.header": "Header:", - "channel_info.id": "ID: ", - "channel_info.notFound": "No Channel Found", - "channel_info.purpose": "Purpose:", - "channel_info.url": "URL:", - "channel_invite.addNewMembers": "Add New Members to ", - "channel_loader.posted": "Posted", - "channel_loader.postedImage": " posted an image", - "channel_loader.socketError": "Please check connection, Mattermost unreachable. If issue persists, ask administrator to [check WebSocket port](!https://about.mattermost.com/default-websocket-port-help).", - "channel_loader.someone": "Someone", - "channel_loader.something": " did something new", - "channel_loader.unknown_error": "We received an unexpected status code from the server.", - "channel_loader.uploadedFile": " uploaded a file", - "channel_loader.uploadedImage": " uploaded an image", - "channel_members_dropdown.channel_admin": "Channel Admin", - "channel_members_dropdown.channel_admins": "Channel Admins", - "channel_members_dropdown.channel_guest": "Channel Guest", - "channel_members_dropdown.channel_member": "Channel Member", - "channel_members_dropdown.channel_members": "Channel Members", - "channel_members_dropdown.make_channel_admin": "Make Channel Admin", - "channel_members_dropdown.make_channel_admins": "Make Channel Admins", - "channel_members_dropdown.make_channel_member": "Make Channel Member", - "channel_members_dropdown.make_channel_members": "Make Channel Members", - "channel_members_dropdown.menuAriaLabel": "Change the role of channel member", - "channel_members_dropdown.remove_from_channel": "Remove from Channel", - "channel_members_modal.addNew": " Add Members", - "channel_members_modal.members": " Members", - "channel_modal.cancel": "Cancel", - "channel_modal.createNew": "Create Channel", - "channel_modal.descriptionHelp": "Describe how this channel should be used.", - "channel_modal.displayNameError": "Display name must have at least 2 characters.", - "channel_modal.edit": "Edit", - "channel_modal.header": "Header", - "channel_modal.headerEx": "E.g.: \"[Link Title](http://example.com)\"", - "channel_modal.headerHelp": "Set text that will appear in the header of the channel beside the channel name. For example, include frequently used links by typing [Link Title](http://example.com).", - "channel_modal.modalTitle": "New Channel", - "channel_modal.name": "Name", - "channel_modal.nameEx": "E.g.: \"Bugs\", \"Marketing\", \"客户支持\"", - "channel_modal.optional": "(optional)", - "channel_modal.privateHint": " - Only invited members can join this channel", - "channel_modal.privateName": "Private", - "channel_modal.publicHint": " - Anyone can join this channel", - "channel_modal.publicName": "Public", - "channel_modal.purpose": "Purpose", - "channel_modal.purposeEx": "E.g.: \"A channel to file bugs and improvements\"", - "channel_modal.type": "Type", - "channel_notifications.allActivity": "For all activity", - "channel_notifications.globalDefault": "Global default ({notifyLevel})", - "channel_notifications.ignoreChannelMentions": "Ignore mentions for @channel, @here and @all", - "channel_notifications.ignoreChannelMentions.help": "When enabled, @channel, @here and @all will not trigger mentions or mention notifications in this channel.", - "channel_notifications.ignoreChannelMentions.off.title": "Off", - "channel_notifications.ignoreChannelMentions.on.title": "On", - "channel_notifications.levels.all": "All", - "channel_notifications.levels.default": "Default", - "channel_notifications.levels.mention": "Mention", - "channel_notifications.levels.none": "None", - "channel_notifications.muteChannel.help": "Muting turns off desktop, email and push notifications for this channel. The channel will not be marked as unread unless you're mentioned.", - "channel_notifications.muteChannel.off.title": "Off", - "channel_notifications.muteChannel.on.title": "On", - "channel_notifications.muteChannel.on.title.collapse": "Mute is enabled. Desktop, email and push notifications will not be sent for this channel.", - "channel_notifications.muteChannel.settings": "Mute channel", - "channel_notifications.never": "Never", - "channel_notifications.onlyMentions": "Only for mentions", - "channel_notifications.override": "Selecting an option other than \"Default\" will override the global notification settings. Desktop notifications are available on Firefox, Safari, and Chrome.", - "channel_notifications.overridePush": "Selecting an option other than \"Global default\" will override the global notification settings for mobile push notifications in account settings. Push notifications must be enabled by the System Admin.", - "channel_notifications.preferences": "Notification Preferences for ", - "channel_notifications.push": "Send mobile push notifications", - "channel_notifications.sendDesktop": "Send desktop notifications", - "channel_select.placeholder": "--- Select a channel ---", - "channel_switch_modal.deactivated": "Deactivated", - "channel_switch_modal.title": "Switch Channels", - "channel_toggle_button.private": "Private", - "channel_toggle_button.public": "Public", - "channelHeader.addToFavorites": "Add to Favorites", - "channelHeader.removeFromFavorites": "Remove from Favorites", - "channelHeader.unmute": "Unmute", - "claim.email_to_ldap.enterLdapPwd": "Enter the ID and password for your AD/LDAP account", - "claim.email_to_ldap.enterPwd": "Enter the password for your {site} email account", - "claim.email_to_ldap.ldapId": "AD/LDAP ID", - "claim.email_to_ldap.ldapIdError": "Please enter your AD/LDAP ID.", - "claim.email_to_ldap.ldapPasswordError": "Please enter your AD/LDAP password.", - "claim.email_to_ldap.ldapPwd": "AD/LDAP Password", - "claim.email_to_ldap.pwd": "Password", - "claim.email_to_ldap.pwdError": "Please enter your password.", - "claim.email_to_ldap.ssoNote": "You must already have a valid AD/LDAP account", - "claim.email_to_ldap.ssoType": "Upon claiming your account, you will only be able to login with AD/LDAP", - "claim.email_to_ldap.switchTo": "Switch Account to AD/LDAP", - "claim.email_to_ldap.title": "Switch Email/Password Account to AD/LDAP", - "claim.email_to_oauth.enterPwd": "Enter the password for your {site} account", - "claim.email_to_oauth.pwd": "Password", - "claim.email_to_oauth.pwdError": "Please enter your password.", - "claim.email_to_oauth.ssoNote": "You must already have a valid {type} account", - "claim.email_to_oauth.ssoType": "Upon claiming your account, you will only be able to login with {type} SSO", - "claim.email_to_oauth.switchTo": "Switch Account to {uiType}", - "claim.email_to_oauth.title": "Switch Email/Password Account to {uiType}", - "claim.ldap_to_email.confirm": "Confirm Password", - "claim.ldap_to_email.email": "After switching your authentication method, you will use {email} to login. Your AD/LDAP credentials will no longer allow access to Mattermost.", - "claim.ldap_to_email.enterLdapPwd": "{ldapPassword}:", - "claim.ldap_to_email.enterPwd": "New email login password:", - "claim.ldap_to_email.ldapPasswordError": "Please enter your AD/LDAP password.", - "claim.ldap_to_email.ldapPwd": "AD/LDAP Password", - "claim.ldap_to_email.pwd": "Password", - "claim.ldap_to_email.pwdError": "Please enter your password.", - "claim.ldap_to_email.pwdNotMatch": "Passwords do not match.", - "claim.ldap_to_email.switchTo": "Switch account to email/password", - "claim.ldap_to_email.title": "Switch AD/LDAP Account to Email/Password", - "claim.oauth_to_email.confirm": "Confirm Password", - "claim.oauth_to_email.description": "Upon changing your account type, you will only be able to login with your email and password.", - "claim.oauth_to_email.enterNewPwd": "Enter a new password for your {site} email account", - "claim.oauth_to_email.enterPwd": "Please enter a password.", - "claim.oauth_to_email.newPwd": "New Password", - "claim.oauth_to_email.pwdNotMatch": "Passwords do not match.", - "claim.oauth_to_email.switchTo": "Switch {type} to Email and Password", - "claim.oauth_to_email.title": "Switch {type} Account to Email", - "combined_system_message.added_to_channel.many_expanded": "{users} and {lastUser} were **added to the channel** by {actor}.", - "combined_system_message.added_to_channel.one": "{firstUser} **added to the channel** by {actor}.", - "combined_system_message.added_to_channel.one_you": "You were **added to the channel** by {actor}.", - "combined_system_message.added_to_channel.two": "{firstUser} and {secondUser} **added to the channel** by {actor}.", - "combined_system_message.added_to_team.many_expanded": "{users} and {lastUser} were **added to the team** by {actor}.", - "combined_system_message.added_to_team.one": "{firstUser} **added to the team** by {actor}.", - "combined_system_message.added_to_team.one_you": "You were **added to the team** by {actor}.", - "combined_system_message.added_to_team.two": "{firstUser} and {secondUser} **added to the team** by {actor}.", - "combined_system_message.joined_channel.many_expanded": "{users} and {lastUser} **joined the channel**.", - "combined_system_message.joined_channel.one": "{firstUser} **joined the channel**.", - "combined_system_message.joined_channel.one_you": "You **joined the channel**.", - "combined_system_message.joined_channel.two": "{firstUser} and {secondUser} **joined the channel**.", - "combined_system_message.joined_team.many_expanded": "{users} and {lastUser} **joined the team**.", - "combined_system_message.joined_team.one": "{firstUser} **joined the team**.", - "combined_system_message.joined_team.one_you": "You **joined the team**.", - "combined_system_message.joined_team.two": "{firstUser} and {secondUser} **joined the team**.", - "combined_system_message.left_channel.many_expanded": "{users} and {lastUser} **left the channel**.", - "combined_system_message.left_channel.one": "{firstUser} **left the channel**.", - "combined_system_message.left_channel.one_you": "You **left the channel**.", - "combined_system_message.left_channel.two": "{firstUser} and {secondUser} **left the channel**.", - "combined_system_message.left_team.many_expanded": "{users} and {lastUser} **left the team**.", - "combined_system_message.left_team.one": "{firstUser} **left the team**.", - "combined_system_message.left_team.one_you": "You **left the team**.", - "combined_system_message.left_team.two": "{firstUser} and {secondUser} **left the team**.", - "combined_system_message.removed_from_channel.many_expanded": "{users} and {lastUser} were **removed from the channel**.", - "combined_system_message.removed_from_channel.one": "{firstUser} was **removed from the channel**.", - "combined_system_message.removed_from_channel.one_you": "You were **removed from the channel**.", - "combined_system_message.removed_from_channel.two": "{firstUser} and {secondUser} were **removed from the channel**.", - "combined_system_message.removed_from_team.many_expanded": "{users} and {lastUser} were **removed from the team**.", - "combined_system_message.removed_from_team.one": "{firstUser} was **removed from the team**.", - "combined_system_message.removed_from_team.one_you": "You were **removed from the team**.", - "combined_system_message.removed_from_team.two": "{firstUser} and {secondUser} were **removed from the team**.", - "combined_system_message.you": "You", - "confirm_modal.cancel": "Cancel", - "convert_channel.cancel": "No, cancel", - "convert_channel.confirm": "Yes, convert to private channel", - "convert_channel.question1": "When you convert **{display_name}** to a private channel, history and membership are preserved. Publicly shared files remain accessible to anyone with the link. Membership in a private channel is by invitation only.", - "convert_channel.question2": "The change is permanent and cannot be undone.", - "convert_channel.question3": "Are you sure you want to convert **{display_name}** to a private channel?", - "convert_channel.title": "Convert {display_name} to a Private Channel?", - "copy_url_context_menu.getChannelLink": "Copy Link", - "create_comment.addComment": "Add a comment...", - "create_comment.comment": "Add Comment", - "create_comment.commentTitle": "Comment", - "create_comment.file": "File uploading", - "create_comment.files": "Files uploading", - "create_post.comment": "Comment", - "create_post.deactivated": "You are viewing an archived channel with a deactivated user.", - "create_post.error_message": "Your message is too long. Character count: {length}/{limit}", - "create_post.fileProcessing": "Processing...", - "create_post.icon": "Create a post", - "create_post.post": "Post", - "create_post.read_only": "This channel is read-only. Only members with permission can post here.", - "create_post.send_message": "Send a message", - "create_post.shortcutsNotSupported": "Keyboard shortcuts are not supported on your device.", - "create_post.tutorialTip.title": "Sending Messages", - "create_post.tutorialTip1": "Type here to write a message and press **Enter** to post it.", - "create_post.tutorialTip2": "Click the **Attachment** button to upload an image or a file.", - "create_post.write": "Write to {channelDisplayName}", - "create_team.agreement": "By proceeding to create your account and use {siteName}, you agree to our [Terms of Service]({TermsOfServiceLink}) and [Privacy Policy]({PrivacyPolicyLink}). If you do not agree, you cannot use {siteName}.", - "create_team.display_name.charLength": "Name must be {min} or more characters up to a maximum of {max}. You can add a longer team description later.", - "create_team.display_name.nameHelp": "Name your team in any language. Your team name shows in menus and headings.", - "create_team.display_name.next": "Next", - "create_team.display_name.required": "This field is required", - "create_team.display_name.teamName": "Team Name", - "create_team.team_url.back": "Back to previous step", - "create_team.team_url.charLength": "Name must be {min} or more characters up to a maximum of {max}", - "create_team.team_url.creatingTeam": "Creating team...", - "create_team.team_url.finish": "Finish", - "create_team.team_url.hint1": "Short and memorable is best", - "create_team.team_url.hint2": "Use lowercase letters, numbers and dashes", - "create_team.team_url.hint3": "Must start with a letter and can't end in a dash", - "create_team.team_url.regex": "Use only lower case letters, numbers and dashes. Must start with a letter and can't end in a dash.", - "create_team.team_url.required": "This field is required", - "create_team.team_url.taken": "This URL [starts with a reserved word](!https://docs.mattermost.com/help/getting-started/creating-teams.html#team-url) or is unavailable. Please try another.", - "create_team.team_url.teamUrl": "Team URL", - "create_team.team_url.unavailable": "This URL is taken or unavailable. Please try another.", - "create_team.team_url.webAddress": "Choose the web address of your new team:", - "custom_emoji.header": "Custom Emoji", - "date_separator.today": "Today", - "date_separator.yesterday": "Yesterday", - "deactivate_member_modal.deactivate": "Deactivate", - "deactivate_member_modal.desc": "This action deactivates {username}. They will be logged out and not have access to any teams or channels on this system.\n", - "deactivate_member_modal.desc.confirm": " Are you sure you want to deactivate {username}?", - "deactivate_member_modal.desc.for_users_with_bot_accounts": "This action deactivates {username}.\n \n * They will be logged out and not have access to any teams or channels on this system.\n * Bot accounts they manage will be disabled along with their integrations. To enable them again, go to [Integrations > Bot Accounts]({siteURL}/_redirect/integrations/bots). [Learn more about bot accounts](!https://mattermost.com/pl/default-bot-accounts).\n \n \n", - "deactivate_member_modal.sso_warning": "You must also deactivate this user in the SSO provider or they will be reactivated on next login or sync.", - "deactivate_member_modal.title": "Deactivate {username}", - "default_channel.purpose": "Post messages here that you want everyone to see. Everyone automatically becomes a permanent member of this channel when they join the team.", - "delete_channel.cancel": "Cancel", - "delete_channel.confirm": "Confirm ARCHIVE Channel", - "delete_channel.del": "Archive", - "delete_channel.question": "This will archive the channel from the team and make its contents inaccessible for all users. \n \nAre you sure you wish to archive the **{display_name}** channel?", - "delete_channel.viewArchived.question": "This will archive the channel from the team. Channel contents will still be accessible by channel members.\n \nAre you sure you wish to archive the **{display_name}** channel?", - "delete_post.cancel": "Cancel", - "delete_post.comment": "Comment", - "delete_post.confirm": "Confirm {term} Delete", - "delete_post.del": "Delete", - "delete_post.post": "Post", - "delete_post.question": "Are you sure you want to delete this {term}?", - "delete_post.warning": "This post has {count, number} {count, plural, one {comment} other {comments}} on it.", - "demote_to_user_modal.demote": "Demote", - "demote_to_user_modal.desc": "This action demotes the user {username} to a guest. It will restrict the user's ability to join public channels and interact with users outside of the channels they are currently members of. Are you sure you want to demote user {username} to guest?", - "demote_to_user_modal.title": "Demote User {username} to Guest", - "device_icons.android": "Android Icon", - "device_icons.apple": "Apple Icon", - "device_icons.linux": "Linux Icon", - "device_icons.windows": "Windows Icon", - "discard_changes_modal.leave": "Yes, Discard", - "discard_changes_modal.message": "You have unsaved changes, are you sure you want to discard them?", - "discard_changes_modal.title": "Discard Changes?", - "edit_channel_header_modal.cancel": "Cancel", - "edit_channel_header_modal.description": "Edit the text appearing next to the channel name in the channel header.", - "edit_channel_header_modal.error": "This channel header is too long, please enter a shorter one", - "edit_channel_header_modal.save": "Save", - "edit_channel_header_modal.title": "Edit Header for {channel}", - "edit_channel_header_modal.title_dm": "Edit Header", - "edit_channel_header.editHeader": "Edit the Channel Header...", - "edit_channel_header.previewHeader": "Edit Header", - "edit_channel_private_purpose_modal.body": "This text appears in the \"View Info\" modal of the private channel.", - "edit_channel_purpose_modal.body": "Describe how this channel should be used. This text appears in the channel list in the \"More...\" menu and helps others decide whether to join.", - "edit_channel_purpose_modal.cancel": "Cancel", - "edit_channel_purpose_modal.error": "This channel purpose is too long, please enter a shorter one", - "edit_channel_purpose_modal.save": "Save", - "edit_channel_purpose_modal.title1": "Edit Purpose", - "edit_channel_purpose_modal.title2": "Edit Purpose for ", - "edit_command.update": "Update", - "edit_command.updating": "Updating...", - "edit_post.cancel": "Cancel", - "edit_post.edit": "Edit {title}", - "edit_post.editPost": "Edit the post...", - "edit_post.save": "Save", - "edit_post.time_limit_button.for_n_seconds": "For {n} seconds", - "edit_post.time_limit_button.no_limit": "Anytime", - "edit_post.time_limit_modal.description": "Setting a time limit applies to all users who have the \"Edit Post\" permissions in any permission scheme.", - "edit_post.time_limit_modal.invalid_time_limit": "Invalid time limit", - "edit_post.time_limit_modal.option_label_anytime": "Anytime", - "edit_post.time_limit_modal.option_label_time_limit.postinput": "seconds after posting", - "edit_post.time_limit_modal.option_label_time_limit.preinput": "Can edit for", - "edit_post.time_limit_modal.save_button": "Save Edit Time", - "edit_post.time_limit_modal.subscript": "Set the length of time users have to edit their messages after posting.", - "edit_post.time_limit_modal.title": "Configure Global Edit Post Time Limit", - "email_verify.almost": "{siteName}: You are almost done", - "email_verify.failed": " Failed to send verification email.", - "email_verify.notVerifiedBody": "Please verify your email address. Check your inbox for an email.", - "email_verify.resend": "Resend Email", - "email_verify.sent": " Verification email sent.", - "emoji_list.actions": "Actions", - "emoji_list.add": "Add Custom Emoji", - "emoji_list.creator": "Creator", - "emoji_list.delete": "Delete", - "emoji_list.delete.confirm.button": "Delete", - "emoji_list.delete.confirm.msg": "This action permanently deletes the custom emoji. Are you sure you want to delete it?", - "emoji_list.delete.confirm.title": "Delete Custom Emoji", - "emoji_list.empty": "No Custom Emoji Found", - "emoji_list.header": "Custom Emoji", - "emoji_list.help": "Custom emoji are available to everyone on your server. Type ':' followed by two characters in a message box to bring up the emoji selection menu.", - "emoji_list.help2": "Tip: If you add #, ##, or ### as the first character on a new line containing emoji, you can use larger sized emoji. To try it out, send a message such as: '# :smile:'.", - "emoji_list.image": "Image", - "emoji_list.name": "Name", - "emoji_list.search": "Search Custom Emoji", - "emoji_picker_item.emoji_aria_label": "{emojiName} emoji", - "emoji_picker.activity": "Activity", - "emoji_picker.close": "Close", - "emoji_picker.custom": "Custom", - "emoji_picker.emojiPicker": "Emoji Picker", - "emoji_picker.flags": "Flags", - "emoji_picker.foods": "Foods", - "emoji_picker.header": "Emoji Picker", - "emoji_picker.nature": "Nature", - "emoji_picker.objects": "Objects", - "emoji_picker.people": "People", - "emoji_picker.places": "Places", - "emoji_picker.recent": "Recently Used", - "emoji_picker.search": "Search emojis", - "emoji_picker.search_emoji": "Search for an emoji", - "emoji_picker.searchResults": "Search Results", - "emoji_picker.symbols": "Symbols", - "error.channel_not_found.message": "The channel you're requesting is private or does not exist. Please contact an Administrator to be added to the channel.", - "error.channel_not_found.message_guest": "Your guest account has no channels assigned. Please contact an administrator.", - "error.channel_not_found.title": "Channel Not Found", - "error.channelNotFound.guest_link": "Back", - "error.channelNotFound.link": "Back to {defaultChannelName}", - "error.generic.link": "Back to {siteName}", - "error.generic.link_login": "Back to Login Page", - "error.generic.message": "An error has occurred.", - "error.generic.title": "Error", - "error.local_storage.help1": "Enable cookies", - "error.local_storage.help2": "Turn off private browsing", - "error.local_storage.help3": "Use a supported browser (IE 11, Chrome 61+, Firefox 60+, Safari 12+, Edge 42+)", - "error.local_storage.message": "Mattermost was unable to load because a setting in your browser prevents the use of its local storage features. To allow Mattermost to load, try the following actions:", - "error.local_storage.title": "Cannot Load Mattermost", - "error.not_found.message": "The page you were trying to reach does not exist", - "error.not_found.title": "Page Not Found", - "error.oauth_access_denied": "You must authorize Mattermost to log in with {service}.", - "error.oauth_access_denied.title": "Authorization Error", - "error.oauth_invalid_param.title": "OAuth Parameter Error", - "error.oauth_missing_code": "The service provider {service} did not provide an authorization code in the redirect URL.", - "error.oauth_missing_code.forum": "If you reviewed the above and are still having trouble with configuration, you may post in our {link} where we'll be happy to help with issues during setup.", - "error.oauth_missing_code.forum.link": "Troubleshooting forum", - "error.oauth_missing_code.gitlab": "For {link} please make sure you followed the setup instructions.", - "error.oauth_missing_code.gitlab.link": "P1 SSO", - "error.oauth_missing_code.google": "For {link} make sure your administrator enabled the Google+ API.", - "error.oauth_missing_code.google.link": "Google Apps", - "error.oauth_missing_code.office365": "For {link} make sure the administrator of your Microsoft organization has enabled the Mattermost app.", - "error.oauth_missing_code.office365.link": "Office 365", - "error.oauth_missing_code.title": "Mattermost Needs Your Help", - "error.plugin_not_found.desc": "The plugin you are looking for does not exist.", - "error.plugin_not_found.title": "Plugin Not Found", - "error.team_not_found.message": "The team you're requesting is private or does not exist. Please contact your Administrator for an invitation.", - "error.team_not_found.title": "Team Not Found", - "file_attachment.thumbnail": "file thumbnail", - "file_info_preview.size": "Size ", - "file_info_preview.type": "File type ", - "file_upload.disabled": "File attachments are disabled.", - "file_upload.drag_folder": "Folders cannot be uploaded. Please drag all files separately.", - "file_upload.fileAbove": "File above {max}MB cannot be uploaded: {filename}", - "file_upload.filesAbove": "Files above {max}MB cannot be uploaded: {filenames}", - "file_upload.generic_error": "There was a problem uploading your files.", - "file_upload.limited": "Uploads limited to {count, number} files maximum. Please use additional posts for more files.", - "file_upload.menuAriaLabel": "Upload type selector", - "file_upload.pasted": "Image Pasted at ", - "file_upload.upload_files": "Upload files", - "file_upload.zeroBytesFile": "You are uploading an empty file: {filename}", - "file_upload.zeroBytesFiles": "You are uploading empty files: {filenames}", - "filtered_channels_list.search": "Search channels", - "filtered_user_list.countTotal": "{count, number} {count, plural, one {member} other {members}} of {total, number} total", - "filtered_user_list.countTotalPage": "{startCount, number} - {endCount, number} {count, plural, one {member} other {members}} of {total, number} total", - "filtered_user_list.next": "Next", - "filtered_user_list.prev": "Previous", - "filtered_user_list.search": "Search users", - "filtered_user_list.team": "Team:", - "filtered_user_list.userStatus": "User Status:", - "flag_post.flag": "Flag for follow up", - "flag_post.unflag": "Unflag", - "full_screen_modal.back": "Back", - "full_screen_modal.close": "Close", - "general_button.close": "Close", - "general_button.esc": "Esc", - "general_tab.allowedDomains": "Allow only users with a specific email domain to join this team", - "general_tab.allowedDomains.ariaLabel": "Allowed Domains", - "general_tab.allowedDomainsEdit": "Click 'Edit' to add an email domain whitelist.", - "general_tab.AllowedDomainsExample": "corp.mattermost.com, mattermost.org", - "general_tab.AllowedDomainsInfo": "Users can only join the team if their email matches a specific domain (e.g. \"mattermost.org\") or list of comma-separated domains (e.g. \"corp.mattermost.com, mattermost.org\").", - "general_tab.chooseDescription": "Please choose a new description for your team", - "general_tab.codeDesc": "Click 'Edit' to regenerate Invite Code.", - "general_tab.codeLongDesc": "The Invite Code is part of the unique team invitation link which is sent to members you’re inviting to this team. Regenerating the code creates a new invitation link and invalidates the previous link.", - "general_tab.codeTitle": "Invite Code", - "general_tab.emptyDescription": "Click 'Edit' to add a team description.", - "general_tab.getTeamInviteLink": "Get Team Invite Link", - "general_tab.no": "No", - "general_tab.openInviteDesc": "When allowed, a link to this team will be included on the landing page allowing anyone with an account to join this team. Changing from \"Yes\" to \"No\" will regenerate the invitation code, create a new invitation link and invalidate the previous link.", - "general_tab.openInviteTitle": "Allow any user with an account on this server to join this team", - "general_tab.regenerate": "Regenerate", - "general_tab.required": "This field is required", - "general_tab.teamDescription": "Team Description", - "general_tab.teamDescriptionInfo": "Team description provides additional information to help users select the right team. Maximum of 50 characters.", - "general_tab.teamIcon": "Team Icon", - "general_tab.teamIconEditHint": "Click 'Edit' to upload an image.", - "general_tab.teamIconEditHintMobile": "Click to upload an image", - "general_tab.teamIconError": "An error occurred while selecting the image.", - "general_tab.teamIconInvalidFileType": "Only BMP, JPG or PNG images may be used for team icons", - "general_tab.teamIconLastUpdated": "Image last updated {date}", - "general_tab.teamIconTooLarge": "Unable to upload team icon. File is too large.", - "general_tab.teamName": "Team Name", - "general_tab.teamNameInfo": "Set the name of the team as it appears on your sign-in screen and at the top of the left-hand sidebar.", - "general_tab.teamNameRestrictions": "Team Name must be {min} or more characters up to a maximum of {max}. You can add a longer team description.", - "general_tab.title": "General Settings", - "general_tab.yes": "Yes", - "generic_icons.add": "Add Icon", - "generic_icons.add-mail": "Add Mail Icon", - "generic_icons.add-reaction": "Add Reaction Icon", - "generic_icons.alert": "Alert Icon", - "generic_icons.archive": "Archive Icon", - "generic_icons.arrow.down": "Down Arrow Icon", - "generic_icons.attach": "Attachment Icon", - "generic_icons.back": "Back Icon", - "generic_icons.bot": "Bot Icon", - "generic_icons.breadcrumb": "Breadcrumb Icon", - "generic_icons.channel.arrow-right": "Arrow right", - "generic_icons.channel.draft": "Channel Draft Icon", - "generic_icons.channel.private": "Private Channel Icon", - "generic_icons.channel.public": "Public Channel Icon", - "generic_icons.close": "Close Icon", - "generic_icons.collapse": "Collapse Icon", - "generic_icons.download": "Download Icon", - "generic_icons.dropdown": "Dropdown Icon", - "generic_icons.edit": "Edit Icon", - "generic_icons.elipsisHorizontalIcon": "Ellipsis Horizontal Icon", - "generic_icons.expand": "Expand Icon", - "generic_icons.fail": "Faliure Icon", - "generic_icons.flag": "Flag Icon", - "generic_icons.flagged": "Flagged Icon", - "generic_icons.info": "Info Icon", - "generic_icons.invite": "Invite Icon", - "generic_icons.invite_members": "Invite Members Icon", - "generic_icons.link": "Link Icon", - "generic_icons.loading": "Loading Icon", - "generic_icons.logout": "Logout Icon", - "generic_icons.mail": "Mail Icon", - "generic_icons.mattermost": "Mattermost Logo", - "generic_icons.member": "Member Icon", - "generic_icons.mention": "Mention Icon", - "generic_icons.menu": "Menu Icon", - "generic_icons.message": "Message Icon", - "generic_icons.muted": "Muted Icon", - "generic_icons.next": "Next Icon", - "generic_icons.pin": "Pin Icon", - "generic_icons.plugin": "Plugin Icon", - "generic_icons.plugins": "Plugins", - "generic_icons.previous": "Previous Icon", - "generic_icons.reload": "Reload Icon", - "generic_icons.remove": "Remove Icon", - "generic_icons.reply": "Reply Icon", - "generic_icons.search": "Search Icon", - "generic_icons.select": "Select Icon", - "generic_icons.settings": "Settings Icon", - "generic_icons.success": "Success Icon", - "generic_icons.upload": "Upload Icon", - "generic_icons.warning": "Warning Icon", - "get_app.continueToBrowser": "View in Browser", - "get_app.dontHaveTheDesktopApp": "Don't have the Desktop App?", - "get_app.dontHaveTheMobileApp": "Don't have the Mobile App?", - "get_app.downloadTheAppNow": "Download the app now.", - "get_app.ifNothingPrompts": "You can view {siteName} in the desktop app or continue in your web browser.", - "get_app.ifNothingPromptsMobile": "You can view {siteName} in the mobile app or continue in your web browser.", - "get_app.launching": "Where would you like to view this?", - "get_app.openingLink": "Opening link in Mattermost...", - "get_app.openingLinkWhiteLabel": "Opening link in the Desktop App...", - "get_app.openLinkInBrowser": "Or, [open this link in your browser.](!{link})", - "get_app.redirectedInMoments": "You will be redirected in a few moments.", - "get_app.rememberMyPreference": "Remember my preference", - "get_app.systemDialogMessage": "View in Desktop App", - "get_app.systemDialogMessageMobile": "View in App", - "get_link.clipboard": " Link copied", - "get_link.close": "Close", - "get_link.copy": "Copy Link", - "get_public_link_modal.help": "The link below allows anyone to see this file without being registered on this server.", - "get_public_link_modal.title": "Copy Public Link", - "gif_picker.gfycat": "Search Gfycat", - "group_list_modal.addGroupButton": "Add Groups", - "group_list_modal.removeGroupButton": "Remove Group", - "groups": "{team} Groups", - "help.attaching.downloading.description": "Download an attached file by clicking the download icon next to the file thumbnail or by opening the file previewer and clicking **Download**.", - "help.attaching.downloading.title": "Downloading Files", - "help.attaching.dragdrop.description": "Upload a file or selection of files by dragging the files from your computer into the right-hand sidebar or center pane. Dragging and dropping attaches the files to the message input box, then you can optionally type a message and press **ENTER** to post.", - "help.attaching.dragdrop.title": "Drag and Drop", - "help.attaching.icon.description": "Alternatively, upload files by clicking the grey paperclip icon inside the message input box. This opens up your system file viewer where you can navigate to the desired files and then click **Open** to upload the files to the message input box. Optionally type a message and then press **ENTER** to post.", - "help.attaching.icon.title": "Attachment Icon", - "help.attaching.limitations.description": "Mattermost supports a maximum of five attached files per post, each with a maximum file size of 50Mb.", - "help.attaching.limitations.title": "File Size Limitations", - "help.attaching.methods.description": "Attach a file by drag and drop or by clicking the attachment icon in the message input box.", - "help.attaching.methods.title": "Attachment Methods", - "help.attaching.notSupported": "Document preview (Word, Excel, PPT) is not yet supported.", - "help.attaching.pasting.description": "On Chrome and Edge browsers, it is also possible to upload files by pasting them from the clipboard. This is not yet supported on other browsers.", - "help.attaching.pasting.title": "Pasting Images", - "help.attaching.previewer.description": "Mattermost has a built in file previewer that is used to view media, download files and share public links. Click the thumbnail of an attached file to open it in the file previewer.", - "help.attaching.previewer.title": "File Previewer", - "help.attaching.publicLinks.description": "Public links allow you to share file attachments with people outside your Mattermost team. Open the file previewer by clicking on the thumbnail of an attachment, then click **Get Public Link**. This opens a dialog box with a link to copy. When the link is shared and opened by another user, the file will automatically download.", - "help.attaching.publicLinks.title": "Sharing Public Links", - "help.attaching.publicLinks2": "If **Get Public Link** is not visible in the file previewer and you prefer the feature enabled, you can request that your System Admin enable the feature from the System Console under **Security** > **Public Links**.", - "help.attaching.supported.description": "If you are trying to preview a media type that is not supported, the file previewer will open a standard media attachment icon. Supported media formats depend heavily on your browser and operating system, but the following formats are supported by Mattermost on most browsers:", - "help.attaching.supported.title": "Supported Media Types", - "help.attaching.supportedListItem1": "Images: BMP, GIF, JPG, JPEG, PNG", - "help.attaching.supportedListItem2": "Video: MP4", - "help.attaching.supportedListItem3": "Audio: MP3, M4A", - "help.attaching.supportedListItem4": "Documents: PDF", - "help.attaching.title": "Attaching Files", - "help.commands.builtin.description": "The following slash commands are available on all Mattermost installations:", - "help.commands.builtin.title": "Built-in Commands", - "help.commands.builtin2": "Begin by typing `/` and a list of slash command options appears above the text input box. The autocomplete suggestions help by providing a format example in black text and a short description of the slash command in grey text.", - "help.commands.custom.description": "Custom slash commands integrate with external applications. For example, a team might configure a custom slash command to check internal health records with `/patient joe smith` or check the weekly weather forecast in a city with `/weather toronto week`. Check with your System Admin or open the autocomplete list by typing `/` to determine if your team configured any custom slash commands.", - "help.commands.custom.title": "Custom Commands", - "help.commands.custom2": "Custom slash commands are disabled by default and can be enabled by the System Admin in the **System Console** > **Integrations** > **Webhooks and Commands**. Learn about configuring custom slash commands on the [developer slash command documentation page](!http://docs.mattermost.com/developer/slash-commands.html).", - "help.commands.intro1": "Slash commands perform operations in Mattermost by typing into the text input box. Enter a `/` followed by a command and some arguments to perform actions.", - "help.commands.intro2": "Built-in slash commands come with all Mattermost installations and custom slash commands are configurable to interact with external applications. Learn about configuring custom slash commands on the [developer slash command documentation page](!http://docs.mattermost.com/developer/slash-commands.html).", - "help.commands.title": "Executing Commands", - "help.composing.deleting.description": "Delete a message by clicking the **[...]** icon next to any message text that you've composed, then click **Delete**. System and Team Admins can delete any message on their system or team.", - "help.composing.deleting.title": "Deleting a message", - "help.composing.editing.description": "Edit a message by clicking the **[...]** icon next to any message text that you've composed, then click **Edit**. After making modifications to the message text, press **ENTER** to save the modifications. Message edits do not trigger new @mention notifications, desktop notifications or notification sounds.", - "help.composing.editing.title": "Editing a Message", - "help.composing.linking.description": "The **Permalink** feature creates a link to any message. Sharing this link with other users in the channel lets them view the linked message in the Message Archives. Users who are not a member of the channel where the message was posted cannot view the permalink. Get the permalink to any message by clicking the **[...]** icon next to the message text > **Permalink** > **Copy Link**.", - "help.composing.linking.title": "Linking to a message", - "help.composing.posting.description": "Write a message by typing into the text input box, then press ENTER to send it. Use SHIFT+ENTER to create a new line without sending a message. To send messages by pressing CTRL+ENTER go to **Main Menu > Account Settings > Send messages on CTRL+ENTER**.", - "help.composing.posting.title": "Posting a Message", - "help.composing.posts.description": "Posts can be considered parent messages. They are the messages that often start a thread of replies. Posts are composed and sent from the text input box at the bottom of the center pane.", - "help.composing.posts.title": "Posts", - "help.composing.replies.description1": "Reply to a message by clicking the reply icon next to any message text. This action opens the right-hand sidebar where you can see the message thread, then compose and send your reply. Replies are indented slightly in the center pane to indicate that they are child messages of a parent post.", - "help.composing.replies.description2": "When composing a reply in the right-hand side, click the expand/collapse icon with two arrows at the top of the sidebar to make things easier to read.", - "help.composing.replies.title": "Replies", - "help.composing.title": "Sending Messages", - "help.composing.types.description": "Reply to posts to keep conversations organized in threads.", - "help.composing.types.title": "Message Types", - "help.formatting.checklist": "Make a task list by including square brackets:", - "help.formatting.checklistExample": "- [ ] Item one\n- [ ] Item two\n- [x] Completed item", - "help.formatting.code.description": "Create a code block by indenting each line by four spaces, or by placing ``` on the line above and below your code.", - "help.formatting.code.title": "Code Block", - "help.formatting.codeBlock": "Code block", - "help.formatting.emojis.description": "Open the emoji autocomplete by typing `:`. A full list of emojis can be found [here](!http://www.emoji-cheat-sheet.com/). It is also possible to create your own [Custom Emoji](!http://docs.mattermost.com/help/settings/custom-emoji.html) if the emoji you want to use doesn't exist.", - "help.formatting.emojis.title": "Emojis", - "help.formatting.example": "Example:", - "help.formatting.githubTheme": "**GitHub Theme**", - "help.formatting.headings.description": "Make a heading by typing # and a space before your title. For smaller headings, use more #'s.", - "help.formatting.headings.title": "Headings", - "help.formatting.headings2": "Alternatively, you can underline the text using `===` or `---` to create headings.", - "help.formatting.headings2Example": "Large Heading\n-------------", - "help.formatting.headingsExample": "## Large Heading\n### Smaller Heading\n#### Even Smaller Heading", - "help.formatting.images.description": "Create in-line images using an `!` followed by the alt text in square brackets and the link in normal brackets. Add hover text by placing it in quotes after the link.", - "help.formatting.images.title": "In-line Images", - "help.formatting.imagesExample": "![alt text]({siteURL}/static/images/logo-email.png \"Mattermost horizontal logo\")\n\nand\n\n[![Atlassian](https://wac-cdn.atlassian.com/assets/img/favicons/atlassian/favicon.png)](https://travis-ci.org/mattermost/mattermost-server) [![Github](https://github.githubassets.com/favicon.ico)](https://github.com/mattermost/mattermost-server)", - "help.formatting.inline.description": "Create in-line monospaced font by surrounding it with backticks.", - "help.formatting.inline.title": "In-line Code", - "help.formatting.intro": "Markdown makes it easy to format messages. Type a message as you normally would, and use these rules to render it with special formatting.", - "help.formatting.lines.description": "Create a line by using three `*`, `_`, or `-`.", - "help.formatting.lines.title": "Lines", - "help.formatting.linkEx": "[Check out Mattermost!](https://about.mattermost.com/)", - "help.formatting.links.description": "Create labeled links by putting the desired text in square brackets and the associated link in normal brackets.", - "help.formatting.links.title": "Links", - "help.formatting.listExample": "* list item one\n* list item two\n * item two sub-point", - "help.formatting.lists.description": "Create a list by using `*` or `-` as bullets. Indent a bullet point by adding two spaces in front of it.", - "help.formatting.lists.title": "Lists", - "help.formatting.monokaiTheme": "**Monokai Theme**", - "help.formatting.ordered": "Make it an ordered list by using numbers instead:", - "help.formatting.orderedExample": "1. Item one\n2. Item two", - "help.formatting.quotes.description": "Create block quotes using `>`.", - "help.formatting.quotes.title": "Block quotes", - "help.formatting.quotesExample": "`> block quotes` renders as:", - "help.formatting.quotesRender": "> block quotes", - "help.formatting.renders": "Renders as:", - "help.formatting.solirizedDarkTheme": "**Solarized Dark Theme**", - "help.formatting.solirizedLightTheme": "**Solarized Light Theme**", - "help.formatting.style.description": "You can use either `_` or `*` around a word to make it italic. Use two to make it bold.", - "help.formatting.style.listItem1": "`_italics_` renders as _italics_", - "help.formatting.style.listItem2": "`**bold**` renders as **bold**", - "help.formatting.style.listItem3": "`**_bold-italic_**` renders as **_bold-italics_**", - "help.formatting.style.listItem4": "`~~strikethrough~~` renders as ~~strikethrough~~", - "help.formatting.style.title": "Text Style", - "help.formatting.supportedSyntax": "Supported languages are: `as`, `applescript`, `osascript`, `scpt`, `bash`, `sh`, `zsh`, `clj`, `boot`, `cl2`, `cljc`, `cljs`, `cljs.hl`, `cljscm`, `cljx`, `hic`, `coffee`, `_coffee`, `cake`, `cjsx`, `cson`, `iced`, `cpp`, `c`, `cc`, `h`, `c++`, `h++`, `hpp`, `cs`, `csharp`, `css`, `d`, `di`, `dart`, `delphi`, `dpr`, `dfm`, `pas`, `pascal`, `freepascal`, `lazarus`, `lpr`, `lfm`, `diff`, `django`, `jinja`, `dockerfile`, `docker`, `erl`, `fortran`, `fsharp`, `fs`, `gcode`, `nc`, `go`, `groovy`, `handlebars`, `hbs`, `html.hbs`, `html.handlebars`, `hs`, `hx`, `java`, `jsp`, `js`, `jsx`, `json`, `jl`, `kt`, `ktm`, `kts`, `less`, `lisp`, `lua`, `mk`, `mak`, `md`, `mkdown`, `mkd`, `matlab`, `m`, `mm`, `objc`, `obj-c`, `ml`, `perl`, `pl`, `php`, `php3`, `php4`, `php5`, `php6`, `ps`, `ps1`, `pp`, `py`, `gyp`, `r`, `ruby`, `rb`, `gemspec`, `podspec`, `thor`, `irb`, `rs`, `scala`, `scm`, `sld`, `scss`, `st`, `styl`, `sql`, `swift`, `tex`, `vbnet`, `vb`, `bas`, `vbs`, `v`, `veo`, `xml`, `html`, `xhtml`, `rss`, `atom`, `xsl`, `plist`, `yaml`", - "help.formatting.syntax.description": "To add syntax highlighting, type the language to be highlighted after the ``` at the beginning of the code block. Mattermost also offers four different code themes (GitHub, Solarized Dark, Solarized Light, Monokai) that can be changed in **Account Settings** > **Display** > **Theme** > **Custom Theme** > **Center Channel Styles**", - "help.formatting.syntax.title": "Syntax Highlighting", - "help.formatting.syntaxEx": "```goAA\npackage main\nimport \"fmt\"\nfunc main() {\n fmt.Println(\"Hello, 世界\")\n}\n```", - "help.formatting.tableExample": "| Left-Aligned | Center Aligned | Right Aligned |\n| :------------ |:---------------:| -----:|\n| Left column 1 | this text | $100 |\n| Left column 2 | is | $10 |\n| Left column 3 | centered | $1 |", - "help.formatting.tables.description": "Create a table by placing a dashed line under the header row and separating the columns with a pipe `|`. (The columns don't need to line up exactly for it to work). Choose how to align table columns by including colons `:` within the header row.", - "help.formatting.tables.title": "Tables", - "help.formatting.title": "Formatting Text", - "help.learnMore": "Learn more about:", - "help.link.attaching": "Attaching Files", - "help.link.commands": "Executing Commands", - "help.link.composing": "Composing Messages and Replies", - "help.link.formatting": "Formatting Messages Using Markdown", - "help.link.mentioning": "Mentioning Teammates", - "help.link.messaging": "Basic Messaging", - "help.mentioning.channel.description": "You can mention an entire channel by typing `@channel`. All members of the channel will receive a mention notification that behaves the same way as if the members had been mentioned personally.", - "help.mentioning.channel.title": "@Channel", - "help.mentioning.channelExample": "@channel great work on interviews this week. I think we found some excellent potential candidates!", - "help.mentioning.mentions.description": "Use @mentions to get the attention of specific team members.", - "help.mentioning.mentions.title": "@Mentions", - "help.mentioning.recent.description": "Click `@` next to the search box to query for your most recent @mentions and words that trigger mentions. Click **Jump** next to a search result in the right-hand sidebar to jump the center pane to the channel and location of the message with the mention.", - "help.mentioning.recent.title": "Recent Mentions", - "help.mentioning.title": "Mentioning Teammates", - "help.mentioning.triggers.description": "In addition to being notified by @username and @channel, you can customize words that trigger mention notifications in **Account Settings** > **Notifications** > **Words that trigger mentions**. By default, you will receive mention notifications on your first name, and you can add more words by typing them into the input box separated by commas. This is useful if you want to be notified of all posts on certain topics, for example, \"interviewing\" or \"marketing\".", - "help.mentioning.triggers.title": "Words That Trigger Mentions", - "help.mentioning.username.description1": "You can mention a teammate by using the `@` symbol plus their username to send them a mention notification.", - "help.mentioning.username.description2": "Type `@` to bring up a list of team members who can be mentioned. To filter the list, type the first few letters of any username, first name, last name, or nickname. The **Up** and **Down** arrow keys can then be used to scroll through entries in the list, and pressing **ENTER** will select which user to mention. Once selected, the username will automatically replace the full name or nickname. The following example sends a special mention notification to **alice** that alerts her of the channel and message where she has been mentioned. If **alice** is away from Mattermost and has [email notifications](!http://docs.mattermost.com/help/getting-started/configuring-notifications.html#email-notifications) turned on, then she will receive an email alert of her mention along with the message text.", - "help.mentioning.username.title": "@Username", - "help.mentioning.usernameCont": "If the user you mentioned does not belong to the channel, a System Message will be posted to let you know. This is a temporary message only seen by the person who triggered it. To add the mentioned user to the channel, go to the dropdown menu beside the channel name and select **Add Members**.", - "help.mentioning.usernameExample": "@alice how did your interview go with the new candidate?", - "help.messaging.attach": "**Attach files** by dragging and dropping into Mattermost or clicking the attachment icon in the text input box.", - "help.messaging.emoji": "**Quickly add emoji** by typing \":\", which will open an emoji autocomplete. If the existing emoji don't cover what you want to express, you can also create your own [Custom Emoji](!http://docs.mattermost.com/help/settings/custom-emoji.html).", - "help.messaging.format": "**Format your messages** using Markdown that supports text styling, headings, links, emoticons, code blocks, block quotes, tables, lists and in-line images.", - "help.messaging.notify": "**Notify teammates** when they are needed by typing `@username`.", - "help.messaging.reply": "**Reply to messages** by clicking the reply arrow next to the message text.", - "help.messaging.title": "Messaging Basics", - "help.messaging.write": "**Write messages** using the text input box at the bottom of Mattermost. Press ENTER to send a message. Use SHIFT+ENTER to create a new line without sending a message.", - "input.clear": "Clear", - "installed_command.header": "Slash Commands", - "installed_commands.add": "Add Slash Command", - "installed_commands.delete.confirm": "This action permanently deletes the slash command and breaks any integrations using it. Are you sure you want to delete it?", - "installed_commands.empty": "No commands found", - "installed_commands.emptySearch": "No commands match **{searchTerm}**", - "installed_commands.header": "Slash Commands", - "installed_commands.help": "Use slash commands to connect external tools to Mattermost. {buildYourOwn} or visit the {appDirectory} to find self-hosted, third-party apps and integrations.", - "installed_commands.help.appDirectory": "App Directory", - "installed_commands.help.buildYourOwn": "Build Your Own", - "installed_commands.search": "Search Slash Commands", - "installed_commands.unnamed_command": "Unnamed Slash Command", - "installed_incoming_webhooks.add": "Add Incoming Webhook", - "installed_incoming_webhooks.delete.confirm": "This action permanently deletes the incoming webhook and breaks any integrations using it. Are you sure you want to delete it?", - "installed_incoming_webhooks.empty": "No incoming webhooks found", - "installed_incoming_webhooks.emptySearch": "No incoming webhooks match **{searchTerm}**", - "installed_incoming_webhooks.header": "Incoming Webhooks", - "installed_incoming_webhooks.help": "Use incoming webhooks to connect external tools to Mattermost. {buildYourOwn} or visit the {appDirectory} to find self-hosted, third-party apps and integrations.", - "installed_incoming_webhooks.help.appDirectory": "App Directory", - "installed_incoming_webhooks.help.buildYourOwn": "Build Your Own", - "installed_incoming_webhooks.search": "Search Incoming Webhooks", - "installed_incoming_webhooks.unknown_channel": "A Private Webhook", - "installed_integrations.callback_urls": "Callback URLs: {urls}", - "installed_integrations.client_id": "Client ID: **{clientId}**", - "installed_integrations.client_secret": "Client Secret: **{clientSecret}**", - "installed_integrations.content_type": "Content-Type: {contentType}", - "installed_integrations.creation": "Created by {creator} on {createAt, date, full}", - "installed_integrations.delete": "Delete", - "installed_integrations.edit": "Edit", - "installed_integrations.hideSecret": "Hide Secret", - "installed_integrations.regenSecret": "Regenerate Secret", - "installed_integrations.regenToken": "Regenerate Token", - "installed_integrations.showSecret": "Show Secret", - "installed_integrations.token": "Token: {token}", - "installed_integrations.triggerWhen": "Trigger When: {triggerWhen}", - "installed_integrations.triggerWords": "Trigger Words: {triggerWords}", - "installed_integrations.unnamed_oauth_app": "Unnamed OAuth 2.0 Application", - "installed_integrations.url": "URL: {url}", - "installed_oauth_apps.add": "Add OAuth 2.0 Application", - "installed_oauth_apps.callbackUrls": "Callback URLs (One Per Line)", - "installed_oauth_apps.cancel": "Cancel", - "installed_oauth_apps.delete.confirm": "This action permanently deletes the OAuth 2.0 application and breaks any integrations using it. Are you sure you want to delete it?", - "installed_oauth_apps.description": "Description", - "installed_oauth_apps.empty": "No OAuth 2.0 Applications found", - "installed_oauth_apps.emptySearch": "No OAuth 2.0 Applications match **{searchTerm}**", - "installed_oauth_apps.header": "OAuth 2.0 Applications", - "installed_oauth_apps.help": "Create {oauthApplications} to securely integrate bots and third-party apps with Mattermost. Visit the {appDirectory} to find available self-hosted apps.", - "installed_oauth_apps.help.appDirectory": "App Directory", - "installed_oauth_apps.help.oauthApplications": "OAuth 2.0 applications", - "installed_oauth_apps.homepage": "Homepage", - "installed_oauth_apps.iconUrl": "Icon URL", - "installed_oauth_apps.is_trusted": "Is Trusted: **{isTrusted}**", - "installed_oauth_apps.name": "Display Name", - "installed_oauth_apps.save": "Save", - "installed_oauth_apps.saving": "Saving...", - "installed_oauth_apps.search": "Search OAuth 2.0 Applications", - "installed_oauth_apps.trusted": "Is Trusted", - "installed_oauth_apps.trusted.no": "No", - "installed_oauth_apps.trusted.yes": "Yes", - "installed_outgoing_webhooks.add": "Add Outgoing Webhook", - "installed_outgoing_webhooks.delete.confirm": "This action permanently deletes the outgoing webhook and breaks any integrations using it. Are you sure you want to delete it?", - "installed_outgoing_webhooks.empty": "No outgoing webhooks found", - "installed_outgoing_webhooks.emptySearch": "No outgoing webhooks match **{searchTerm}**", - "installed_outgoing_webhooks.header": "Outgoing Webhooks", - "installed_outgoing_webhooks.help": "Use outgoing webhooks to connect external tools to Mattermost. {buildYourOwn} or visit the {appDirectory} to find self-hosted, third-party apps and integrations.", - "installed_outgoing_webhooks.help.appDirectory": "App Directory", - "installed_outgoing_webhooks.help.buildYourOwn": "Build your own", - "installed_outgoing_webhooks.search": "Search Outgoing Webhooks", - "installed_outgoing_webhooks.unknown_channel": "A Private Webhook", - "integrations.add": "Add", - "integrations.command.description": "Slash commands send events to external integrations", - "integrations.command.title": "Slash Commands", - "integrations.delete.confirm.button": "Delete", - "integrations.delete.confirm.title": "Delete Integration", - "integrations.done": "Done", - "integrations.edit": "Edit", - "integrations.header": "Integrations", - "integrations.help": "Visit the {appDirectory} to find self-hosted, third-party apps and integrations for Mattermost.", - "integrations.help.appDirectory": "App Directory", - "integrations.incomingWebhook.description": "Incoming webhooks allow external integrations to send messages", - "integrations.incomingWebhook.title": "Incoming Webhooks", - "integrations.oauthApps.description": "OAuth 2.0 allows external applications to make authorized requests to the Mattermost API", - "integrations.oauthApps.title": "OAuth 2.0 Applications", - "integrations.outgoingWebhook.description": "Outgoing webhooks allow external integrations to receive and respond to messages", - "integrations.outgoingWebhook.title": "Outgoing Webhooks", - "integrations.successful": "Setup Successful", - "interactive_dialog.cancel": "Cancel", - "interactive_dialog.element.optional": "(optional)", - "interactive_dialog.submit": "Submit", - "interactive_dialog.submitting": "Submitting...", - "intro_messages.addGroups": "Add groups to this private channel", - "intro_messages.addGroupsToTeam": "Add other groups to this team", - "intro_messages.anyMember": " Any member can join and read this channel.", - "intro_messages.beginning": "Beginning of {name}", - "intro_messages.creator": "This is the start of the {name} channel, created by {creator} on {date}.", - "intro_messages.creatorPrivate": "This is the start of the {name} private channel, created by {creator} on {date}.", - "intro_messages.default": "**Welcome to {display_name}!**\n \nPost messages here that you want everyone to see. Everyone automatically becomes a permanent member of this channel when they join the team.", - "intro_messages.DM": "This is the start of your direct message history with {teammate}.\nDirect messages and files shared here are not shown to people outside this area.", - "intro_messages.GM": "This is the start of your group message history with {names}.\nMessages and files shared here are not shown to people outside this area.", - "intro_messages.group_message": "This is the start of your group message history with these teammates. Messages and files shared here are not shown to people outside this area.", - "intro_messages.invite": "Invite others to this channel", - "intro_messages.inviteOthers": "Invite others to this team", - "intro_messages.invitePrivate": "Invite others to this private channel", - "intro_messages.noCreator": "This is the start of the {name} channel, created on {date}.", - "intro_messages.noCreatorPrivate": "This is the start of the {name} private channel, created on {date}.", - "intro_messages.offTopic": "This is the start of {display_name}, a channel for non-work-related conversations.", - "intro_messages.onlyInvited": " Only invited members can see this private channel.", - "intro_messages.purpose": " This channel's purpose is: {purpose}", - "intro_messages.purposePrivate": " This private channel's purpose is: {purpose}", - "intro_messages.readonly.default": "**Welcome to {display_name}!**\n \nMessages can only be posted by system admins. Everyone automatically becomes a permanent member of this channel when they join the team.", - "intro_messages.setHeader": "Set a Header", - "intro_messages.teammate": "This is the start of your direct message history with this teammate. Direct messages and files shared here are not shown to people outside this area.", - "invitation_modal.confirm.done": "Done", - "invitation_modal.confirm.guests_title": "**Guests** Invited to **{teamName}**", - "invitation_modal.confirm.members_subtitle": "**{sentCount, number} {sentCount, plural, one {person} other {people}}** {sentCount, plural, one {has} other {have}} been invited, and **{notSentCount, number} {notSentCount, plural, one {invitation} other {invitations}}** {notSentCount, plural, one {was} other {were}} not sent", - "invitation_modal.confirm.members_subtitle_without_not_sent": "**{sentCount, number} {sentCount, plural, one {person} other {people}}** {sentCount, plural, one {has} other {have}} been invited", - "invitation_modal.confirm.members_subtitle_without_sent": "**{notSentCount, number} {notSentCount, plural, one {invitation} other {invitations}}** {notSentCount, plural, one {was} other {were}} not sent", - "invitation_modal.confirm.members_subtitle_without_sent_and_not_sent": "No invitation sent", - "invitation_modal.confirm.members_title": "**Members** Invited to **{teamName}**", - "invitation_modal.confirm.not-sent-header": "Invitations Not Sent", - "invitation_modal.confirm.sent-header": "Successful Invites", - "invitation_modal.guests.add_channels.placeholder": "Search and add channels", - "invitation_modal.guests.add_channels.title": "Search and Add Channels", - "invitation_modal.guests.add_people.description": "Add existing guests or send email invites to new guests.", - "invitation_modal.guests.add_people.description-email-disabled": "Add existing guests.", - "invitation_modal.guests.add_people.title": "Invite People", - "invitation_modal.guests.add-channels.description": "Specify the channels the guests have access to.", - "invitation_modal.guests.custom-message.description": "Create a custom message to make your invite more personal.", - "invitation_modal.guests.custom-message.link": "Set a custom message", - "invitation_modal.guests.custom-message.title": "Custom message", - "invitation_modal.guests.invite_button": "Invite Guests", - "invitation_modal.guests.search-and-add.placeholder": "Add guests or email addresses", - "invitation_modal.guests.search-and-add.placeholder-email-disabled": "Add guests", - "invitation_modal.guests.title": "Invite **Guests** to {teamName}", - "invitation_modal.guests.users_emails_input.no_user_found_matching": "No one found matching **{text}**, type email to invite", - "invitation_modal.guests.users_emails_input.no_user_found_matching-email-disabled": "No one found matching **{text}**", - "invitation_modal.guests.users_emails_input.valid_email": "Invite **{email}** as a guest", - "invitation_modal.invite_guests.description": "Invite guests to one or more channels. Guests only have access to messages, files, and people in the channels they are members of.", - "invitation_modal.invite_guests.title": "Invite **Guests**", - "invitation_modal.invite_members.description": "Invite new team members with a link or by email. Team members have access to messages and files in open teams and public channels.", - "invitation_modal.invite_members.description-email-disabled": "Invite new team members with a link. Team members have access to messages and files in open teams and public channels.", - "invitation_modal.invite_members.title": "Invite **Members**", - "invitation_modal.invite.more": "Invite More People", - "invitation_modal.members.invite_button": "Invite Members", - "invitation_modal.members.or": "OR", - "invitation_modal.members.search_and_add.title": "Add or Invite People", - "invitation_modal.members.search-and-add.description": "Add existing members or send email invites to new members.", - "invitation_modal.members.search-and-add.description-email-disabled": "Add existing members to this team.", - "invitation_modal.members.search-and-add.placeholder": "Add members or email addresses", - "invitation_modal.members.search-and-add.placeholder-email-disabled": "Add members", - "invitation_modal.members.share_link.copy_button": "Copy Link", - "invitation_modal.members.share_link.description": "Share this link to invite people to this team.", - "invitation_modal.members.share_link.input": "team invite link", - "invitation_modal.members.share_link.link_copied": "Link Copied", - "invitation_modal.members.share_link.title": "Share This Link", - "invitation_modal.members.title": "Invite **Members** to {teamName}", - "invitation_modal.members.users_emails_input.no_user_found_matching": "No one found matching **{text}**, type email to invite", - "invitation_modal.members.users_emails_input.no_user_found_matching-email-disabled": "No one found matching **{text}**", - "invitation_modal.members.users_emails_input.valid_email": "Invite **{email}** as a team member", - "invitation_modal.title": "Invite people to **{teamName}**", - "invitation-modal.confirm.details-header": "Details", - "invitation-modal.confirm.not-valid-channel": "Does not match a valid channel name.", - "invitation-modal.confirm.not-valid-user-or-email": "Does not match a valid user or email.", - "invitation-modal.confirm.people-header": "People", - "invitation-modal.discard-changes.button": "Yes, Discard", - "invitation-modal.discard-changes.message": "You have unsent invitations, are you sure you want to discard them?", - "invitation-modal.discard-changes.title": "Discard Changes", - "invite.guests.added-to-channel": "An invitation email has been sent.", - "invite.guests.already-all-channels-member": "This person is already a member of all the channels.", - "invite.guests.already-some-channels-member": "This person is already a member of some of the channels.", - "invite.guests.new-member": "This guest has been added to the team and {count, plural, one {channel} other {channels}}.", - "invite.guests.unable-to-add-the-user-to-the-channels": "Unable to add the guest to the channels.", - "invite.members.added-to-team": "This member has been added to the team.", - "invite.members.already-member": "This person is already a team member.", - "invite.members.invite-sent": "An invitation email has been sent.", - "invite.members.unable-to-add-the-user-to-the-team": "Unable to add the user to the team.", - "invite.members.user-is-guest": "Contact your admin to make this guest a full member.", - "invite.members.user-is-not-guest": "This person is already a member.", - "join_team_group_constrained_denied": "You need to be a member of a linked group to join this team.", - "join_team_group_constrained_denied_admin": "You need to be a member of a linked group to join this team. You can add a group to this team [here]({siteURL}/admin_console/user_management/groups).", - "katex.error": "Couldn't compile your Latex code. Please review the syntax and try again.", - "last_users_message.added_to_channel.type": "were **added to the channel** by {actor}.", - "last_users_message.added_to_team.type": "were **added to the team** by {actor}.", - "last_users_message.first": "{firstUser} and ", - "last_users_message.joined_channel.type": "**joined the channel**.", - "last_users_message.joined_team.type": "**joined the team**.", - "last_users_message.left_channel.type": "**left the channel**.", - "last_users_message.left_team.type": "**left the team**.", - "last_users_message.others": "{numOthers} others ", - "last_users_message.removed_from_channel.type": "were **removed from the channel**.", - "last_users_message.removed_from_team.type": "were **removed from the team**.", - "leave_private_channel_modal.leave": "Yes, leave channel", - "leave_private_channel_modal.message": "Are you sure you wish to leave the private channel {channel}? You must be re-invited in order to re-join this channel in the future.", - "leave_private_channel_modal.title": "Leave Private Channel {channel}", - "leave_team_modal.desc": "You will be removed from all public and private channels. If the team is private you will not be able to rejoin the team. Are you sure?", - "leave_team_modal.no": "No", - "leave_team_modal.title": "Leave the team?", - "leave_team_modal.yes": "Yes", - "list_modal.paginatorCount": "{startCount, number} - {endCount, number} of {total, number} total", - "loading_screen.loading": "Loading", - "local": "local", - "login_mfa.enterToken": "To complete the sign in process, please enter a token from your smartphone's authenticator", - "login_mfa.submit": "Submit", - "login_mfa.submitting": "Submitting...", - "login_mfa.token": "MFA Token", - "login.changed": " Sign-in method changed successfully", - "login.create": "Create one now.", - "login.createTeam": "Create a team", - "login.email": "Email", - "login.forgot": "I forgot my password.", - "login.get_terms_error": "Unable to load terms of service. If this issue persists, contact your System Administrator.", - "login.gitlab": "P1 SSO", - "login.google": "Google Apps", - "login.invalidPassword": "Your password is incorrect.", - "login.ldapCreate": " Enter your AD/LDAP username and password to create an account.", - "login.ldapUsername": "AD/LDAP Username", - "login.ldapUsernameLower": "AD/LDAP username", - "login.noAccount": "Don't have an account? ", - "login.noEmail": "Please enter your email", - "login.noEmailLdapUsername": "Please enter your email or {ldapUsername}", - "login.noEmailUsername": "Please enter your email or username", - "login.noEmailUsernameLdapUsername": "Please enter your email, username or {ldapUsername}", - "login.noLdapUsername": "Please enter your {ldapUsername}", - "login.noMethods": "No sign-in methods are enabled. Please contact your System Administrator.", - "login.noPassword": "Please enter your password", - "login.noUsername": "Please enter your username", - "login.noUsernameLdapUsername": "Please enter your username or {ldapUsername}", - "login.office365": "Office 365", - "login.or": "or", - "login.password": "Password", - "login.passwordChanged": " Password updated successfully", - "login.placeholderOr": " or ", - "login.session_expired": "Your session has expired. Please log in again.", - "login.session_expired.notification": "Session Expired: Please sign in to continue receiving notifications.", - "login.session_expired.title": "* {siteName} - Session Expired", - "login.signIn": "Sign in", - "login.signInLoading": "Signing in...", - "login.signInWith": "Sign in with:", - "login.terms_rejected": "You must agree to the terms of service before accessing {siteName}. Please contact your System Administrator for more details.", - "login.username": "Username", - "login.userNotFound": "We couldn't find an account matching your login credentials.", - "login.verified": " Email Verified", - "manage_channel_groups_modal.search_placeholder": "Search groups", - "manage_team_groups_modal.search_placeholder": "Search groups", - "marketplace_list.count_total_page": "{startCount, number} - {endCount, number} {total, plural, one {plugin} other {plugins}} of {total, number} total", - "marketplace_modal.install_plugins": "Install Plugins", - "marketplace_modal.installing": "Installing...", - "marketplace_modal.list.configure": "Configure", - "marketplace_modal.list.Install": "Install", - "marketplace_modal.list.try_again": "Try Again", - "marketplace_modal.list.update": "Update", - "marketplace_modal.list.update_available": "Update available:", - "marketplace_modal.list.update_confirmation.confirm_button": "Update", - "marketplace_modal.list.update_confirmation.message.current": "You currently have {installedVersion} installed.", - "marketplace_modal.list.update_confirmation.message.current_with_release_notes": "You currently have {installedVersion} installed. View the release notes to learn about the changes included in this update.", - "marketplace_modal.list.update_confirmation.message.intro": "Are you sure you want to update the {name} plugin to {version}?", - "marketplace_modal.list.update_confirmation.message.warning_major_version": "This update may contain breaking changes.", - "marketplace_modal.list.update_confirmation.message.warning_major_version_with_release_notes": "This update may contain breaking changes. Consult the release notes before upgrading.", - "marketplace_modal.list.update_confirmation.title": "Confirm Plugin Update", - "marketplace_modal.no_plugins": "There are no plugins available at this time.", - "marketplace_modal.no_plugins_installed": "You do not have any plugins installed.", - "marketplace_modal.search": "Search Plugins", - "marketplace_modal.tabs.all_plugins": "All Plugins", - "marketplace_modal.tabs.installed_plugins": "Installed", - "marketplace_modal.title": "Plugin Marketplace", - "members_popover.button.message": "message", - "members_popover.manageMembers": "Manage Members", - "members_popover.title": "Channel Members", - "members_popover.viewMembers": "View Members", - "message_submit_error.invalidCommand": "Command with a trigger of ''{command}'' not found. ", - "message_submit_error.sendAsMessageLink": "Click here to send as a message.", - "mfa.confirm.complete": "**Set up complete!**", - "mfa.confirm.okay": "Okay", - "mfa.confirm.secure": "Your account is now secure. Next time you sign in, you will be asked to enter a code from the Google Authenticator app on your phone.", - "mfa.setup.badCode": "Invalid code. If this issue persists, contact your System Administrator.", - "mfa.setup.code": "MFA Code", - "mfa.setup.codeError": "Please enter the code from Google Authenticator.", - "mfa.setup.required": "**Multi-factor authentication is required on {siteName}.**", - "mfa.setup.save": "Save", - "mfa.setup.secret": "Secret: {secret}", - "mfa.setup.step1": "**Step 1: **On your phone, download Google Authenticator from [iTunes](!https://itunes.apple.com/us/app/google-authenticator/id388497605?mt=8') or [Google Play](!https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=en)", - "mfa.setup.step2": "**Step 2: **Use Google Authenticator to scan this QR code, or manually type in the secret key", - "mfa.setup.step3": "**Step 3: **Enter the code generated by Google Authenticator", - "mfa.setupTitle": "Multi-factor Authentication Setup", - "mobile.set_status.away.icon": "Away Icon", - "mobile.set_status.dnd.icon": "Do Not Disturb Icon", - "mobile.set_status.offline.icon": "Offline Icon", - "mobile.set_status.online.icon": "Online Icon", - "modal.manual_status.ask": "Do not ask me again", - "modal.manual_status.auto_responder.message_": "Would you like to switch your status to \"{status}\" and disable Automatic Replies?", - "modal.manual_status.auto_responder.message_away": "Would you like to switch your status to \"Away\" and disable Automatic Replies?", - "modal.manual_status.auto_responder.message_dnd": "Would you like to switch your status to \"Do Not Disturb\" and disable Automatic Replies?", - "modal.manual_status.auto_responder.message_offline": "Would you like to switch your status to \"Offline\" and disable Automatic Replies?", - "modal.manual_status.auto_responder.message_online": "Would you like to switch your status to \"Online\" and disable Automatic Replies?", - "modal.manual_status.button_": "Yes, set my status to \"{status}\"", - "modal.manual_status.button_away": "Yes, set my status to \"Away\"", - "modal.manual_status.button_dnd": "Yes, set my status to \"Do Not Disturb\"", - "modal.manual_status.button_offline": "Yes, set my status to \"Offline\"", - "modal.manual_status.button_online": "Yes, set my status to \"Online\"", - "modal.manual_status.cancel_": "No, keep it as \"{status}\"", - "modal.manual_status.cancel_away": "No, keep it as \"Away\"", - "modal.manual_status.cancel_dnd": "No, keep it as \"Do Not Disturb\"", - "modal.manual_status.cancel_offline": "No, keep it as \"Offline\"", - "modal.manual_status.cancel_ooo": "No, keep it as \"Out of Office\"", - "modal.manual_status.message_": "Would you like to switch your status to \"{status}\"?", - "modal.manual_status.message_away": "Would you like to switch your status to \"Away\"?", - "modal.manual_status.message_dnd": "Would you like to switch your status to \"Do Not Disturb\"?", - "modal.manual_status.message_offline": "Would you like to switch your status to \"Offline\"?", - "modal.manual_status.message_online": "Would you like to switch your status to \"Online\"?", - "modal.manual_status.title_": "Your Status is Set to \"{status}\"", - "modal.manual_status.title_away": "Your Status is Set to \"Away\"", - "modal.manual_status.title_dnd": "Your Status is Set to \"Do Not Disturb\"", - "modal.manual_status.title_offline": "Your Status is Set to \"Offline\"", - "modal.manual_status.title_ooo": "Your Status is Set to \"Out of Office\"", - "more_channels.create": "Create Channel", - "more_channels.createClick": "Click 'Create New Channel' to make a new one", - "more_channels.joining": "Joining...", - "more_channels.next": "Next", - "more_channels.noMore": "No more channels to join", - "more_channels.prev": "Previous", - "more_channels.show_archived_channels": "Show: Archived Channels", - "more_channels.show_public_channels": "Show: Public Channels", - "more_channels.title": "More Channels", - "more_direct_channels.directchannel.deactivated": "{displayname} - Deactivated", - "more_direct_channels.directchannel.you": "{displayname} (you)", - "more_direct_channels.new_convo_note": "This will start a new conversation. If you're adding a lot of people, consider creating a private channel instead.", - "more_direct_channels.new_convo_note.full": "You've reached the maximum number of people for this conversation. Consider creating a private channel instead.", - "more_direct_channels.title": "Direct Messages", - "more_public_direct_channels.channels": "Channels", - "more_public_direct_channels.direct_messages": "Direct Messages", - "more_public_direct_channels.title": "Channels and Direct Messages", - "msg_typing.areTyping": "{users} and {last} are typing...", - "msg_typing.isTyping": "{user} is typing...", - "multiselect.add": "Add", - "multiselect.addChannelsPlaceholder": "Search and add channels", - "multiselect.addGroupsPlaceholder": "Search and add groups", - "multiselect.adding": "Adding...", - "multiselect.addTeamsPlaceholder": "Search and add teams", - "multiselect.go": "Go", - "multiselect.list.notFound": "No items found", - "multiselect.loading": "Loading...", - "multiselect.numGroupsRemaining": "Use ↑↓ to browse, ↵ to select. You can add {num, number} more {num, plural, one {group} other {groups}}. ", - "multiselect.numMembers": "{memberOptions, number} of {totalCount, number} members", - "multiselect.numPeopleRemaining": "Use ↑↓ to browse, ↵ to select. You can add up to {num, number} more {num, plural, one {person} {people}} at a time. ", - "multiselect.numRemaining": "You can add {num, number} more", - "multiselect.placeholder": "Search and add members", - "multiselect.selectChannels": "Use ↑↓ to browse, ↵ to select.", - "multiselect.selectTeams": "Use ↑↓ to browse, ↵ to select.", - "navbar_dropdown.about": "About {appTitle}", - "navbar_dropdown.accountSettings": "Account Settings", - "navbar_dropdown.addGroupsToTeam": "Add Groups to Team", - "navbar_dropdown.console": "System Console", - "navbar_dropdown.create": "Create a Team", - "navbar_dropdown.emoji": "Custom Emoji", - "navbar_dropdown.help": "Help", - "navbar_dropdown.integrations": "Integrations", - "navbar_dropdown.invitePeople": "Invite People", - "navbar_dropdown.invitePeopleExtraText": "Add or invite people to the team", - "navbar_dropdown.join": "Join Another Team", - "navbar_dropdown.keyboardShortcuts": "Keyboard Shortcuts", - "navbar_dropdown.leave": "Leave Team", - "navbar_dropdown.leave.icon": "Leave Team Icon", - "navbar_dropdown.logout": "Log Out", - "navbar_dropdown.manageGroups": "Manage Groups", - "navbar_dropdown.manageMembers": "Manage Members", - "navbar_dropdown.marketplace": "Plugin Marketplace", - "navbar_dropdown.menuAriaLabel": "main menu", - "navbar_dropdown.nativeApps": "Download Apps", - "navbar_dropdown.report": "Report a Problem", - "navbar_dropdown.switchTo": "Switch to ", - "navbar_dropdown.teamSettings": "Team Settings", - "navbar_dropdown.viewMembers": "View Members", - "navbar.addGroups": "Add Groups", - "navbar.addMembers": "Add Members", - "navbar.click": "Click here", - "navbar.clickToAddHeader": "{clickHere} to add one.", - "navbar.noHeader": "No channel header yet.", - "navbar.preferences": "Notification Preferences", - "navbar.toggle2": "Toggle sidebar", - "navbar.viewInfo": "View Info", - "navbar.viewPinnedPosts": "View Pinned Posts", - "no_results.channel_search.subtitle": "Check the spelling or try another search.", - "no_results.channel_search.title": "No results for {channelName}", - "notification.dm": "Direct Message", - "notify_all.confirm": "Confirm", - "notify_all.question": "By using @all or @channel you are about to send notifications to {totalMembers} people. Are you sure you want to do this?", - "notify_all.question_groups": "By using **{mentions}** and **{finalMention}** you are about to send notifications to at least **{totalMembers} people**. Are you sure you want to do this?", - "notify_all.question_one_group": "By using **{mention}** you are about to send notifications to **{totalMembers} people**. Are you sure you want to do this?", - "notify_all.question_timezone": "By using @all or @channel you are about to send notifications to **{totalMembers} people** in **{timezones, number} {timezones, plural, one {timezone} other {timezones}}**. Are you sure you want to do this?", - "notify_all.question_timezone_groups": "By using **{mentions}** and **{finalMention}** you are about to send notifications to at least **{totalMembers} people** in **{timezones, number} {timezones, plural, one {timezone} other {timezones}}**. Are you sure you want to do this?", - "notify_all.question_timezone_one_group": "By using **{mention}** you are about to send notifications to **{totalMembers} people** in **{timezones, number} {timezones, plural, one {timezone} other {timezones}}**. Are you sure you want to do this?", - "notify_all.title.confirm": "Confirm Sending Notifications to Entire Channel", - "notify_all.title.confirm_groups": "Confirm sending notifications to groups", - "numMembers": "{num, number} {num, plural, one {member} other {members}}", - "password_form.change": "Change my password", - "password_form.enter": "Enter a new password for your {siteName} account.", - "password_form.error": "Please enter at least {chars} characters.", - "password_form.pwd": "Password", - "password_form.title": "Password Reset", - "password_send.checkInbox": "Please check your inbox.", - "password_send.description": "To reset your password, enter the email address you used to sign up", - "password_send.email": "Email", - "password_send.error": "Please enter a valid email address.", - "password_send.link": "If the account exists, a password reset email will be sent to:", - "password_send.reset": "Reset my password", - "password_send.title": "Password Reset", - "passwordRequirements": "Password Requirements:", - "pdf_preview.max_pages": "Download to read more pages", - "pending_post_actions.cancel": "Cancel", - "pending_post_actions.retry": "Retry", - "permalink.error.access": "Permalink belongs to a deleted message or to a channel to which you do not have access.", - "permalink.error.title": "Message Not Found", - "post_body.check_for_out_of_channel_groups_mentions.message": "did not get notified by this mention because they are not in the channel. They cannot be added to the channel because they are not a member of the linked groups. To add them to this channel, they must be added to the linked groups.", - "post_body.check_for_out_of_channel_mentions.link.and": " and ", - "post_body.check_for_out_of_channel_mentions.link.private": "add them to this private channel", - "post_body.check_for_out_of_channel_mentions.link.public": "add them to the channel", - "post_body.check_for_out_of_channel_mentions.message_last": "? They will have access to all message history.", - "post_body.check_for_out_of_channel_mentions.message.multiple": "did not get notified by this mention because they are not in the channel. Would you like to ", - "post_body.check_for_out_of_channel_mentions.message.one": "did not get notified by this mention because they are not in the channel. Would you like to ", - "post_body.commentedOn": "Commented on {name}'s message: ", - "post_body.deleted": "(message deleted)", - "post_body.plusMore": " plus {count, number} other {count, plural, one {file} other {files}}", - "post_delete.notPosted": "Comment could not be posted", - "post_delete.okay": "Okay", - "post_delete.someone": "Someone deleted the message on which you tried to post a comment.", - "post_info.auto_responder": "AUTOMATIC REPLY", - "post_info.bot": "BOT", - "post_info.comment_icon.tooltip.reply": "Reply", - "post_info.del": "Delete", - "post_info.dot_menu.tooltip.more_actions": "More actions", - "post_info.edit": "Edit", - "post_info.guest": "GUEST", - "post_info.info.view_additional_info": "View additional info", - "post_info.menuAriaLabel": "Post extra options", - "post_info.message.show_less": "Show less", - "post_info.message.show_more": "Show more", - "post_info.message.visible": "(Only visible to you)", - "post_info.message.visible.compact": " (Only visible to you)", - "post_info.permalink": "Copy Link", - "post_info.pin": "Pin to Channel", - "post_info.pinned": "Pinned", - "post_info.reply": "Reply", - "post_info.submenu.icon": "submenu icon", - "post_info.submenu.mobile": "mobile submenu", - "post_info.system": "System", - "post_info.tooltip.add_reactions": "Add Reaction", - "post_info.unpin": "Unpin from Channel", - "post_info.unread": "Mark as Unread", - "post_message_view.edited": "(edited)", - "post.ariaLabel.attachment": ", 1 attachment", - "post.ariaLabel.attachmentMultiple": ", {attachmentCount} attachments", - "post.ariaLabel.message": "At {time} {date}, {authorName} wrote, {message}", - "post.ariaLabel.messageIsFlagged": ", message is flagged", - "post.ariaLabel.messageIsFlaggedAndPinned": ", message is flagged and pinned", - "post.ariaLabel.messageIsPinned": ", message is pinned", - "post.ariaLabel.reaction": ", 1 reaction", - "post.ariaLabel.reactionMultiple": ", {reactionCount} reactions", - "post.ariaLabel.replyMessage": "At {time} {date}, {authorName} replied, {message}", - "postlist.toast.history": "Viewing message history", - "postlist.toast.newMessages": "{count, number} new {count, plural, one {message} other {messages}", - "postlist.toast.newMessagesSince": "{count, number} new {count, plural, one {message} other {messages}} since {date} at {time}", - "postlist.toast.scrollToBottom": "Jump to recents", - "postlist.toast.scrollToLatest": "Jump to new messages", - "posts_view.loadMore": "Load More messages", - "posts_view.newMsg": "New Messages", - "promote_to_user_modal.desc": "This action promotes the guest {username} to a member. It will allow the user to join public channels and interact with users outside of the channels they are currently members of. Are you sure you want to promote guest {username} to user?", - "promote_to_user_modal.promote": "Promote", - "promote_to_user_modal.title": "Promote guest {username} to user", - "quick_switch_modal.channels": "Channels", - "quick_switch_modal.channelsShortcut.mac": "- ⌘K", - "quick_switch_modal.channelsShortcut.windows": "- CTRL+K", - "quick_switch_modal.help": "Start typing then use TAB to toggle channels/teams, **▲▼** to browse, **ENTER** to select, **ESC** to dismiss.", - "quick_switch_modal.help_mobile": "Type to find a channel.", - "quick_switch_modal.help_no_team": "Type to find a channel. Use **▲▼** to browse, **ENTER** to select, **ESC** to dismiss.", - "quick_switch_modal.switchChannels": "Switch Channels", - "quick_switch_modal.teams": "Teams", - "quick_switch_modal.teamsShortcut.mac": "- ⌘⌥K", - "quick_switch_modal.teamsShortcut.windows": "- CTRL+ALT+K", - "reaction_list.addReactionTooltip": "Add a reaction", - "reaction.add.ariaLabel": "Add a reaction", - "reaction.clickToAdd": "(click to add)", - "reaction.clickToRemove": "(click to remove)", - "reaction.container.ariaLabel": "reactions", - "reaction.othersReacted": "{otherUsers, number} {otherUsers, plural, one {user} other {users}}", - "reaction.reacted": "{users} {reactionVerb} with {emoji}", - "reaction.reactionVerb.user": "reacted", - "reaction.reactionVerb.users": "reacted", - "reaction.reactionVerb.you": "reacted", - "reaction.reactionVerb.youAndUsers": "reacted", - "reaction.reactWidth.ariaLabel": "react with", - "reaction.removeReact.ariaLabel": "remove reaction", - "reaction.usersAndOthersReacted": "{users} and {otherUsers, number} other {otherUsers, plural, one {user} other {users}}", - "reaction.usersReacted": "{users} and {lastUser}", - "reaction.you": "You", - "remove_group_confirm_button": "Yes, Remove Group and {memberCount, plural, one {Member} other {Members}}", - "remove_group_confirm_message": "{memberCount, number} {memberCount, plural, one {member} other {members}} associated to this group will be removed from the team. Are you sure you wish to remove this group and {memberCount} {memberCount, plural, one {member} other {members}}?", - "remove_group_confirm_title": "Remove Group and {memberCount, number} {memberCount, plural, one {Member} other {Members}}", - "removed_channel.channelName": "the channel", - "removed_channel.from": "Removed from ", - "removed_channel.okay": "Okay", - "removed_channel.remover": "{remover} removed you from {channel}", - "removed_channel.someone": "Someone", - "rename_channel.cancel": "Cancel", - "rename_channel.defaultError": " - Cannot be changed for the default channel", - "rename_channel.displayName": "Display Name", - "rename_channel.displayNameHolder": "Enter display name", - "rename_channel.maxLength": "This field must be less than {maxLength, number} characters", - "rename_channel.minLength": "Display name must have at least {minLength, number} characters.", - "rename_channel.save": "Save", - "rename_channel.title": "Rename Channel", - "rename_channel.url": "URL", - "revoke_user_sessions_modal.desc": "This action revokes all sessions for {username}. They will be logged out from all devices. Are you sure you want to revoke all sessions for {username}?", - "revoke_user_sessions_modal.revoke": "Revoke", - "revoke_user_sessions_modal.title": "Revoke Sessions for {username}", - "rhs_card.jump": "Jump", - "rhs_card.message_by": "Message by {avatar} {user}", - "rhs_comment.comment": "Comment", - "rhs_header.backToFlaggedTooltip": "Back to flagged posts", - "rhs_header.backToPinnedTooltip": "Back to pinned posts", - "rhs_header.backToResultsTooltip": "Back to search results", - "rhs_header.closeSidebarTooltip": "Close the sidebar", - "rhs_header.closeTooltip.icon": "Close the sidebar icon", - "rhs_header.details": "Thread", - "rhs_header.expandSidebarTooltip": "Expand the sidebar", - "rhs_header.expandSidebarTooltip.icon": "Expand the sidebar icon", - "rhs_header.expandTooltip.icon": "Shrink the sidebar icon", - "rhs_header.shrinkSidebarTooltip": "Shrink the sidebar", - "rhs_root.mobile.add_reaction": "Add Reaction", - "rhs_root.mobile.flag": "Flag", - "rhs_root.mobile.unflag": "Unflag", - "rhs_thread.rootPostDeletedMessage.body": "Part of this thread has been deleted due to a data retention policy. You can no longer reply to this thread.", - "save_button.save": "Save", - "save_button.saving": "Saving", - "search_bar.search": "Search", - "search_bar.usage.title": "Search Options", - "search_header.loading": "Searching...", - "search_header.results": "Search Results", - "search_header.title2": "Recent Mentions", - "search_header.title3": "Flagged Posts", - "search_header.title5": "Extra Information", - "search_item.channelArchived": "Archived", - "search_item.direct": "Direct Message (with {username})", - "search_item.jump": "Jump", - "search_list_option.after": "Messages after a date", - "search_list_option.before": "Messages before a date", - "search_list_option.exclude": "Exclude search terms", - "search_list_option.from": "Messages from a user", - "search_list_option.in": "Messages in a channel", - "search_list_option.on": "Messages on a date", - "search_list_option.phrases": "Messages with phrases", - "search_results.noResults": "No results found. Try again?", - "search_results.noResults.partialPhraseSuggestion": "If you're searching a partial phrase (ex. searching \"rea\", looking for \"reach\" or \"reaction\"), append a * to your search term.", - "search_results.noResults.stopWordsSuggestion": "Two letter searches and common words like \"this\", \"a\" and \"is\" won't appear in search results due to excessive results returned.", - "search_results.usage.dataRetention": "Only messages posted in the last {days} days are returned. Contact your System Administrator for more detail.", - "search_results.usageFlag1": "You haven't flagged any messages yet.", - "search_results.usageFlag2": "You can add a flag to messages and comments by clicking the {flagIcon} icon next to the timestamp.", - "search_results.usageFlag4": "Flags are a way to mark messages for follow up. Your flags are personal, and cannot be seen by other users.", - "search_results.usagePin1": "There are no pinned messages yet.", - "search_results.usagePin2": "All members of this channel can pin important or useful messages.", - "search_results.usagePin3": "Pinned messages are visible to all channel members.", - "search_results.usagePin4": "To pin a message: Go to the message that you want to pin and click [...] > \"Pin to channel\".", - "select_team.icon": "Select Team Icon", - "select_team.join.icon": "Join Team Icon", - "select_team.private.icon": "Private Team", - "setting_item_max.cancel": "Cancel", - "setting_item_min.edit": "Edit", - "setting_picture.cancel": "Cancel", - "setting_picture.help.profile": "Upload a picture in BMP, JPG or PNG format. Maximum file size: {max}", - "setting_picture.help.team": "Upload a team icon in BMP, JPG or PNG format.\nSquare images with a solid background color are recommended.", - "setting_picture.remove": "Remove This Icon", - "setting_picture.remove_profile_picture": "Remove Profile Picture", - "setting_picture.save": "Save", - "setting_picture.select": "Select", - "setting_picture.uploading": "Uploading...", - "setting_upload.import": "Import", - "setting_upload.noFile": "No file selected.", - "setting_upload.select": "Select file", - "shortcuts.browser.channel_next": "Forward in history:\tAlt|Right", - "shortcuts.browser.channel_next.mac": "Forward in history:\t⌘|]", - "shortcuts.browser.channel_prev": "Back in history:\tAlt|Left", - "shortcuts.browser.channel_prev.mac": "Back in history:\t⌘|[", - "shortcuts.browser.font_decrease": "Zoom out:\tCtrl|-", - "shortcuts.browser.font_decrease.mac": "Zoom out:\t⌘|-", - "shortcuts.browser.font_increase": "Zoom in:\tCtrl|+", - "shortcuts.browser.font_increase.mac": "Zoom in:\t⌘|+", - "shortcuts.browser.header": "Built-in Browser Commands", - "shortcuts.browser.highlight_next": "Highlight text to the next line:\tShift|Down", - "shortcuts.browser.highlight_prev": "Highlight text to the previous line:\tShift|Up", - "shortcuts.browser.input.header": "Works inside an input field", - "shortcuts.browser.newline": "Create a new line:\tShift|Enter", - "shortcuts.files.header": "Files", - "shortcuts.files.upload": "Upload files:\tCtrl|U", - "shortcuts.files.upload.mac": "Upload files:\t⌘|U", - "shortcuts.header": "Keyboard Shortcuts\tCtrl|/", - "shortcuts.header.mac": "Keyboard Shortcuts\t⌘|/", - "shortcuts.info": "Begin a message with / for a list of all the commands at your disposal.", - "shortcuts.msgs.comp.channel": "Channel:\t~|[a-z]|Tab", - "shortcuts.msgs.comp.emoji": "Emoji:\t:|[a-z]|Tab", - "shortcuts.msgs.comp.header": "Autocomplete", - "shortcuts.msgs.comp.last_reaction": "React to last message:\tCtrl|Shift|⧵", - "shortcuts.msgs.comp.last_reaction.mac": "React to last message:\t⌘|Shift|⧵", - "shortcuts.msgs.comp.username": "Username:\t@|[a-z]|Tab", - "shortcuts.msgs.edit": "Edit last message in channel:\tUp", - "shortcuts.msgs.header": "Messages", - "shortcuts.msgs.input.header": "Works inside an empty input field", - "shortcuts.msgs.reply": "Reply to last message in channel:\tShift|Up", - "shortcuts.msgs.reprint_next": "Reprint next message:\tCtrl|Down", - "shortcuts.msgs.reprint_next.mac": "Reprint next message:\t⌘|Down", - "shortcuts.msgs.reprint_prev": "Reprint previous message:\tCtrl|Up", - "shortcuts.msgs.reprint_prev.mac": "Reprint previous message:\t⌘|Up", - "shortcuts.nav.direct_messages_menu": "Direct messages menu:\tCtrl|Shift|K", - "shortcuts.nav.direct_messages_menu.mac": "Direct messages menu:\t⌘|Shift|K", - "shortcuts.nav.focus_center": "Set focus to input field:\tCtrl|Shift|L", - "shortcuts.nav.focus_center.mac": "Set focus to input field:\t⌘|Shift|L", - "shortcuts.nav.header": "Navigation", - "shortcuts.nav.next": "Next channel:\tAlt|Down", - "shortcuts.nav.next.mac": "Next channel:\t⌥|Down", - "shortcuts.nav.open_close_sidebar": "Open or close the right sidebar\tCtrl|.", - "shortcuts.nav.open_close_sidebar.mac": "Open or close the right sidebar\t⌘|.", - "shortcuts.nav.prev": "Previous channel:\tAlt|Up", - "shortcuts.nav.prev.mac": "Previous channel:\t⌥|Up", - "shortcuts.nav.recent_mentions": "Recent mentions:\tCtrl|Shift|M", - "shortcuts.nav.recent_mentions.mac": "Recent mentions:\t⌘|Shift|M", - "shortcuts.nav.settings": "Account settings:\tCtrl|Shift|A", - "shortcuts.nav.settings.mac": "Account settings:\t⌘|Shift|A", - "shortcuts.nav.switcher": "Quick channel switcher:\tCtrl|K", - "shortcuts.nav.switcher.mac": "Quick channel switcher:\t⌘|K", - "shortcuts.nav.unread_next": "Next unread channel:\tAlt|Shift|Down", - "shortcuts.nav.unread_next.mac": "Next unread channel:\t⌥|Shift|Down", - "shortcuts.nav.unread_prev": "Previous unread channel:\tAlt|Shift|Up", - "shortcuts.nav.unread_prev.mac": "Previous unread channel:\t⌥|Shift|Up", - "shortcuts.team_nav.next": "Next team:\tCtrl|Alt|Down", - "shortcuts.team_nav.next.mac": "Next team:\t⌘|⌥|Down", - "shortcuts.team_nav.prev": "Previous team:\tCtrl|Alt|Up", - "shortcuts.team_nav.prev.mac": "Previous team:\t⌘|⌥|Up", - "shortcuts.team_nav.switcher": "Switch to a specific team:\tCtrl|Alt|[1-9]", - "shortcuts.team_nav.switcher.mac": "Switch to a specific team:\t⌘|⌥|[1-9]", - "sidebar_header.tutorial.body1": "The **Main Menu** is where you can **Invite New Members**, access your **Account Settings** and set your **Theme Color**.", - "sidebar_header.tutorial.body2": "Team administrators can also access their **Team Settings** from this menu.", - "sidebar_header.tutorial.body3": "System administrators will find a **System Console** option to administrate the entire system.", - "sidebar_header.tutorial.title": "Main Menu", - "sidebar_left.add_channel_dropdown.browseChannels": "Browse Channels", - "sidebar_left.add_channel_dropdown.browseOrCreateChannels": "Browse or create channels", - "sidebar_left.add_channel_dropdown.createNewChannel": "Create New Channel", - "sidebar_left.add_channel_dropdown.dropdownAriaLabel": "Add Channel Dropdown", - "sidebar_left.channel_filter.allChannels": "All channels", - "sidebar_left.channel_filter.filterByUnread": "Filter by unread", - "sidebar_left.channel_filter.filteredBy": "FILTERED BY:", - "sidebar_left.channel_filter.showAllChannels": "Show all channels", - "sidebar_left.channel_filter.unread": "Unread", - "sidebar_left.channel_filter.viewing": "VIEWING:", - "sidebar_left.channel_navigator.channelSwitcherLabel": "Channel Switcher", - "sidebar_left.channel_navigator.goBackLabel": "Back", - "sidebar_left.channel_navigator.goForwardLabel": "Forward", - "sidebar_left.channel_navigator.jumpTo": "Jump to...", - "sidebar_right_menu.console": "System Console", - "sidebar_right_menu.flagged": "Flagged Posts", - "sidebar_right_menu.recentMentions": "Recent Mentions", - "sidebar.browseChannelDirectChannel": "Browse channels and direct messages", - "sidebar.createChannel": "Create a public channel", - "sidebar.createDirectMessage": "Write a direct message", - "sidebar.createGroup": "Create a private channel", - "sidebar.createPublicPrivateChannel": "Create a public or private channel", - "sidebar.directchannel.you": "{displayname} (you)", - "sidebar.leave": "Leave the channel", - "sidebar.mainMenu": "Main Menu", - "sidebar.moreDmAria": "See more direct messages", - "sidebar.moreElips": "More...", - "sidebar.morePublicAria": "See more public channels", - "sidebar.morePublicDmAria": "See more public channels and direct messages", - "sidebar.removeList": "Remove from this list", - "sidebar.team_select": "{siteName} - Join a team", - "sidebar.tutorialScreen1.body": "**Channels** organize conversations across different topics. They're open to everyone on your team. To send private communications use **Direct Messages** for a single person or **Private Channels** for multiple people.", - "sidebar.tutorialScreen1.title": "Channels", - "sidebar.tutorialScreen2.body1": "Here are two public channels to start:", - "sidebar.tutorialScreen2.body2": "**{townsquare}** is a place for team-wide communication. Everyone in your team is a member of this channel.", - "sidebar.tutorialScreen2.body3": "**{offtopic}** is a place for fun and humor outside of work-related channels. You and your team can decide what other channels to create.", - "sidebar.tutorialScreen2.title": "\"{townsquare}\" and \"{offtopic}\" channels", - "sidebar.tutorialScreen3.body1": "Click **\"More...\"** to create a new channel or join an existing one.", - "sidebar.tutorialScreen3.body2": "You can also create a new channel by clicking the **\"+\" symbol** next to the public or private channel header.", - "sidebar.tutorialScreen3.title": "Creating and Joining Channels", - "sidebar.types.alpha": "CHANNELS", - "sidebar.types.direct": "DIRECT MESSAGES", - "sidebar.types.favorite": "FAVORITE CHANNELS", - "sidebar.types.private": "PRIVATE CHANNELS", - "sidebar.types.public": "PUBLIC CHANNELS", - "sidebar.types.recent": "RECENT ACTIVITY", - "sidebar.types.unreads": "UNREADS", - "sidebar.unreads": "More Unreads", - "signup_team_system_console": "Go to System Console", - "signup_team.guest_without_channels": "Your guest account has no channels assigned. Please contact an administrator.", - "signup_team.join_open": "Teams you can join: ", - "signup_team.no_open_teams": "No teams are available to join. Please ask your administrator for an invite.", - "signup_team.no_open_teams_canCreate": "No teams are available to join. Please create a new team or ask your administrator for an invite.", - "signup_user_completed.choosePwd": "Choose your password", - "signup_user_completed.chooseUser": "Choose your username", - "signup_user_completed.create": "Create Account", - "signup_user_completed.emailHelp": "Valid email required for sign-up", - "signup_user_completed.emailIs": "Your email address is **{email}**. You'll use this address to sign in to {siteName}.", - "signup_user_completed.expired": "You've already completed the signup process for this invitation or this invitation has expired.", - "signup_user_completed.failed_update_user_state": "Please clear your cache and try to log in.", - "signup_user_completed.haveAccount": "Already have an account?", - "signup_user_completed.invalid_invite": "The invite link was invalid. Please speak with your Administrator to receive an invitation.", - "signup_user_completed.lets": "Let's create your account", - "signup_user_completed.no_open_server": "This server does not allow open signups. Please speak with your Administrator to receive an invitation.", - "signup_user_completed.none": "No user creation method has been enabled. Please contact an administrator for access.", - "signup_user_completed.required": "This field is required", - "signup_user_completed.reserved": "This username is reserved, please choose a new one.", - "signup_user_completed.signIn": "Click here to sign in.", - "signup_user_completed.userHelp": "You can use lowercase letters, numbers, periods, dashes, and underscores.", - "signup_user_completed.usernameLength": "Usernames have to begin with a lowercase letter and be {min}-{max} characters long. You can use lowercase letters, numbers, periods, dashes, and underscores.", - "signup_user_completed.validEmail": "Please enter a valid email address", - "signup_user_completed.whatis": "What's your email address?", - "signup.email": "Email and Password", - "signup.email.icon": "Email Icon", - "signup.gitlab": "P1 SSO", - "signup.google": "Google Account", - "signup.ldap": "AD/LDAP Credentials", - "signup.ldap.icon": "AD/LDAP Icon", - "signup.office365": "Office 365", - "signup.saml.icon": "SAML Icon", - "signup.title": "Create an account with:", - "status_dropdown.menuAriaLabel": "set status", - "status_dropdown.set_away": "Away", - "status_dropdown.set_dnd": "Do Not Disturb", - "status_dropdown.set_dnd.extra": "Disables desktop, email and push notifications", - "status_dropdown.set_offline": "Offline", - "status_dropdown.set_online": "Online", - "status_dropdown.set_ooo": "Out of Office", - "status_dropdown.set_ooo.extra": "Automatic Replies are enabled", - "string.id": "default message", - "suggestion_list.no_matches": "No items match __{value}__", - "suggestion.archive": "Archived Channels", - "suggestion.mention.all": "Notifies everyone in this channel", - "suggestion.mention.channel": "Notifies everyone in this channel", - "suggestion.mention.channels": "My Channels", - "suggestion.mention.groups": "Group Mentions", - "suggestion.mention.here": "Notifies everyone online in this channel", - "suggestion.mention.members": "Channel Members", - "suggestion.mention.morechannels": "Other Channels", - "suggestion.mention.moremembers": "Other Members", - "suggestion.mention.nonmembers": "Not in Channel", - "suggestion.mention.special": "Special Mentions", - "suggestion.mention.unread.channels": "Unread Channels", - "suggestion.search.direct": "Direct Messages", - "suggestion.search.private": "Private Channels", - "suggestion.search.public": "Public Channels", - "suggestion.user.isCurrent": "(you)", - "system_notice.adminVisible": "Only visible to System Admins", - "system_notice.adminVisible.icon": "Only visible to System Admins Icon", - "system_notice.body.api3": "If you’ve created or installed integrations in the last two years, find out how [recent changes](!https://about.mattermost.com/default-apiv3-deprecation-guide) may have affected them.", - "system_notice.body.ee_upgrade_advice": "Enterprise Edition is recommended to ensure optimal operation and reliability. [Learn more](!https://mattermost.com/performance).", - "system_notice.body.ie11_deprecation": "Your browser, IE11, will no longer be supported in an upcoming release. [Find out how to move to another browser in one simple step](!https://forum.mattermost.org/t/mattermost-is-dropping-support-for-internet-explorer-ie11-in-v5-16/7575).", - "system_notice.body.permissions": "Some policy and permission System Console settings have moved with the release of [advanced permissions](!https://about.mattermost.com/default-advanced-permissions) in Enterprise E10 and E20.", - "system_notice.dont_show": "Don't Show Again", - "system_notice.remind_me": "Remind me Later", - "system_notice.title": "**Notice**\nfrom Mattermost", - "system_users_list.count": "{count, number} {count, plural, one {user} other {users}}", - "system_users_list.countPage": "{startCount, number} - {endCount, number} {count, plural, one {user} other {users}} of {total, number} total", - "system_users_list.countSearch": "{count, number} {count, plural, one {user} other {users}} of {total, number} total", - "team_channel_settings.group.group_user_row.numberOfGroups": "{amount, number} {amount, plural, one {Group} other {Groups}}", - "team_import_tab.failure": " Import failure: ", - "team_import_tab.import": "Import", - "team_import_tab.importHelpCliDocsLink": "CLI tool for Slack import", - "team_import_tab.importHelpDocsLink": "documentation", - "team_import_tab.importHelpExporterLink": "Slack Advanced Exporter", - "team_import_tab.importHelpExportInstructions": "Slack > Administration > Workspace settings > Import/Export Data > Export > Start Export", - "team_import_tab.importHelpLine1": "Slack import to Mattermost supports importing of messages in your Slack team's public channels.", - "team_import_tab.importHelpLine2": "To import a team from Slack, go to {exportInstructions}. See {uploadDocsLink} to learn more.", - "team_import_tab.importHelpLine3": "To import posts with attached files, see {slackAdvancedExporterLink} for details.", - "team_import_tab.importHelpLine4": "For Slack teams with over 10,000 messages, we recommend using the {cliLink}.", - "team_import_tab.importing": "Importing...", - "team_import_tab.importSlack": "Import from Slack (Beta)", - "team_import_tab.successful": " Import successful: ", - "team_import_tab.summary": "View Summary", - "team_member_modal.invitePeople": "Invite People", - "team_member_modal.members": "{team} Members", - "team_members_dropdown.confirmDemoteDescription": "If you demote yourself from the System Admin role and there is not another user with System Admin privileges, you'll need to re-assign a System Admin by accessing the Mattermost server through a terminal and running the following command.", - "team_members_dropdown.confirmDemoteRoleTitle": "Confirm Demotion from System Admin Role", - "team_members_dropdown.confirmDemotion": "Confirm Demotion", - "team_members_dropdown.confirmDemotionCmd": "platform roles system_admin {username}", - "team_members_dropdown.guest": "Guest", - "team_members_dropdown.inactive": "Inactive", - "team_members_dropdown.leave_team": "Remove from Team", - "team_members_dropdown.makeAdmin": "Make Team Admin", - "team_members_dropdown.makeMember": "Make Team Member", - "team_members_dropdown.makeTeamAdmins": "Make Team Admins", - "team_members_dropdown.makeTeamMembers": "Make Team Members", - "team_members_dropdown.member": "Member", - "team_members_dropdown.menuAriaLabel": "Change the role of a team member", - "team_members_dropdown.systemAdmin": "System Admin", - "team_members_dropdown.teamAdmin": "Team Admin", - "team_members_dropdown.teamAdmins": "Team Admins", - "team_members_dropdown.teamMembers": "Team Members", - "team_settings_modal.generalTab": "General", - "team_settings_modal.importTab": "Import", - "team_settings_modal.title": "Team Settings", - "team_settings.openInviteDescription.ariaLabel": "Invite Code", - "team_settings.openInviteDescription.groupConstrained": "No, members of this team are added and removed by linked groups. [Learn More](!https://mattermost.com/pl/default-ldap-group-constrained-team-channel.html)", - "team_settings.openInviteSetting.groupConstrained": "No, members of this team are added and removed by linked groups.", - "team_sidebar.join": "Other teams you can join", - "team.button.ariaLabel": "{teamName} team", - "team.button.mentions.ariaLabel": "{teamName} team, {mentionCount} mentions", - "team.button.name_undefined": "This team does not have a name", - "team.button.tooltip": "Ctrl+Alt+{order}", - "team.button.tooltip.mac": "⌘ ⌥ {order}", - "team.button.unread.ariaLabel": "{teamName} team unread", - "terms_of_service.agreeButton": "I Agree", - "terms_of_service.api_error": "Unable to complete the request. If this issue persists, contact your System Administrator.", - "terms_of_service.disagreeButton": "I Disagree", - "test": "Button Text", - "textbox.bold": "**bold**", - "textbox.edit": "Edit message", - "textbox.help": "Help", - "textbox.inlinecode": "`inline code`", - "textbox.italic": "_italic_", - "textbox.preformatted": "```preformatted```", - "textbox.preview": "Preview", - "textbox.quote": ">quote", - "textbox.strike": "strike", - "tutorial_intro.allSet": "You're all set", - "tutorial_intro.end": "Click \"Next\" to enter {channel}. This is the first channel teammates see when they sign up. Use it for posting updates everyone needs to know.", - "tutorial_intro.invite": "Invite Teammates", - "tutorial_intro.mobileApps": "Install the apps for {link} for easy access and notifications on the go.", - "tutorial_intro.mobileAppsLinkText": "PC, Mac, iOS and Android", - "tutorial_intro.next": "Next", - "tutorial_intro.screenOne.body1": "Your team communication all in one place, instantly searchable and available anywhere.", - "tutorial_intro.screenOne.body2": "Keep your team connected to help them achieve what matters most.", - "tutorial_intro.screenOne.title1": "Welcome to:", - "tutorial_intro.screenOne.title2": "Mattermost", - "tutorial_intro.screenTwo.body1": "Communication happens in public discussion channels, private channels and direct messages.", - "tutorial_intro.screenTwo.body2": "Everything is archived and searchable from any web-enabled desktop, laptop or phone.", - "tutorial_intro.screenTwo.title": "How Mattermost Works:", - "tutorial_intro.skip": "Skip Tutorial", - "tutorial_intro.support": "Need anything, just email us at ", - "tutorial_intro.whenReady": " when you're ready.", - "tutorial_tip.next": "Next", - "tutorial_tip.ok": "Okay", - "tutorial_tip.out": "Opt out of these tips.", - "tutorial_tip.seen": "Seen this before? ", - "unarchive_channel.cancel": "Cancel", - "unarchive_channel.confirm": "Confirm UNARCHIVE Channel", - "unarchive_channel.del": "Unarchive", - "unarchive_channel.viewArchived.question": "Are you sure you wish to unarchive the **{display_name}** channel?", - "update_command.confirm": "Edit Slash Command", - "update_command.question": "Your changes may break the existing slash command. Are you sure you would like to update it?", - "update_command.update": "Update", - "update_incoming_webhook.update": "Update", - "update_incoming_webhook.updating": "Updating...", - "update_oauth_app.confirm": "Edit OAuth 2.0 application", - "update_oauth_app.question": "Your changes may break the existing OAuth 2.0 application. Are you sure you would like to update it?", - "update_outgoing_webhook.confirm": "Edit Outgoing Webhook", - "update_outgoing_webhook.question": "Your changes may break the existing outgoing webhook. Are you sure you would like to update it?", - "update_outgoing_webhook.update": "Update", - "upload_overlay.info": "Drop a file to upload it.", - "user_list.notFound": "No users found", - "user_profile.account.editSettings": "Edit Account Settings", - "user_profile.account.localTime": "Local Time: ", - "user_profile.account.post_was_created": "This post was created by an integration from", - "user_profile.add_user_to_channel": "Add to a Channel", - "user_profile.add_user_to_channel.icon": "Add User to Channel Icon", - "user_profile.send.dm": "Send Message", - "user_profile.send.dm.icon": "Send Message Icon", - "user.settings.advance.confirmDeactivateAccountTitle": "Confirm Deactivation", - "user.settings.advance.confirmDeactivateDesc": "Are you sure you want to deactivate your account? This can only be reversed by your System Administrator.", - "user.settings.advance.deactivate_member_modal.deactivateButton": "Yes, deactivate my account", - "user.settings.advance.deactivateAccountTitle": "Deactivate Account", - "user.settings.advance.deactivateDesc": "Deactivating your account removes your ability to log in to this server and disables all email and mobile notifications. To reactivate your account, contact your System Administrator.", - "user.settings.advance.deactivateDescShort": "Click 'Edit' to deactivate your account", - "user.settings.advance.enabledFeatures": "{count, number} {count, plural, one {Feature} other {Features}} Enabled", - "user.settings.advance.formattingDesc": "If enabled, posts will be formatted to create links, show emoji, style the text, and add line breaks. By default, this setting is enabled.", - "user.settings.advance.formattingTitle": "Enable Post Formatting", - "user.settings.advance.icon": "Advanced Settings Icon", - "user.settings.advance.joinLeaveDesc": "When \"On\", System Messages saying a user has joined or left a channel will be visible. When \"Off\", the System Messages about joining or leaving a channel will be hidden. A message will still show up when you are added to a channel, so you can receive a notification.", - "user.settings.advance.joinLeaveTitle": "Enable Join/Leave Messages", - "user.settings.advance.markdown_preview": "Show markdown preview option in message input box", - "user.settings.advance.off": "Off", - "user.settings.advance.on": "On", - "user.settings.advance.onForAllMessages": "On for all messages", - "user.settings.advance.onForCode": "On only for code blocks starting with ```", - "user.settings.advance.preReleaseDesc": "Check any pre-released features you'd like to preview. You may also need to refresh the page before the setting will take effect.", - "user.settings.advance.preReleaseTitle": "Preview Pre-release Features", - "user.settings.advance.sendDesc": "When enabled, CTRL + ENTER will send the message and ENTER inserts a new line.", - "user.settings.advance.sendDesc.mac": "When enabled, ⌘ + ENTER will send the message and ENTER inserts a new line.", - "user.settings.advance.sendTitle": "Send Messages on CTRL+ENTER", - "user.settings.advance.sendTitle.mac": "Send Messages on ⌘+ENTER", - "user.settings.advance.title": "Advanced Settings", - "user.settings.custom_theme.awayIndicator": "Away Indicator", - "user.settings.custom_theme.buttonBg": "Button BG", - "user.settings.custom_theme.buttonColor": "Button Text", - "user.settings.custom_theme.centerChannelBg": "Center Channel BG", - "user.settings.custom_theme.centerChannelColor": "Center Channel Text", - "user.settings.custom_theme.centerChannelTitle": "Center Channel Styles", - "user.settings.custom_theme.codeTheme": "Code Theme", - "user.settings.custom_theme.copied": "✔ Copied", - "user.settings.custom_theme.copyPaste": "Copy and paste to share theme colors:", - "user.settings.custom_theme.copyThemeColors": "Copy Theme Colors", - "user.settings.custom_theme.dndIndicator": "Do Not Disturb Indicator", - "user.settings.custom_theme.errorTextColor": "Error Text Color", - "user.settings.custom_theme.linkButtonTitle": "Link and Button Styles", - "user.settings.custom_theme.linkColor": "Link Color", - "user.settings.custom_theme.mentionBg": "Mention Jewel BG", - "user.settings.custom_theme.mentionColor": "Mention Jewel Text", - "user.settings.custom_theme.mentionHighlightBg": "Mention Highlight BG", - "user.settings.custom_theme.mentionHighlightLink": "Mention Highlight Link", - "user.settings.custom_theme.newMessageSeparator": "New Message Separator", - "user.settings.custom_theme.onlineIndicator": "Online Indicator", - "user.settings.custom_theme.sidebarBg": "Sidebar BG", - "user.settings.custom_theme.sidebarHeaderBg": "Sidebar Header BG", - "user.settings.custom_theme.sidebarHeaderTextColor": "Sidebar Header Text", - "user.settings.custom_theme.sidebarText": "Sidebar Text", - "user.settings.custom_theme.sidebarTextActiveBorder": "Sidebar Text Active Border", - "user.settings.custom_theme.sidebarTextActiveColor": "Sidebar Text Active Color", - "user.settings.custom_theme.sidebarTextHoverBg": "Sidebar Text Hover BG", - "user.settings.custom_theme.sidebarTitle": "Sidebar Styles", - "user.settings.custom_theme.sidebarUnreadText": "Sidebar Unread Text", - "user.settings.display.channeldisplaymode": "Select the width of the center channel.", - "user.settings.display.channelDisplayTitle": "Channel Display", - "user.settings.display.clockDisplay": "Clock Display", - "user.settings.display.collapseDesc": "Set whether previews of image links and image attachment thumbnails show as expanded or collapsed by default. This setting can also be controlled using the slash commands /expand and /collapse.", - "user.settings.display.collapseDisplay": "Default Appearance of Image Previews", - "user.settings.display.collapseOff": "Collapsed", - "user.settings.display.collapseOn": "Expanded", - "user.settings.display.fixedWidthCentered": "Fixed width, centered", - "user.settings.display.fullScreen": "Full width", - "user.settings.display.icon": "Display Settings Icon", - "user.settings.display.language": "Language", - "user.settings.display.linkPreviewDesc": "When available, the first web link in a message will show a preview of the website content below the message.", - "user.settings.display.linkPreviewDisplay": "Website Link Previews", - "user.settings.display.linkPreviewOff": "Off", - "user.settings.display.linkPreviewOn": "On", - "user.settings.display.messageDisplayClean": "Standard", - "user.settings.display.messageDisplayCleanDes": "Easy to scan and read.", - "user.settings.display.messageDisplayCompact": "Compact", - "user.settings.display.messageDisplayCompactDes": "Fit as many messages on the screen as we can.", - "user.settings.display.messageDisplayDescription": "Select how messages in a channel should be displayed.", - "user.settings.display.messageDisplayTitle": "Message Display", - "user.settings.display.militaryClock": "24-hour clock (example: 16:00)", - "user.settings.display.normalClock": "12-hour clock (example: 4:00 PM)", - "user.settings.display.preferTime": "Select how you prefer time displayed.", - "user.settings.display.teammateNameDisplay": "This field is handled through your System Administrator. If you want to change it, you need to do so through your System Administrator.", - "user.settings.display.teammateNameDisplayDescription": "Set how to display other user's names in posts and the Direct Messages list.", - "user.settings.display.teammateNameDisplayFullname": "Show first and last name", - "user.settings.display.teammateNameDisplayNicknameFullname": "Show nickname if one exists, otherwise show first and last name", - "user.settings.display.teammateNameDisplayTitle": "Teammate Name Display", - "user.settings.display.teammateNameDisplayUsername": "Show username", - "user.settings.display.theme.applyToAllTeams": "Apply new theme to all my teams", - "user.settings.display.theme.customTheme": "Custom Theme", - "user.settings.display.theme.describe": "Open to manage your theme", - "user.settings.display.theme.import": "Import theme colors from Slack", - "user.settings.display.theme.otherThemes": "See other themes", - "user.settings.display.theme.themeColors": "Theme Colors", - "user.settings.display.theme.title": "Theme", - "user.settings.display.timezone": "Timezone", - "user.settings.display.title": "Display Settings", - "user.settings.general.close": "Close", - "user.settings.general.confirmEmail": "Confirm Email", - "user.settings.general.currentEmail": "Current Email", - "user.settings.general.currentPassword": "Current Password", - "user.settings.general.email": "Email", - "user.settings.general.emailGitlabCantUpdate": "Login occurs through P1 SSO ({email}). [Click here](!http://sso.collab.cdl.af.mil) to update.", - "user.settings.general.emailGoogleCantUpdate": "Login occurs through Google. Email cannot be updated. Email address used for notifications is {email}.", - "user.settings.general.emailHelp1": "Email is used for sign-in, notifications, and password reset. Email requires verification if changed.", - "user.settings.general.emailHelp3": "Email is used for sign-in, notifications, and password reset.", - "user.settings.general.emailLdapCantUpdate": "Login occurs through AD/LDAP. Email cannot be updated. Email address used for notifications is {email}.", - "user.settings.general.emailMatch": "The new emails you entered do not match.", - "user.settings.general.emailOffice365CantUpdate": "Login occurs through Office 365. Email cannot be updated. Email address used for notifications is {email}.", - "user.settings.general.emailSamlCantUpdate": "Login occurs through SAML. Email cannot be updated. Email address used for notifications is {email}.", - "user.settings.general.emptyName": "Click 'Edit' to add your full name", - "user.settings.general.emptyNickname": "Click 'Edit' to add a nickname", - "user.settings.general.emptyPassword": "Please enter your current password.", - "user.settings.general.emptyPosition": "Click 'Edit' to add your job title / position", - "user.settings.general.field_handled_externally": "This field is handled through your login provider. If you want to change it, you need to do so through your login provider.", - "user.settings.general.firstName": "First Name", - "user.settings.general.fullName": "Full Name", - "user.settings.general.icon": "General Settings Icon", - "user.settings.general.imageTooLarge": "Unable to upload profile image. File is too large.", - "user.settings.general.imageUpdated": "Image last updated {date}", - "user.settings.general.incorrectPassword": "Your password is incorrect.", - "user.settings.general.lastName": "Last Name", - "user.settings.general.loginGitlab": "Login done through P1 SSO ({email})", - "user.settings.general.loginGoogle": "Login done through Google ({email})", - "user.settings.general.loginLdap": "Login done through AD/LDAP ({email})", - "user.settings.general.loginOffice365": "Login done through Office 365 ({email})", - "user.settings.general.loginSaml": "Login done through SAML ({email})", - "user.settings.general.mobile.emptyName": "Click to add your full name", - "user.settings.general.mobile.emptyNickname": "Click to add a nickname", - "user.settings.general.mobile.emptyPosition": "Click to add your job title / position", - "user.settings.general.mobile.uploadImage": "Click to upload an image", - "user.settings.general.newEmail": "New Email", - "user.settings.general.nickname": "Nickname", - "user.settings.general.nicknameExtra": "Use Nickname for a name you might be called that is different from your first name and username. This is most often used when two or more people have similar sounding names and usernames.", - "user.settings.general.notificationsExtra": "By default, you will receive mention notifications when someone types your first name. Go to {notify} settings to change this default.", - "user.settings.general.notificationsLink": "Notifications", - "user.settings.general.position": "Position", - "user.settings.general.positionExtra": "Use Position for your role or job title. This will be shown in your profile popover.", - "user.settings.general.profilePicture": "Profile Picture", - "user.settings.general.sendAgain": "Send again", - "user.settings.general.sending": "Sending", - "user.settings.general.title": "General Settings", - "user.settings.general.uploadImage": "Click 'Edit' to upload an image.", - "user.settings.general.username": "Username", - "user.settings.general.usernameInfo": "Pick something easy for teammates to recognize and recall.", - "user.settings.general.usernameReserved": "This username is reserved, please choose a new one.", - "user.settings.general.usernameRestrictions": "Username must begin with a letter, and contain between {min} to {max} lowercase characters made up of numbers, letters, and the symbols '.', '-', and '_'.", - "user.settings.general.validEmail": "Please enter a valid email address", - "user.settings.general.validImage": "Only BMP, JPG or PNG images may be used for profile pictures", - "user.settings.import_theme.cancel": "Cancel", - "user.settings.import_theme.importBody": "To import a theme, go to a Slack team and look for \"Preferences -> Sidebar Theme\". Open the custom theme option, copy the theme color values and paste them here:", - "user.settings.import_theme.importHeader": "Import Slack Theme", - "user.settings.import_theme.submit": "Submit", - "user.settings.import_theme.submitError": "Invalid format, please try copying and pasting in again.", - "user.settings.languages.change": "Change interface language", - "user.settings.languages.promote": "Select which language Mattermost displays in the user interface.\n \nWould you like to help with translations? Join the [Mattermost Translation Server](!http://translate.mattermost.com/) to contribute.", - "user.settings.mfa.add": "Add MFA to Account", - "user.settings.mfa.addHelp": "Adding multi-factor authentication will make your account more secure by requiring a code from your mobile phone each time you sign in.", - "user.settings.mfa.remove": "Remove MFA from Account", - "user.settings.mfa.removeHelp": "Removing multi-factor authentication means you will no longer require a phone-based passcode to sign-in to your account.", - "user.settings.mfa.requiredHelp": "Multi-factor authentication is required on this server. Resetting is only recommended when you need to switch code generation to a new mobile device. You will be required to set it up again immediately.", - "user.settings.mfa.reset": "Reset MFA on Account", - "user.settings.mfa.title": "Multi-factor Authentication", - "user.settings.modal.advanced": "Advanced", - "user.settings.modal.confirmBtns": "Yes, Discard", - "user.settings.modal.confirmMsg": "You have unsaved changes, are you sure you want to discard them?", - "user.settings.modal.confirmTitle": "Discard Changes?", - "user.settings.modal.display": "Display", - "user.settings.modal.general": "General", - "user.settings.modal.notifications": "Notifications", - "user.settings.modal.security": "Security", - "user.settings.modal.sidebar": "Sidebar", - "user.settings.modal.title": "Account Settings", - "user.settings.notifications.allActivity": "For all activity", - "user.settings.notifications.autoResponder": "Automatic Direct Message Replies", - "user.settings.notifications.autoResponderDefault": "Hello, I am out of office and unable to respond to messages.", - "user.settings.notifications.autoResponderDisabled": "Disabled", - "user.settings.notifications.autoResponderEnabled": "Enabled", - "user.settings.notifications.autoResponderHint": "Set a custom message that will be automatically sent in response to Direct Messages. Mentions in Public and Private Channels will not trigger the automated reply. Enabling Automatic Replies sets your status to Out of Office and disables email and push notifications.", - "user.settings.notifications.autoResponderPlaceholder": "Message", - "user.settings.notifications.channelWide": "Channel-wide mentions \"@channel\", \"@all\", \"@here\"", - "user.settings.notifications.comments": "Reply notifications", - "user.settings.notifications.commentsAny": "Trigger notifications on messages in reply threads that I start or participate in", - "user.settings.notifications.commentsInfo": "In addition to notifications for when you're mentioned, select if you would like to receive notifications on reply threads.", - "user.settings.notifications.commentsNever": "Do not trigger notifications on messages in reply threads unless I'm mentioned", - "user.settings.notifications.commentsRoot": "Trigger notifications on messages in threads that I start", - "user.settings.notifications.desktop": "Send desktop notifications", - "user.settings.notifications.desktop.allNoSound": "For all activity, without sound", - "user.settings.notifications.desktop.allSound": "For all activity, with sound", - "user.settings.notifications.desktop.allSoundHidden": "For all activity", - "user.settings.notifications.desktop.mentionsNoSound": "For mentions and direct messages, without sound", - "user.settings.notifications.desktop.mentionsSound": "For mentions and direct messages, with sound", - "user.settings.notifications.desktop.mentionsSoundHidden": "For mentions and direct messages", - "user.settings.notifications.desktop.sound": "Notification sound", - "user.settings.notifications.desktop.title": "Desktop Notifications", - "user.settings.notifications.email.disabled": "Email notifications are not enabled", - "user.settings.notifications.email.disabled_long": "Email notifications have not been enabled by your System Administrator.", - "user.settings.notifications.email.everyHour": "Every hour", - "user.settings.notifications.email.everyXMinutes": "Every {count, plural, one {minute} other {{count, number} minutes}}", - "user.settings.notifications.email.immediately": "Immediately", - "user.settings.notifications.email.never": "Never", - "user.settings.notifications.email.send": "Send email notifications", - "user.settings.notifications.emailBatchingInfo": "Notifications received over the time period selected are combined and sent in a single email.", - "user.settings.notifications.emailInfo": "Email notifications are sent for mentions and direct messages when you are offline or away for more than 5 minutes.", - "user.settings.notifications.emailNotifications": "Email Notifications", - "user.settings.notifications.header": "Notifications", - "user.settings.notifications.icon": "Notification Settings Icon", - "user.settings.notifications.info": "Desktop notifications are available on Edge, Firefox, Safari, Chrome and Mattermost Desktop Apps.", - "user.settings.notifications.mentionsInfo": "Mentions trigger when someone sends a message that includes your username (\"@{username}\") or any of the options selected above.", - "user.settings.notifications.never": "Never", - "user.settings.notifications.noWords": "No words configured", - "user.settings.notifications.off": "Off", - "user.settings.notifications.on": "On", - "user.settings.notifications.onlyMentions": "Only for mentions and direct messages", - "user.settings.notifications.push": "Mobile Push Notifications", - "user.settings.notifications.push_notification.status": "Trigger push notifications when", - "user.settings.notifications.sensitiveName": "Your case sensitive first name \"{first_name}\"", - "user.settings.notifications.sensitiveUsername": "Your non-case sensitive username \"{username}\"", - "user.settings.notifications.sensitiveWords": "Other non-case sensitive words, separated by commas:", - "user.settings.notifications.soundConfig": "Please configure notification sounds in your browser settings", - "user.settings.notifications.sounds_info": "Notification sounds are available on Firefox, Edge, Safari, Chrome and Mattermost Desktop Apps.", - "user.settings.notifications.title": "Notification Settings", - "user.settings.notifications.wordsTrigger": "Words That Trigger Mentions", - "user.settings.push_notification.allActivity": "For all activity", - "user.settings.push_notification.allActivityAway": "For all activity when away or offline", - "user.settings.push_notification.allActivityOffline": "For all activity when offline", - "user.settings.push_notification.allActivityOnline": "For all activity when online, away or offline", - "user.settings.push_notification.away": "Away or offline", - "user.settings.push_notification.disabled": "Push notifications are not enabled", - "user.settings.push_notification.disabled_long": "Push notifications have not been enabled by your System Administrator.", - "user.settings.push_notification.info": "Notification alerts are pushed to your mobile device when there is activity in Mattermost.", - "user.settings.push_notification.offline": "Offline", - "user.settings.push_notification.online": "Online, away or offline", - "user.settings.push_notification.onlyMentions": "For mentions and direct messages", - "user.settings.push_notification.onlyMentionsAway": "For mentions and direct messages when away or offline", - "user.settings.push_notification.onlyMentionsOffline": "For mentions and direct messages when offline", - "user.settings.push_notification.onlyMentionsOnline": "For mentions and direct messages when online, away or offline", - "user.settings.push_notification.send": "Send mobile push notifications", - "user.settings.push_notification.status_info": "Notification alerts are only pushed to your mobile device when your online status matches the selection above.", - "user.settings.security.active": "Active", - "user.settings.security.close": "Close", - "user.settings.security.currentPassword": "Current Password", - "user.settings.security.currentPasswordError": "Please enter your current password.", - "user.settings.security.deauthorize": "Deauthorize", - "user.settings.security.emailPwd": "Email and Password", - "user.settings.security.gitlab": "P1 SSO", - "user.settings.security.google": "Google", - "user.settings.security.icon": "Security Settings Icon", - "user.settings.security.inactive": "Inactive", - "user.settings.security.lastUpdated": "Last updated {date} at {time}", - "user.settings.security.ldap": "AD/LDAP", - "user.settings.security.loginGitlab": "Login done through P1 SSO", - "user.settings.security.loginGoogle": "Login done through Google Apps", - "user.settings.security.loginLdap": "Login done through AD/LDAP", - "user.settings.security.loginOffice365": "Login done through Office 365", - "user.settings.security.loginSaml": "Login done through SAML", - "user.settings.security.logoutActiveSessions": "View and Log Out of Active Sessions", - "user.settings.security.logoutActiveSessions.icon": "Active Sessions Icon", - "user.settings.security.method": "Sign-in Method", - "user.settings.security.newPassword": "New Password", - "user.settings.security.noApps": "No OAuth 2.0 Applications are authorized.", - "user.settings.security.oauthApps": "OAuth 2.0 Applications", - "user.settings.security.oauthAppsDescription": "Click 'Edit' to manage your OAuth 2.0 Applications", - "user.settings.security.oauthAppsHelp": "Applications act on your behalf to access your data based on the permissions you grant them.", - "user.settings.security.office365": "Office 365", - "user.settings.security.oneSignin": "You may only have one sign-in method at a time. Switching sign-in method will send an email notifying you if the change was successful.", - "user.settings.security.password": "Password", - "user.settings.security.passwordError": "Your password must contain between {min} and {max} characters.", - "user.settings.security.passwordErrorLowercase": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter.", - "user.settings.security.passwordErrorLowercaseNumber": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter and at least one number.", - "user.settings.security.passwordErrorLowercaseNumberSymbol": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter, at least one number, and at least one symbol (e.g. \"~!@#$%^&*()\").", - "user.settings.security.passwordErrorLowercaseSymbol": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter and at least one symbol (e.g. \"~!@#$%^&*()\").", - "user.settings.security.passwordErrorLowercaseUppercase": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter and at least one uppercase letter.", - "user.settings.security.passwordErrorLowercaseUppercaseNumber": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter, at least one uppercase letter, and at least one number.", - "user.settings.security.passwordErrorLowercaseUppercaseNumberSymbol": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter, at least one uppercase letter, at least one number, and at least one symbol (e.g. \"~!@#$%^&*()\").", - "user.settings.security.passwordErrorLowercaseUppercaseSymbol": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter, at least one uppercase letter, and at least one symbol (e.g. \"~!@#$%^&*()\").", - "user.settings.security.passwordErrorNumber": "Your password must contain between {min} and {max} characters made up of at least one number.", - "user.settings.security.passwordErrorNumberSymbol": "Your password must contain between {min} and {max} characters made up of at least one number and at least one symbol (e.g. \"~!@#$%^&*()\").", - "user.settings.security.passwordErrorSymbol": "Your password must contain between {min} and {max} characters made up of at least one symbol (e.g. \"~!@#$%^&*()\").", - "user.settings.security.passwordErrorUppercase": "Your password must contain between {min} and {max} characters made up of at least one uppercase letter.", - "user.settings.security.passwordErrorUppercaseNumber": "Your password must contain between {min} and {max} characters made up of at least one uppercase letter and at least one number.", - "user.settings.security.passwordErrorUppercaseNumberSymbol": "Your password must contain between {min} and {max} characters made up of at least one uppercase letter, at least one number, and at least one symbol (e.g. \"~!@#$%^&*()\").", - "user.settings.security.passwordErrorUppercaseSymbol": "Your password must contain between {min} and {max} characters made up of at least one uppercase letter and at least one symbol (e.g. \"~!@#$%^&*()\").", - "user.settings.security.passwordGitlabCantUpdate": "Login occurs through P1 SSO. [Click here](!http://sso.collab.cdl.af.mil) to update.", - "user.settings.security.passwordGoogleCantUpdate": "Login occurs through Google Apps. Password cannot be updated.", - "user.settings.security.passwordLdapCantUpdate": "Login occurs through AD/LDAP. Password cannot be updated.", - "user.settings.security.passwordMatchError": "The new passwords you entered do not match.", - "user.settings.security.passwordMinLength": "Invalid minimum length, cannot show preview.", - "user.settings.security.passwordOffice365CantUpdate": "Login occurs through Office 365. Password cannot be updated.", - "user.settings.security.passwordSamlCantUpdate": "This field is handled through your login provider. If you want to change it, you need to do so through your login provider.", - "user.settings.security.retypePassword": "Retype New Password", - "user.settings.security.saml": "SAML", - "user.settings.security.switchEmail": "Switch to Using Email and Password", - "user.settings.security.switchGitlab": "Switch to Using P1 SSO", - "user.settings.security.switchGoogle": "Switch to Using Google SSO", - "user.settings.security.switchLdap": "Switch to Using AD/LDAP", - "user.settings.security.switchOffice365": "Switch to Using Office 365 SSO", - "user.settings.security.switchSaml": "Switch to Using SAML SSO", - "user.settings.security.title": "Security Settings", - "user.settings.security.viewHistory": "View Access History", - "user.settings.security.viewHistory.icon": "Access History Icon", - "user.settings.sidebar.after_seven_days": "After 7 days with no new messages", - "user.settings.sidebar.autoCloseDMDesc": "Direct Message conversations can be reopened with the “+” button in the sidebar or using the Channel Switcher (CTRL+K).", - "user.settings.sidebar.autoCloseDMTitle": "Automatically Close Direct Messages", - "user.settings.sidebar.channelSidebarOrganizationSection.desc": "When enabled, access experimental channel sidebar features, including collapsible sections and unreads filtering. [Learn more](!https://about.mattermost.com/default-sidebar/) or [give us feedback](!https://about.mattermost.com/default-sidebar-survey/)", - "user.settings.sidebar.channelSidebarOrganizationSectionTitle": "Experimental Sidebar Features", - "user.settings.sidebar.channelSwitcherSectionDesc.mac": "The channel switcher is shown at the bottom of the sidebar and is used to jump between channels quickly. It can also be accessed using CMD + K.", - "user.settings.sidebar.channelSwitcherSectionDesc.windows": "The channel switcher is shown at the bottom of the sidebar and is used to jump between channels quickly. It can also be accessed using CTRL + K.", - "user.settings.sidebar.channelSwitcherSectionTitle": "Channel Switcher", - "user.settings.sidebar.favorites": "Favorites grouped separately", - "user.settings.sidebar.favoritesDesc": "Channels marked as favorites will be grouped separately.", - "user.settings.sidebar.favoritesShort": "Favorites grouped separately", - "user.settings.sidebar.groupAndSortChannelsTitle": "Channel Grouping and Sorting", - "user.settings.sidebar.groupByNone": "Combine all channel types", - "user.settings.sidebar.groupByNoneShort": "No grouping", - "user.settings.sidebar.groupByType": "Channels grouped by type", - "user.settings.sidebar.groupByTypeShort": "Group by channel type", - "user.settings.sidebar.groupChannelsTitle": "Channel grouping", - "user.settings.sidebar.groupDesc": "Group channels by type, or combine all types into a list.", - "user.settings.sidebar.icon": "Sidebar Settings Icon", - "user.settings.sidebar.never": "Never", - "user.settings.sidebar.off": "Off", - "user.settings.sidebar.on": "On", - "user.settings.sidebar.sortAlpha": "Alphabetically", - "user.settings.sidebar.sortAlphaShort": "sorted alphabetically", - "user.settings.sidebar.sortChannelsTitle": "Channel sorting", - "user.settings.sidebar.sortDesc": "Sort channels alphabetically, or by most recent post.", - "user.settings.sidebar.sortRecent": "Recency", - "user.settings.sidebar.sortRecentShort": "sorted by recency", - "user.settings.sidebar.title": "Sidebar Settings", - "user.settings.sidebar.unreads": "Unreads grouped separately", - "user.settings.sidebar.unreadsDesc": "Group unread channels separately until read.", - "user.settings.sidebar.unreadsFavoritesShort": "Unreads and favorites grouped separately", - "user.settings.sidebar.unreadsShort": "Unreads grouped separately", - "user.settings.timezones.automatic": "Set automatically", - "user.settings.timezones.change": "Change timezone", - "user.settings.timezones.promote": "Select the timezone used for timestamps in the user interface and email notifications.", - "user.settings.tokens.activate": "Enable", - "user.settings.tokens.cancel": "Cancel", - "user.settings.tokens.clickToEdit": "Click 'Edit' to manage your personal access tokens", - "user.settings.tokens.confirmCopyButton": "Yes, I have copied the token", - "user.settings.tokens.confirmCopyMessage": "Make sure you have copied and saved the access token below. You won't be able to see it again!", - "user.settings.tokens.confirmCopyTitle": "Copied Your Token?", - "user.settings.tokens.confirmCreateButton": "Yes, Create", - "user.settings.tokens.confirmCreateMessage": "You are generating a personal access token with System Admin permissions. Are you sure want to create this token?", - "user.settings.tokens.confirmCreateTitle": "Create System Admin Personal Access Token", - "user.settings.tokens.confirmDeleteButton": "Yes, Delete", - "user.settings.tokens.confirmDeleteMessage": "Any integrations using this token will no longer be able to access the Mattermost API. You cannot undo this action. \n \nAre you sure want to delete the **{description}** token?", - "user.settings.tokens.confirmDeleteTitle": "Delete Token?", - "user.settings.tokens.copy": "Please copy the access token below. You won't be able to see it again!", - "user.settings.tokens.create": "Create Token", - "user.settings.tokens.deactivate": "Disable", - "user.settings.tokens.deactivatedWarning": "(Disabled)", - "user.settings.tokens.delete": "Delete", - "user.settings.tokens.description": "[Personal access tokens](!https://about.mattermost.com/default-user-access-tokens) function similarly to session tokens and can be used by integrations to [authenticate against the REST API](!https://about.mattermost.com/default-api-authentication).", - "user.settings.tokens.description_mobile": "[Personal access tokens](!https://about.mattermost.com/default-user-access-tokens) function similarly to session tokens and can be used by integrations to [authenticate against the REST API](!https://about.mattermost.com/default-api-authentication). Create new tokens on your desktop.", - "user.settings.tokens.id": "Token ID: ", - "user.settings.tokens.name": "Token Description: ", - "user.settings.tokens.nameHelp": "Enter a description for your token to remember what it does.", - "user.settings.tokens.nameRequired": "Please enter a description.", - "user.settings.tokens.save": "Save", - "user.settings.tokens.title": "Personal Access Tokens", - "user.settings.tokens.token": "Access Token: ", - "user.settings.tokens.tokenDesc": "Token Description: ", - "user.settings.tokens.tokenId": "Token ID: ", - "user.settings.tokens.tokenLoading": "Loading...", - "user.settings.tokens.userAccessTokensNone": "No personal access tokens.", - "version_bar.new": "A new version of Mattermost is available.", - "version_bar.refresh": "Refresh the app now", - "view_image_popover.download": "Download", - "view_image_popover.file": "File {count, number} of {total, number}", - "view_image_popover.open": "Open", - "view_image_popover.publicLink": "Get a public link", - "view_image.loading": "Loading ", - "web.footer.about": "About", - "web.footer.help": "Help", - "web.footer.privacy": "Privacy", - "web.footer.terms": "Terms", - "web.header.back": "Back", - "web.header.logout": "Logout", - "web.root.signup_info": "All team communication in one place, searchable and accessible anywhere", - "widgets.channels_input.empty": "No channels found", - "widgets.channels_input.loading": "Loading", - "widgets.users_emails_input.loading": "Loading", - "widgets.users_emails_input.no_user_found_matching": "No one found matching **{text}**, type email address", - "widgets.users_emails_input.valid_email": "Add **{email}**", - "yourcomputer": "Your computer" -} \ No newline at end of file diff --git a/image/p1-bg.jpg b/image/p1-bg.jpg deleted file mode 100644 index 979ef7d624a34ff47a7036efa2ccbfa175f87faf..0000000000000000000000000000000000000000 Binary files a/image/p1-bg.jpg and /dev/null differ diff --git a/image/root.html b/image/root.html deleted file mode 100644 index 7245afd8d6d7076bf59f765e676eaf5391c652e7..0000000000000000000000000000000000000000 --- a/image/root.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - - - - - - P1 Enterprise Chat - - - - - - - - - - - - - - - - - - - - - - - - -
-
-

Cannot connect to Mattermost

-
-

We're having trouble connecting to Mattermost. If refreshing this page (Ctrl+R or Command+R) does not - work, please verify that your computer is connected to the internet.


-
-
-
-
-
-
-
-
-
-
- - - - - \ No newline at end of file diff --git a/tests/cy-run.sh b/tests/cy-run.sh new file mode 100755 index 0000000000000000000000000000000000000000..2df7a77796b123ada7ac4d0d357ac452e4fedebc --- /dev/null +++ b/tests/cy-run.sh @@ -0,0 +1,16 @@ + +#!/usr/bin/env bash +echo "Running Cypress e2e tests headlessly without copying files" + +# explanation of the "docker run" command line arguments +# +# -it = interactive terminal +# -v $PWD:/e2e = map current folder to /e2e inside the container +# -w /e2e = set working directy to /e2e +# $@ = pass any arguments to this script to the Cypress command +# like "./cy-run.sh --record" +# +# Docker image "cypress/included:3.2.0" has its entrypoint +# set to "cypress run" by default + +docker run -it -v $PWD:/e2e -w /e2e cypress/included:5.0.0 $@ diff --git a/tests/cypress.json b/tests/cypress.json new file mode 100644 index 0000000000000000000000000000000000000000..a12fbe832c0e030653d4b22464d82afd4bea356f --- /dev/null +++ b/tests/cypress.json @@ -0,0 +1,11 @@ +{ + "pluginsFile": false, + "supportFile": false, + "fixturesFolder": false, + "env": { + "mm_url": "chat.bigbang.dev", + "mm_email": "test@bigbang.dev", + "mm_user": "bigbang", + "mm_password": "Bigbang#123" + } +} diff --git a/tests/cypress/integration/mattermost-health.spec.js b/tests/cypress/integration/mattermost-health.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..e990632302a04034e6acd19c9b47e29c236bf251 --- /dev/null +++ b/tests/cypress/integration/mattermost-health.spec.js @@ -0,0 +1,16 @@ +describe('Basic Mattermost', function() { + it('Check Mattermost is accessible', function() { + cy.visit(Cypress.env('mm_url')) + cy.get('input[id="email"]').type(Cypress.env('mm_email')) + cy.get('input[id="name"]').type(Cypress.env('mm_user')) + cy.get('input[id="password"]').type(Cypress.env('mm_password')) + cy.get('button[id="createAccountButton"]').click() + + cy.get('a[id="createNewTeamLink"]').click() + cy.get('input[id="teamNameInput"]').type(Cypress.env('mm_user')) + cy.get('button[id="teamNameNextButton"]').click() + cy.get('button[id="teamURLFinishButton"]').click() + + cy.title().should('include', 'Town Square - ') + }) +}) diff --git a/tests/dependencies.yaml b/tests/dependencies.yaml index 55708cecbbb7544a34866dc27c7333df4cb910ac..3b18fbc707fe4712a18b56f139f543c0b01d7bb1 100644 --- a/tests/dependencies.yaml +++ b/tests/dependencies.yaml @@ -1,9 +1,9 @@ mattermostoperator: git: "https://repo1.dso.mil/platform-one/big-bang/apps/collaboration-tools/mattermost-operator.git" namespace: "mattermost-operator" - branch: "bb-1162" + branch: "1.12.0-bb.0" miniooperator: git: "https://repo1.dso.mil/platform-one/big-bang/apps/application-utilities/minio-operator.git" namespace: "minio-operator" - branch: "bb-1233" + branch: "2.0.9-bb.1" diff --git a/tests/main-test-gateway.yaml b/tests/main-test-gateway.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1c7d7d1bd7598367474f3123659e7de6de5c88d3 --- /dev/null +++ b/tests/main-test-gateway.yaml @@ -0,0 +1,26 @@ +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + name: main + namespace: istio-system +spec: + selector: + istio: ingressgateway + servers: + - hosts: + - '*' + port: + name: http + number: 80 + protocol: HTTP + tls: + httpsRedirect: true + - hosts: + - '*.bigbang.dev' + port: + name: https + number: 443 + protocol: HTTPS + tls: + credentialName: wildcard-cert + mode: SIMPLE diff --git a/tests/policy/mattermost-minio-ib.rego b/tests/policy/mattermost-minio-ib.rego new file mode 100644 index 0000000000000000000000000000000000000000..63d7c44351a15aa1eabce6048c630cc8f5788d0f --- /dev/null +++ b/tests/policy/mattermost-minio-ib.rego @@ -0,0 +1,35 @@ +package main + +name = input.metadata.name + +registries_allow := ["registry1.dsop.io/ironbank", "registry1.dso.mil/ironbank", "registry.dsop.io", "registry.dso.mil"] +registries_warn := ["registry.dsop.io", "registry.dso.mil"] + +in_allowed_registries(image) { + startswith(image, registries_allow[i]) +} + +in_warning_registries(image) { + startswith(image, registries_warn[i]) +} + +# Deny non-approved registries +deny[msg] { + image := input.spec.image + not in_allowed_registries(image) + msg := sprintf("Image '%v' in '%v' is not from approved registries", [image, name]) +} + +# Warn about non-Ironbank Images +warn[msg] { + image := input.spec.image + in_warning_registries(image) + msg := sprintf("Image '%v' in '%v' is not from Ironbank", [image, name]) +} + +# Warn about DSOP Images +warn[msg] { + image := input.spec.image + contains(image, ".dsop.io") + msg := sprintf("Update 'dsop.io' to 'dso.mil' for image '%v' in '%v'", [image, name]) +} diff --git a/tests/policy/postgres-ib.rego b/tests/policy/postgres-ib.rego new file mode 100644 index 0000000000000000000000000000000000000000..df2e9a1b515e472e22d9f0c6675f61ac96005880 --- /dev/null +++ b/tests/policy/postgres-ib.rego @@ -0,0 +1,35 @@ +package main + +name = input.metadata.name + +registries_allow_pg := ["registry1.dsop.io/ironbank", "registry1.dso.mil/ironbank", "registry.dsop.io", "registry.dso.mil"] +registries_warn_pg := ["registry.dsop.io", "registry.dso.mil"] + +in_allowed_registries_pg(image) { + startswith(image, registries_allow[i]) +} + +in_warning_registries_pg(image) { + startswith(image, registries_warn[i]) +} + +# Deny non-approved registries +deny[msg] { + image := input.spec.dockerImage + not in_allowed_registries_pg(image) + msg := sprintf("Image '%v' in '%v' is not from approved registries", [image, name]) +} + +# Warn about non-Ironbank Images +warn[msg] { + image := input.spec.dockerImage + in_warning_registries_pg(image) + msg := sprintf("Image '%v' in '%v' is not from Ironbank", [image, name]) +} + +# Warn about DSOP Images +warn[msg] { + image := input.spec.dockerImage + contains(image, ".dsop.io") + msg := sprintf("Update 'dsop.io' to 'dso.mil' for image '%v' in '%v'", [image, name]) +} diff --git a/tests/test-values.yml b/tests/test-values.yml index d6e4d6c6fff74ca94d3e7e1d064f315bdaedecb0..c142742c4c6a5d80a01bd7f4728001f196fd11af 100644 --- a/tests/test-values.yml +++ b/tests/test-values.yml @@ -1,11 +1,126 @@ +hostname: bigbang.dev + +istio: + # Toggle istio integration + enabled: true + chat: + # Toggle vs creation + enabled: true + annotations: {} + labels: {} + gateways: + - istio-system/main + hosts: + - chat.{{ .Values.hostname }} + +# NOTE: Requires enterprise.enabled to have any effect +monitoring: + enabled: true + namespace: monitoring + +sso: + enabled: false + client_id: platform1_a8604cc9-f5e9-4656-802d-d05624370245_bb8-mattermost + client_secret: nothing # Change to your Keycloak client secret + auth_endpoint: https://login.dso.mil/oauth/authorize + token_endpoint: https://login.dso.mil/oauth/token + user_api_endpoint: https://login.dso.mil/api/v4/user + # Repo and image tag -image: +image: + name: registry.dso.mil/platform-one/big-bang/apps/collaboration-tools/mattermost/mattermost + tag: 5.31.0 imagePullPolicy: IfNotPresent - name: "registry1.dsop.io/ironbank/opensource/mattermost/mattermost-operator:v1.5.0" -#Mattermost operator desired replicas -replicas: - count: 1 +global: + imagePullSecrets: + - name: private-registry-mil + +# Mattermost instance desired replicas +replicaCount: 1 + +users: 100 # Allowable: 100, 1000, 5000, 10000, 25000 + +enterprise: + enabled: false + license: "" + # Example: + # license: | + # LICENSE HERE + +nameOverride: "" + +resources: {} + # limits: + # cpu: 500m + # memory: 512Mi + # requests: + # cpu: 250m + # memory: 256Mi + +# Available options are "soft" and "hard" +antiAffinity: "" + +nodeAffinity: {} + # requiredDuringSchedulingIgnoredDuringExecution: + # nodeSelectorTerms: + # - matchExpressions: + # - key: type + # operator: In + # values: + # - "mattermost-optimized" + +mattermostEnvs: {} + # Add any Mattermost Envs as a map to customize the install, examples: + # MM_TEAMSETTINGS_SITENAME: "DoD Platform One" + # MM_TEAMSETTINGS_CUSTOMDESCRIPTIONTEXT: "Enterprise collaboration services to support DoD telework users" + # MM_SUPPORTSETTINGS_PRIVACYPOLICYLINK: "https://www.privacy.af.mil/Policy-and-Guidelines/" + # MM_SUPPORTSETTINGS_ABOUTLINK: "https://software.af.mil/" + # MM_SUPPORTSETTINGS_CUSTOMTERMSOFSERVICEENABLED: "false" + +minio: + install: true + + accessKey: minio + secretKey: minio#123 # default key, change this! + +postgresql: + install: true + + image: + registry: "registry1.dso.mil/ironbank" + repository: "opensource/postgres/postgresql11" + tag: "11.10" + + pullSecrets: + - private-registry-mil + + postgresqlUsername: "mattermost" + postgresqlPassword: "bigbang" # default password, change this! + postgresqlDatabase: "mattermost" + + fullnameOverride: "mattermost-postgresql" # Overrides the name used for resource creation + + securityContext: + fsGroup: 26 + containerSecurityContext: + runAsUser: 26 + + # Set the configs to allow listening and connecting from other pods + postgresqlConfiguration: {"listen_addresses": "*"} + pgHbaConfiguration: |- + local all all md5 + host all all all md5 + +database: + # Name of an existing secret to pull credentials from, leave empty for chart created database + # Must at minimum contain DB_CONNECTION_STRING + secret: "" -# Watched namespace, blank for all namspaces -watchedNamespace: +fileStore: + # Name of an existing secret to pull credentials from, leave empty for chart created minio + secret: "" + # URL for existing file store, leave empty for chart created minio + url: "" + # Bucket for existing file store, leave empty for chart created minio + bucket: "" \ No newline at end of file