diff --git a/.github/workflows/integration_test.yaml b/.github/workflows/integration_test.yaml index ebd3c341..801904c7 100644 --- a/.github/workflows/integration_test.yaml +++ b/.github/workflows/integration_test.yaml @@ -23,6 +23,8 @@ jobs: self-hosted-runner-arch: X64 self-hosted-runner-label: pfe-ci builder-runner-label: X64 + pre-run-script: | + -c "./tests/integration/aproxy_prerouting_workaround.sh" allure-report: if: ${{ !cancelled() && github.event_name == 'schedule' }} needs: diff --git a/docs/changelog.md b/docs/changelog.md index 1c87110d..f14883ad 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,6 +1,9 @@ +## [#198 Update integration tests](https://github.com/canonical/github-runner-image-builder-operator/pull/198) (2026-02-17) +* Update integration tests that were intentionally not done in #185. + ## [#185 Remove aproxy installation and add proxy support in workload](https://github.com/canonical/github-runner-image-builder-operator/pull/185) (2026-01-20) * Remove `aproxy` snap installation in the charm and inject proxy values from the model config into the workload process. diff --git a/tests/integration/aproxy_prerouting_workaround.sh b/tests/integration/aproxy_prerouting_workaround.sh new file mode 100755 index 00000000..93db6d35 --- /dev/null +++ b/tests/integration/aproxy_prerouting_workaround.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# Copyright 2026 Canonical Ltd. +# See LICENSE file for licensing details. + +# Aproxy is installed on the CI runners and we want to test if the charm and workload respect the +# proxy values without aproxy. This script adds a nftables rule to bypass aproxy for any traffic +# originating from the LXD container, except for the juju controller traffic which is needed +# to spin up machines for the charms. + +set -euo pipefail + +# charmcraft pack runs inside the LXD container and needs to go through proxy so it +# will be done before modifying the nftables rules. +/snap/bin/charmcraft pack -p tests/integration/data/charm + +IP=$(lxc list -c 4 --format csv | awk '{print $1}' | head -n 1) + +if [[ -z "${IP:-}" ]]; then + echo "Error: no IPv4 address found from 'lxc list'. Ensure an LXC container with an IPv4 address is running." >&2 + exit 1 +fi + +echo "IP=$IP" + +if ! sudo nft list chain ip aproxy prerouting >/dev/null 2>&1; then + echo "Error: nftables chain 'ip aproxy prerouting' not found. Ensure aproxy is configured before running this script." >&2 + exit 1 +fi + +# we want only the juju controller traffic to go through aproxy to spin up machines for the charms. +# Any other charm related traffic should handle proxy by itself. +sudo nft insert rule ip aproxy prerouting index 0 ip saddr != "$IP" return diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 96bc13c9..1d130d93 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -10,10 +10,6 @@ import os import secrets import string - -# subprocess module is used to call juju cli directly due to constraints with private-endpoint -# models -import subprocess # nosec: B404 from dataclasses import dataclass from datetime import datetime, timezone from pathlib import Path @@ -64,6 +60,8 @@ # This is required to dynamically load async fixtures in async def model_fixture() nest_asyncio.apply() +TEST_CHARM_FILE = "./test_ubuntu-22.04-amd64.charm" + @dataclass class _Secret: @@ -105,7 +103,10 @@ async def model_fixture(proxy: ProxyConfig, ops_test: OpsTest) -> AsyncGenerator { "juju-http-proxy": proxy.http, "juju-https-proxy": proxy.https, - "juju-no-proxy": proxy.no_proxy, + "apt-http-proxy": proxy.http, + "apt-https-proxy": proxy.https, + "snap-http-proxy": proxy.http, + "snap-https-proxy": proxy.https, } ) yield ops_test.model @@ -117,25 +118,15 @@ def dispatch_time_fixture(): return datetime.now(tz=timezone.utc) -@pytest.fixture(scope="module", name="test_charm_file") -def test_charm_file_fixture() -> str: - """Build the charm and return the path to the built charm.""" - subprocess.check_call( # nosec: B603 - ["/snap/bin/charmcraft", "pack", "-p", "tests/integration/data/charm"] - ) - return "./test_ubuntu-22.04-amd64.charm" - - @pytest_asyncio.fixture(scope="module", name="test_charm") async def test_charm_fixture( model: Model, test_id: str, - test_charm_file: str, private_endpoint_configs: PrivateEndpointConfigs, ) -> AsyncGenerator[Application, None]: """The test charm that becomes active when valid relation data is given.""" app_name = f"test-{test_id}" - app = await _deploy_test_charm(app_name, model, private_endpoint_configs, test_charm_file) + app = await _deploy_test_charm(app_name, model, private_endpoint_configs) yield app @@ -147,12 +138,11 @@ async def test_charm_fixture( async def test_charm_2( model: Model, test_id: str, - test_charm_file: str, private_endpoint_configs: PrivateEndpointConfigs, ) -> AsyncGenerator[Application, None]: """A second test charm that becomes active when valid relation data is given.""" app_name = f"test2-{test_id}" - app = await _deploy_test_charm(app_name, model, private_endpoint_configs, test_charm_file) + app = await _deploy_test_charm(app_name, model, private_endpoint_configs) yield app @@ -165,7 +155,6 @@ async def _deploy_test_charm( app_name: str, model: Model, private_endpoint_configs: PrivateEndpointConfigs, - test_charm_file: str, ): """Deploy the test charm with the given application name. @@ -173,12 +162,11 @@ async def _deploy_test_charm( app_name: The name of the application to deploy. model: The Juju model to deploy the charm in. private_endpoint_configs: The OpenStack private endpoint configurations. - test_charm_file: The path to the built test charm file. """ logger.info("Deploying built test charm") app: Application = await model.deploy( - test_charm_file, + TEST_CHARM_FILE, app_name, config={ "openstack-auth-url": private_endpoint_configs["auth_url"],