Skip to content

Commit

Permalink
Added removal of the current container from docker network of the ITDE
Browse files Browse the repository at this point in the history
  • Loading branch information
tkilias committed Jan 30, 2024
1 parent aa1496f commit f73ea58
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 11 deletions.
44 changes: 39 additions & 5 deletions exasol/itde_manager.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Tuple
from typing import Tuple, Optional

import docker # type: ignore
from docker.models.networks import Network
from exasol_integration_test_docker_environment.lib import api # type: ignore
from exasol_integration_test_docker_environment.lib.data.container_info import ContainerInfo # type: ignore
from exasol_integration_test_docker_environment.lib.docker import ( # type: ignore
Expand Down Expand Up @@ -48,6 +49,8 @@ def bring_itde_up(conf: Secrets) -> None:
mem_size = f'{conf.get(AILabConfig.mem_size, "4")} GiB'
disk_size = f'{conf.get(AILabConfig.disk_size, "10")} GiB'

_remove_current_container_from_db_network(conf)

env_info, _ = api.spawn_test_environment(
environment_name=ENVIRONMENT_NAME,
nameserver=(NAME_SERVER_ADDRESS,),
Expand Down Expand Up @@ -85,11 +88,41 @@ def bring_itde_up(conf: Secrets) -> None:
def _add_current_container_to_db_network(container_info: ContainerInfo):
network_name = container_info.network_info.network_name
with ContextDockerClient() as docker_client:
ip_addresses = [ip.ip for ip in IPRetriever().ips()
if ip.is_IPv4 and isinstance(ip.ip, str)]
ip_addresses = _get_ipv4_ddresses()
container = ContainerByIp(docker_client).find(ip_addresses)
if not container:
return
network = _get_docker_network(docker_client, network_name)
if network:
network.connect(container.id)


def _get_docker_network(docker_client: docker.DockerClient, network_name: str) -> Optional[Network]:
networks = docker_client.networks.list(names=[network_name])
if len(networks) == 1:
network = networks[0]
return network
return None


def _remove_current_container_from_db_network(conf: Secrets):
network_name = conf.get(AILabConfig.itde_network)
if not network_name:
return
with ContextDockerClient() as docker_client:
ip_addresses = _get_ipv4_ddresses()
container = ContainerByIp(docker_client).find(ip_addresses)
if container is not None:
docker_client.networks.get(network_name).connect(container)
if not container:
return
network = _get_docker_network(docker_client, network_name)
if network:
network.disconnect(container.id)


def _get_ipv4_ddresses():
ip_addresses = [ip.ip for ip in IPRetriever().ips()
if ip.is_IPv4 and isinstance(ip.ip, str)]
return ip_addresses


def is_itde_running(conf: Secrets) -> Tuple[bool, bool]:
Expand Down Expand Up @@ -143,6 +176,7 @@ def take_itde_down(conf: Secrets) -> None:
are taken from the provided secret store. If the names are not found
there no action is taken.
"""
_remove_current_container_from_db_network(conf)

remove_container(conf)
remove_volume(conf)
Expand Down
84 changes: 78 additions & 6 deletions test/integration/test_itde_manager_in_docker_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ def find_wheel_name(output_bytes: bytes) -> str:


@pytest.fixture
def itde_startup_impl():
def itde_connect_test_impl():
"""
This fixture returns the source code for starting up ITDE.
This fixture returns the test source code for starting up ITDE and connecting to it.
The source code needs to appended to the wheel file inside the Docker container called TEST_CONTAINER.
"""

Expand Down Expand Up @@ -128,7 +128,67 @@ def run_test():


@pytest.fixture
def docker_container(wheel_path, itde_startup_impl, docker_image):
def itde_recreation_after_take_down():
"""
This fixture returns the test source code for starting up ITDE again, after a first start and take down.
The source code needs to appended to the wheel file inside the Docker container called TEST_CONTAINER.
"""

def run_test():
from pathlib import Path

from exasol.ai_lab_config import AILabConfig
from exasol.itde_manager import bring_itde_up
from exasol.itde_manager import take_itde_down
from exasol.secret_store import Secrets

secrets = Secrets(db_file=Path("secrets.sqlcipher"), master_password="test")
secrets.save(AILabConfig.mem_size.value, "2")
secrets.save(AILabConfig.disk_size.value, "4")

bring_itde_up(secrets)
take_itde_down(secrets)
bring_itde_up(secrets)
take_itde_down(secrets)

function_source_code = textwrap.dedent(dill.source.getsource(run_test))
source_code = f"{function_source_code}\nrun_test()"
return source_code


@pytest.fixture
def itde_recreation_without_take_down():
"""
This fixture returns the test source code for starting up ITDE again, after a first start and no take down.
The source code needs to appended to the wheel file inside the Docker container called TEST_CONTAINER.
"""

def run_test():
from pathlib import Path

from exasol.ai_lab_config import AILabConfig
from exasol.itde_manager import bring_itde_up
from exasol.itde_manager import take_itde_down
from exasol.secret_store import Secrets

secrets = Secrets(db_file=Path("secrets.sqlcipher"), master_password="test")
secrets.save(AILabConfig.mem_size.value, "2")
secrets.save(AILabConfig.disk_size.value, "4")

bring_itde_up(secrets)
bring_itde_up(secrets)
take_itde_down(secrets)

function_source_code = textwrap.dedent(dill.source.getsource(run_test))
source_code = f"{function_source_code}\nrun_test()"
return source_code


@pytest.fixture
def docker_container(wheel_path, docker_image,
itde_connect_test_impl,
itde_recreation_after_take_down,
itde_recreation_without_take_down):
"""
Create a Docker container named TEST_CONTAINER to manage an instance of ITDE.
Copy the wheel file resulting from building the current project NC into the container.
Expand All @@ -148,7 +208,9 @@ def docker_container(wheel_path, itde_startup_impl, docker_image):
try:
copy = DockerContainerCopy(container)
copy.add_file(str(wheel_path), wheel_path.name)
copy.add_string_to_file("test.py", itde_startup_impl)
copy.add_string_to_file("itde_connect_test_impl.py", itde_connect_test_impl)
copy.add_string_to_file("itde_recreation_after_take_down.py", itde_recreation_after_take_down)
copy.add_string_to_file("itde_recreation_without_take_down.py", itde_recreation_without_take_down)
copy.copy("/tmp")
exit_code, output = container.exec_run(
f"python3 -m pip install /tmp/{wheel_path.name} "
Expand All @@ -160,6 +222,16 @@ def docker_container(wheel_path, itde_startup_impl, docker_image):
remove_docker_container([container.id])


def test_bring_itde_up(docker_container):
exec_result = docker_container.exec_run("python3 /tmp/test.py")
def test_itde_connect(docker_container):
exec_result = docker_container.exec_run("python3 /tmp/itde_connect_test_impl.py")
assert exec_result.exit_code == 0, exec_result.output


def test_itde_recreation_after_take_down(docker_container):
exec_result = docker_container.exec_run("python3 /tmp/itde_recreation_after_take_down.py")
assert exec_result.exit_code == 0, exec_result.output


def test_itde_recreation_without_take_down(docker_container):
exec_result = docker_container.exec_run("python3 /tmp/itde_recreation_without_take_down.py")
assert exec_result.exit_code == 0, exec_result.output

0 comments on commit f73ea58

Please sign in to comment.