diff --git a/README.md b/README.md index 9d47142f..c6cbd202 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ from a trusted, auditable repository | **[pgAudit](pgaudit)** | PostgreSQL audit extension | [github.com/pgaudit/pgaudit](https://github.com/pgaudit/pgaudit) | CNPG maintainers | | **[pg_crash](pg-crash)** | **Disruptive** fault injection and chaos engineering extension | [github.com/cybertec-postgresql/pg_crash](https://github.com/cybertec-postgresql/pg_crash) | CNPG maintainers | | **[pg_ivm](pg-ivm)** | Incremental View Maintenance for PostgreSQL | [github.com/sraoss/pg_ivm](https://github.com/sraoss/pg_ivm) | @shusaan | +| **[pgRouting](pgrouting)** | Geospatial routing and network analysis for PostgreSQL/PostGIS | [pgrouting.org](https://pgrouting.org/) | | | **[pgvector](pgvector)** | Vector similarity search for PostgreSQL | [github.com/pgvector/pgvector](https://github.com/pgvector/pgvector) | CNPG maintainers | | **[PostGIS](postgis)** | Geospatial database extension for PostgreSQL | [postgis.net/](https://postgis.net/) | CNPG maintainers | | **[TimescaleDB Apache-2 Edition](timescaledb-oss)** | Time-series database for PostgreSQL (open source version) | [github.com/timescale/timescaledb/](https://github.com/timescale/timescaledb/) | @shusaan | diff --git a/pgrouting/Dockerfile b/pgrouting/Dockerfile new file mode 100644 index 00000000..a4be5140 --- /dev/null +++ b/pgrouting/Dockerfile @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: Copyright © contributors to CloudNativePG, established as CloudNativePG a Series of LF Projects, LLC. +# SPDX-License-Identifier: Apache-2.0 + +ARG BASE=ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie +FROM $BASE AS builder + +ARG PG_MAJOR +ARG EXT_VERSION + +USER 0 + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + "postgresql-${PG_MAJOR}-pgrouting=${EXT_VERSION}" \ + "postgresql-${PG_MAJOR}-pgrouting-scripts=${EXT_VERSION}" + +FROM scratch +ARG PG_MAJOR + +# Licenses +COPY --from=builder /usr/share/doc/postgresql-${PG_MAJOR}-pgrouting/copyright /licenses/postgresql-${PG_MAJOR}-pgrouting/ + +# Libraries +COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/libpgrouting* /lib/ +COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/bitcode/ /lib/bitcode/ + +# Share +COPY --from=builder /usr/share/postgresql/${PG_MAJOR}/extension/pgrouting* /share/extension/ + +USER 65532:65532 diff --git a/pgrouting/README.md b/pgrouting/README.md new file mode 100644 index 00000000..da25937c --- /dev/null +++ b/pgrouting/README.md @@ -0,0 +1,104 @@ +# pgRouting + + +[pgRouting](https://pgrouting.org/) extends the [PostGIS](https://postgis.net/)/PostgreSQL geospatial database to +provide geospatial routing and other network analysis functionality. + +This image provides a convenient way to deploy and manage `pgRouting` with [CloudNativePG](https://cloudnative-pg.io/). + +> [!NOTE] +> `pgRouting` depends on `PostGIS`. When deploying `pgRouting`, you must also include the `postgis` extension image in +> your Cluster definition. + +## Usage + +### 1. Add the pgRouting and PostGIS extension images to your Cluster + +Define the `postgis` and `pgrouting` extensions under the `postgresql.extensions` section of your `Cluster` resource. +For example: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: cluster-pgrouting +spec: + imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie + instances: 1 + + storage: + size: 1Gi + + postgresql: + extensions: + - name: postgis + image: + # renovate: suite=trixie-pgdg depName=postgresql-18-postgis-3 + reference: ghcr.io/cloudnative-pg/postgis-extension:3.6.4-18-trixie + ld_library_path: + - system + env: + - name: GDAL_DATA + value: ${image_root}/share/gdal + - name: PROJ_DATA + value: ${image_root}/share/proj + - name: pgrouting + image: + # renovate: suite=trixie-pgdg depName=postgresql-18-pgrouting + reference: ghcr.io/cloudnative-pg/pgrouting:4.0.1-18-trixie +``` + +### 2. Enable the extension in a database + +You can install `pgrouting` in a specific database by creating or updating a `Database` resource: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Database +metadata: + name: cluster-pgrouting-app +spec: + name: app + owner: app + cluster: + name: cluster-pgrouting + extensions: + - name: postgis + # renovate: suite=trixie-pgdg depName=postgresql-18-postgis-3 extractVersion=^(?\d+\.\d+\.\d+) + version: '3.6.4' + - name: pgrouting + # renovate: suite=trixie-pgdg depName=postgresql-18-pgrouting extractVersion=^(?\d+\.\d+\.\d+) + version: '4.0.1' +``` + +### 3. Verify installation + +Once the database is ready, connect to it with `psql` and run: + +```sql +\dx +``` + +You should see `postgis` and `pgrouting` listed among the installed extensions. + +--- + +## Licenses and Copyright + +`pgRouting`: + +- **Copyright:** pgRouting Contributors +- **License:** GNU General Public License v2.0 or later (`GPL-2.0-or-later`) + +All relevant license and copyright information for the `pgrouting` extension +and its dependencies are bundled within the image at: + +```text +/licenses/ +``` + +By using this image, you agree to comply with the terms of the licenses +contained therein. diff --git a/pgrouting/metadata.hcl b/pgrouting/metadata.hcl new file mode 100644 index 00000000..fd78d500 --- /dev/null +++ b/pgrouting/metadata.hcl @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: Copyright © contributors to CloudNativePG, established as CloudNativePG a Series of LF Projects, LLC. +# SPDX-License-Identifier: Apache-2.0 +metadata = { + name = "pgrouting" + sql_name = "pgrouting" + image_name = "pgrouting" + licenses = ["GPL-2.0-or-later"] + shared_preload_libraries = [] + postgresql_parameters = {} + extension_control_path = [] + dynamic_library_path = [] + ld_library_path = [] + bin_path = [] + env = {} + auto_update_os_libs = false + required_extensions = ["postgis"] + create_extension = true + + versions = { + bookworm = { + "18" = { + // renovate: suite=bookworm-pgdg depName=postgresql-18-pgrouting + package = "4.0.1-1.pgdg12+1" + // renovate: suite=bookworm-pgdg depName=postgresql-18-pgrouting extractVersion=^(?\d+\.\d+\.\d+) + sql = "4.0.1" + } + } + trixie = { + "18" = { + // renovate: suite=trixie-pgdg depName=postgresql-18-pgrouting + package = "4.0.1-1.pgdg13+1" + // renovate: suite=trixie-pgdg depName=postgresql-18-pgrouting extractVersion=^(?\d+\.\d+\.\d+) + sql = "4.0.1" + } + } + } +} diff --git a/pgrouting/test/chainsaw-test.yaml b/pgrouting/test/chainsaw-test.yaml new file mode 100644 index 00000000..44d17ee7 --- /dev/null +++ b/pgrouting/test/chainsaw-test.yaml @@ -0,0 +1,28 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: verify-pgrouting-extension +spec: + timeouts: + apply: 5s + assert: 3m + delete: 30s + description: Verify pgrouting extension is properly installed + steps: + - name: Create a Cluster with the extension + try: + - apply: + file: cluster.yaml + - apply: + file: database.yaml + - assert: + file: cluster-assert.yaml + - assert: + file: database-assert.yaml + + - name: Verify extension is installed + try: + - apply: + file: check-extension.yaml + - assert: + file: check-extension-assert.yaml diff --git a/pgrouting/test/check-extension-assert.yaml b/pgrouting/test/check-extension-assert.yaml new file mode 100644 index 00000000..a7971fc7 --- /dev/null +++ b/pgrouting/test/check-extension-assert.yaml @@ -0,0 +1,6 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: extension-installed +status: + succeeded: 1 diff --git a/pgrouting/test/check-extension.yaml b/pgrouting/test/check-extension.yaml new file mode 100644 index 00000000..46736c93 --- /dev/null +++ b/pgrouting/test/check-extension.yaml @@ -0,0 +1,28 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: extension-installed +spec: + template: + spec: + restartPolicy: OnFailure + containers: + - name: data-test + env: + - name: PGSSLROOTCERT + - name: EXT_VERSION + value: ($values.version) + - name: DB_URI + valueFrom: + secretKeyRef: + name: (join('-', [$values.name, 'app'])) + key: uri + # renovate: datasource=docker depName=alpine/psql versioning=docker + image: alpine/psql:18.4@sha256:b3e4fc061da067813ddc5a8844b1992a50d5f1dce72d46be8ee5d0b964a3e894 + command: ['sh', '-c'] + args: + - | + set -e + DB_URI=$(echo $DB_URI | sed "s|/\*|/|") + test "$(psql "$DB_URI" -tAc "SELECT EXISTS (SELECT FROM pg_catalog.pg_extension WHERE extname = 'postgis')" -q)" = "t" + test "$(psql "$DB_URI" -tAc "SELECT EXISTS (SELECT FROM pg_catalog.pg_extension WHERE extname = 'pgrouting' AND extversion = '${EXT_VERSION}')" -q)" = "t" diff --git a/pgrouting/test/cluster-assert.yaml b/pgrouting/test/cluster-assert.yaml new file mode 100644 index 00000000..e6420cef --- /dev/null +++ b/pgrouting/test/cluster-assert.yaml @@ -0,0 +1,8 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: ($values.name) +status: + instances: 1 + readyInstances: 1 + phase: Cluster in healthy state diff --git a/pgrouting/test/cluster.yaml b/pgrouting/test/cluster.yaml new file mode 100644 index 00000000..48d6fe06 --- /dev/null +++ b/pgrouting/test/cluster.yaml @@ -0,0 +1,15 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: ($values.name) +spec: + imageName: ($values.pg_image) + instances: 1 + + storage: + size: 1Gi + + postgresql: + parameters: ($values.postgresql_parameters) + shared_preload_libraries: ($values.shared_preload_libraries) + extensions: ($values.extensions) diff --git a/pgrouting/test/database-assert.yaml b/pgrouting/test/database-assert.yaml new file mode 100644 index 00000000..9417b87b --- /dev/null +++ b/pgrouting/test/database-assert.yaml @@ -0,0 +1,5 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Database +metadata: + name: (join('-', [$values.name, 'app'])) +status: ($values.database_assert_status) diff --git a/pgrouting/test/database.yaml b/pgrouting/test/database.yaml new file mode 100644 index 00000000..2d6810c2 --- /dev/null +++ b/pgrouting/test/database.yaml @@ -0,0 +1,10 @@ +apiVersion: postgresql.cnpg.io/v1 +kind: Database +metadata: + name: (join('-', [$values.name, 'app'])) +spec: + name: app + owner: app + cluster: + name: ($values.name) + extensions: ($values.database_config.extensions_spec)