diff --git a/README.md b/README.md index 26c4be1..7088602 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,7 @@ View [our docs](https://coder.com/docs/setup/installation) for detailed installa | postgres.noPasswordEnv | bool | If enabled, passwordSecret will be specified as a volumeMount and the env `DB_PASSWORD_PATH` will be set instead to point to that location. The default behaviour is to set the environment variable `DB_PASSWORD` to the value of the postgres password secret. | `false` | | postgres.passwordSecret | string | Name of an existing secret in the current namespace with the password of the PostgreSQL instance. The password must be contained in the secret field `password`. This should be set to an empty string if the database does not require a password to connect. | `""` | | postgres.port | string | Port of the external PostgreSQL instance. | `""` | +| postgres.searchPath | string | Optional. Schema for coder tables in the external PostgresSQL instance. This changes the 'search_path' client configuration option (https://www.postgresql.org/docs/current/runtime-config-client.html). By default, the 'public' schema will be used. | `""` | | postgres.ssl | object | Options for configuring the SSL cert, key, and root cert when connecting to Postgres. | `{"certSecret":{"key":"","name":""},"keySecret":{"key":"","name":""},"rootCertSecret":{"key":"","name":""}}` | | postgres.ssl.certSecret | object | Secret containing a PEM encoded cert file. | `{"key":"","name":""}` | | postgres.ssl.certSecret.key | string | Key pointing to a certificate in the secret. | `""` | diff --git a/templates/_common.tpl b/templates/_common.tpl index 36bcf16..9cfb4ea 100644 --- a/templates/_common.tpl +++ b/templates/_common.tpl @@ -45,6 +45,10 @@ storageClassName: {{ .Values.postgres.default.storageClassName | quote }} value: {{ .Values.postgres.sslMode | quote }} - name: DB_NAME value: {{ .Values.postgres.database | quote }} +{{- if ne .Values.postgres.searchPath "" }} +- name: DB_SEARCH_PATH + value: {{ .Values.postgres.searchPath | quote }} +{{- end }} {{- if ne .Values.postgres.ssl.certSecret.name "" }} - name: DB_CERT value: "/etc/ssl/certs/pg/cert/{{ .Values.postgres.ssl.certSecret.key }}" diff --git a/tests/postgres_test.go b/tests/postgres_test.go index 2df3410..1f1d59a 100644 --- a/tests/postgres_test.go +++ b/tests/postgres_test.go @@ -23,6 +23,8 @@ func Test_PostgresNoPasswordEnv(t *testing.T) { cv.Postgres.Host = pointer.String("1.1.1.1") cv.Postgres.Port = pointer.String("5432") cv.Postgres.User = pointer.String("postgres") + // Empty string is the same as no value + cv.Postgres.SearchPath = pointer.String("") cv.Postgres.Database = pointer.String("postgres") cv.Postgres.PasswordSecret = pointer.String("pg-pass") @@ -40,7 +42,47 @@ func Test_PostgresNoPasswordEnv(t *testing.T) { assert.NotNil(t, env.ValueFrom.SecretKeyRef) && assert.Equal(t, "pg-pass", env.ValueFrom.SecretKeyRef.Name) }) + + AssertNoEnvVar(t, c.Env, "DB_PASSWORD_PATH") + AssertNoEnvVar(t, c.Env, "DB_SEARCH_PATH") + AssertNoVolumeMount(t, c.VolumeMounts, "pg-pass") + }) + } + }) + + // Setting some extra pg vars + t.Run("OffSomeVars", func(t *testing.T) { + t.Parallel() + + objs := LoadChart(t).MustRender(t, func(cv *CoderValues) { + cv.Postgres.Default.Enable = pointer.Bool(false) + + cv.Postgres.Host = pointer.String("1.1.1.1") + cv.Postgres.Port = pointer.String("5432") + cv.Postgres.User = pointer.String("postgres") + cv.Postgres.SearchPath = pointer.String("custom_search") + + cv.Postgres.Database = pointer.String("postgres") + cv.Postgres.PasswordSecret = pointer.String("pg-pass") + }) + coderd := MustFindDeployment(t, objs, "coderd") + + for _, cnt := range []string{"migrations", "coderd"} { + // Combine both init and regular containers. + cnts := append(coderd.Spec.Template.Spec.InitContainers, coderd.Spec.Template.Spec.Containers...) + + AssertContainer(t, cnts, cnt, func(t testing.TB, c corev1.Container) { + AssertEnvVar(t, c.Env, "DB_PASSWORD", func(t testing.TB, env corev1.EnvVar) { + _ = assert.Empty(t, env.Value) && + assert.NotNil(t, env.ValueFrom) && + assert.NotNil(t, env.ValueFrom.SecretKeyRef) && + assert.Equal(t, "pg-pass", env.ValueFrom.SecretKeyRef.Name) + }) + AssertNoEnvVar(t, c.Env, "DB_PASSWORD_PATH") + AssertEnvVar(t, c.Env, "DB_SEARCH_PATH", func(t testing.TB, env corev1.EnvVar) { + assert.Equal(t, "custom_search", env.Value) + }) AssertNoVolumeMount(t, c.VolumeMounts, "pg-pass") }) } diff --git a/tests/values.go b/tests/values.go index 493cffe..5d3def9 100644 --- a/tests/values.go +++ b/tests/values.go @@ -271,6 +271,7 @@ type PostgresValues struct { User *string `json:"user" yaml:"user"` SSLMode *string `json:"sslMode" yaml:"sslMode"` Database *string `json:"database" yaml:"database"` + SearchPath *string `json:"searchPath" yaml:"searchPath"` PasswordSecret *string `json:"passwordSecret" yaml:"passwordSecret"` Default *PostgresDefaultValues `json:"default" yaml:"default"` SSL *PostgresSSLValues `json:"ssl" yaml:"ssl"` diff --git a/values.yaml b/values.yaml index 7fad021..99b16f8 100644 --- a/values.yaml +++ b/values.yaml @@ -360,6 +360,11 @@ postgres: # postgres.database -- Name of the database that Coder will use. # You must create this database first. database: "" + # postgres.searchPath -- Optional. Schema for coder tables in the external + # PostgresSQL instance. This changes the 'search_path' client configuration + # option (https://www.postgresql.org/docs/current/runtime-config-client.html). + # By default, the 'public' schema will be used. + searchPath: "" # postgres.passwordSecret -- Name of an existing secret in the # current namespace with the password of the PostgreSQL instance. # The password must be contained in the secret field `password`.