fix: unblock instanceable connectivity store-service install + clean up on delete
Live verification on pic1 of the connectivity v2 multi-instance feature
surfaced four integration bugs that prevented installing any published
connectivity store service (proxy/wireguard-ext/openvpn-client/sshuttle)
and left stale host routing state behind. All four are fixed here:
1. manifest_validator rejected the CI-published `name:tag@sha256:<digest>`
image form (it required digest-only), while service_store_manager already
accepted it — so every published store image failed validation. Allow an
optional tag before the digest, matching service_store_manager.
2. The cell-api image shipped the docker CLI but not the Compose v2 plugin,
so every `docker compose` ServiceComposer runs (pull/up/down for store
services) failed with "'compose' is not a docker command". Copy the
compose plugin binary from the docker-cli stage.
3. service_store_manager.install ran the base compose up for instanceable
services, whose template still contains ${INSTANCE_ID}/${REDIRECT_PORT}
(there is no base container — one runs per connection instance). It now
verifies the image signature but defers the container to connection
creation for instanceable manifests.
4. delete_connection freed the record/secrets/container but never removed the
connection's individually-managed `ip rule fwmark->table` or its FORWARD
kill-switch (apply_routes only flushes the PIC_CONNECTIVITY chains and
re-adds rules for surviving connections), leaking stale host routing state.
It now tears both down; added _remove_killswitch.
Verified end-to-end on pic1: two proxy instances allocate distinct
marks/tables/ports (skipping in-use resources), render distinct per-instance
containers, two peers route through distinct instances (per-peer MARK +
REDIRECT), delete is blocked while referenced (409) and cleans its ip rule.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -175,6 +175,19 @@ class TestValidateManifest(unittest.TestCase):
|
||||
self.assertTrue(ok)
|
||||
self.assertEqual(errs, [])
|
||||
|
||||
def test_image_tag_and_digest_passes(self):
|
||||
# The publish pipeline writes back name:tag@sha256:<digest> (a valid OCI
|
||||
# reference). The validator must accept the tag alongside the digest —
|
||||
# service_store_manager already does, and rejecting it here blocks every
|
||||
# published store image from installing.
|
||||
digest = 'a' * 64
|
||||
ok, errs = validate_manifest(
|
||||
_minimal_manifest(
|
||||
image=f'git.pic.ngo/roof/svc-proxy:latest@sha256:{digest}')
|
||||
)
|
||||
self.assertTrue(ok, errs)
|
||||
self.assertEqual(errs, [])
|
||||
|
||||
def test_image_wrong_registry_rejected(self):
|
||||
digest = 'a' * 64
|
||||
ok, errs = validate_manifest(
|
||||
|
||||
Reference in New Issue
Block a user