Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(prefect-server): better support for internal and external database configs #365

Merged
merged 11 commits into from
Aug 13, 2024
Merged
20 changes: 20 additions & 0 deletions .github/workflows/helm-unittest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# https://github.com/marketplace/actions/helm-unit-tests

name: Run Helm unit tests

on: pull_request

# Do not grant jobs any permissions by default
permissions: {}

jobs:
unittest:
runs-on: ubuntu-latest
permissions:
# required to read from the repo
contents: read
steps:
- uses: actions/checkout@v3
- uses: d3adb5/helm-unittest-action@v2
with:
helm-version: v3.15.3
1 change: 1 addition & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
helm-docs = '1.13.1'
pre-commit = '3.7.1'
helm = '3.15'
helm-ct = '3.11.0'
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,19 @@ Please make sure that your changes have been linted & the chart documentation ha

Make sure that any new functionality is well tested! You can do this by installing the chart locally, see [above](https://github.com/PrefectHQ/prefect-helm#installing-development-versions) for how to do this.

You can also create and run test suites via [helm-unittest](https://github.com/helm-unittest/helm-unittest).
Related test files are stored under `./charts/<chart>/tests/*_test.yaml`.
Refer to the `helm-unittest` repository for more information.

The following helper script will run the tests via the `helm-unittest` Docker image in case you don't have the binary installed locally:

```shell
./scripts/helm_unittest.sh
```

When `helm-unittest` is available via the [`mise` registry](https://mise.jdx.dev/registry.html), we'll add it to `.mise.toml`
for easy local installation.

### Opening a PR

A helpful PR explains WHAT changed and WHY the change is important. Please take time to make your PR descriptions as helpful as possible. If you are opening a PR from a forked repository - please follow [these](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork) docs to allow `prefect-helm` maintainers to push commits to your local branch.
2 changes: 2 additions & 0 deletions charts/prefect-server/.helmignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@
.idea/
*.tmproj
.vscode/
# helm-unittest
tests
52 changes: 35 additions & 17 deletions charts/prefect-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ Note: If you choose to make modifications to either the `server.prefectApiUrl` o

### Handling Connection Secrets

If you are installing the chart as-is (and therefore installing PostgreSQL) - you'll need to update one of two fields:
1. `postgresql.auth.password`: a password you want to set for the prefect user
#### Using the bundled PostgreSQL chart

By default, Bitnami's PostgreSQL Helm Chart will be deployed. This is **not intended for production use**, and is only
included to provide a functional proof of concept installation.

In this scenario, you'll need to provide _either one_ of the following fields:

1. `postgresql.auth.password`: a password you want to set for the prefect user (default: `prefect-rocks`)

2. `postgresql.auth.existingSecret`: name of an existing secret in your cluster with the following field:

Expand All @@ -38,24 +44,33 @@ If you are installing the chart as-is (and therefore installing PostgreSQL) - yo
- hostname = `<release-name>-postgresql.<release-namespace>:<postgresql.containerPorts.postgresql>`
- database = `postgresql.auth.database`

Two secrets are created when not providing an existing secret name:
1. `prefect-server-postgresql-connection`: used by the prefect-server deployment to connect to the postgresql database.

2. `<release-name>-postgresql-0`: defines the `postgresql.auth.username`'s password on the postgresql server to allow successful authentication from the prefect server.

#### Using an external instance of PostgreSQL

If you want to disable the bundled PostgreSQL chart and use an external instance, provide the following configuration:

```yaml
prefect-server:
postgresql:
# Disable the objects from the bundled PostgreSQL chart
enabled: false
auth:
# Provide the name of an existing secret following the instructions above.
existingSecret: <existing secret name>
```

Two secrets are created when not providing an existing secret name:
1. `prefect-server-postgresql-connection`: used by the prefect-server deployment to connect to the postgresql database.

2. `<release-name>-postgresql-0`: defines the `postgresql.auth.username`'s password on the postgresql server to allow successful authentication from the prefect server.

No secrets are created when providing an existing secret.
secret:
# Option 1: provide the name of an existing secret following the instructions above.
create: false
name: <existing secret name>

# Option 2: provide the connection string details directly
create: true
username: myuser
password: mypass
host: myhost.com
port: 1234
database: mydb
```

### Connecting with SSL configured

Expand Down Expand Up @@ -134,16 +149,19 @@ No secrets are created when providing an existing secret.
| namespaceOverride | string | `""` | fully override common.names.namespace |
| postgresql.auth.database | string | `"server"` | name for a custom database |
| postgresql.auth.enablePostgresUser | bool | `false` | determines whether an admin user is created within postgres |
| postgresql.auth.existingSecret | string | `""` | Name of existing secret to use for PostgreSQL credentials. |
| postgresql.auth.password | string | `"prefect-rocks"` | password for the custom user. Ignored if `auth.existingSecret` with key `password` is provided |
| postgresql.auth.username | string | `"prefect"` | name for a custom user |
| postgresql.containerPorts | object | `{"postgresql":5432}` | PostgreSQL container port |
| postgresql.enabled | bool | `true` | enable use of bitnami/postgresql subchart |
| postgresql.externalHostname | string | `""` | |
| postgresql.image.tag | string | `"14.3.0"` | Version tag, corresponds to tags at https://hub.docker.com/r/bitnami/postgresql/ |
| postgresql.primary.initdb.user | string | `"postgres"` | specify the PostgreSQL username to execute the initdb scripts |
| postgresql.primary.persistence.enabled | bool | `false` | enable PostgreSQL Primary data persistence using PVC |
| postgresql.primary.persistence.size | string | `"8Gi"` | PVC Storage Request for PostgreSQL volume |
| secret.create | bool | `true` | whether to create a Secret containing the PostgreSQL connection string |
| secret.database | string | `""` | database for the PostgreSQL connection string |
| secret.host | string | `""` | host for the PostgreSQL connection string |
| secret.name | string | `""` | name for the Secret containing the PostgreSQL connection string To provide an existing Secret, provide a name and set `create=false` |
| secret.password | string | `""` | password for the PostgreSQL connection string |
| secret.port | string | `""` | port for the PostgreSQL connection string |
| secret.username | string | `""` | username for the PostgreSQL connection string |
| server.affinity | object | `{}` | affinity for server pods assignment |
| server.autoscaling.enabled | bool | `false` | enable autoscaling for server |
| server.autoscaling.maxReplicas | int | `100` | maximum number of server replicas |
Expand Down
41 changes: 28 additions & 13 deletions charts/prefect-server/README.md.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ Note: If you choose to make modifications to either the `server.prefectApiUrl` o

### Handling Connection Secrets

If you are installing the chart as-is (and therefore installing PostgreSQL) - you'll need to update one of two fields:
1. `postgresql.auth.password`: a password you want to set for the prefect user
#### Using the bundled PostgreSQL chart

By default, Bitnami's PostgreSQL Helm Chart will be deployed. This is **not intended for production use**, and is only
included to provide a functional proof of concept installation.

In this scenario, you'll need to provide _either one_ of the following fields:

1. `postgresql.auth.password`: a password you want to set for the prefect user (default: `prefect-rocks`)

2. `postgresql.auth.existingSecret`: name of an existing secret in your cluster with the following field:

Expand All @@ -37,24 +43,33 @@ If you are installing the chart as-is (and therefore installing PostgreSQL) - yo
- hostname = `<release-name>-postgresql.<release-namespace>:<postgresql.containerPorts.postgresql>`
- database = `postgresql.auth.database`

Two secrets are created when not providing an existing secret name:
1. `prefect-server-postgresql-connection`: used by the prefect-server deployment to connect to the postgresql database.

2. `<release-name>-postgresql-0`: defines the `postgresql.auth.username`'s password on the postgresql server to allow successful authentication from the prefect server.

#### Using an external instance of PostgreSQL

If you want to disable the bundled PostgreSQL chart and use an external instance, provide the following configuration:

```yaml
prefect-server:
postgresql:
# Disable the objects from the bundled PostgreSQL chart
enabled: false
auth:
# Provide the name of an existing secret following the instructions above.
existingSecret: <existing secret name>
```

Two secrets are created when not providing an existing secret name:
1. `prefect-server-postgresql-connection`: used by the prefect-server deployment to connect to the postgresql database.

2. `<release-name>-postgresql-0`: defines the `postgresql.auth.username`'s password on the postgresql server to allow successful authentication from the prefect server.

No secrets are created when providing an existing secret.
secret:
# Option 1: provide the name of an existing secret following the instructions above.
create: false
name: <existing secret name>

# Option 2: provide the connection string details directly
create: true
username: myuser
password: mypass
host: myhost.com
port: 1234
database: mydb
```

### Connecting with SSL configured

Expand Down
82 changes: 73 additions & 9 deletions charts/prefect-server/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,80 @@ Create the name of the service account to use
{{- end -}}
{{- end -}}

// ----- Connection string templates ------

{{/*
server.postgres-hostname:
Generate the hostname of the postgresql service
If a subchart is used, evaluate using its fullname function
as {subchart.fullname}-{namespace}
and append the namespace at the end.
Otherwise, the configured external hostname will be returned
*/}}
{{- define "server.postgres-hostname" -}}
{{- if .Values.postgresql.enabled -}}
{{- $subchart_overrides := .Values.postgresql -}}
{{- $name := include "postgresql.v1.primary.fullname" (dict "Values" $subchart_overrides "Chart" (dict "Name" "postgresql") "Release" .Release) -}}
{{- printf "%s.%s" $name .Release.Namespace -}}
{{- $subchart_overrides := .Values.postgresql -}}
{{- $name := include "postgresql.v1.primary.fullname" (dict "Values" $subchart_overrides "Chart" (dict "Name" "postgresql") "Release" .Release) -}}
{{- printf "%s.%s" $name .Release.Namespace -}}
{{- else -}}
{{- .Values.secret.host | required ".Values.secret.host is required." -}}
{{- end -}}
{{- end -}}

{{/*
server.postgres-port:
Generate the port of the postgresql service
If a subchart is used, evaluate using its port function
Otherwise, the configured port will be returned
*/}}
{{- define "server.postgres-port" -}}
{{- if .Values.postgresql.enabled -}}
{{- $subchart_overrides := .Values.postgresql -}}
{{- include "postgresql.v1.service.port" (dict "Values" $subchart_overrides) -}}
{{- else -}}
{{- .Values.secret.port | required ".Values.secret.port is required." -}}
{{- end -}}
{{- end -}}

{{/*
server.postgres-username:
Generate the username for postgresql
If a subchart is used, evaluate using its username function
Otherwise, the configured username will be returned
*/}}
{{- define "server.postgres-username" -}}
{{- if .Values.postgresql.enabled -}}
{{- $subchart_overrides := .Values.postgresql -}}
{{- include "postgresql.v1.username" (dict "Values" $subchart_overrides) -}}
{{- else -}}
{{- .Values.postgresql.externalHostname -}}
{{- .Values.secret.username | required ".Values.secret.username is required." -}}
{{- end -}}
{{- end -}}

{{/*
server.postgres-password:
Generate the password for postgresql
If a subchart is used, evaluate using its password value
Otherwise, the configured password will be returned
*/}}
{{- define "server.postgres-password" -}}
{{- if .Values.postgresql.enabled -}}
{{- .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required." -}}
{{- else -}}
{{- .Values.secret.password | required ".Values.secret.password is required." -}}
{{- end -}}
{{- end -}}

{{/*
server.postgres-database:
Generate the database for postgresql
If a subchart is used, evaluate using its database value
Otherwise, the configured database will be returned
*/}}
{{- define "server.postgres-database" -}}
{{- if .Values.postgresql.enabled -}}
{{- .Values.postgresql.auth.database | required ".Values.postgresql.auth.database is required." -}}
{{- else -}}
{{- .Values.secret.database | required ".Values.secret.database is required." -}}
{{- end -}}
{{- end -}}

Expand All @@ -31,11 +91,11 @@ Create the name of the service account to use
Generates the connection string for the postgresql service
*/}}
{{- define "server.postgres-connstr" -}}
{{- $user := .Values.postgresql.auth.username -}}
{{- $pass := .Values.postgresql.auth.password | required ".Values.postgresql.auth.password is required." -}}
{{- $user := include "server.postgres-username" . -}}
{{- $pass := include "server.postgres-password" . -}}
{{- $host := include "server.postgres-hostname" . -}}
{{- $port := .Values.postgresql.containerPorts.postgresql | toString -}}
{{- $db := .Values.postgresql.auth.database -}}
{{- $port := include "server.postgres-port" . -}}
{{- $db := include "server.postgres-database" . -}}
{{- printf "postgresql+asyncpg://%s:%s@%s:%s/%s" $user $pass $host $port $db -}}
{{- end -}}

Expand All @@ -48,12 +108,16 @@ Create the name of the service account to use
{{- define "server.postgres-string-secret-name" -}}
{{- if .Values.postgresql.auth.existingSecret -}}
{{- .Values.postgresql.auth.existingSecret -}}
{{- else if .Values.secret.name -}}
{{- .Values.secret.name -}}
{{- else -}}
{{- $name := include "common.names.fullname" . -}}
{{- printf "%s-%s" $name "postgresql-connection" -}}
{{- end -}}
{{- end -}}

// ----- End connection string templates -----

{{- define "server.uiUrl" -}}
{{- if .Values.server.uiConfig.prefectUiUrl -}}
{{- .Values.server.uiConfig.prefectUiUrl -}}
Expand Down
2 changes: 1 addition & 1 deletion charts/prefect-server/templates/secret.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{{- if and .Values.postgresql.enabled (not .Values.postgresql.auth.existingSecret) }}
{{- if .Values.secret.create }}
apiVersion: v1
kind: Secret
metadata:
Expand Down
Loading
Loading