From a2504bd36a663500e44f1469045bd7f35d0a901b Mon Sep 17 00:00:00 2001 From: yu Date: Mon, 19 Aug 2024 11:44:45 +0200 Subject: [PATCH 1/5] add test_start_elk_manager --- .../tests/test_start_elk_manager.py | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 emulation-system/tests/test_start_elk_manager.py diff --git a/emulation-system/tests/test_start_elk_manager.py b/emulation-system/tests/test_start_elk_manager.py new file mode 100644 index 000000000..ea29caa94 --- /dev/null +++ b/emulation-system/tests/test_start_elk_manager.py @@ -0,0 +1,167 @@ +from typing import List, Any, Generator +import pytest +import docker +import logging +import grpc +from unittest.mock import MagicMock +from docker.types import IPAMConfig, IPAMPool +import time +from csle_common.dao.emulation_config.emulation_env_config import EmulationEnvConfig +from csle_common.util.emulation_util import EmulationUtil +import csle_common.constants.constants as constants +from csle_common.controllers.elk_controller import ELKController +import csle_collector.elk_manager.elk_manager_pb2_grpc +import csle_collector.elk_manager.elk_manager_pb2 +import csle_collector.elk_manager.query_elk_manager +from csle_common.metastore.metastore_facade import MetastoreFacade +from IPython.lib.editorhooks import emacs + + +@pytest.fixture(scope="module") +def docker_client() -> None: + """ + Initialize and Provide a Docker client instance for the test + + :return: None + """ + return docker.from_env() + + +@pytest.fixture(scope="module") +def network(docker_client) -> None: + """ + Create a custom network with a specific subnet + + :param docker_client: docker_client + :yield: network + + :return: None + """ + subnet = "15.15.15.0/24" + ipam_pool = IPAMPool(subnet=subnet) + ipam_config = IPAMConfig(pool_configs=[ipam_pool]) + logging.info(f"Creating virtual network with subnet: {subnet}") + network = docker_client.networks.create("test_network", driver="bridge", ipam=ipam_config) + yield network + network.remove() + + +def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGES.BLANK) -> List[Any]: + """ + Get all the containers except the blank ones + + :param docker_client: docker_client + + :return: None + """ + # Get all images except those with the excluded tag + config = MetastoreFacade.get_config(id=1) + match_tag = config.version + all_images = docker_client.images.list() + derived_images = [ + image + for image in all_images + if any(match_tag in tag for tag in image.tags) + and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) + and all(excluded_tag not in tag for tag in image.tags) + ] + return derived_images[:1] + + +@pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) +def container_setup(request, docker_client, network) -> Generator: + """ + Starts a Docker container before running tests and ensures its stopped and removed after tests complete. + + :param request: request + :param docker_client: docker_client + :yield: container + + :return: None + """ + # Create and start each derived container + image = request.param + container = docker_client.containers.create( + image.tags[0], + command="sh -c 'while true; do sleep 3600; done'", + detach=True, + ) + network.connect(container) + container.start() + yield container + logging.info(f"Stopping and removing container: {container.id} with image: {container.image.tags}") + container.stop() + container.remove() + + +def test_start_elk_manager(container_setup) -> None: + """ + Start elk_manager in a container + + :param container_setup: container_setup + + :return: None + """ + failed_containers = [] + containers_info = [] + container_setup.reload() + assert container_setup.status == "running" + # Mock emulation_env_config + emulation_env_config = MagicMock(spec=EmulationEnvConfig) + emulation_env_config.get_connection.return_value = MagicMock() + emulation_env_config.elk_config = MagicMock() + emulation_env_config.elk_config.container.docker_gw_bridge_ip = container_setup.attrs[constants.DOCKER.NETWORK_SETTINGS][constants.DOCKER.IP_ADDRESS_INFO] + emulation_env_config.elk_config.get_connection.return_value = MagicMock() + emulation_env_config.elk_config.elk_manager_port = 50051 + emulation_env_config.elk_config.elk_manager_log_dir = "/var/log/elk" + emulation_env_config.elk_config.elk_manager_log_file = "elk.log" + emulation_env_config.elk_config.elk_manager_max_workers = 4 + + ip = emulation_env_config.elk_config.container.docker_gw_bridge_ip + port = emulation_env_config.elk_config.elk_manager_port + try: + # Start host_manager command + cmd = ( + f"/root/miniconda3/bin/python3 /elk_manager.py " + f"--port {emulation_env_config.elk_config.elk_manager_port} " + f"--logdir {emulation_env_config.elk_config.elk_manager_log_dir} " + f"--logfile {emulation_env_config.elk_config.elk_manager_log_file} " + f"--maxworkers {emulation_env_config.elk_config.elk_manager_max_workers}" + ) + # Run cmd in the container + logging.info(f"Starting elk manager in container: {container_setup.id} " + f"with image: {container_setup.image.tags}") + container_setup.exec_run(cmd, detach=True) + # Check if elk_manager starts + cmd = ( + f"sh -c '{constants.COMMANDS.PS_AUX} | {constants.COMMANDS.GREP} " + f"{constants.COMMANDS.SPACE_DELIM}{constants.TRAFFIC_COMMANDS.ELK_MANAGER_FILE_NAME}'" + ) + logging.info(f"Verifying that elk manager is running in container: {container_setup.id} " + f"with image: {container_setup.image.tags}") + result = container_setup.exec_run(cmd) + output = result.output.decode("utf-8") + print("output:") + print(output) + assert constants.COMMANDS.SEARCH_ELK_MANAGER in output, "Elk manager is not running in the container" + time.sleep(5) + # Call grpc + with grpc.insecure_channel(f"{ip}:{port}", options=constants.GRPC_SERVERS.GRPC_OPTIONS) as channel: + stub = csle_collector.elk_manager.elk_manager_pb2_grpc.ElkManagerStub(channel) + elk_dto = csle_collector.elk_manager.query_elk_manager.get_elk_status(stub) + assert elk_dto + except Exception as e: + print(f"Error occurred in container {container_setup.name}: {e}") + failed_containers.append(container_setup.name) + containers_info.append( + { + "container_status": container_setup.status, + "container_image": container_setup.image.tags, + "name": container_setup.name, + "error": str(e), + } + ) + if failed_containers: + logging.info("Containers that failed to start the elk manager:") + logging.info(containers_info) + assert not failed_containers, f"T{failed_containers} failed" From 8f12f4d08f042230412b76103c9c3db6b567bada Mon Sep 17 00:00:00 2001 From: yu Date: Mon, 19 Aug 2024 11:54:35 +0200 Subject: [PATCH 2/5] add tests/test_start_kafka_manager.py --- .../tests/test_start_kafka_manager.py | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 emulation-system/tests/test_start_kafka_manager.py diff --git a/emulation-system/tests/test_start_kafka_manager.py b/emulation-system/tests/test_start_kafka_manager.py new file mode 100644 index 000000000..f5182e7a4 --- /dev/null +++ b/emulation-system/tests/test_start_kafka_manager.py @@ -0,0 +1,166 @@ +from typing import List, Any, Generator +import pytest +import docker +import logging +import grpc +from unittest.mock import MagicMock +from docker.types import IPAMConfig, IPAMPool +import time +from csle_common.dao.emulation_config.emulation_env_config import EmulationEnvConfig +from csle_common.util.emulation_util import EmulationUtil +import csle_common.constants.constants as constants +import csle_collector.kafka_manager.kafka_manager_pb2_grpc +import csle_collector.kafka_manager.kafka_manager_pb2 +import csle_collector.kafka_manager.query_kafka_server +from csle_common.metastore.metastore_facade import MetastoreFacade +from IPython.lib.editorhooks import emacs + + +@pytest.fixture(scope="module") +def docker_client() -> None: + """ + Initialize and Provide a Docker client instance for the test + + :return: None + """ + return docker.from_env() + + +@pytest.fixture(scope="module") +def network(docker_client) -> None: + """ + Create a custom network with a specific subnet + + :param docker_client: docker_client + :yield: network + + :return: None + """ + subnet = "15.15.15.0/24" + ipam_pool = IPAMPool(subnet=subnet) + ipam_config = IPAMConfig(pool_configs=[ipam_pool]) + logging.info(f"Creating virtual network with subnet: {subnet}") + network = docker_client.networks.create("test_network", driver="bridge", ipam=ipam_config) + yield network + network.remove() + + +def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGES.BLANK) -> List[Any]: + """ + Get all the containers except the blank ones + + :param docker_client: docker_client + + :return: None + """ + # Get all images except those with the excluded tag + config = MetastoreFacade.get_config(id=1) + match_tag = config.version + all_images = docker_client.images.list() + derived_images = [ + image + for image in all_images + if any(match_tag in tag for tag in image.tags) + and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) + and all(excluded_tag not in tag for tag in image.tags) + ] + return derived_images[:1] + + +@pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) +def container_setup(request, docker_client, network) -> Generator: + """ + Starts a Docker container before running tests and ensures its stopped and removed after tests complete. + + :param request: request + :param docker_client: docker_client + :yield: container + + :return: None + """ + # Create and start each derived container + image = request.param + container = docker_client.containers.create( + image.tags[0], + command="sh -c 'while true; do sleep 3600; done'", + detach=True, + ) + network.connect(container) + container.start() + yield container + logging.info(f"Stopping and removing container: {container.id} with image: {container.image.tags}") + container.stop() + container.remove() + + +def test_start_kafka_manager(container_setup) -> None: + """ + Start kafka_manager in a container + + :param container_setup: container_setup + + :return: None + """ + failed_containers = [] + containers_info = [] + container_setup.reload() + assert container_setup.status == "running" + # Mock emulation_env_config + emulation_env_config = MagicMock(spec=EmulationEnvConfig) + emulation_env_config.get_connection.return_value = MagicMock() + emulation_env_config.kafka_config = MagicMock() + emulation_env_config.kafka_config.container.docker_gw_bridge_ip = container_setup.attrs[constants.DOCKER.NETWORK_SETTINGS][constants.DOCKER.IP_ADDRESS_INFO] + emulation_env_config.kafka_config.get_connection.return_value = MagicMock() + emulation_env_config.kafka_config.kafka_manager_port = 50051 + emulation_env_config.kafka_config.kafka_manager_log_dir = "/var/log/kafka" + emulation_env_config.kafka_config.kafka_manager_log_file = "kafka.log" + emulation_env_config.kafka_config.kafka_manager_max_workers = 4 + + ip = emulation_env_config.kafka_config.container.docker_gw_bridge_ip + port = emulation_env_config.kafka_config.kafka_manager_port + try: + # Start host_manager command + cmd = ( + f"/root/miniconda3/bin/python3 /kafka_manager.py " + f"--port {emulation_env_config.kafka_config.kafka_manager_port} " + f"--logdir {emulation_env_config.kafka_config.kafka_manager_log_dir} " + f"--logfile {emulation_env_config.kafka_config.kafka_manager_log_file} " + f"--maxworkers {emulation_env_config.kafka_config.kafka_manager_max_workers}" + ) + # Run cmd in the container + logging.info(f"Starting kafka manager in container: {container_setup.id} " + f"with image: {container_setup.image.tags}") + container_setup.exec_run(cmd, detach=True) + # Check if kafka_manager starts + cmd = ( + f"sh -c '{constants.COMMANDS.PS_AUX} | {constants.COMMANDS.GREP} " + f"{constants.COMMANDS.SPACE_DELIM}{constants.TRAFFIC_COMMANDS.KAFKA_MANAGER_FILE_NAME}'" + ) + logging.info(f"Verifying that kafka manager is running in container: {container_setup.id} " + f"with image: {container_setup.image.tags}") + result = container_setup.exec_run(cmd) + output = result.output.decode("utf-8") + print("output:") + print(output) + assert constants.COMMANDS.SEARCH_KAFKA_MANAGER in output, "Kafka manager is not running in the container" + time.sleep(5) + # Call grpc + with grpc.insecure_channel(f"{ip}:{port}", options=constants.GRPC_SERVERS.GRPC_OPTIONS) as channel: + stub = csle_collector.kafka_manager.kafka_manager_pb2_grpc.KafkaManagerStub(channel) + kafka_dto = csle_collector.kafka_manager.query_kafka_server.get_kafka_status(stub) + assert kafka_dto + except Exception as e: + print(f"Error occurred in container {container_setup.name}: {e}") + failed_containers.append(container_setup.name) + containers_info.append( + { + "container_status": container_setup.status, + "container_image": container_setup.image.tags, + "name": container_setup.name, + "error": str(e), + } + ) + if failed_containers: + logging.info("Containers that failed to start the kafka manager:") + logging.info(containers_info) + assert not failed_containers, f"T{failed_containers} failed" From 30bfa4e24b7479e7204f633b80096c94f69f907d Mon Sep 17 00:00:00 2001 From: yu Date: Mon, 19 Aug 2024 12:00:58 +0200 Subject: [PATCH 3/5] add tests/test_start_ossec_manager.py --- .../tests/test_start_elk_manager.py | 2 - .../tests/test_start_kafka_manager.py | 4 +- .../tests/test_start_ossec_manager.py | 162 ++++++++++++++++++ 3 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 emulation-system/tests/test_start_ossec_manager.py diff --git a/emulation-system/tests/test_start_elk_manager.py b/emulation-system/tests/test_start_elk_manager.py index ea29caa94..2d4bb1404 100644 --- a/emulation-system/tests/test_start_elk_manager.py +++ b/emulation-system/tests/test_start_elk_manager.py @@ -141,8 +141,6 @@ def test_start_elk_manager(container_setup) -> None: f"with image: {container_setup.image.tags}") result = container_setup.exec_run(cmd) output = result.output.decode("utf-8") - print("output:") - print(output) assert constants.COMMANDS.SEARCH_ELK_MANAGER in output, "Elk manager is not running in the container" time.sleep(5) # Call grpc diff --git a/emulation-system/tests/test_start_kafka_manager.py b/emulation-system/tests/test_start_kafka_manager.py index f5182e7a4..677061c12 100644 --- a/emulation-system/tests/test_start_kafka_manager.py +++ b/emulation-system/tests/test_start_kafka_manager.py @@ -64,7 +64,7 @@ def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGE and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) and all(excluded_tag not in tag for tag in image.tags) ] - return derived_images[:1] + return derived_images @pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) @@ -140,8 +140,6 @@ def test_start_kafka_manager(container_setup) -> None: f"with image: {container_setup.image.tags}") result = container_setup.exec_run(cmd) output = result.output.decode("utf-8") - print("output:") - print(output) assert constants.COMMANDS.SEARCH_KAFKA_MANAGER in output, "Kafka manager is not running in the container" time.sleep(5) # Call grpc diff --git a/emulation-system/tests/test_start_ossec_manager.py b/emulation-system/tests/test_start_ossec_manager.py new file mode 100644 index 000000000..7c62f9e46 --- /dev/null +++ b/emulation-system/tests/test_start_ossec_manager.py @@ -0,0 +1,162 @@ +from typing import List, Any, Generator +import pytest +import docker +import logging +import grpc +from unittest.mock import MagicMock +from docker.types import IPAMConfig, IPAMPool +import time +from csle_common.dao.emulation_config.emulation_env_config import EmulationEnvConfig +from csle_common.util.emulation_util import EmulationUtil +import csle_common.constants.constants as constants +import csle_collector.ossec_ids_manager.ossec_ids_manager_pb2_grpc +import csle_collector.ossec_ids_manager.ossec_ids_manager_pb2 +import csle_collector.ossec_ids_manager.query_ossec_ids_manager +from csle_common.metastore.metastore_facade import MetastoreFacade +from IPython.lib.editorhooks import emacs + + +@pytest.fixture(scope="module") +def docker_client() -> None: + """ + Initialize and Provide a Docker client instance for the test + + :return: None + """ + return docker.from_env() + + +@pytest.fixture(scope="module") +def network(docker_client) -> None: + """ + Create a custom network with a specific subnet + + :param docker_client: docker_client + :yield: network + + :return: None + """ + subnet = "15.15.15.0/24" + ipam_pool = IPAMPool(subnet=subnet) + ipam_config = IPAMConfig(pool_configs=[ipam_pool]) + logging.info(f"Creating virtual network with subnet: {subnet}") + network = docker_client.networks.create("test_network", driver="bridge", ipam=ipam_config) + yield network + network.remove() + + +def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGES.BLANK) -> List[Any]: + """ + Get all the containers except the blank ones + + :param docker_client: docker_client + + :return: None + """ + # Get all images except those with the excluded tag + config = MetastoreFacade.get_config(id=1) + match_tag = config.version + all_images = docker_client.images.list() + derived_images = [ + image + for image in all_images + if any(match_tag in tag for tag in image.tags) + and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) + and all(excluded_tag not in tag for tag in image.tags) + ] + return derived_images[:1] + + +@pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) +def container_setup(request, docker_client, network) -> Generator: + """ + Starts a Docker container before running tests and ensures its stopped and removed after tests complete. + + :param request: request + :param docker_client: docker_client + :yield: container + + :return: None + """ + # Create and start each derived container + image = request.param + container = docker_client.containers.create( + image.tags[0], + command="sh -c 'while true; do sleep 3600; done'", + detach=True, + ) + network.connect(container) + container.start() + yield container + logging.info(f"Stopping and removing container: {container.id} with image: {container.image.tags}") + container.stop() + container.remove() + + +def test_start_ossec_manager(container_setup) -> None: + """ + Start ossec_manager in a container + + :param container_setup: container_setup + + :return: None + """ + failed_containers = [] + containers_info = [] + container_setup.reload() + assert container_setup.status == "running" + # Mock emulation_env_config + emulation_env_config = MagicMock(spec=EmulationEnvConfig) + emulation_env_config.get_connection.return_value = MagicMock() + emulation_env_config.ossec_ids_manager_config = MagicMock() + emulation_env_config.ossec_ids_manager_config.ossec_ids_manager_port = 50051 + emulation_env_config.ossec_ids_manager_config.ossec_ids_manager_log_dir = "/var/log/ossec" + emulation_env_config.ossec_ids_manager_config.ossec_ids_manager_log_file = "ossec.log" + emulation_env_config.ossec_ids_manager_config.ossec_ids_manager_max_workers = 4 + + ip = container_setup.attrs[constants.DOCKER.NETWORK_SETTINGS][constants.DOCKER.IP_ADDRESS_INFO] + port = emulation_env_config.ossec_ids_manager_config.ossec_ids_manager_port + try: + # Start host_manager command + cmd = ( + f"/root/miniconda3/bin/python3 /ossec_ids_manager.py " + f"--port {emulation_env_config.ossec_ids_manager_config.ossec_ids_manager_port} " + f"--logdir {emulation_env_config.ossec_ids_manager_config.ossec_ids_manager_log_dir} " + f"--logfile {emulation_env_config.ossec_ids_manager_config.ossec_ids_manager_log_file} " + f"--maxworkers {emulation_env_config.ossec_ids_manager_config.ossec_ids_manager_max_workers}" + ) + # Run cmd in the container + logging.info(f"Starting ossec manager in container: {container_setup.id} " + f"with image: {container_setup.image.tags}") + container_setup.exec_run(cmd, detach=True) + # Check if ossec_manager starts + cmd = ( + f"sh -c '{constants.COMMANDS.PS_AUX} | {constants.COMMANDS.GREP} " + f"{constants.COMMANDS.SPACE_DELIM}{constants.TRAFFIC_COMMANDS.OSSEC_IDS_MANAGER_FILE_NAME}'" + ) + logging.info(f"Verifying that ossec manager is running in container: {container_setup.id} " + f"with image: {container_setup.image.tags}") + result = container_setup.exec_run(cmd) + output = result.output.decode("utf-8") + assert constants.COMMANDS.SEARCH_OSSEC_IDS_MANAGER in output, "ossec manager is not running in the container" + time.sleep(5) + # Call grpc + with grpc.insecure_channel(f"{ip}:{port}", options=constants.GRPC_SERVERS.GRPC_OPTIONS) as channel: + stub = csle_collector.ossec_ids_manager.ossec_ids_manager_pb2_grpc.OSSECIdsManagerStub(channel) + status = csle_collector.ossec_ids_manager.query_ossec_ids_manager.get_ossec_ids_monitor_status(stub=stub) + assert status + except Exception as e: + print(f"Error occurred in container {container_setup.name}: {e}") + failed_containers.append(container_setup.name) + containers_info.append( + { + "container_status": container_setup.status, + "container_image": container_setup.image.tags, + "name": container_setup.name, + "error": str(e), + } + ) + if failed_containers: + logging.info("Containers that failed to start the ossec manager:") + logging.info(containers_info) + assert not failed_containers, f"T{failed_containers} failed" From 8090946d562f0670a3dce5248390bb1378a13e79 Mon Sep 17 00:00:00 2001 From: yu Date: Mon, 19 Aug 2024 12:16:43 +0200 Subject: [PATCH 4/5] add test_start_ryu_manager.py --- .../tests/test_start_elk_manager.py | 27 +-- .../tests/test_start_kafka_manager.py | 27 +-- .../tests/test_start_ossec_manager.py | 17 +- .../tests/test_start_ryu_manager.py | 169 ++++++++++++++++++ 4 files changed, 211 insertions(+), 29 deletions(-) create mode 100644 emulation-system/tests/test_start_ryu_manager.py diff --git a/emulation-system/tests/test_start_elk_manager.py b/emulation-system/tests/test_start_elk_manager.py index 2d4bb1404..d439a26a3 100644 --- a/emulation-system/tests/test_start_elk_manager.py +++ b/emulation-system/tests/test_start_elk_manager.py @@ -65,7 +65,7 @@ def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGE and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) and all(excluded_tag not in tag for tag in image.tags) ] - return derived_images[:1] + return derived_images[:1] @pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) @@ -82,7 +82,7 @@ def container_setup(request, docker_client, network) -> Generator: # Create and start each derived container image = request.param container = docker_client.containers.create( - image.tags[0], + image.tags[0], command="sh -c 'while true; do sleep 3600; done'", detach=True, ) @@ -110,35 +110,40 @@ def test_start_elk_manager(container_setup) -> None: emulation_env_config = MagicMock(spec=EmulationEnvConfig) emulation_env_config.get_connection.return_value = MagicMock() emulation_env_config.elk_config = MagicMock() - emulation_env_config.elk_config.container.docker_gw_bridge_ip = container_setup.attrs[constants.DOCKER.NETWORK_SETTINGS][constants.DOCKER.IP_ADDRESS_INFO] + emulation_env_config.elk_config.container.docker_gw_bridge_ip = container_setup.attrs[ + constants.DOCKER.NETWORK_SETTINGS + ][constants.DOCKER.IP_ADDRESS_INFO] emulation_env_config.elk_config.get_connection.return_value = MagicMock() emulation_env_config.elk_config.elk_manager_port = 50051 emulation_env_config.elk_config.elk_manager_log_dir = "/var/log/elk" emulation_env_config.elk_config.elk_manager_log_file = "elk.log" emulation_env_config.elk_config.elk_manager_max_workers = 4 - + ip = emulation_env_config.elk_config.container.docker_gw_bridge_ip port = emulation_env_config.elk_config.elk_manager_port try: - # Start host_manager command + # Start elk_manager command cmd = ( - f"/root/miniconda3/bin/python3 /elk_manager.py " + f"/root/miniconda3/bin/python3 /elk_manager.py " f"--port {emulation_env_config.elk_config.elk_manager_port} " f"--logdir {emulation_env_config.elk_config.elk_manager_log_dir} " f"--logfile {emulation_env_config.elk_config.elk_manager_log_file} " f"--maxworkers {emulation_env_config.elk_config.elk_manager_max_workers}" ) # Run cmd in the container - logging.info(f"Starting elk manager in container: {container_setup.id} " - f"with image: {container_setup.image.tags}") + logging.info( + f"Starting elk manager in container: {container_setup.id} " f"with image: {container_setup.image.tags}" + ) container_setup.exec_run(cmd, detach=True) # Check if elk_manager starts cmd = ( f"sh -c '{constants.COMMANDS.PS_AUX} | {constants.COMMANDS.GREP} " f"{constants.COMMANDS.SPACE_DELIM}{constants.TRAFFIC_COMMANDS.ELK_MANAGER_FILE_NAME}'" ) - logging.info(f"Verifying that elk manager is running in container: {container_setup.id} " - f"with image: {container_setup.image.tags}") + logging.info( + f"Verifying that elk manager is running in container: {container_setup.id} " + f"with image: {container_setup.image.tags}" + ) result = container_setup.exec_run(cmd) output = result.output.decode("utf-8") assert constants.COMMANDS.SEARCH_ELK_MANAGER in output, "Elk manager is not running in the container" @@ -147,7 +152,7 @@ def test_start_elk_manager(container_setup) -> None: with grpc.insecure_channel(f"{ip}:{port}", options=constants.GRPC_SERVERS.GRPC_OPTIONS) as channel: stub = csle_collector.elk_manager.elk_manager_pb2_grpc.ElkManagerStub(channel) elk_dto = csle_collector.elk_manager.query_elk_manager.get_elk_status(stub) - assert elk_dto + assert elk_dto except Exception as e: print(f"Error occurred in container {container_setup.name}: {e}") failed_containers.append(container_setup.name) diff --git a/emulation-system/tests/test_start_kafka_manager.py b/emulation-system/tests/test_start_kafka_manager.py index 677061c12..fa355c4b1 100644 --- a/emulation-system/tests/test_start_kafka_manager.py +++ b/emulation-system/tests/test_start_kafka_manager.py @@ -64,7 +64,7 @@ def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGE and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) and all(excluded_tag not in tag for tag in image.tags) ] - return derived_images + return derived_images @pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) @@ -81,7 +81,7 @@ def container_setup(request, docker_client, network) -> Generator: # Create and start each derived container image = request.param container = docker_client.containers.create( - image.tags[0], + image.tags[0], command="sh -c 'while true; do sleep 3600; done'", detach=True, ) @@ -109,35 +109,40 @@ def test_start_kafka_manager(container_setup) -> None: emulation_env_config = MagicMock(spec=EmulationEnvConfig) emulation_env_config.get_connection.return_value = MagicMock() emulation_env_config.kafka_config = MagicMock() - emulation_env_config.kafka_config.container.docker_gw_bridge_ip = container_setup.attrs[constants.DOCKER.NETWORK_SETTINGS][constants.DOCKER.IP_ADDRESS_INFO] + emulation_env_config.kafka_config.container.docker_gw_bridge_ip = container_setup.attrs[ + constants.DOCKER.NETWORK_SETTINGS + ][constants.DOCKER.IP_ADDRESS_INFO] emulation_env_config.kafka_config.get_connection.return_value = MagicMock() emulation_env_config.kafka_config.kafka_manager_port = 50051 emulation_env_config.kafka_config.kafka_manager_log_dir = "/var/log/kafka" emulation_env_config.kafka_config.kafka_manager_log_file = "kafka.log" emulation_env_config.kafka_config.kafka_manager_max_workers = 4 - + ip = emulation_env_config.kafka_config.container.docker_gw_bridge_ip port = emulation_env_config.kafka_config.kafka_manager_port try: - # Start host_manager command + # Start kafka_manager command cmd = ( - f"/root/miniconda3/bin/python3 /kafka_manager.py " + f"/root/miniconda3/bin/python3 /kafka_manager.py " f"--port {emulation_env_config.kafka_config.kafka_manager_port} " f"--logdir {emulation_env_config.kafka_config.kafka_manager_log_dir} " f"--logfile {emulation_env_config.kafka_config.kafka_manager_log_file} " f"--maxworkers {emulation_env_config.kafka_config.kafka_manager_max_workers}" ) # Run cmd in the container - logging.info(f"Starting kafka manager in container: {container_setup.id} " - f"with image: {container_setup.image.tags}") + logging.info( + f"Starting kafka manager in container: {container_setup.id} " f"with image: {container_setup.image.tags}" + ) container_setup.exec_run(cmd, detach=True) # Check if kafka_manager starts cmd = ( f"sh -c '{constants.COMMANDS.PS_AUX} | {constants.COMMANDS.GREP} " f"{constants.COMMANDS.SPACE_DELIM}{constants.TRAFFIC_COMMANDS.KAFKA_MANAGER_FILE_NAME}'" ) - logging.info(f"Verifying that kafka manager is running in container: {container_setup.id} " - f"with image: {container_setup.image.tags}") + logging.info( + f"Verifying that kafka manager is running in container: {container_setup.id} " + f"with image: {container_setup.image.tags}" + ) result = container_setup.exec_run(cmd) output = result.output.decode("utf-8") assert constants.COMMANDS.SEARCH_KAFKA_MANAGER in output, "Kafka manager is not running in the container" @@ -146,7 +151,7 @@ def test_start_kafka_manager(container_setup) -> None: with grpc.insecure_channel(f"{ip}:{port}", options=constants.GRPC_SERVERS.GRPC_OPTIONS) as channel: stub = csle_collector.kafka_manager.kafka_manager_pb2_grpc.KafkaManagerStub(channel) kafka_dto = csle_collector.kafka_manager.query_kafka_server.get_kafka_status(stub) - assert kafka_dto + assert kafka_dto except Exception as e: print(f"Error occurred in container {container_setup.name}: {e}") failed_containers.append(container_setup.name) diff --git a/emulation-system/tests/test_start_ossec_manager.py b/emulation-system/tests/test_start_ossec_manager.py index 7c62f9e46..31676e784 100644 --- a/emulation-system/tests/test_start_ossec_manager.py +++ b/emulation-system/tests/test_start_ossec_manager.py @@ -64,7 +64,7 @@ def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGE and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) and all(excluded_tag not in tag for tag in image.tags) ] - return derived_images[:1] + return derived_images[:1] @pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) @@ -81,7 +81,7 @@ def container_setup(request, docker_client, network) -> Generator: # Create and start each derived container image = request.param container = docker_client.containers.create( - image.tags[0], + image.tags[0], command="sh -c 'while true; do sleep 3600; done'", detach=True, ) @@ -126,16 +126,19 @@ def test_start_ossec_manager(container_setup) -> None: f"--maxworkers {emulation_env_config.ossec_ids_manager_config.ossec_ids_manager_max_workers}" ) # Run cmd in the container - logging.info(f"Starting ossec manager in container: {container_setup.id} " - f"with image: {container_setup.image.tags}") + logging.info( + f"Starting ossec manager in container: {container_setup.id} " f"with image: {container_setup.image.tags}" + ) container_setup.exec_run(cmd, detach=True) # Check if ossec_manager starts cmd = ( f"sh -c '{constants.COMMANDS.PS_AUX} | {constants.COMMANDS.GREP} " f"{constants.COMMANDS.SPACE_DELIM}{constants.TRAFFIC_COMMANDS.OSSEC_IDS_MANAGER_FILE_NAME}'" ) - logging.info(f"Verifying that ossec manager is running in container: {container_setup.id} " - f"with image: {container_setup.image.tags}") + logging.info( + f"Verifying that ossec manager is running in container: {container_setup.id} " + f"with image: {container_setup.image.tags}" + ) result = container_setup.exec_run(cmd) output = result.output.decode("utf-8") assert constants.COMMANDS.SEARCH_OSSEC_IDS_MANAGER in output, "ossec manager is not running in the container" @@ -144,7 +147,7 @@ def test_start_ossec_manager(container_setup) -> None: with grpc.insecure_channel(f"{ip}:{port}", options=constants.GRPC_SERVERS.GRPC_OPTIONS) as channel: stub = csle_collector.ossec_ids_manager.ossec_ids_manager_pb2_grpc.OSSECIdsManagerStub(channel) status = csle_collector.ossec_ids_manager.query_ossec_ids_manager.get_ossec_ids_monitor_status(stub=stub) - assert status + assert status except Exception as e: print(f"Error occurred in container {container_setup.name}: {e}") failed_containers.append(container_setup.name) diff --git a/emulation-system/tests/test_start_ryu_manager.py b/emulation-system/tests/test_start_ryu_manager.py new file mode 100644 index 000000000..c0ad97fde --- /dev/null +++ b/emulation-system/tests/test_start_ryu_manager.py @@ -0,0 +1,169 @@ +from typing import List, Any, Generator +import pytest +import docker +import logging +import grpc +from unittest.mock import MagicMock +from docker.types import IPAMConfig, IPAMPool +import time +from csle_common.dao.emulation_config.emulation_env_config import EmulationEnvConfig +from csle_common.util.emulation_util import EmulationUtil +import csle_common.constants.constants as constants +import csle_collector.ryu_manager.ryu_manager_pb2_grpc +import csle_collector.ryu_manager.ryu_manager_pb2 +import csle_collector.ryu_manager.query_ryu_manager +from csle_common.metastore.metastore_facade import MetastoreFacade +from IPython.lib.editorhooks import emacs + + +@pytest.fixture(scope="module") +def docker_client() -> None: + """ + Initialize and Provide a Docker client instance for the test + + :return: None + """ + return docker.from_env() + + +@pytest.fixture(scope="module") +def network(docker_client) -> None: + """ + Create a custom network with a specific subnet + + :param docker_client: docker_client + :yield: network + + :return: None + """ + subnet = "15.15.15.0/24" + ipam_pool = IPAMPool(subnet=subnet) + ipam_config = IPAMConfig(pool_configs=[ipam_pool]) + logging.info(f"Creating virtual network with subnet: {subnet}") + network = docker_client.networks.create("test_network", driver="bridge", ipam=ipam_config) + yield network + network.remove() + + +def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGES.BLANK) -> List[Any]: + """ + Get all the containers except the blank ones + + :param docker_client: docker_client + + :return: None + """ + # Get all images except those with the excluded tag + config = MetastoreFacade.get_config(id=1) + match_tag = config.version + all_images = docker_client.images.list() + derived_images = [ + image + for image in all_images + if any(match_tag in tag for tag in image.tags) + and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) + and all(excluded_tag not in tag for tag in image.tags) + ] + return derived_images[:1] + + +@pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) +def container_setup(request, docker_client, network) -> Generator: + """ + Starts a Docker container before running tests and ensures its stopped and removed after tests complete. + + :param request: request + :param docker_client: docker_client + :yield: container + + :return: None + """ + # Create and start each derived container + image = request.param + container = docker_client.containers.create( + image.tags[0], + command="sh -c 'while true; do sleep 3600; done'", + detach=True, + ) + network.connect(container) + container.start() + yield container + logging.info(f"Stopping and removing container: {container.id} with image: {container.image.tags}") + container.stop() + container.remove() + + +def test_start_ryu_manager(container_setup) -> None: + """ + Start ryu_manager in a container + + :param container_setup: container_setup + + :return: None + """ + failed_containers = [] + containers_info = [] + container_setup.reload() + assert container_setup.status == "running" + # Mock emulation_env_config + emulation_env_config = MagicMock(spec=EmulationEnvConfig) + emulation_env_config.get_connection.return_value = MagicMock() + emulation_env_config.sdn_controller_config = MagicMock() + emulation_env_config.sdn_controller_config.container.docker_gw_bridge_ip = container_setup.attrs[ + constants.DOCKER.NETWORK_SETTINGS + ][constants.DOCKER.IP_ADDRESS_INFO] + emulation_env_config.sdn_controller_config.get_connection.return_value = MagicMock() + emulation_env_config.sdn_controller_config.ryu_manager_port = 50051 + emulation_env_config.sdn_controller_config.ryu_manager_log_dir = "/var/log/ryu" + emulation_env_config.sdn_controller_config.ryu_manager_log_file = "ryu.log" + emulation_env_config.sdn_controller_config.ryu_manager_max_workers = 4 + + ip = emulation_env_config.sdn_controller_config.container.docker_gw_bridge_ip + port = emulation_env_config.sdn_controller_config.ryu_manager_port + try: + # Start ryu_manager command + cmd = ( + f"/root/miniconda3/bin/python3 /ryu_manager.py " + f"--port {emulation_env_config.sdn_controller_config.ryu_manager_port} " + f"--logdir {emulation_env_config.sdn_controller_config.ryu_manager_log_dir} " + f"--logfile {emulation_env_config.sdn_controller_config.ryu_manager_log_file} " + f"--maxworkers {emulation_env_config.sdn_controller_config.ryu_manager_max_workers}" + ) + # Run cmd in the container + logging.info( + f"Starting ryu manager in container: {container_setup.id} " f"with image: {container_setup.image.tags}" + ) + container_setup.exec_run(cmd, detach=True) + # Check if ryu_manager starts + cmd = ( + f"sh -c '{constants.COMMANDS.PS_AUX} | {constants.COMMANDS.GREP} " + f"{constants.COMMANDS.SPACE_DELIM}{constants.TRAFFIC_COMMANDS.RYU_MANAGER_FILE_NAME}'" + ) + logging.info( + f"Verifying that ryu manager is running in container: {container_setup.id} " + f"with image: {container_setup.image.tags}" + ) + result = container_setup.exec_run(cmd) + output = result.output.decode("utf-8") + assert constants.COMMANDS.SEARCH_RYU_MANAGER in output, "ryu manager is not running in the container" + time.sleep(5) + # Call grpc + with grpc.insecure_channel(f"{ip}:{port}", options=constants.GRPC_SERVERS.GRPC_OPTIONS) as channel: + stub = csle_collector.ryu_manager.ryu_manager_pb2_grpc.RyuManagerStub(channel) + ryu_dto = csle_collector.ryu_manager.query_ryu_manager.get_ryu_status(stub) + assert ryu_dto + except Exception as e: + print(f"Error occurred in container {container_setup.name}: {e}") + failed_containers.append(container_setup.name) + containers_info.append( + { + "container_status": container_setup.status, + "container_image": container_setup.image.tags, + "name": container_setup.name, + "error": str(e), + } + ) + if failed_containers: + logging.info("Containers that failed to start the ryu manager:") + logging.info(containers_info) + assert not failed_containers, f"T{failed_containers} failed" From 852c804796bfc51fcd09ded99a00a47b8039a2df Mon Sep 17 00:00:00 2001 From: yu Date: Mon, 19 Aug 2024 13:02:57 +0200 Subject: [PATCH 5/5] all tests passed --- .../tests/test_start_elk_manager.py | 2 +- .../tests/test_start_ossec_manager.py | 2 +- .../tests/test_start_ryu_manager.py | 2 +- .../tests/test_start_traffic_manager.py | 169 ++++++++++++++++++ 4 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 emulation-system/tests/test_start_traffic_manager.py diff --git a/emulation-system/tests/test_start_elk_manager.py b/emulation-system/tests/test_start_elk_manager.py index d439a26a3..6bc497545 100644 --- a/emulation-system/tests/test_start_elk_manager.py +++ b/emulation-system/tests/test_start_elk_manager.py @@ -65,7 +65,7 @@ def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGE and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) and all(excluded_tag not in tag for tag in image.tags) ] - return derived_images[:1] + return derived_images @pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) diff --git a/emulation-system/tests/test_start_ossec_manager.py b/emulation-system/tests/test_start_ossec_manager.py index 31676e784..c5a75e75c 100644 --- a/emulation-system/tests/test_start_ossec_manager.py +++ b/emulation-system/tests/test_start_ossec_manager.py @@ -64,7 +64,7 @@ def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGE and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) and all(excluded_tag not in tag for tag in image.tags) ] - return derived_images[:1] + return derived_images @pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) diff --git a/emulation-system/tests/test_start_ryu_manager.py b/emulation-system/tests/test_start_ryu_manager.py index c0ad97fde..ccb3ebbe6 100644 --- a/emulation-system/tests/test_start_ryu_manager.py +++ b/emulation-system/tests/test_start_ryu_manager.py @@ -64,7 +64,7 @@ def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGE and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) and all(excluded_tag not in tag for tag in image.tags) ] - return derived_images[:1] + return derived_images @pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) diff --git a/emulation-system/tests/test_start_traffic_manager.py b/emulation-system/tests/test_start_traffic_manager.py new file mode 100644 index 000000000..ba6046c96 --- /dev/null +++ b/emulation-system/tests/test_start_traffic_manager.py @@ -0,0 +1,169 @@ +from typing import List, Any, Generator +import pytest +import docker +import logging +import grpc +from unittest.mock import MagicMock +from docker.types import IPAMConfig, IPAMPool +import time +from csle_common.dao.emulation_config.emulation_env_config import EmulationEnvConfig +from csle_common.util.emulation_util import EmulationUtil +import csle_common.constants.constants as constants +import csle_collector.traffic_manager.traffic_manager_pb2_grpc +import csle_collector.traffic_manager.traffic_manager_pb2 +import csle_collector.traffic_manager.query_traffic_manager +from csle_common.metastore.metastore_facade import MetastoreFacade +from IPython.lib.editorhooks import emacs + + +@pytest.fixture(scope="module") +def docker_client() -> None: + """ + Initialize and Provide a Docker client instance for the test + + :return: None + """ + return docker.from_env() + + +@pytest.fixture(scope="module") +def network(docker_client) -> None: + """ + Create a custom network with a specific subnet + + :param docker_client: docker_client + :yield: network + + :return: None + """ + subnet = "15.15.15.0/24" + ipam_pool = IPAMPool(subnet=subnet) + ipam_config = IPAMConfig(pool_configs=[ipam_pool]) + logging.info(f"Creating virtual network with subnet: {subnet}") + network = docker_client.networks.create("test_network", driver="bridge", ipam=ipam_config) + yield network + network.remove() + + +def get_derived_containers(docker_client, excluded_tag=constants.CONTAINER_IMAGES.BLANK) -> List[Any]: + """ + Get all the containers except the blank ones + + :param docker_client: docker_client + + :return: None + """ + # Get all images except those with the excluded tag + config = MetastoreFacade.get_config(id=1) + match_tag = config.version + all_images = docker_client.images.list() + derived_images = [ + image + for image in all_images + if any(match_tag in tag for tag in image.tags) + and all(constants.CONTAINER_IMAGES.BASE not in tag for tag in image.tags) + and all(excluded_tag not in tag for tag in image.tags) + ] + return derived_images + + +@pytest.fixture(scope="module", params=get_derived_containers(docker.from_env())) +def container_setup(request, docker_client, network) -> Generator: + """ + Starts a Docker container before running tests and ensures its stopped and removed after tests complete. + + :param request: request + :param docker_client: docker_client + :yield: container + + :return: None + """ + # Create and start each derived container + image = request.param + container = docker_client.containers.create( + image.tags[0], + command="sh -c 'while true; do sleep 3600; done'", + detach=True, + ) + network.connect(container) + container.start() + yield container + logging.info(f"Stopping and removing container: {container.id} with image: {container.image.tags}") + container.stop() + container.remove() + + +def test_start_traffic_manager(container_setup) -> None: + """ + Start traffic_manager in a container + + :param container_setup: container_setup + + :return: None + """ + failed_containers = [] + containers_info = [] + container_setup.reload() + assert container_setup.status == "running" + # Mock emulation_env_config + emulation_env_config = MagicMock(spec=EmulationEnvConfig) + emulation_env_config.get_connection.return_value = MagicMock() + emulation_env_config.node_traffic_config = MagicMock() + emulation_env_config.node_traffic_config.container.docker_gw_bridge_ip = container_setup.attrs[ + constants.DOCKER.NETWORK_SETTINGS + ][constants.DOCKER.IP_ADDRESS_INFO] + emulation_env_config.node_traffic_config.get_connection.return_value = MagicMock() + emulation_env_config.node_traffic_config.traffic_manager_port = 50051 + emulation_env_config.node_traffic_config.traffic_manager_log_dir = "/var/log/traffic" + emulation_env_config.node_traffic_config.traffic_manager_log_file = "traffic.log" + emulation_env_config.node_traffic_config.traffic_manager_max_workers = 4 + + ip = emulation_env_config.node_traffic_config.container.docker_gw_bridge_ip + port = emulation_env_config.node_traffic_config.traffic_manager_port + try: + # Start traffic_manager command + cmd = ( + f"/root/miniconda3/bin/python3 /traffic_manager.py " + f"--port {emulation_env_config.node_traffic_config.traffic_manager_port} " + f"--logdir {emulation_env_config.node_traffic_config.traffic_manager_log_dir} " + f"--logfile {emulation_env_config.node_traffic_config.traffic_manager_log_file} " + f"--maxworkers {emulation_env_config.node_traffic_config.traffic_manager_max_workers}" + ) + # Run cmd in the container + logging.info( + f"Starting traffic manager in container: {container_setup.id} " f"with image: {container_setup.image.tags}" + ) + container_setup.exec_run(cmd, detach=True) + # Check if traffic_manager starts + cmd = ( + f"sh -c '{constants.COMMANDS.PS_AUX} | {constants.COMMANDS.GREP} " + f"{constants.COMMANDS.SPACE_DELIM}{constants.TRAFFIC_COMMANDS.TRAFFIC_MANAGER_FILE_NAME}'" + ) + logging.info( + f"Verifying that traffic manager is running in container: {container_setup.id} " + f"with image: {container_setup.image.tags}" + ) + result = container_setup.exec_run(cmd) + output = result.output.decode("utf-8") + assert constants.COMMANDS.SEARCH_TRAFFIC_MANAGER in output, "traffic manager is not running in the container" + time.sleep(5) + # Call grpc + with grpc.insecure_channel(f"{ip}:{port}", options=constants.GRPC_SERVERS.GRPC_OPTIONS) as channel: + stub = csle_collector.traffic_manager.traffic_manager_pb2_grpc.TrafficManagerStub(channel) + status = csle_collector.traffic_manager.query_traffic_manager.get_traffic_status(stub=stub) + assert status + except Exception as e: + print(f"Error occurred in container {container_setup.name}: {e}") + failed_containers.append(container_setup.name) + containers_info.append( + { + "container_status": container_setup.status, + "container_image": container_setup.image.tags, + "name": container_setup.name, + "error": str(e), + } + ) + if failed_containers: + logging.info("Containers that failed to start the traffic manager:") + logging.info(containers_info) + assert not failed_containers, f"T{failed_containers} failed"