Skip to content

test(integration): cover IPv6 deployments; pin single-kernel lib to IPv6 fixes - #1937

Draft
marceloneppel wants to merge 6 commits into
16/edgefrom
fix/ipv6-deployment-16-edge
Draft

test(integration): cover IPv6 deployments; pin single-kernel lib to IPv6 fixes#1937
marceloneppel wants to merge 6 commits into
16/edgefrom
fix/ipv6-deployment-16-edge

Conversation

@marceloneppel

Copy link
Copy Markdown
Member

Issue

On a Juju model whose peer relation binding resolves to an IPv6 address, leader-elected fails with httpx.InvalidURL: Invalid port: '...:8008' and the unit loops in hook-failed. Details and diagnosis: #1928 (internal DPE-11019). Two library-level causes: Patroni REST API URLs built from bare IPv6 literals (rejected by the HTTP clients — an IPv6 literal must be bracketed in a URL authority), and a rendered pg_hba.conf with only IPv4 CIDRs, which rejects Patroni's own bootstrap role-creation connection coming from the unit's IPv6 address (Patroni then cancels the initialization in a wipe-and-restart loop).

Solution

The fixes live in the single-kernel library (postgresql-single-kernel-library fix branch, commit 76faaa9168f7431b170e52865daab5631880d76f): IPv6 literals bracketed in every URL authority, and IPv6 twins for the rendered pg_hba rules (::/0 per IPv4 rule, ::1/128 loopback, family-aware prefix lengths for self addresses). This PR pins the library to that commit, adds a jubilant integration test (tests/integration/test_ipv6_deployment.py) that deploys with the peer relation bound to an IPv6-only space plus IPv4-only and dual-stack variants, and wires the three spread tasks running it. Scenario selection is environment-driven (PG_IP_FAMILY, PG_IPV6_SUBNET) and passed through the integration tox env.

Checklist

  • I have added or updated any relevant documentation.
  • I have cleaned any remaining cloud resources from my accounts.

Pin the single-kernel library to the 16/edge commit that brackets IPv6
literals in every URL it builds (Patroni REST API requests, patroni_url,
primary health checks and client-facing endpoints). With a bare IPv6
literal, HTTP clients parse the address at the first colon and reject
the URL (httpx.InvalidURL), which crashes every hook touching the
cluster status on IPv6 clouds (#1928) because httpx.InvalidURL escapes
the request helper's HTTPError/ValueError handling.

Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
Add a jubilant integration test that deploys the charm with the peer
relation binding forced to a Juju space holding only the IPv6 subnet,
plus IPv4-only and dual-stack variants, and wire one spread task per
scenario. On an IPv6 binding the charm's own cluster networking (Patroni
REST API, cluster status queries) runs purely over IPv6, which is the
condition that crashed every hook before the single-kernel library
bracketed IPv6 literals in URL authorities (#1928).

The get-primary action exercises the exact path that crashed: it queries
the cluster status through the charm-built Patroni API URL.

Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
The scenario selector variables must be listed in the integration
tox env's pass_env, otherwise tox strips them and the test silently
runs as the dual-stack scenario instead of the requested address
family. Parse the network-get binding output correctly: juju 3.6
returns addresses under bind-addresses[].addresses[].value.

Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
Re-running the scenario against a model that already has the space must
not fail: create the space only when absent, keeping the test idempotent
like every other handler in the charm.

Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
Bump the pin from 57606c1 to 76faaa9: on top of the URL-authority
bracketing, the library now renders pg_hba rules matching IPv6 clients
(::/0 twins for every IPv4 rule, ::1/128 loopback and /128 masks for
IPv6 self addresses). Without them the bootstrap's own role-creation
connection from the unit's IPv6 address is rejected with FATAL 28000
and Patroni cancels the bootstrap in a ~7s wipe-and-restart loop.

Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
@github-actions github-actions Bot added the Libraries: Out of sync The charm libs used are out-of-sync label Sep 2, 2026
@marceloneppel marceloneppel added the bug Something isn't working as expected label Sep 2, 2026
The deterministic IPv6 prefix is configured on lxdbr0 after the
controller bootstrapped, so Juju only learns the subnet through
reload-spaces. Without it, add-space fails with 'subnet not found'
on CI (where the prefix is set post-bootstrap), and the IPv6 scenario
never reaches the deploy. The call was accidentally dropped when the
space creation was made idempotent.

Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working as expected Libraries: Out of sync The charm libs used are out-of-sync

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant