Skip to content

Commit 790be27

Browse files
committed
add tds-fdw extension
Closes #181 Signed-off-by: Tobias Florek <me@ibotty.net>
1 parent fd09e3f commit 790be27

6 files changed

Lines changed: 211 additions & 0 deletions

File tree

.github/workflows/bake.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ on:
1313
- postgis
1414
- pgaudit
1515
- pg-crash
16+
- tds-fdw
1617

1718
defaults:
1819
run:

tds-fdw/Dockerfile

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
ARG BASE=ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie
2+
FROM $BASE AS builder
3+
4+
ARG PG_MAJOR
5+
ARG EXT_VERSION
6+
7+
USER 0
8+
9+
RUN set -eux && \
10+
# Initial system libraries
11+
ldconfig -p | awk '{print $NF}' | grep '^/' | sort | uniq > /tmp/base-image-libs.out && \
12+
# Install tds-fdw
13+
apt-get update && \
14+
apt-get install -y --no-install-recommends \
15+
"postgresql-${PG_MAJOR}-tds-fdw=${EXT_VERSION}"
16+
17+
# Gather tds-fdw system libraries and their licenses
18+
RUN mkdir -p /system /licenses && \
19+
# Get libraries
20+
ldd /usr/lib/postgresql/${PG_MAJOR}/lib/tds-fdw*.so \
21+
| awk '{print $3}' | grep '^/' | sort | uniq > /tmp/all-deps.out && \
22+
# Extract all the libs that aren't already part of the base image
23+
comm -13 /tmp/base-image-libs.out /tmp/all-deps.out > /tmp/libraries.out && \
24+
while read -r lib; do \
25+
resolved=$(readlink -f "$lib"); \
26+
dir=$(dirname "$lib"); \
27+
base=$(basename "$lib"); \
28+
# Copy the real file
29+
cp -a "$resolved" /system/; \
30+
# Reconstruct all its symlinks
31+
for file in "$dir"/"${base%.so*}.so"*; do \
32+
[ -e "$file" ] || continue; \
33+
# If it's a symlink and it resolves to the same real file, we reconstruct it
34+
if [ -L "$file" ] && [ "$(readlink -f "$file")" = "$resolved" ]; then \
35+
ln -sf "$(basename "$resolved")" "/system/$(basename "$file")"; \
36+
fi; \
37+
done; \
38+
done < /tmp/libraries.out && \
39+
# Get licenses
40+
for lib in $(find /system -maxdepth 1 -type f -name '*.so*'); do \
41+
# Get the name of the pkg that installed the library
42+
pkg=$(dpkg -S "$(basename "$lib")" | grep -v "diversion by" | awk -F: '/:/{print $1; exit}'); \
43+
[ -z "$pkg" ] && continue; \
44+
mkdir -p "/licenses/$pkg" && cp -a "/usr/share/doc/$pkg/copyright" "/licenses/$pkg/copyright"; \
45+
done
46+
47+
48+
FROM scratch
49+
ARG PG_MAJOR
50+
51+
# Licenses
52+
COPY --from=builder /licenses /licenses/
53+
COPY --from=builder \
54+
/usr/share/doc/postgresql-${PG_MAJOR}-tds-fdw/copyright \
55+
/licenses/postgresql-${PG_MAJOR}-tds-fdw/
56+
57+
# Libraries
58+
COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/tds_fdw* /lib/
59+
60+
COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/bitcode/ /lib/bitcode/
61+
62+
# Share
63+
COPY --from=builder \
64+
/usr/share/postgresql/${PG_MAJOR}/extension/tds_fdw* \
65+
/share/extension/
66+
67+
# System libs
68+
COPY --from=builder /system /system/
69+
70+
USER 65532:65532

tds-fdw/README.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# TDS-FDW
2+
3+
[TDS-FDW](https://github.com/tds-fdw/tds-fdw/) is a PostgreSQL foreign data
4+
wrapper to connect to TDS databases (Sybase and Microsoft SQL Server).
5+
6+
This image provides a convenient way to deploy and manage `tds-fdw` with
7+
[CloudNativePG](https://cloudnative-pg.io/).
8+
9+
## Usage
10+
11+
### 1. Add the tds-fdw extension image to your Cluster
12+
13+
Define the `tds-fdw` extension under the `postgresql.extensions` section of
14+
your `Cluster` resource. For example:
15+
16+
```yaml
17+
apiVersion: postgresql.cnpg.io/v1
18+
kind: Cluster
19+
metadata:
20+
name: cluster-tds-fdw
21+
spec:
22+
imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie
23+
instances: 1
24+
25+
storage:
26+
size: 1Gi
27+
28+
postgresql:
29+
extensions:
30+
- name: tds-fdw
31+
image:
32+
# renovate: suite=trixie-pgdg depName=postgresql-18-tds-fdw
33+
reference: ghcr.io/cloudnative-pg/tds-fdw-extension:3.6.2-18-trixie
34+
ld_library_path:
35+
- system
36+
# Requires CloudNativePG 1.29 (or higher)
37+
env:
38+
- name: GDAL_DATA
39+
value: ${image_root}/share/gdal
40+
- name: PROJ_DATA
41+
value: ${image_root}/share/proj
42+
```
43+
44+
### 2. Enable the extension in a database
45+
46+
You can install `tds-fdw` in a specific database by creating or updating a
47+
`Database` resource. For example, to enable it in the `app` database:
48+
49+
```yaml
50+
apiVersion: postgresql.cnpg.io/v1
51+
kind: Database
52+
metadata:
53+
name: cluster-tds-fdw-app
54+
spec:
55+
name: app
56+
owner: app
57+
cluster:
58+
name: cluster-tds-fdw
59+
extensions:
60+
- name: tds-fdw
61+
# renovate: suite=trixie-pgdg depName=postgresql-18-tds-fdw extractVersion=^(?<version>\d+\.\d+\.\d+)
62+
version: '2.0.5'
63+
```
64+
65+
### 3. Verify installation
66+
67+
Once the database is ready, connect to it with `psql` and run:
68+
69+
```sql
70+
\dx
71+
```
72+
73+
You should see `tds_fdw` listed among the installed extensions.
74+
75+
76+
### 4. Verify OS dependencies are properly satisfied
77+
78+
TDS-FDW requires several OS dependencies that are being provided via the `system` directory.
79+
CloudNativePG makes them available to PostgreSQL by adding the directory to LD_LIBRARY_PATH for the PostgreSQL process.
80+
81+
To verify that all tds_fdw shared libraries requirements are being properly satisfied,
82+
connect to the container and run:
83+
84+
```bash
85+
cd /extensions/tds_fdw/lib
86+
LD_LIBRARY_PATH=/extensions/tds_fdw/system ldd tds_fdw*
87+
```
88+
89+
Make sure there are no missing shared libraries.

tds-fdw/metadata.hcl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
metadata = {
2+
name = "tds-fdw"
3+
sql_name = "tds_fdw"
4+
image_name = "tds-fdw-extension"
5+
licenses = [ "GPL-2.0-or-later", "MIT", "LGPL-2.1-or-later",
6+
"GPL-3.0-or-later", "Apache-2.0", "PostgreSQL", "Zlib" ]
7+
shared_preload_libraries = []
8+
postgresql_parameters = {}
9+
extension_control_path = []
10+
dynamic_library_path = []
11+
ld_library_path = ["system"]
12+
bin_path = []
13+
env = {
14+
"GDAL_DATA" = "$${image_root}/share/gdal",
15+
"PROJ_DATA" = "$${image_root}/share/proj",
16+
}
17+
auto_update_os_libs = true
18+
required_extensions = []
19+
create_extension = true
20+
21+
versions = {
22+
bookworm = {
23+
"18" = {
24+
// renovate: suite=bookworm-pgdg depName=postgresql-18-tds-fdw
25+
package = "2.0.5-1.pgdg12+1"
26+
// renovate: suite=bookworm-pgdg depName=postgresql-18-tds-fdw extractVersion=^(?<version>\d+\.\d+\.\d+)
27+
sql = "2.0.5"
28+
}
29+
}
30+
trixie = {
31+
"18" = {
32+
// renovate: suite=trixie-pgdg depName=postgresql-18-tds-fdw
33+
package = "2.0.5-1.pgdg13+1"
34+
// renovate: suite=trixie-pgdg depName=postgresql-18-tds-fdw extractVersion=^(?<version>\d+\.\d+\.\d+)
35+
sql = "2.0.5"
36+
}
37+
}
38+
}
39+
}
40+
41+
target "default" {
42+
name = "${metadata.name}-${sanitize(getExtensionVersion(distro, pgVersion))}-${pgVersion}-${distro}"
43+
matrix = {
44+
pgVersion = pgVersions
45+
distro = distributions
46+
}
47+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
freetds-common_1.3.17+ds-2_all.deb MD5Sum:cf0b6f1497041544e07c2811f436184c
2+
libsybdb5_1.3.17+ds-2_amd64.deb MD5Sum:239206783945be0f1c7f97c19cd46ff8
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
freetds-common_1.3.17+ds-2+deb13u1_all.deb MD5Sum:36e923199e94040883f33ea90f07f558
2+
libsybdb5_1.3.17+ds-2+deb13u1_amd64.deb MD5Sum:6b3f1f9d9362f7f5e7f0a1eef8cdb4df

0 commit comments

Comments
 (0)