Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/bake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:
- postgis
- pgaudit
- pg-crash
- tds-fdw

defaults:
run:
Expand Down Expand Up @@ -55,6 +56,9 @@ jobs:
pg-crash:
- 'pg-crash/**'
- *shared
tds-fdw:
- 'tds-fdw/**'
- *shared

# Compute a matrix containing the list of all extensions that have been modified
- name: Compute matrix
Expand Down
70 changes: 70 additions & 0 deletions tds-fdw/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
ARG BASE=ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie
FROM $BASE AS builder

ARG PG_MAJOR
ARG EXT_VERSION

USER 0

RUN set -eux && \
# Initial system libraries
ldconfig -p | awk '{print $NF}' | grep '^/' | sort | uniq > /tmp/base-image-libs.out && \
# Install tds-fdw
apt-get update && \
apt-get install -y --no-install-recommends \
"postgresql-${PG_MAJOR}-tds-fdw=${EXT_VERSION}"

# Gather tds-fdw system libraries and their licenses
RUN mkdir -p /system /licenses && \
# Get libraries
ldd /usr/lib/postgresql/${PG_MAJOR}/lib/tds-fdw*.so \
| awk '{print $3}' | grep '^/' | sort | uniq > /tmp/all-deps.out && \
# Extract all the libs that aren't already part of the base image
comm -13 /tmp/base-image-libs.out /tmp/all-deps.out > /tmp/libraries.out && \
while read -r lib; do \
resolved=$(readlink -f "$lib"); \
dir=$(dirname "$lib"); \
base=$(basename "$lib"); \
# Copy the real file
cp -a "$resolved" /system/; \
# Reconstruct all its symlinks
for file in "$dir"/"${base%.so*}.so"*; do \
[ -e "$file" ] || continue; \
# If it's a symlink and it resolves to the same real file, we reconstruct it
if [ -L "$file" ] && [ "$(readlink -f "$file")" = "$resolved" ]; then \
ln -sf "$(basename "$resolved")" "/system/$(basename "$file")"; \
fi; \
done; \
done < /tmp/libraries.out && \
# Get licenses
for lib in $(find /system -maxdepth 1 -type f -name '*.so*'); do \
# Get the name of the pkg that installed the library
pkg=$(dpkg -S "$(basename "$lib")" | grep -v "diversion by" | awk -F: '/:/{print $1; exit}'); \
[ -z "$pkg" ] && continue; \
mkdir -p "/licenses/$pkg" && cp -a "/usr/share/doc/$pkg/copyright" "/licenses/$pkg/copyright"; \
done


FROM scratch
ARG PG_MAJOR

# Licenses
COPY --from=builder /licenses /licenses/
COPY --from=builder \
/usr/share/doc/postgresql-${PG_MAJOR}-tds-fdw/copyright \
/licenses/postgresql-${PG_MAJOR}-tds-fdw/

# Libraries
COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/tds_fdw* /lib/

COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/bitcode/ /lib/bitcode/

# Share
COPY --from=builder \
/usr/share/postgresql/${PG_MAJOR}/extension/tds_fdw* \
/share/extension/

# System libs
COPY --from=builder /system /system/

USER 65532:65532
89 changes: 89 additions & 0 deletions tds-fdw/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# TDS-FDW

[TDS-FDW](https://github.com/tds-fdw/tds-fdw/) is a PostgreSQL foreign data
wrapper to connect to TDS databases (Sybase and Microsoft SQL Server).

This image provides a convenient way to deploy and manage `tds-fdw` with
[CloudNativePG](https://cloudnative-pg.io/).

## Usage

### 1. Add the tds-fdw extension image to your Cluster

Define the `tds-fdw` extension under the `postgresql.extensions` section of
your `Cluster` resource. For example:

```yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-tds-fdw
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie
instances: 1

storage:
size: 1Gi

postgresql:
extensions:
- name: tds-fdw
image:
# renovate: suite=trixie-pgdg depName=postgresql-18-tds-fdw
reference: ghcr.io/cloudnative-pg/tds-fdw-extension:3.6.2-18-trixie
ld_library_path:
- system
# Requires CloudNativePG 1.29 (or higher)
env:
- name: GDAL_DATA
value: ${image_root}/share/gdal
- name: PROJ_DATA
value: ${image_root}/share/proj
```

### 2. Enable the extension in a database

You can install `tds-fdw` in a specific database by creating or updating a
`Database` resource. For example, to enable it in the `app` database:

```yaml
apiVersion: postgresql.cnpg.io/v1
kind: Database
metadata:
name: cluster-tds-fdw-app
spec:
name: app
owner: app
cluster:
name: cluster-tds-fdw
extensions:
- name: tds-fdw
# renovate: suite=trixie-pgdg depName=postgresql-18-tds-fdw extractVersion=^(?<version>\d+\.\d+\.\d+)
version: '2.0.5'
```

### 3. Verify installation

Once the database is ready, connect to it with `psql` and run:

```sql
\dx
```

You should see `tds_fdw` listed among the installed extensions.


### 4. Verify OS dependencies are properly satisfied

TDS-FDW requires several OS dependencies that are being provided via the `system` directory.
CloudNativePG makes them available to PostgreSQL by adding the directory to LD_LIBRARY_PATH for the PostgreSQL process.

To verify that all tds_fdw shared libraries requirements are being properly satisfied,
connect to the container and run:

```bash
cd /extensions/tds_fdw/lib
LD_LIBRARY_PATH=/extensions/tds_fdw/system ldd tds_fdw*
```

Make sure there are no missing shared libraries.
47 changes: 47 additions & 0 deletions tds-fdw/metadata.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
metadata = {
name = "tds-fdw"
sql_name = "tds_fdw"
image_name = "tds-fdw-extension"
licenses = [ "GPL-2.0-or-later", "MIT", "LGPL-2.1-or-later",
"GPL-3.0-or-later", "Apache-2.0", "PostgreSQL", "Zlib" ]
shared_preload_libraries = []
postgresql_parameters = {}
extension_control_path = []
dynamic_library_path = []
ld_library_path = ["system"]
bin_path = []
env = {
"GDAL_DATA" = "$${image_root}/share/gdal",
"PROJ_DATA" = "$${image_root}/share/proj",
}
auto_update_os_libs = true
required_extensions = []
create_extension = true

versions = {
bookworm = {
"18" = {
// renovate: suite=bookworm-pgdg depName=postgresql-18-tds-fdw
package = "2.0.5-1.pgdg12+1"
// renovate: suite=bookworm-pgdg depName=postgresql-18-tds-fdw extractVersion=^(?<version>\d+\.\d+\.\d+)
sql = "2.0.5"
}
}
trixie = {
"18" = {
// renovate: suite=trixie-pgdg depName=postgresql-18-tds-fdw
package = "2.0.5-1.pgdg13+1"
// renovate: suite=trixie-pgdg depName=postgresql-18-tds-fdw extractVersion=^(?<version>\d+\.\d+\.\d+)
sql = "2.0.5"
}
}
}
}

target "default" {
name = "${metadata.name}-${sanitize(getExtensionVersion(distro, pgVersion))}-${pgVersion}-${distro}"
matrix = {
pgVersion = pgVersions
distro = distributions
}
}
2 changes: 2 additions & 0 deletions tds-fdw/system-libs/18-bookworm-os-libs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
freetds-common_1.3.17+ds-2_all.deb MD5Sum:cf0b6f1497041544e07c2811f436184c
libsybdb5_1.3.17+ds-2_amd64.deb MD5Sum:239206783945be0f1c7f97c19cd46ff8
2 changes: 2 additions & 0 deletions tds-fdw/system-libs/18-trixie-os-libs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
freetds-common_1.3.17+ds-2+deb13u1_all.deb MD5Sum:36e923199e94040883f33ea90f07f558
libsybdb5_1.3.17+ds-2+deb13u1_amd64.deb MD5Sum:6b3f1f9d9362f7f5e7f0a1eef8cdb4df