Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .github/workflows/integration_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ jobs:
pre-run-script: |
-c "chmod +x tests/integration/pre_run_script.sh
./tests/integration/pre_run_script.sh"
# self-hosted-runner: true
# self-hosted-runner-label: "edge"
python-version: "3.12"
runs-on: "ubuntu-24.04"
self-hosted-runner: true
self-hosted-runner-label: "edge"
modules: '["test_charm", "test_proxy"]'
allure-report:
if: always() && !cancelled()
needs: integration-tests
uses: canonical/operator-workflows/.github/workflows/allure_report.yaml@main
10 changes: 3 additions & 7 deletions charmcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@
# See LICENSE file for licensing details.

type: charm
bases:
- build-on:
- name: ubuntu
channel: "22.04"
run-on:
- name: ubuntu
channel: "22.04"
platforms:
ubuntu@22.04:amd64:
ubuntu@24.04:amd64:

parts:
charm:
Expand Down
3 changes: 1 addition & 2 deletions metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ docs: https://discourse.charmhub.io/t/tmate-ssh-server-documentation-overview/12
issues: https://github.com/canonical/tmate-ssh-server-operator/issues
source: https://github.com/canonical/tmate-ssh-server-operator
summary: Tmate SSH Relay Server
series:
- jammy

tags:
- application_development
- ops
Expand Down
69 changes: 32 additions & 37 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"""Fixtures for tmate-ssh-server charm integration tests."""
import logging
import secrets

# Subprocess module is used to check series
import subprocess # nosec B404
import typing
from pathlib import Path

Expand All @@ -29,22 +32,47 @@ def model_fixture(ops_test: OpsTest) -> Model:
return ops_test.model


@pytest.fixture(name="codename", scope="module")
def codename_fixture():
"""Series codename for deploying any-charm."""
return (
subprocess.check_output(["/usr/bin/lsb_release", "-cs"]) # nosec B603
.strip()
.decode("utf-8")
)


@pytest.fixture(name="series", scope="module")
def series_fixture():
"""Series version for deploying any-charm."""
return (
subprocess.check_output(["/usr/bin/lsb_release", "-rs"]) # nosec B603
.strip()
.decode("utf-8")
)


@pytest_asyncio.fixture(scope="module", name="charm")
async def charm_fixture(request: pytest.FixtureRequest, ops_test: OpsTest) -> str:
async def charm_fixture(
request: pytest.FixtureRequest, ops_test: OpsTest, series: str
) -> str | Path:
"""The path to charm."""
charm = request.config.getoption("--charm-file")
if not charm:
charm = await ops_test.build_charm(".")
else:
charm = f"./{charm}"
charm_dir = Path(f"./{charm}").parent
charm_matching_series = list(charm_dir.rglob(f"*{series}*.charm"))
assert charm_matching_series, f"No build found for series {series}"
return f"./{charm_matching_series[0]}"

return charm


@pytest_asyncio.fixture(scope="module", name="tmate_ssh_server")
async def tmate_ssh_server_fixture(model: Model, charm: str):
async def tmate_ssh_server_fixture(model: Model, charm: str, codename: str):
"""The tmate-ssh-server application fixture."""
app = await model.deploy(charm)
app = await model.deploy(charm, series=codename)
await model.wait_for_idle(apps=[app.name], wait_for_active=True)
return app

Expand Down Expand Up @@ -158,36 +186,3 @@ async def proxy_machine_fixture(ops_test: OpsTest, machine: Machine):
)
assert retcode == 0, f"Failed to restart squid service, {stdout} {stderr}"
return machine


@pytest_asyncio.fixture(scope="module", name="machine_ip")
async def machine_ip_fixture(machine: Machine) -> str:
"""The machine public IP address."""

def get_machine_ip_address() -> typing.Optional[str]:
"""Get latest machine IP address.

Returns:
The latest machine IP address if ready, None otherwise.
"""
latest_machine = machine.latest()
addresses = latest_machine.data["addresses"]
try:
address = next(
iter(
[
address["value"]
for address in addresses
if address["scope"] != "local-machine"
]
)
)
except StopIteration:
return None
return address

await wait_for(get_machine_ip_address)

# mypy doesn't understand that get_machine_ip_address has to be str from wait_for statement
# above.
return typing.cast(str, get_machine_ip_address())
24 changes: 24 additions & 0 deletions tests/integration/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,30 @@
import time
import typing

from juju.machine import Machine


def get_machine_ip_address(machine: Machine) -> typing.Optional[str]:
"""Get latest machine IP address.

Args:
machine: The machine to get the IP address for.

Returns:
The latest machine IP address if ready, None otherwise.
"""
latest_machine = machine.latest()
addresses = latest_machine.data["addresses"]
try:
address = next(
iter(
[address["value"] for address in addresses if address["scope"] != "local-machine"]
)
)
except StopIteration:
return None
return address


async def wait_for(
func: typing.Callable[[], typing.Union[typing.Awaitable, typing.Any]],
Expand Down
9 changes: 6 additions & 3 deletions tests/integration/test_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from juju.unit import Unit
from pytest_operator.plugin import OpsTest

from .helpers import wait_for
from .helpers import get_machine_ip_address, wait_for

logger = logging.getLogger(__name__)

Expand All @@ -19,13 +19,16 @@ async def test_proxy(
model: Model,
charm: str,
proxy_machine: Machine,
machine_ip: str,
codename: str,
):
"""
arrange: given a model configured with squid proxy ip address.
act: when tmate charm is deployed.
assert: proxy log contains docker access.
"""
machine_ip: str | None = await wait_for(lambda: get_machine_ip_address(machine=proxy_machine))
assert machine_ip is not None, "Proxy machine IP address not found."

await model.set_config(
{
"juju-http-proxy": f"http://{machine_ip}:3218",
Expand All @@ -34,7 +37,7 @@ async def test_proxy(
)

logger.info("Deploying tmate charm.")
app = await model.deploy(charm)
app = await model.deploy(charm, series=codename)
await model.wait_for_idle(apps=[app.name], wait_for_active=True)
unit: Unit = next(iter(app.units))

Expand Down
12 changes: 7 additions & 5 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,16 @@ commands =
[testenv:integration]
description = Run integration tests
deps =
pytest
-r{toxinidir}/requirements.txt
allure-pytest>=2.8.18
git+https://github.com/canonical/data-platform-workflows@v24.0.0\#subdirectory=python/pytest_plugins/allure_pytest_collection_report
juju>=3,<4
ops
pytest-operator
pytest-asyncio
# Type error problem with newer version of macaroonbakery
macaroonbakery==1.3.2
-r{toxinidir}/requirements.txt
ops
pytest
pytest-asyncio
pytest-operator
commands =
pytest --tb native --ignore={[vars]tst_path}unit --log-cli-level=INFO -s {posargs}

Expand Down
Loading