diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index 0e8c266d..aea43206 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -3,7 +3,7 @@ name: recceiver on: push: - branches: [ "master" ] + branches: [ "*" ] paths: - server/** pull_request: diff --git a/server/docker/test-remove-infotag.yml b/server/docker/test-bash-ioc.yml similarity index 95% rename from server/docker/test-remove-infotag.yml rename to server/docker/test-bash-ioc.yml index ae4a43aa..17b1d5a0 100644 --- a/server/docker/test-remove-infotag.yml +++ b/server/docker/test-bash-ioc.yml @@ -1,4 +1,4 @@ -name: test-removeinfotag +name: test-bash-ioc include: - cf-compose.yml services: diff --git a/server/docker/test-multi-recc.yml b/server/docker/test-multi-recc.yml index f66fa173..cbe24010 100644 --- a/server/docker/test-multi-recc.yml +++ b/server/docker/test-multi-recc.yml @@ -36,7 +36,7 @@ services: restart: true environment: - IOCSH_NAME=IOC1-2 - hostname: ioc1-1 + hostname: ioc1-2 recc2: extends: recc1 diff --git a/server/docker/test-single-ioc.yml b/server/docker/test-single-ioc.yml new file mode 100644 index 00000000..6e4908df --- /dev/null +++ b/server/docker/test-single-ioc.yml @@ -0,0 +1,33 @@ +name: test-single-ioc +include: + - cf-compose.yml +services: + recc1: + extends: + file: ../compose.yml + service: recc + depends_on: + cf: + condition: service_healthy + restart: true + hostname: recc1 + networks: + - net-1-recc-1 + - net-2-cf + ioc1-1: + extends: + file: ../../client/ioc-compose.yml + service: ioc1 + depends_on: + recc1: + condition: service_healthy + restart: true + environment: + - IOCSH_NAME=IOC1-1 + hostname: ioc1-1 + networks: + - net-1-recc-1 + +networks: + net-1-recc-1: + driver: bridge diff --git a/server/tests/docker.py b/server/tests/docker.py index e479edcf..eacb7097 100644 --- a/server/tests/docker.py +++ b/server/tests/docker.py @@ -1,4 +1,5 @@ import logging +import time from pathlib import Path from typing import Optional @@ -10,7 +11,7 @@ LOG: logging.Logger = logging.getLogger(__name__) -def test_compose(compose_file=Path("docker") / Path("test-multi-recc.yml")) -> DockerCompose: +def test_compose(compose_file: Path) -> DockerCompose: current_path = Path(__file__).parent.resolve() return DockerCompose( @@ -30,17 +31,24 @@ def fetch_containers_and_log_logs(compose: DockerCompose) -> None: LOG.debug(log.decode("utf-8")) -@pytest.fixture(scope="class") -def setup_compose(): - LOG.info("Setup test environment") - compose = test_compose() - compose.start() - yield compose - LOG.info("Teardown test environment") - LOG.info("Stopping docker compose") - if LOG.level <= logging.DEBUG: - fetch_containers_and_log_logs(compose) - compose.stop() +class ComposeFixtureFactory: + def __init__(self, compose_file: Path) -> None: + self.compose_file = compose_file + + def return_fixture(self): + @pytest.fixture(scope="class") + def setup_compose() -> DockerCompose: + LOG.info("Setup test environment") + compose = test_compose(self.compose_file) + compose.start() + yield compose + LOG.info("Teardown test environment") + LOG.info("Stopping docker compose") + if LOG.level <= logging.DEBUG: + fetch_containers_and_log_logs(compose) + compose.stop() + + return setup_compose def restart_container(compose: DockerCompose, host_name: str) -> str: @@ -65,3 +73,27 @@ def start_container( if container_id: docker_client = DockerClient() docker_client.containers.get(container_id).start() + + +def clone_container( + compose: DockerCompose, + new_host_name: str, + host_name: Optional[str] = None, + container_id: Optional[str] = None, + sleep_time=10, +) -> str: + container_id = container_id or compose.get_container(host_name).ID + if not container_id: + raise Exception("Container not found") + + docker_client = DockerClient() + container = docker_client.containers.get(container_id) + image = container.image + networks = container.attrs["NetworkSettings"]["Networks"].keys() + container.stop() + time.sleep(sleep_time) + container.remove() + docker_client.containers.run( + image, detach=True, environment={"IOC_NAME": host_name}, hostname=new_host_name, network=list(networks)[0] + ) + return container_id diff --git a/server/tests/test_remove_property.py b/server/tests/test_bash_ioc.py similarity index 85% rename from server/tests/test_remove_property.py rename to server/tests/test_bash_ioc.py index 7b5950d3..85a087bb 100644 --- a/server/tests/test_remove_property.py +++ b/server/tests/test_bash_ioc.py @@ -2,14 +2,13 @@ import threading from pathlib import Path -import pytest from testcontainers.compose import DockerCompose from docker import DockerClient from docker.models.containers import Container from .client_checks import INACTIVE_PROPERTY, check_channel_property, create_client_and_wait, wait_for_sync -from .docker import fetch_containers_and_log_logs, test_compose # noqa: F401 +from .docker import ComposeFixtureFactory LOG: logging.Logger = logging.getLogger(__name__) @@ -19,18 +18,7 @@ encoding="utf-8", ) - -@pytest.fixture(scope="class") -def setup_compose(): - LOG.info("Setup remove test environment") - compose = test_compose(Path("docker") / Path("test-remove-infotag.yml")) - compose.start() - yield compose - LOG.info("Teardown test environment") - LOG.info("Stopping docker compose") - if LOG.level <= logging.DEBUG: - fetch_containers_and_log_logs(compose) - compose.stop() +setup_compose = ComposeFixtureFactory(Path("docker") / Path("test-bash-ioc.yml")).return_fixture() def docker_exec_new_command(container: Container, command: str): diff --git a/server/tests/test_e2e.py b/server/tests/test_multiple_recceiver.py similarity index 86% rename from server/tests/test_e2e.py rename to server/tests/test_multiple_recceiver.py index 3ba10435..0fc864a5 100644 --- a/server/tests/test_e2e.py +++ b/server/tests/test_multiple_recceiver.py @@ -1,10 +1,12 @@ import logging +from pathlib import Path import pytest from channelfinder import ChannelFinderClient +from testcontainers.compose import DockerCompose from .client_checks import create_client_and_wait -from .docker import setup_compose # noqa: F401 +from .docker import ComposeFixtureFactory LOG: logging.Logger = logging.getLogger(__name__) @@ -13,13 +15,15 @@ # 4 iocs, 6 channels per ioc (2 reccaster.db, 2 somerecords.db, 2 aliases in somerecords.db) EXPECTED_DEFAULT_CHANNEL_COUNT = 32 +setup_compose = ComposeFixtureFactory(Path("docker") / Path("test-multi-recc.yml")).return_fixture() + @pytest.fixture(scope="class") -def cf_client(setup_compose): # noqa: F811 +def cf_client(setup_compose: DockerCompose): # noqa: F811 return create_client_and_wait(setup_compose, EXPECTED_DEFAULT_CHANNEL_COUNT) -class TestE2E: +class TestMultipleRecceiver: def test_number_of_channels_and_channel_name(self, cf_client: ChannelFinderClient) -> None: channels = cf_client.find(name="*") assert len(channels) == EXPECTED_DEFAULT_CHANNEL_COUNT diff --git a/server/tests/test_restart.py b/server/tests/test_single_ioc.py similarity index 81% rename from server/tests/test_restart.py rename to server/tests/test_single_ioc.py index fcf08e72..c767639b 100644 --- a/server/tests/test_restart.py +++ b/server/tests/test_single_ioc.py @@ -1,5 +1,6 @@ import logging import time +from pathlib import Path import pytest from channelfinder import ChannelFinderClient @@ -12,17 +13,25 @@ create_client_and_wait, wait_for_sync, ) -from .docker import restart_container, setup_compose, shutdown_container, start_container # noqa: F401 +from .docker import ( + ComposeFixtureFactory, + clone_container, + restart_container, + shutdown_container, + start_container, +) PROPERTIES_TO_MATCH = ["pvStatus", "recordType", "recordDesc", "alias", "hostName", "iocName", "recceiverID"] LOG: logging.Logger = logging.getLogger(__name__) -EXPECTED_DEFAULT_CHANNEL_COUNT = 32 +EXPECTED_DEFAULT_CHANNEL_COUNT = 8 + +setup_compose = ComposeFixtureFactory(Path("docker") / Path("test-single-ioc.yml")).return_fixture() @pytest.fixture(scope="class") -def cf_client(setup_compose): # noqa: F811 +def cf_client(setup_compose: DockerCompose) -> ChannelFinderClient: # noqa: F811 return create_client_and_wait(setup_compose, expected_channel_count=EXPECTED_DEFAULT_CHANNEL_COUNT) @@ -104,3 +113,16 @@ def test_status_property_works_between_cf_down( ) channels_inactive = cf_client.find(property=[("iocName", "IOC1-1")]) assert all(INACTIVE_PROPERTY in ch["properties"] for ch in channels_inactive) + + +class TestMoveIocHost: + def test_move_ioc_host( + self, + setup_compose: DockerCompose, # noqa: F811 + cf_client: ChannelFinderClient, + ) -> None: + channels_begin = cf_client.find(name="*") + clone_container(setup_compose, "ioc1-1-new", host_name="ioc1-1") + wait_for_sync(cf_client, lambda cf_client: check_channel_property(cf_client, "IOC1-1:Msg-I")) + channels_end = cf_client.find(name="*") + assert len(channels_begin) == len(channels_end)