Skip to content

Commit 370a799

Browse files
Create data directory symlink (#1217)
* Update canonical/data-platform-workflows action to v41 (#1211) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * feat(storage): add symlink from default PostgreSQL data path Create a symlink from /var/lib/postgresql/16/main to /var/lib/pg/data/16/main to provide compatibility with the standard PostgreSQL data directory location. Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com> --------- Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1 parent 6e14e88 commit 370a799

File tree

8 files changed

+92
-7
lines changed

8 files changed

+92
-7
lines changed

.github/workflows/approve_renovate_pr.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ on:
1010
jobs:
1111
approve-pr:
1212
name: Approve Renovate pull request
13-
uses: canonical/data-platform-workflows/.github/workflows/approve_renovate_pr.yaml@v40.0.2
13+
uses: canonical/data-platform-workflows/.github/workflows/approve_renovate_pr.yaml@v41.0.0
1414
permissions:
1515
pull-requests: write # Needed to approve PR

.github/workflows/check_pr.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ on:
1616
jobs:
1717
check-pr:
1818
name: Check pull request
19-
uses: canonical/data-platform-workflows/.github/workflows/check_charm_pr.yaml@v40.0.2
19+
uses: canonical/data-platform-workflows/.github/workflows/check_charm_pr.yaml@v41.0.0

.github/workflows/ci.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ on:
2828
jobs:
2929
lint:
3030
name: Lint
31-
uses: canonical/data-platform-workflows/.github/workflows/lint.yaml@v40.0.2
31+
uses: canonical/data-platform-workflows/.github/workflows/lint.yaml@v41.0.0
3232

3333
unit-test:
3434
name: Unit test charm
@@ -50,7 +50,7 @@ jobs:
5050

5151
build:
5252
name: Build charm
53-
uses: canonical/data-platform-workflows/.github/workflows/build_charm.yaml@v40.0.2
53+
uses: canonical/data-platform-workflows/.github/workflows/build_charm.yaml@v41.0.0
5454

5555
integration-test:
5656
name: Integration test charm

.github/workflows/promote.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ on:
2525
jobs:
2626
promote:
2727
name: Promote charms
28-
uses: canonical/data-platform-workflows/.github/workflows/_promote_charms.yaml@v40.0.2
28+
uses: canonical/data-platform-workflows/.github/workflows/_promote_charms.yaml@v41.0.0
2929
with:
3030
track: '16'
3131
from-risk: ${{ inputs.from-risk }}

.github/workflows/release.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ on:
1818
jobs:
1919
tag:
2020
name: Create charm refresh compatibility version git tag
21-
uses: canonical/data-platform-workflows/.github/workflows/tag_charm_edge.yaml@v40.0.2
21+
uses: canonical/data-platform-workflows/.github/workflows/tag_charm_edge.yaml@v41.0.0
2222
with:
2323
track: '16'
2424
permissions:
@@ -38,7 +38,7 @@ jobs:
3838
needs:
3939
- tag
4040
- ci-tests
41-
uses: canonical/data-platform-workflows/.github/workflows/release_charm_edge.yaml@v40.0.2
41+
uses: canonical/data-platform-workflows/.github/workflows/release_charm_edge.yaml@v41.0.0
4242
with:
4343
track: ${{ needs.tag.outputs.track }}
4444
artifact-prefix: ${{ needs.ci-tests.outputs.artifact-prefix }}

src/charm.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,23 @@ def _create_pgdata(self, container: Container):
11671167
group=WORKLOAD_OS_GROUP,
11681168
make_parents=True,
11691169
)
1170+
# Create a symlink from the default PostgreSQL data directory to our data directory
1171+
# (e.g., /var/lib/postgresql/16/main -> /var/lib/pg/data/16/main)
1172+
default_pgdata_path = "/var/lib/postgresql/16/main"
1173+
if not container.exists(default_pgdata_path):
1174+
container.make_dir(
1175+
"/var/lib/postgresql/16",
1176+
user=WORKLOAD_OS_USER,
1177+
group=WORKLOAD_OS_GROUP,
1178+
make_parents=True,
1179+
)
1180+
container.exec(["ln", "-s", self.pgdata_path, default_pgdata_path]).wait()
1181+
container.exec([
1182+
"chown",
1183+
"-h",
1184+
f"{WORKLOAD_OS_USER}:{WORKLOAD_OS_GROUP}",
1185+
default_pgdata_path,
1186+
]).wait()
11701187
# Also, fix the permissions from the parent directory.
11711188
container.exec([
11721189
"chown",

tests/integration/test_symlinks.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env python3
2+
# Copyright 2026 Canonical Ltd.
3+
# See LICENSE file for licensing details.
4+
5+
"""Integration tests for PostgreSQL symlinks (pgdata)."""
6+
7+
import logging
8+
9+
import pytest
10+
from pytest_operator.plugin import OpsTest
11+
12+
from .helpers import (
13+
METADATA,
14+
PGDATA_PATH,
15+
build_and_deploy,
16+
run_command_on_unit,
17+
)
18+
19+
logger = logging.getLogger(__name__)
20+
21+
APP_NAME = METADATA["name"]
22+
UNIT_IDS = [0, 1, 2]
23+
PGDATA_SYMLINK_PATH = "/var/lib/postgresql/16/main"
24+
25+
26+
@pytest.mark.abort_on_fail
27+
@pytest.mark.skip_if_deployed
28+
async def test_build_and_deploy(ops_test: OpsTest, charm):
29+
"""Build the charm-under-test and deploy it.
30+
31+
Assert on the unit status before any relations/configurations take place.
32+
"""
33+
async with ops_test.fast_forward():
34+
await build_and_deploy(ops_test, charm, len(UNIT_IDS), APP_NAME)
35+
for unit_id in UNIT_IDS:
36+
assert ops_test.model.applications[APP_NAME].units[unit_id].workload_status == "active"
37+
38+
39+
@pytest.mark.parametrize("unit_id", UNIT_IDS)
40+
async def test_pgdata_symlinks(ops_test: OpsTest, unit_id: int):
41+
"""Test that symlink for pgdata is correctly created."""
42+
unit_name = f"{APP_NAME}/{unit_id}"
43+
44+
# Check pgdata symlink exists and points to correct location
45+
pgdata_symlink_check = await run_command_on_unit(
46+
ops_test, unit_name, f"readlink -f {PGDATA_SYMLINK_PATH}"
47+
)
48+
assert pgdata_symlink_check.strip() == PGDATA_PATH, (
49+
f"Expected pgdata symlink to point to {PGDATA_PATH}, got {pgdata_symlink_check.strip()}"
50+
)
51+
52+
# Verify symlink is owned by postgres:postgres
53+
pgdata_owner = await run_command_on_unit(
54+
ops_test, unit_name, f"stat -c '%U:%G' {PGDATA_SYMLINK_PATH}"
55+
)
56+
assert pgdata_owner.strip() == "postgres:postgres", (
57+
f"Expected pgdata symlink to be owned by postgres:postgres, got {pgdata_owner.strip()}"
58+
)

tests/unit/test_charm.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,8 +1544,18 @@ def test_create_pgdata(harness):
15441544
group="postgres",
15451545
make_parents=True,
15461546
),
1547+
call(
1548+
"/var/lib/postgresql/16",
1549+
user="postgres",
1550+
group="postgres",
1551+
make_parents=True,
1552+
),
15471553
])
15481554
container.exec.assert_has_calls([
1555+
call(["ln", "-s", "/var/lib/pg/data/16/main", "/var/lib/postgresql/16/main"]),
1556+
call().wait(),
1557+
call(["chown", "-h", "postgres:postgres", "/var/lib/postgresql/16/main"]),
1558+
call().wait(),
15491559
call(["chown", "postgres:postgres", "/var/lib/pg/archive"]),
15501560
call().wait(),
15511561
call(["chown", "postgres:postgres", "/var/lib/pg/data"]),

0 commit comments

Comments
 (0)