From 36604231ede6413ccf3402b515951fc8bea15799 Mon Sep 17 00:00:00 2001 From: jmv74211 Date: Fri, 13 Aug 2021 16:24:51 +0200 Subject: [PATCH 1/7] add: Add logging module #1713 --- .../wazuh_testing/tools/logging.py | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 deps/wazuh_testing/wazuh_testing/tools/logging.py diff --git a/deps/wazuh_testing/wazuh_testing/tools/logging.py b/deps/wazuh_testing/wazuh_testing/tools/logging.py new file mode 100644 index 0000000000..09c1b5d28c --- /dev/null +++ b/deps/wazuh_testing/wazuh_testing/tools/logging.py @@ -0,0 +1,108 @@ +import logging +import os + +class Logging: + """Class to handle modules logging. It is a wrapper class from logging standard python module. + + Args: + logger_name (str): Logger name + level (str): Logger level: DEBUG, INFO, WARNING, ERROR or CRITICAL + stdout (boolean): True for add stodut stream handler False otherwise + log_file (str): True for add file handler, False otherwise + + Attributes: + logger_name (str): Logger name + level (str): Logger level: DEBUG, INFO, WARNING, ERROR or CRITICAL + stdout (boolean): True for add stodut stream handler False otherwise + log_file (str): True for add file handler, False otherwise + """ + def __init__(self, logger_name, level='INFO', stdout=True, log_file=None): + self.logger = logging.getLogger(logger_name) + self.level = level + self.stdout = stdout + self.log_file = log_file + + self.__validate_parameters() + self.__initialize_parameters() + self.__default_config() + + def __validate_parameters(self): + """Verify class parameters value""" + if self.level not in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']: + raise ValueError('LOGGER level must be one of the following values: DEBUG, INFO, WARNING, ERROR, CRITICAL') + + def __initialize_parameters(self): + """Set logger level, mapping the string into enum constant""" + level_mapping = { + 'DEBUG': logging.DEBUG, + 'INFO': logging.INFO, + 'WARNING': logging.WARNING, + 'ERORR': logging.ERROR, + 'CRITICAL': logging.CRITICAL + } + + self.level = level_mapping[self.level] + + def __default_config(self): + """Set default handler configuration""" + formatter = logging.Formatter(fmt='%(asctime)s - %(levelname)s - %(module)s - %(message)s') + self.logger.setLevel(self.level) + + if self.stdout: + handler = logging.StreamHandler() + handler.setFormatter(formatter) + self.logger.addHandler(handler) + + if self.log_file: + # Create folder path if not exist + if not os.path.exists(os.path.dirname(self.log_file)): + os.makedirs(os.path.dirname(self.log_file)) + + handler = logging.FileHandler(self.log_file) + handler.setFormatter(formatter) + self.logger.addHandler(handler) + + @staticmethod + def __logger_exists(logger_name): + """Get if logger exists or not. + + Returns: + boolean: True if logger exists, false otherwise + """ + return logger_name in logging.Logger.manager.loggerDict + + @staticmethod + def get_logger(logger_name): + """Get the logger object if exists + + Returns: + logging.Logger: Logger object + + Raises: + ValueError: If logger not exists + + """ + if not Logging.__logger_exists(logger_name): + raise ValueError(f"Logger {logger_name} does not exist") + + return logging.getLogger(logger_name) + + def debug(self, message): + """Log DEBUG message""" + self.logger.debug(message) + + def info(self, message): + """Log INFO message""" + self.logger.info(message) + + def warning(self, message): + """Log WARNING message""" + self.logger.warning(message) + + def error(self, message): + """Log ERROR message""" + self.logger.error(message) + + def critical(self, message): + """Log CRITICAL message""" + self.logger.critical(message) From 6144b989c2147e312d5c2f8b2417e355a9102e56 Mon Sep 17 00:00:00 2001 From: jmv74211 Date: Wed, 25 Aug 2021 12:57:00 +0200 Subject: [PATCH 2/7] add: Add logging to QACTL deployment modules #1713 --- .../qa_ctl/deployment/DockerWrapper.py | 13 ++++++- .../qa_ctl/deployment/QAInfraestructure.py | 28 +++++++++++---- .../qa_ctl/deployment/VagrantWrapper.py | 35 +++++++++++-------- .../qa_ctl/deployment/Vagrantfile.py | 11 ++++-- .../wazuh_testing/tools/exceptions.py | 6 ++++ .../wazuh_testing/tools/logging.py | 3 -- 6 files changed, 70 insertions(+), 26 deletions(-) create mode 100644 deps/wazuh_testing/wazuh_testing/tools/exceptions.py diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/DockerWrapper.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/DockerWrapper.py index f1538dde2d..f77eb02c24 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/DockerWrapper.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/DockerWrapper.py @@ -1,7 +1,11 @@ import docker -from wazuh_testing.qa_ctl.deployment.Instance import Instance + from json import dumps +from wazuh_testing.qa_ctl.deployment.Instance import Instance +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging + class DockerWrapper(Instance): """Class to handle docker operations. This class uses the docker python SDK to read a dockerfile and create @@ -35,6 +39,8 @@ class DockerWrapper(Instance): no static IP will be assigned. network_name (string): Name of the docker network. """ + LOGGER = Logging.get_logger(QACTL_LOGGER) + def __init__(self, docker_client, dockerfile_path, name, remove=False, ports=None, detach=True, stdout=False, stderr=False, ip=None, network_name=None): self.docker_client = docker_client @@ -68,6 +74,7 @@ def get_container(self): return self.docker_client.containers.get(self.name) def run(self): + DockerWrapper.LOGGER.debug(f"Running {self.name} cointainer...") container = self.docker_client.containers.run(image=self.image, name=self.name, ports=self.ports, remove=self.remove, detach=self.detach, stdout=self.stdout, stderr=self.stderr) @@ -81,6 +88,7 @@ def restart(self): docker.errors.APIError: If the server returns an error. """ try: + DockerWrapper.LOGGER.debug(f"Restarting {self.name} cointainer...") self.get_container().restart() except docker.errors.NotFound: pass @@ -92,6 +100,7 @@ def halt(self): docker.errors.APIError: If the server returns an error. """ try: + DockerWrapper.LOGGER.debug(f"Stopping {self.name} cointainer...") self.get_container().stop() except docker.errors.NotFound: pass @@ -111,11 +120,13 @@ def destroy(self, remove_image=False): pass try: + DockerWrapper.LOGGER.debug(f"Removing {self.name} cointainer...") self.get_container().remove() except docker.errors.NotFound: pass if remove_image: + DockerWrapper.LOGGER.debug(f"Removing {self.image.id} docker image...") self.docker_client.images.remove(image=self.image.id, force=True) def get_instance_info(self): diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/QAInfraestructure.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/QAInfraestructure.py index 0b95c33f2a..532cc52123 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/QAInfraestructure.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/QAInfraestructure.py @@ -7,7 +7,9 @@ from wazuh_testing.qa_ctl.deployment.DockerWrapper import DockerWrapper from wazuh_testing.qa_ctl.deployment.VagrantWrapper import VagrantWrapper from wazuh_testing.tools.thread_executor import ThreadExecutor - +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging +from wazuh_testing.tools.exceptions import QAValueError class QAInfraestructure: """Class to handle multiples instances objects. @@ -17,16 +19,17 @@ class QAInfraestructure: template. Class Attributes: - DOCKER_NETWORK_NAME: Name of the docker network where the containers will be connected. + DOCKER_NETWORK_NAME (str): Name of the docker network where the containers will be connected. + LOGGER (Logging): Logger object. Instance Attributes: instances (list): List with the instances to handle. docker_client (Docker Client): Client to communicate with the docker daemon. docker_network (Docker Network): Network object to handle container's static IP address. network_address (IPNetwork): Docker network address. - """ DOCKER_NETWORK_NAME = 'wazuh_net' + LOGGER = Logging.get_logger(QACTL_LOGGER) def __init__(self, instance_list): self.instances = [] @@ -34,6 +37,7 @@ def __init__(self, instance_list): self.docker_network = None self.network_address = None + QAInfraestructure.LOGGER.debug('Processing deployment configuration...') for host in instance_list: for provider in instance_list[host]['provider']: data = instance_list[host]['provider'][provider] @@ -41,6 +45,7 @@ def __init__(self, instance_list): continue if provider == 'vagrant': + QAInfraestructure.LOGGER.debug(f"Setting {data['vm_name']} vagrant instance for deployment...") quiet_out = True if 'quiet_out' not in data else data['quiet_out'] vagrant_instance = VagrantWrapper(data['vagrantfile_path'], data['vagrant_box'], data['label'], data['vm_name'], data['vm_cpu'], data['vm_memory'], @@ -48,6 +53,7 @@ def __init__(self, instance_list): self.instances.append(vagrant_instance) elif provider == 'docker': + QAInfraestructure.LOGGER.debug(f"Setting {data['name']} docker instance for deployment...") if not self.docker_client: self.docker_client = docker.from_env() @@ -65,14 +71,17 @@ def __init__(self, instance_list): self.network_address = network if network != self.network_address: - raise ValueError('Two different networks where found for docker containers when only one ' - f"network is allowed: {network} != {self.network_address}") + exception_message = 'Two different networks where found for docker containers when only ' \ + f"one network is allowed: {network} != {self.network_address}" + raise QAValueError(exception_message, QAInfraestructure.LOGGER.critical) if not self.docker_network: # Try to get the DOCKER_NETWORK_NAME network, if it fails, try to create it. try: self.docker_network = self.docker_client.networks.get(self.DOCKER_NETWORK_NAME) except docker.errors.NotFound: + QAInfraestructure.LOGGER.debug(f"Docker network {self.network_address} not found." + 'Creating it...') ipam_pool = docker.types.IPAMPool(subnet=str(self.network_address), gateway=str(self.network_address[-2])) @@ -84,7 +93,6 @@ def __init__(self, instance_list): docker_instance = DockerWrapper(self.docker_client, data['dockerfile_path'], data['name'], _remove, _ports, _detach, _stdout, _stderr, ip=_ip, network_name=self.DOCKER_NETWORK_NAME) - self.instances.append(docker_instance) def __threads_runner(self, threads): @@ -101,24 +109,30 @@ def __threads_runner(self, threads): def run(self): """Execute the run method on every configured instance.""" + QAInfraestructure.LOGGER.info(f"Running {len(self.instances)} instances deployment...") self.__threads_runner([ThreadExecutor(instance.run) for instance in self.instances]) def halt(self): """Execute the 'halt' method on every configured instance.""" + QAInfraestructure.LOGGER.info(f"Stopping {len(self.instances)} instances...") self.__threads_runner([ThreadExecutor(instance.halt) for instance in self.instances]) def restart(self): """Execute the 'restart' method on every configured instance.""" + QAInfraestructure.LOGGER.info(f"Restarting {len(self.instances)} instances...") self.__threads_runner([ThreadExecutor(instance.restart) for instance in self.instances]) def destroy(self): """Execute the 'destroy' method on every configured instance.""" + QAInfraestructure.LOGGER.info(f"Destroying {len(self.instances)} instances...") self.__threads_runner([ThreadExecutor(instance.destroy) for instance in self.instances]) if self.docker_network: + QAInfraestructure.LOGGER.debug('Removing docker network...') try: self.docker_network.remove() except docker.errors.NotFound: + QAInfraestructure.LOGGER.error('Could not remove docker network') pass def status(self): @@ -128,6 +142,7 @@ def status(self): (dict): Contains the status for each configured instance. """ status = {} + QAInfraestructure.LOGGER.debug('Getting instances status...') for instance in self.instances: status[instance.get_name()] = instance.status() @@ -140,6 +155,7 @@ def get_instances_info(self): (dict): Dictionary with the information for each configured instance. """ info = {} + QAInfraestructure.LOGGER.debug('Getting instances info...') for instance in self.instances: info[instance.get_name()] = instance.get_instance_info() diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/VagrantWrapper.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/VagrantWrapper.py index d920fd17f8..490f5918d5 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/VagrantWrapper.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/VagrantWrapper.py @@ -4,9 +4,11 @@ import os import vagrant from shutil import rmtree + from wazuh_testing.qa_ctl.deployment.Instance import Instance import wazuh_testing.qa_ctl.deployment.Vagrantfile as vfile - +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class VagrantWrapper(Instance): """Class to handle Vagrant operations. The class will use the Vagrantfile class to create a vagrantfile in @@ -26,13 +28,14 @@ class VagrantWrapper(Instance): Attributes: vagrantfile (Vagrantfile): Vagrantfile object containing the vagrantfile information. vagrant (Vagrant): Vagrant object to handle vagrant operations - + vm_name (String): Name that will be assigned to the VM """ + LOGGER = Logging.get_logger(QACTL_LOGGER) def __init__(self, vagrant_root_folder, vm_box, vm_label, vm_name, vm_cpus, vm_memory, vm_system, vm_ip, quiet_out=True): - self.box_folder = os.path.join(vagrant_root_folder, vm_name) + self.vm_name = vm_name os.makedirs(self.box_folder, exist_ok=True) self.vagrantfile = vfile.Vagrantfile(self.box_folder, vm_box, vm_label, vm_name, vm_cpus, vm_memory, @@ -42,33 +45,37 @@ def __init__(self, vagrant_root_folder, vm_box, vm_label, vm_name, vm_cpus, vm_m self.vagrantfile.write_vagrantfile() def run(self): - """Writes the vagrantfile and starts the VM specified in the vagrantfile.""" + """Write the vagrantfile and starts the VM specified in the vagrantfile.""" + VagrantWrapper.LOGGER.debug(f"Running {self.vm_name} vagrant up...") self.vagrant.up() def halt(self): - """Stops the VM specified in the vagrantfile.""" + """Stop the VM specified in the vagrantfile.""" + VagrantWrapper.LOGGER.debug(f"Running {self.vm_name} vagrant halt...") self.vagrant.halt() def restart(self): - """Restarts the VM specified in the vagrantfile.""" + """Restart the VM specified in the vagrantfile.""" + VagrantWrapper.LOGGER.debug(f"Running {self.vm_name} vagrant restrt...") self.vagrant.restart() def destroy(self): - """Destroys the VM specified in the vagrantfile and remove the vagrantfile.""" + """Destroy the VM specified in the vagrantfile and remove the vagrantfile.""" + VagrantWrapper.LOGGER.debug(f"Running {self.vm_name} vagrant destroy...") self.vagrant.destroy() self.vagrantfile.remove_vagrantfile() rmtree(self.box_folder) def suspend(self): - """Suspends the VM specified in the vagrantfile.""" + """Suspend the VM specified in the vagrantfile.""" self.vagrant.suspend() def resume(self): - """Resumes the VM specified in the vagrantfile.""" + """Resume the VM specified in the vagrantfile.""" self.vagrant.resume() def get_vagrant_version(self): - """Gets the vagrant version of the host. + """Get the vagrant version of the host. Returns: (str): Vagrant version. @@ -76,7 +83,7 @@ def get_vagrant_version(self): return self.vagrant.version() def status(self): - """Gets the status of the VM specified in the vagrantfile. + """Get the status of the VM specified in the vagrantfile. The vagrant module returns a list of namedtuples like the following `[Status(name='ubuntu', state='not_created', provider='virtualbox')]` but we are only interested in the `state` field. @@ -87,7 +94,7 @@ def status(self): return self.vagrant.status()[0].state def get_ssh_config(self): - """Gets the config of the VM specified in the vagrantfile. + """Get the config of the VM specified in the vagrantfile. Returns: (dict): Dictionary with the configuration of the VM. @@ -95,7 +102,7 @@ def get_ssh_config(self): return self.vagrant.conf() def get_instance_info(self): - """Gets the instance info. + """Get the instance info. Returns: (dict): Dictionary with the parameters of the VM. @@ -103,7 +110,7 @@ def get_instance_info(self): return str(self.vagrantfile) def get_name(self): - """Gets the name of the VM. + """Get the name of the VM. Returns: (str): Name of the VM. diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/Vagrantfile.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/Vagrantfile.py index 07ef204ab1..f41fbf4379 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/Vagrantfile.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/Vagrantfile.py @@ -4,7 +4,9 @@ from pathlib import Path import os import json -import logging + +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class Vagrantfile(): @@ -37,6 +39,7 @@ class Vagrantfile(): It MUST start with '/' to assign properly the group in VirtualBox. private_ip (str): IP of the VM. """ + LOGGER = Logging.get_logger(QACTL_LOGGER) TEMPLATE_FILE = os.path.join( Path(__file__).parent, 'vagrantfile_template.txt') REPLACE_PATTERN = 'json_box = {}\n' @@ -61,7 +64,7 @@ def __get_box_url(self): try: return box_mapping[self.box_image] except KeyError: - logging.warning('Using a box not tested') + Vagrantfile.LOGGER.warning('Using a non default box...') return None def __str__(self): @@ -84,6 +87,7 @@ def read_vagrantfile_template(self): List: List with the content of the template vagrant template.""" with open(self.TEMPLATE_FILE, 'r') as template_fd: return template_fd.readlines() + Vagrantfile.LOGGER.debug(f"Read vagrantfile {self.TEMPLATE_FILE} template") def write_vagrantfile(self): """Replace the self.REPLACE_PATTERN line with a string with the parameters in JSON format and write the new @@ -95,8 +99,11 @@ def write_vagrantfile(self): with open(self.file_path, 'w') as vagrantfile_fd: vagrantfile_fd.writelines(read_lines) + Vagrantfile.LOGGER.debug(f"Vagranfile written in {self.file_path}") + def remove_vagrantfile(self): """Removes the file self.file_path if it exists.""" if os.path.exists(self.file_path): os.remove(self.file_path) + Vagrantfile.LOGGER.debug(f"{self.file_path} Vagranfile was removed") diff --git a/deps/wazuh_testing/wazuh_testing/tools/exceptions.py b/deps/wazuh_testing/wazuh_testing/tools/exceptions.py new file mode 100644 index 0000000000..8ba6b76b39 --- /dev/null +++ b/deps/wazuh_testing/wazuh_testing/tools/exceptions.py @@ -0,0 +1,6 @@ + +class QAValueError(Exception): + def __init__(self, message, logger=None): + self.message = message + logger(message) + super().__init__(self.message) diff --git a/deps/wazuh_testing/wazuh_testing/tools/logging.py b/deps/wazuh_testing/wazuh_testing/tools/logging.py index 09c1b5d28c..5b195a4d36 100644 --- a/deps/wazuh_testing/wazuh_testing/tools/logging.py +++ b/deps/wazuh_testing/wazuh_testing/tools/logging.py @@ -82,9 +82,6 @@ def get_logger(logger_name): ValueError: If logger not exists """ - if not Logging.__logger_exists(logger_name): - raise ValueError(f"Logger {logger_name} does not exist") - return logging.getLogger(logger_name) def debug(self, message): From 6ae265bc2041ba9c6930c7563b8952fedd0405f0 Mon Sep 17 00:00:00 2001 From: jmv74211 Date: Wed, 25 Aug 2021 16:08:03 +0200 Subject: [PATCH 3/7] add: Add logging to QACTL provisioning modules #1713 --- deps/wazuh_testing/wazuh_testing/qa_ctl/__init__.py | 1 + .../qa_ctl/provisioning/QAProvisioning.py | 11 ++++++++++- .../qa_ctl/provisioning/ansible/AnsiblePlaybook.py | 6 +++++- .../qa_ctl/provisioning/ansible/AnsibleRunner.py | 6 ++++++ .../qa_ctl/provisioning/qa_framework/QAFramework.py | 8 +++++++- .../provisioning/wazuh_deployment/AgentDeployment.py | 1 + .../provisioning/wazuh_deployment/LocalPackage.py | 11 +++++++++-- .../provisioning/wazuh_deployment/WazuhDeployment.py | 7 +++++++ .../provisioning/wazuh_deployment/WazuhPackage.py | 1 - .../provisioning/wazuh_deployment/WazuhS3Package.py | 5 ++++- .../provisioning/wazuh_deployment/WazuhSources.py | 8 ++++++-- 11 files changed, 56 insertions(+), 9 deletions(-) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/__init__.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/__init__.py index e69de29bb2..43495ae54c 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/__init__.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/__init__.py @@ -0,0 +1 @@ +QACTL_LOGGER = 'qactl' diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/QAProvisioning.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/QAProvisioning.py index e8f22b681d..d7868066c0 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/QAProvisioning.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/QAProvisioning.py @@ -1,4 +1,5 @@ from time import sleep + from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleInstance import AnsibleInstance from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleInventory import AnsibleInventory from wazuh_testing.qa_ctl.provisioning.wazuh_deployment.LocalPackage import LocalPackage @@ -9,6 +10,8 @@ from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleTask import AnsibleTask from wazuh_testing.qa_ctl.provisioning.qa_framework.QAFramework import QAFramework from wazuh_testing.tools.thread_executor import ThreadExecutor +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class QAProvisioning(): @@ -30,6 +33,8 @@ class QAProvisioning(): inventory_file_path (string): Path of the inventory file generated. wazuh_installation_paths (dict): Dict indicating the Wazuh installation paths for every host. """ + LOGGER = Logging.get_logger(QACTL_LOGGER) + def __init__(self, provision_info): self.provision_info = provision_info self.instances_list = [] @@ -62,6 +67,8 @@ def __read_ansible_instance(self, host_info): def __process_inventory_data(self): """Process config file info to generate the ansible inventory file.""" + QAProvisioning.LOGGER.debug('Processing inventory data from provisioning hosts info...') + for root_key, root_value in self.provision_info.items(): if root_key == "hosts": for _, host_value in root_value.items(): @@ -83,6 +90,7 @@ def __process_config_data(self, host_provision_info): Args: host_provision_info (dict): Dicionary with host provisioning info """ + QAProvisioning.LOGGER.debug('Processing provisioning data from hosts..') current_host = host_provision_info['host_info']['host'] if 'wazuh_deployment' in host_provision_info: @@ -151,6 +159,7 @@ def __check_hosts_connection(self, hosts='all'): Args: hosts (str): Hosts to check. """ + QAProvisioning.LOGGER.info('Checking hosts SSH connection...') wait_for_connection = AnsibleTask({'name': 'Waiting for SSH hosts connection are reachable', 'wait_for_connection': {'delay': 5, 'timeout': 60}}) @@ -161,9 +170,9 @@ def __check_hosts_connection(self, hosts='all'): def run(self): """Provision all hosts in a parallel way""" self.__check_hosts_connection() - provision_threads = [ThreadExecutor(self.__process_config_data, parameters={'host_provision_info': host_value}) for _, host_value in self.provision_info['hosts'].items()] + QAProvisioning.LOGGER.info(f"Provisioning {len(provision_threads)} instances...") for runner_thread in provision_threads: runner_thread.start() diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsiblePlaybook.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsiblePlaybook.py index 4666fd04e9..349cfbf007 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsiblePlaybook.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsiblePlaybook.py @@ -4,7 +4,8 @@ from tempfile import gettempdir from wazuh_testing.tools.time import get_current_timestamp - +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class AnsiblePlaybook(): """Class to create playbook file with a custom tasks list @@ -29,6 +30,8 @@ class AnsiblePlaybook(): playbook_vars (dict): Variables for playbook generate_file (bool): If True, write playbook in file. """ + LOGGER = Logging.get_logger(QACTL_LOGGER) + def __init__(self, name='generic_playbook', tasks_list=None, playbook_file_path=None, hosts='all', gather_facts=False, ignore_errors=False, become=False, playbook_vars=None, generate_file=True): self.name = name @@ -70,4 +73,5 @@ def write_playbook_to_file(self): def delete_playbook_file(self): if os.path.exists(self.playbook_file_path): + AnsiblePlaybook.LOGGER.debug(f"Removing {self.playbook_file_path} playbook") os.remove(self.playbook_file_path) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsibleRunner.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsibleRunner.py index a2a779ae0c..84f9ff7051 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsibleRunner.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsibleRunner.py @@ -4,6 +4,8 @@ from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleOutput import AnsibleOutput from wazuh_testing.qa_ctl.provisioning.ansible.AnsiblePlaybook import AnsiblePlaybook +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class AnsibleRunner: @@ -19,6 +21,8 @@ class AnsibleRunner: ansible_playbook_path (string): Path where is located the playbook file. private_data_dir (string): Path where the artifacts files (result files) will be stored. """ + LOGGER = Logging.get_logger(QACTL_LOGGER) + def __init__(self, ansible_inventory_path, ansible_playbook_path, private_data_dir=gettempdir()): self.ansible_inventory_path = ansible_inventory_path self.ansible_playbook_path = ansible_playbook_path @@ -30,6 +34,8 @@ def run(self): Returns: AnsibleOutput: Result of the ansible playbook run. """ + AnsibleRunner.LOGGER.debug(f"Running {self.ansible_playbook_path} ansible-playbook with " + f"{self.ansible_inventory_path} inventory") runner = ansible_runner.run(private_data_dir=self.private_data_dir, playbook=self.ansible_playbook_path, inventory=self.ansible_inventory_path) ansible_output = AnsibleOutput(runner) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/qa_framework/QAFramework.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/qa_framework/QAFramework.py index eb720e220a..ed49edfc85 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/qa_framework/QAFramework.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/qa_framework/QAFramework.py @@ -2,7 +2,8 @@ from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleTask import AnsibleTask from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleRunner import AnsibleRunner - +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class QAFramework(): """Encapsulates all the functionality regarding the preparation and installation of qa-framework @@ -17,6 +18,7 @@ class QAFramework(): qa_repository (str): Url to the QA repository. qa_branch (str): QA branch of the qa repository. """ + LOGGER = Logging.get_logger(QACTL_LOGGER) def __init__(self, workdir=gettempdir(), qa_repository='https://github.com/wazuh/wazuh-qa.git', qa_branch='master'): self.qa_repository = qa_repository @@ -35,6 +37,8 @@ def install_dependencies(self, inventory_file_path, hosts='all'): 'args': {'chdir': self.workdir}}) ansible_tasks = [dependencies_task] playbook_parameters = {'hosts': hosts, 'tasks_list': ansible_tasks} + QAFramework.LOGGER.debug(f"Installing python dependencies in {hosts} hosts.") + AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters) def install_framework(self, inventory_file_path, hosts='all'): @@ -48,6 +52,7 @@ def install_framework(self, inventory_file_path, hosts='all'): 'args': {'chdir': f"{self.workdir}/deps/wazuh_testing"}}) ansible_tasks = [install_framework_task] playbook_parameters = {'hosts': hosts, 'tasks_list': ansible_tasks, 'become': True} + QAFramework.LOGGER.debug(f"Installing wazuh-qa framework in {hosts} hosts.") AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters) @@ -65,5 +70,6 @@ def download_qa_repository(self, inventory_file_path, hosts='all'): 'version': self.qa_branch}}) ansible_tasks = [create_path_task, download_qa_repo_task] playbook_parameters = {'hosts': hosts, 'tasks_list': ansible_tasks} + QAFramework.LOGGER.debug(f"Downloading qa-repository in {hosts} hosts") AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/AgentDeployment.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/AgentDeployment.py index 0f118c8a5d..8aa62bb7cf 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/AgentDeployment.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/AgentDeployment.py @@ -26,6 +26,7 @@ class AgentDeployment(WazuhDeployment): server_ip (string): Manager IP to connect. """ + def install(self): """Child method to install Wazuh in agent diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/LocalPackage.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/LocalPackage.py index 60ee6b6ebd..eb74cda753 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/LocalPackage.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/LocalPackage.py @@ -1,10 +1,15 @@ +import os + +from pathlib import Path + from wazuh_testing.qa_ctl.provisioning.wazuh_deployment.WazuhPackage import WazuhPackage from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleTask import AnsibleTask -from pathlib import Path -import os +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class LocalPackage(WazuhPackage): + LOGGER = Logging.get_logger(QACTL_LOGGER) def __init__(self, wazuh_target, installation_files_path, local_package_path, version=None, system=None): self.local_package_path = local_package_path @@ -17,6 +22,8 @@ def download_installation_files(self, inventory_file_path, hosts='all'): {self.installation_files_path}", 'copy': {'src': self.local_package_path, 'dest': self.installation_files_path}}) + LocalPackage.LOGGER.debug(f"Copying local package {self.local_package_path} to {self.installation_files_path}" + f" in {hosts} hosts") super().download_installation_files(inventory_file_path, [copy_ansible_task], hosts) return os.path.join(self.installation_files_path, self.package_name) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhDeployment.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhDeployment.py index 8548aea970..dcaff1181f 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhDeployment.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhDeployment.py @@ -5,6 +5,8 @@ from tempfile import gettempdir from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleTask import AnsibleTask from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleRunner import AnsibleRunner +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class WazuhDeployment(ABC): @@ -28,6 +30,8 @@ class WazuhDeployment(ABC): hosts (string): Group of hosts to be deployed. server_ip (string): Manager IP to let agent get autoenrollment. """ + LOGGER = Logging.get_logger(QACTL_LOGGER) + def __init__(self, installation_files_path, inventory_file_path, configuration=None, install_mode='package', install_dir_path='/var/ossec', hosts='all', server_ip=None): @@ -46,6 +50,7 @@ def install(self, install_type): Returns: AnsibleOutput: Result of the ansible playbook run. """ + WazuhDeployment.LOGGER.debug(f"Installing wazuh {install_type} via {self.install_mode} in {self.hosts} hosts..") tasks_list = [] parent_path = Path(__file__).parent if self.install_mode == 'sources': @@ -111,6 +116,7 @@ def __control_service(self, command, install_type): Returns: AnsibleOutput: Result of the ansible playbook run. """ + WazuhDeployment.LOGGER.debug(f"{command}ing wazuh service in {self.hosts} hosts") tasks_list = [] service_name = install_type if install_type == 'agent' else 'manager' service_command = f'{command}ed' if command != 'stop' else 'stopped' @@ -173,6 +179,7 @@ def health_check(self): Returns: AnsibleOutput: Result of the ansible playbook run. """ + WazuhDeployment.LOGGER.debug(f"Doing wazuh deployment healthcheck in {self.hosts} hosts") tasks_list = [] tasks_list.append(AnsibleTask({'name': 'Read ossec.log searching errors', 'lineinfile': {'path': f'{self.install_dir_path}/logs/ossec.log', diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhPackage.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhPackage.py index d7a9a378d4..a874a8d7b4 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhPackage.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhPackage.py @@ -4,7 +4,6 @@ class WazuhPackage(WazuhInstallation, ABC): - def __init__(self, version, system, wazuh_target, installation_files_path): self.version = version self.system = system diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhS3Package.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhS3Package.py index c67f00bea8..c76376da96 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhS3Package.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhS3Package.py @@ -1,8 +1,10 @@ from wazuh_testing.qa_ctl.provisioning.wazuh_deployment.WazuhPackage import WazuhPackage from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleTask import AnsibleTask - +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class WazuhS3Package(WazuhPackage): + LOGGER = Logging.get_logger(QACTL_LOGGER) def __init__(self, wazuh_target, installation_files_path, version, system, revision, repository, architecture): self.revision = revision @@ -23,4 +25,5 @@ def download_installation_files(self, s3_package_url, inventory_file_path, hosts 'dest': self.installation_files_path}, 'register': 'download_state', 'retries': 6, 'delay': 10, 'until': 'download_state is success'}) + WazuhS3Package.LOGGER.debug(f"Downloading Wazuh S3 package from in {hosts} hosts") super().download_installation_files(inventory_file_path, [download_s3_package], hosts) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhSources.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhSources.py index 358745e3ee..90ba4810e2 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhSources.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhSources.py @@ -1,9 +1,12 @@ -from wazuh_testing.qa_ctl.provisioning.wazuh_deployment.WazuhInstallation import WazuhInstallation -from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleTask import AnsibleTask import os +from wazuh_testing.qa_ctl.provisioning.wazuh_deployment.WazuhInstallation import WazuhInstallation +from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleTask import AnsibleTask +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class WazuhSources(WazuhInstallation): + LOGGER = Logging.get_logger(QACTL_LOGGER) def __init__(self, wazuh_target, installation_files_path, wazuh_branch='master', wazuh_repository_url='https://github.com/wazuh/wazuh.git'): @@ -17,6 +20,7 @@ def download_installation_files(self, inventory_file_path, hosts='all'): 'shell': f"cd {self.installation_files_path} && " + 'curl -Ls https://github.com/wazuh/wazuh/archive/' + f"{self.wazuh_branch}.tar.gz | tar zx && mv wazuh-*/* ."}) + WazuhSources.LOGGER.debug(f"Downloading Wazuh sources from {self.wazuh_branch} branch in {hosts} hosts") super().download_installation_files(inventory_file_path, [download_wazuh_sources_task], hosts) return self.installation_files_path From 2e7d5493a86fff384bed6cc1eca608eb40f2a3fe Mon Sep 17 00:00:00 2001 From: jmv74211 Date: Thu, 26 Aug 2021 09:13:15 +0200 Subject: [PATCH 4/7] add: Add logging to QACTL run test modules #1713 --- .../wazuh_testing/qa_ctl/run_tests/Pytest.py | 10 +++++++--- .../wazuh_testing/qa_ctl/run_tests/QARunTests.py | 12 ++++++++++++ .../wazuh_testing/qa_ctl/run_tests/TestLauncher.py | 6 +++++- deps/wazuh_testing/wazuh_testing/scripts/qa_ctl.py | 5 +++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/Pytest.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/Pytest.py index 5e00e59839..cf2ae83514 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/Pytest.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/Pytest.py @@ -8,6 +8,8 @@ from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleTask import AnsibleTask from wazuh_testing.qa_ctl.run_tests.Test import Test from wazuh_testing.tools.time import get_current_timestamp +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class Pytest(Test): @@ -48,8 +50,8 @@ class Pytest(Test): markers(list(str), None): Set of markers to be added to the test execution command hosts(list(), ['all']): List of hosts aliases where the tests will be runned """ - RUN_PYTEST = 'python3 -m pytest ' + LOGGER = Logging.get_logger(QACTL_LOGGER) def __init__(self, tests_result_path, tests_path, tests_run_dir, tiers=[], stop_after_first_failure=False, keyword_expression=None, traceback='auto', dry_run=False, custom_args=[], verbose_level=False, @@ -78,7 +80,6 @@ def run(self, ansible_inventory_path): Args: ansible_inventory_path (str): Path to ansible inventory file """ - assets_folder = 'assets/' reports_folder = 'reports/' assets_zip = "assets.zip" @@ -175,8 +176,11 @@ def run(self, ansible_inventory_path): playbook_parameters = {'become': True, 'tasks_list': ansible_tasks, 'playbook_file_path': playbook_file_path, "hosts": self.hosts} - + Pytest.LOGGER.debug(f"Running {pytest_command} on {self.hosts} hosts...") + Pytest.LOGGER.info(f"Running {self.tests_path} test on {self.hosts} hosts...") AnsibleRunner.run_ephemeral_tasks(ansible_inventory_path, playbook_parameters, raise_on_error=False) + Pytest.LOGGER.debug(f"Saving {self.tests_path} test resulsts of {self.hosts} hosts in {self.tests_result_path}") + self.result = TestResult(html_report_file_path=os.path.join(self.tests_result_path, html_report_file_name), plain_report_file_path=os.path.join(self.tests_result_path, plain_report_file_name)) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/QARunTests.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/QARunTests.py index 2a0c80d939..de2815821e 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/QARunTests.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/QARunTests.py @@ -3,6 +3,8 @@ from wazuh_testing.qa_ctl.run_tests.TestLauncher import TestLauncher from wazuh_testing.qa_ctl.run_tests.Pytest import Pytest from wazuh_testing.tools.thread_executor import ThreadExecutor +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class RunQATests(): @@ -15,6 +17,7 @@ class RunQATests(): inventory_file_path (string): Path of the inventory file generated. test_launchers (list(TestLauncher)): Test launchers objects (one for each host). """ + LOGGER = Logging.get_logger(QACTL_LOGGER) def __init__(self, tests_parameters): self.inventory_file_path = None @@ -49,6 +52,7 @@ def __process_inventory_data(self, instances_info): Args: instances_info (dict): Dictionary with hosts configuration. """ + RunQATests.LOGGER.debug('Processing inventory data from testing hosts info...') instances_list = [] for _, host_value in instances_info.items(): @@ -68,6 +72,8 @@ def __process_test_data(self, instances_info): Args: instances_info (dict): Dictionary with hosts configuration. """ + RunQATests.LOGGER.debug('Processing testing data from hosts..') + for _, host_value in instances_info.items(): test_launcher = TestLauncher([], self.inventory_file_path) for module_key, module_value in host_value.items(): @@ -120,8 +126,14 @@ def run(self): """Run testing threads. One thread per TestLauncher object""" runner_threads = [ThreadExecutor(test_launcher.run) for test_launcher in self.test_launchers] + RunQATests.LOGGER.info(f"Launching {len(runner_threads)} tests...") + for runner_thread in runner_threads: runner_thread.start() + RunQATests.LOGGER.info(f'Waiting until tests finish...') + for runner_thread in runner_threads: runner_thread.join() + + RunQATests.LOGGER.info(f'Tests have been finished...') \ No newline at end of file diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/TestLauncher.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/TestLauncher.py index f83f2a9be3..1f73d91426 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/TestLauncher.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/TestLauncher.py @@ -5,6 +5,8 @@ from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleRunner import AnsibleRunner from wazuh_testing.qa_ctl.provisioning.ansible.AnsibleTask import AnsibleTask from wazuh_testing.tools.time import get_current_timestamp +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging class TestLauncher: @@ -21,7 +23,7 @@ class TestLauncher: qa_framework_path (str, None): remote directory path where the qa repository will be download to """ - + LOGGER = Logging.get_logger(QACTL_LOGGER) DEBUG_OPTIONS = ["syscheck.debug=2", "agent.debug=2", "monitord.rotate_log=0", "analysisd.debug=2", "wazuh_modules.debug=2", "wazuh_database.interval=1", "wazuh_db.commit_time=2", "wazuh_db.commit_time_max=3", "remoted.debug=2"] @@ -53,6 +55,8 @@ def __set_local_internal_options(self, hosts): playbook_parameters = {'become': True, 'tasks_list': ansible_tasks, 'playbook_file_path': playbook_file_path, 'hosts': hosts} + TestLauncher.LOGGER.debug(f"Setting local_internal_options configuration in {hosts} hosts") + AnsibleRunner.run_ephemeral_tasks(self.ansible_inventory_path, playbook_parameters, raise_on_error=False) def add(self, test): diff --git a/deps/wazuh_testing/wazuh_testing/scripts/qa_ctl.py b/deps/wazuh_testing/wazuh_testing/scripts/qa_ctl.py index 63c265d192..ac815bf19a 100644 --- a/deps/wazuh_testing/wazuh_testing/scripts/qa_ctl.py +++ b/deps/wazuh_testing/wazuh_testing/scripts/qa_ctl.py @@ -11,11 +11,14 @@ from wazuh_testing.qa_ctl.deployment.QAInfraestructure import QAInfraestructure from wazuh_testing.qa_ctl.provisioning.QAProvisioning import QAProvisioning from wazuh_testing.qa_ctl.run_tests.QARunTests import RunQATests +from wazuh_testing.qa_ctl import QACTL_LOGGER +from wazuh_testing.tools.logging import Logging DEPLOY_KEY = 'deployment' PROVISION_KEY = 'provision' TEST_KEY = 'tests' +LOGGER = Logging(QACTL_LOGGER, level='INFO', log_file='/home/jmv74211/test.log') _data_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'data') @@ -47,7 +50,9 @@ def main(): # Validate configuration schema with open(arguments.config) as config_file_fd: yaml_config = yaml.safe_load(config_file_fd) + LOGGER.debug('User configuration template has been read') validate_conf(yaml_config) + LOGGER.debug('User configuration template has been validated') # Run QACTL modules try: From 572f0883c068d04642a26a893946d9eda551e2b4 Mon Sep 17 00:00:00 2001 From: jmv74211 Date: Thu, 26 Aug 2021 13:41:33 +0200 Subject: [PATCH 5/7] add: Add config module to QACTL #1713 --- .../qa_ctl/configuration/__init__.py | 0 .../configuration/qa_ctl_configuration.py | 32 ++++++++++ .../qa_ctl/deployment/QAInfraestructure.py | 8 ++- .../qa_ctl/provisioning/QAProvisioning.py | 27 +++++---- .../provisioning/ansible/AnsibleRunner.py | 14 +++-- .../provisioning/qa_framework/QAFramework.py | 15 +++-- .../wazuh_deployment/AgentDeployment.py | 8 ++- .../wazuh_deployment/LocalPackage.py | 5 +- .../wazuh_deployment/ManagerDeployment.py | 5 +- .../wazuh_deployment/WazuhDeployment.py | 17 ++++-- .../wazuh_deployment/WazuhInstallation.py | 6 +- .../wazuh_deployment/WazuhPackage.py | 5 +- .../wazuh_deployment/WazuhS3Package.py | 5 +- .../wazuh_testing/qa_ctl/run_tests/Pytest.py | 13 +++-- .../qa_ctl/run_tests/QARunTests.py | 8 ++- .../qa_ctl/run_tests/TestLauncher.py | 8 ++- .../wazuh_testing/scripts/qa_ctl.py | 58 +++++++++++++------ .../wazuh_testing/tools/logging.py | 10 +++- 18 files changed, 179 insertions(+), 65 deletions(-) create mode 100644 deps/wazuh_testing/wazuh_testing/qa_ctl/configuration/__init__.py create mode 100644 deps/wazuh_testing/wazuh_testing/qa_ctl/configuration/qa_ctl_configuration.py diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/configuration/__init__.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/configuration/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/configuration/qa_ctl_configuration.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/configuration/qa_ctl_configuration.py new file mode 100644 index 0000000000..aeb754b6ef --- /dev/null +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/configuration/qa_ctl_configuration.py @@ -0,0 +1,32 @@ + +class QACTLConfiguration: + + def __init__(self, configuration_data): + self.configuration_data = configuration_data + self.vagrant_output = False + self.ansible_output = False + self.logging_enable = True + self.logging_level = 'INFO' + self.logging_file = None + + self.__read_configuration_data() + + def __read_configuration_data(self): + if 'config' in self.configuration_data: + if 'vagrant_output' in self.configuration_data['config']: + self.vagrant_output = self.configuration_data['config']['vagrant_output'] + if 'ansible_output' in self.configuration_data['config']: + self.ansible_output = self.configuration_data['config']['ansible_output'] + if 'logging' in self.configuration_data['config']: + if 'enable' in self.configuration_data['config']['logging']: + self.logging_enable = self.configuration_data['config']['logging']['enable'] + if 'level' in self.configuration_data['config']['logging']: + self.logging_level = self.configuration_data['config']['logging']['level'] + if 'file' in self.configuration_data['config']['logging']: + self.logging_file = self.configuration_data['config']['logging']['file'] + + + def __str__(self): + return f"vagrant_output: {self.vagrant_output}\nansible_output: {self.ansible_output}\n" \ + f"logging_enable: {self.logging_enable}\nloggin_level: {self.logging_level}\n"\ + f"logging_file: {self.logging_file}\n" diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/QAInfraestructure.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/QAInfraestructure.py index 532cc52123..68c83768b8 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/QAInfraestructure.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/QAInfraestructure.py @@ -11,18 +11,21 @@ from wazuh_testing.tools.logging import Logging from wazuh_testing.tools.exceptions import QAValueError + class QAInfraestructure: """Class to handle multiples instances objects. Args: instance_list (dict): Dictionary with the information of the instances. Must follow the format of the yaml template. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. Class Attributes: DOCKER_NETWORK_NAME (str): Name of the docker network where the containers will be connected. LOGGER (Logging): Logger object. Instance Attributes: + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. instances (list): List with the instances to handle. docker_client (Docker Client): Client to communicate with the docker daemon. docker_network (Docker Network): Network object to handle container's static IP address. @@ -31,7 +34,8 @@ class QAInfraestructure: DOCKER_NETWORK_NAME = 'wazuh_net' LOGGER = Logging.get_logger(QACTL_LOGGER) - def __init__(self, instance_list): + def __init__(self, instance_list, qa_ctl_configuration): + self.qa_ctl_configuration = qa_ctl_configuration self.instances = [] self.docker_client = None self.docker_network = None @@ -46,7 +50,7 @@ def __init__(self, instance_list): if provider == 'vagrant': QAInfraestructure.LOGGER.debug(f"Setting {data['vm_name']} vagrant instance for deployment...") - quiet_out = True if 'quiet_out' not in data else data['quiet_out'] + quiet_out = True if not self.qa_ctl_configuration.vagrant_output else False vagrant_instance = VagrantWrapper(data['vagrantfile_path'], data['vagrant_box'], data['label'], data['vm_name'], data['vm_cpu'], data['vm_memory'], data['vm_system'], data['vm_ip'], quiet_out) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/QAProvisioning.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/QAProvisioning.py index d7868066c0..7731f00078 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/QAProvisioning.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/QAProvisioning.py @@ -17,31 +17,29 @@ class QAProvisioning(): """Class to control different options and instances to provisioning with Wazuh and QA Framework. - Attributes: + Args: provision_info (dict): Dict with all the info needed coming from config file. - instances_list (list): List with every instance (each host) needed to build the ansible inventory. - group_dict (dict): Dict with groups and every host belonging to them. - host_list (list): List with every host given in config file. - inventory_file_path (string): Path of the inventory file generated. - wazuh_installation_paths (dict): Dict indicating the Wazuh installation paths for every host. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. - Args: + Attributes: provision_info (dict): Dict with all the info needed coming from config file. instances_list (list): List with every instance (each host) needed to build the ansible inventory. group_dict (dict): Dict with groups and every host belonging to them. host_list (list): List with every host given in config file. inventory_file_path (string): Path of the inventory file generated. wazuh_installation_paths (dict): Dict indicating the Wazuh installation paths for every host. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. """ LOGGER = Logging.get_logger(QACTL_LOGGER) - def __init__(self, provision_info): + def __init__(self, provision_info, qa_ctl_configuration): self.provision_info = provision_info self.instances_list = [] self.group_dict = {} self.host_list = [] self.inventory_file_path = None self.wazuh_installation_paths = {} + self.qa_ctl_configuration = qa_ctl_configuration self.__process_inventory_data() @@ -115,6 +113,8 @@ def __process_config_data(self, host_provision_info): if wazuh_install_path: installation_files_parameters['wazuh_install_path'] = wazuh_install_path + installation_files_parameters['qa_ctl_configuration'] = self.qa_ctl_configuration + if install_type == "sources": installation_files_parameters['wazuh_branch'] = wazuh_branch installation_instance = WazuhSources(**installation_files_parameters) @@ -129,11 +129,13 @@ def __process_config_data(self, host_provision_info): deployment_instance = AgentDeployment(remote_files_path, inventory_file_path=self.inventory_file_path, install_mode=install_type, hosts=current_host, - server_ip=manager_ip) + server_ip=manager_ip, + qa_ctl_configuration=self.qa_ctl_configuration) if install_target == "manager": deployment_instance = ManagerDeployment(remote_files_path, inventory_file_path=self.inventory_file_path, - install_mode=install_type, hosts=current_host) + install_mode=install_type, hosts=current_host, + qa_ctl_configuration=self.qa_ctl_configuration) deployment_instance.install() if health_check: @@ -148,7 +150,7 @@ def __process_config_data(self, host_provision_info): wazuh_qa_branch = None if 'wazuh_qa_branch' not in qa_framework_info \ else qa_framework_info['wazuh_qa_branch'] - qa_instance = QAFramework(qa_branch=wazuh_qa_branch) + qa_instance = QAFramework(qa_branch=wazuh_qa_branch, qa_ctl_configuration=self.qa_ctl_configuration) qa_instance.download_qa_repository(inventory_file_path=self.inventory_file_path, hosts=current_host) qa_instance.install_dependencies(inventory_file_path=self.inventory_file_path, hosts=current_host) qa_instance.install_framework(inventory_file_path=self.inventory_file_path, hosts=current_host) @@ -165,7 +167,8 @@ def __check_hosts_connection(self, hosts='all'): playbook_parameters = {'hosts': hosts, 'tasks_list': [wait_for_connection]} - AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters) + AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) def run(self): """Provision all hosts in a parallel way""" diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsibleRunner.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsibleRunner.py index 84f9ff7051..8ae2329188 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsibleRunner.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/ansible/AnsibleRunner.py @@ -15,18 +15,21 @@ class AnsibleRunner: ansible_inventory_path (string): Path where is located the ansible inventory file. ansible_playbook_path (string): Path where is located the playbook file. private_data_dir (string): Path where the artifacts files (result files) will be stored. + output (boolean): True for showing ansible task output in stdout False otherwise. Attributes: ansible_inventory_path (string): Path where is located the ansible inventory file. ansible_playbook_path (string): Path where is located the playbook file. private_data_dir (string): Path where the artifacts files (result files) will be stored. + output (boolean): True for showing ansible task output in stdout False otherwise. """ LOGGER = Logging.get_logger(QACTL_LOGGER) - def __init__(self, ansible_inventory_path, ansible_playbook_path, private_data_dir=gettempdir()): + def __init__(self, ansible_inventory_path, ansible_playbook_path, private_data_dir=gettempdir(), output=False): self.ansible_inventory_path = ansible_inventory_path self.ansible_playbook_path = ansible_playbook_path self.private_data_dir = private_data_dir + self.output = output def run(self): """Run the ansible playbook in the indicated hosts. @@ -34,10 +37,11 @@ def run(self): Returns: AnsibleOutput: Result of the ansible playbook run. """ + quiet = not self.output AnsibleRunner.LOGGER.debug(f"Running {self.ansible_playbook_path} ansible-playbook with " f"{self.ansible_inventory_path} inventory") runner = ansible_runner.run(private_data_dir=self.private_data_dir, playbook=self.ansible_playbook_path, - inventory=self.ansible_inventory_path) + inventory=self.ansible_inventory_path, quiet=quiet) ansible_output = AnsibleOutput(runner) if ansible_output.rc != 0: @@ -46,11 +50,13 @@ def run(self): return ansible_output @staticmethod - def run_ephemeral_tasks(ansible_inventory_path, playbook_parameters, raise_on_error=True): + def run_ephemeral_tasks(ansible_inventory_path, playbook_parameters, raise_on_error=True, output=False): ansible_playbook = AnsiblePlaybook(**playbook_parameters) + quiet = not output try: - runner = ansible_runner.run(playbook=ansible_playbook.playbook_file_path, inventory=ansible_inventory_path) + runner = ansible_runner.run(playbook=ansible_playbook.playbook_file_path, inventory=ansible_inventory_path, + quiet=quiet) ansible_output = AnsibleOutput(runner) if ansible_output.rc != 0 and raise_on_error: diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/qa_framework/QAFramework.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/qa_framework/QAFramework.py index ed49edfc85..790abb3fbf 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/qa_framework/QAFramework.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/qa_framework/QAFramework.py @@ -12,18 +12,22 @@ class QAFramework(): workdir (str): Directory where the qa repository files are stored qa_repository (str): Url to the QA repository. qa_branch (str): QA branch of the qa repository. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. Attributes: workdir (str): Directory where the qa repository files are stored qa_repository (str): Url to the QA repository. qa_branch (str): QA branch of the qa repository. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. """ LOGGER = Logging.get_logger(QACTL_LOGGER) - def __init__(self, workdir=gettempdir(), qa_repository='https://github.com/wazuh/wazuh-qa.git', qa_branch='master'): + def __init__(self, qa_ctl_configuration, workdir=gettempdir(), qa_branch='master', + qa_repository='https://github.com/wazuh/wazuh-qa.git'): self.qa_repository = qa_repository self.qa_branch = qa_branch self.workdir = f"{workdir}/wazuh-qa" + self.qa_ctl_configuration = qa_ctl_configuration def install_dependencies(self, inventory_file_path, hosts='all'): """Install all the necessary dependencies to allow the execution of the tests. @@ -39,7 +43,8 @@ def install_dependencies(self, inventory_file_path, hosts='all'): playbook_parameters = {'hosts': hosts, 'tasks_list': ansible_tasks} QAFramework.LOGGER.debug(f"Installing python dependencies in {hosts} hosts.") - AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters) + AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) def install_framework(self, inventory_file_path, hosts='all'): """Install the wazuh_testing framework to allow the execution of the tests. @@ -54,7 +59,8 @@ def install_framework(self, inventory_file_path, hosts='all'): playbook_parameters = {'hosts': hosts, 'tasks_list': ansible_tasks, 'become': True} QAFramework.LOGGER.debug(f"Installing wazuh-qa framework in {hosts} hosts.") - AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters) + AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) def download_qa_repository(self, inventory_file_path, hosts='all'): """Download the qa-framework in the specified attribute workdir. @@ -72,4 +78,5 @@ def download_qa_repository(self, inventory_file_path, hosts='all'): playbook_parameters = {'hosts': hosts, 'tasks_list': ansible_tasks} QAFramework.LOGGER.debug(f"Downloading qa-repository in {hosts} hosts") - AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters) + AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/AgentDeployment.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/AgentDeployment.py index 8aa62bb7cf..e752ebdaac 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/AgentDeployment.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/AgentDeployment.py @@ -15,6 +15,7 @@ class AgentDeployment(WazuhDeployment): install_dir_path (string): Path where the Wazuh installation will be stored. hosts (string): Group of hosts to be deployed. server_ip (string): Manager IP to connect. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. Attributes: installation_files (string): Path where is located the Wazuh instalation files. @@ -24,6 +25,7 @@ class AgentDeployment(WazuhDeployment): install_dir_path (string): Path where the Wazuh installation will be stored. hosts (string): Group of hosts to be deployed. server_ip (string): Manager IP to connect. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. """ @@ -86,7 +88,8 @@ def register_agent(self): self.stop_service() - output = AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters) + output = AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) self.start_service() @@ -110,4 +113,5 @@ def health_check(self): playbook_parameters = {'tasks_list': tasks_list, 'hosts': self.hosts, 'gather_facts': True, 'become': True} - return AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters) + return AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/LocalPackage.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/LocalPackage.py index eb74cda753..c9e7504e5a 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/LocalPackage.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/LocalPackage.py @@ -11,11 +11,12 @@ class LocalPackage(WazuhPackage): LOGGER = Logging.get_logger(QACTL_LOGGER) - def __init__(self, wazuh_target, installation_files_path, local_package_path, version=None, system=None): + def __init__(self, wazuh_target, installation_files_path, local_package_path, qa_ctl_configuration, version=None, + system=None): self.local_package_path = local_package_path self.package_name = Path(self.local_package_path).name super().__init__(wazuh_target=wazuh_target, installation_files_path=installation_files_path, version=version, - system=system) + system=system, qa_ctl_configuration=qa_ctl_configuration) def download_installation_files(self, inventory_file_path, hosts='all'): copy_ansible_task = AnsibleTask({'name': f"Copy {self.local_package_path} package to \ diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/ManagerDeployment.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/ManagerDeployment.py index f03011f954..42d1dd6802 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/ManagerDeployment.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/ManagerDeployment.py @@ -15,6 +15,7 @@ class ManagerDeployment(WazuhDeployment): install_dir_path (string): Path where the Wazuh installation will be stored. hosts (string): Group of hosts to be deployed. server_ip (string): Manager IP to connect. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. Attributes: installation_files (string): Path where is located the Wazuh instalation files. @@ -24,6 +25,7 @@ class ManagerDeployment(WazuhDeployment): install_dir_path (string): Path where the Wazuh installation will be stored. hosts (string): Group of hosts to be deployed. server_ip (string): Manager IP to connect. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. """ def install(self): @@ -78,4 +80,5 @@ def health_check(self): playbook_parameters = {'tasks_list': tasks_list, 'hosts': self.hosts, 'gather_facts': True, 'become': True} - return AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters) + return AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhDeployment.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhDeployment.py index dcaff1181f..9c5c30e01a 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhDeployment.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhDeployment.py @@ -20,6 +20,7 @@ class WazuhDeployment(ABC): install_dir_path (string): Path where the Wazuh installation will be stored. hosts (string): Group of hosts to be deployed. server_ip (string): Manager IP to let agent get autoenrollment. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. Attributes: installation_files_path (string): Path where is located the Wazuh instalation files. @@ -29,10 +30,11 @@ class WazuhDeployment(ABC): install_dir_path (string): Path where the Wazuh installation will be stored. hosts (string): Group of hosts to be deployed. server_ip (string): Manager IP to let agent get autoenrollment. + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. """ LOGGER = Logging.get_logger(QACTL_LOGGER) - def __init__(self, installation_files_path, inventory_file_path, configuration=None, + def __init__(self, installation_files_path, inventory_file_path, qa_ctl_configuration, configuration=None, install_mode='package', install_dir_path='/var/ossec', hosts='all', server_ip=None): self.installation_files_path = installation_files_path @@ -42,6 +44,7 @@ def __init__(self, installation_files_path, inventory_file_path, configuration=N self.install_dir_path = install_dir_path self.hosts = hosts self.server_ip = server_ip + self.qa_ctl_configuration = qa_ctl_configuration @abstractmethod def install(self, install_type): @@ -108,7 +111,8 @@ def install(self, install_type): playbook_parameters = {'tasks_list': tasks_list, 'hosts': self.hosts, 'gather_facts': True, 'become': True} - return AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters) + return AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) def __control_service(self, command, install_type): """Private method to control the Wazuh service in different systems. @@ -143,7 +147,8 @@ def __control_service(self, command, install_type): playbook_parameters = {'tasks_list': tasks_list, 'hosts': self.hosts, 'gather_facts': True, 'become': True} - return AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters) + return AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) @abstractmethod def start_service(self, install_type): @@ -199,7 +204,8 @@ def health_check(self): playbook_parameters = {'tasks_list': tasks_list, 'hosts': self.hosts, 'gather_facts': True, 'become': True} - return AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters) + return AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) def wazuh_is_already_installed(self): """Check if Wazuh is installed in the system @@ -215,7 +221,8 @@ def wazuh_is_already_installed(self): playbook_parameters = {'tasks_list': tasks_list, 'hosts': self.hosts, 'gather_facts': True, 'become': True} - output = AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters, raise_on_error=False) + output = AnsibleRunner.run_ephemeral_tasks(self.inventory_file_path, playbook_parameters, raise_on_error=False, + output=self.qa_ctl_configuration.ansible_output) if output.rc == 0: return False diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhInstallation.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhInstallation.py index 0aeef63292..c5fb27f621 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhInstallation.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhInstallation.py @@ -5,9 +5,10 @@ class WazuhInstallation(ABC): - def __init__(self, wazuh_target, installation_files_path): + def __init__(self, wazuh_target, installation_files_path, qa_ctl_configuration): self.wazuh_target = wazuh_target self.installation_files_path = installation_files_path + self.qa_ctl_configuration = qa_ctl_configuration super().__init__() @abstractmethod @@ -18,4 +19,5 @@ def download_installation_files(self, inventory_file_path, ansible_tasks, hosts= ansible_tasks.insert(0, create_path_task) playbook_parameters = {'hosts': hosts, 'tasks_list': ansible_tasks} - AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters) + AnsibleRunner.run_ephemeral_tasks(inventory_file_path, playbook_parameters, + output=self.qa_ctl_configuration.ansible_output) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhPackage.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhPackage.py index a874a8d7b4..95eeeefb27 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhPackage.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhPackage.py @@ -4,10 +4,11 @@ class WazuhPackage(WazuhInstallation, ABC): - def __init__(self, version, system, wazuh_target, installation_files_path): + def __init__(self, version, system, wazuh_target, installation_files_path, qa_ctl_configuration): self.version = version self.system = system - super().__init__(wazuh_target=wazuh_target, installation_files_path=installation_files_path) + super().__init__(wazuh_target=wazuh_target, installation_files_path=installation_files_path, + qa_ctl_configuration=qa_ctl_configuration) @abstractmethod def download_installation_files(self, inventory_file_path, ansible_tasks, hosts='all'): diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhS3Package.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhS3Package.py index c76376da96..f9ad39e6a1 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhS3Package.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/provisioning/wazuh_deployment/WazuhS3Package.py @@ -6,12 +6,13 @@ class WazuhS3Package(WazuhPackage): LOGGER = Logging.get_logger(QACTL_LOGGER) - def __init__(self, wazuh_target, installation_files_path, version, system, revision, repository, architecture): + def __init__(self, wazuh_target, installation_files_path, version, system, revision, repository, architecture, + qa_ctl_configuration): self.revision = revision self.repository = repository self.architecture = architecture super().__init__(wazuh_target=wazuh_target, installation_files_path=installation_files_path, version=version, - system=system) + system=system, qa_ctl_configuration=qa_ctl_configuration) def get_package_name(self): pass diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/Pytest.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/Pytest.py index cf2ae83514..6c685c1d3c 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/Pytest.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/Pytest.py @@ -20,6 +20,7 @@ class Pytest(Test): tests_result_path(str): Path to the directory where the reports will be stored in the local machine tests_path (str): Path to the set of tests to be executed tests_run_dir (str): Path to the directory from where the tests are going to be executed + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. tiers (list(int), []): List of tiers to be executed stop_after_first_failure (boolean, False): If set to true then the tests' execution will stop after the first failure @@ -37,6 +38,7 @@ class Pytest(Test): tests_result_path(str): Path to the directory where the reports will be stored in the local machine tests_path (str): Path to the set of tests to be executed tests_run_dir (str): Path to the directory from where the tests are going to be executed + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. tier (srt, None): List of tiers to be executed stop_after_first_failure (boolean, False): If set to true then the tests' execution will stop after the first failure @@ -53,9 +55,10 @@ class Pytest(Test): RUN_PYTEST = 'python3 -m pytest ' LOGGER = Logging.get_logger(QACTL_LOGGER) - def __init__(self, tests_result_path, tests_path, tests_run_dir, tiers=[], stop_after_first_failure=False, - keyword_expression=None, traceback='auto', dry_run=False, custom_args=[], verbose_level=False, - log_level=None, markers=[], hosts=['all']): + def __init__(self, tests_result_path, tests_path, tests_run_dir, qa_ctl_configuration, + tiers=[], stop_after_first_failure=False, keyword_expression=None, traceback='auto', dry_run=False, + custom_args=[], verbose_level=False, log_level=None, markers=[], hosts=['all']): + self.qa_ctl_configuration = qa_ctl_configuration self.tiers = tiers self.stop_after_first_failure = stop_after_first_failure self.keyword_expression = keyword_expression @@ -178,7 +181,9 @@ def run(self, ansible_inventory_path): playbook_file_path, "hosts": self.hosts} Pytest.LOGGER.debug(f"Running {pytest_command} on {self.hosts} hosts...") Pytest.LOGGER.info(f"Running {self.tests_path} test on {self.hosts} hosts...") - AnsibleRunner.run_ephemeral_tasks(ansible_inventory_path, playbook_parameters, raise_on_error=False) + + AnsibleRunner.run_ephemeral_tasks(ansible_inventory_path, playbook_parameters, raise_on_error=False, + output=self.qa_ctl_configuration.ansible_output) Pytest.LOGGER.debug(f"Saving {self.tests_path} test resulsts of {self.hosts} hosts in {self.tests_result_path}") diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/QARunTests.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/QARunTests.py index de2815821e..968aeace16 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/QARunTests.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/QARunTests.py @@ -12,16 +12,19 @@ class RunQATests(): Args: test_parameters (dict): a dictionary containing all the required data to build the tests + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. Attributes: inventory_file_path (string): Path of the inventory file generated. test_launchers (list(TestLauncher)): Test launchers objects (one for each host). + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. """ LOGGER = Logging.get_logger(QACTL_LOGGER) - def __init__(self, tests_parameters): + def __init__(self, tests_parameters, qa_ctl_configuration): self.inventory_file_path = None self.test_launchers = [] + self.qa_ctl_configuration = qa_ctl_configuration self.__process_inventory_data(tests_parameters) self.__process_test_data(tests_parameters) @@ -75,7 +78,7 @@ def __process_test_data(self, instances_info): RunQATests.LOGGER.debug('Processing testing data from hosts..') for _, host_value in instances_info.items(): - test_launcher = TestLauncher([], self.inventory_file_path) + test_launcher = TestLauncher([], self.inventory_file_path, self.qa_ctl_configuration) for module_key, module_value in host_value.items(): hosts = host_value['host_info']['host'] if module_key == 'test': @@ -96,6 +99,7 @@ def __build_test(self, test_params, host=['all']): if test_params['type'] == 'pytest': test_dict = {} test_dict['hosts'] = [host] + test_dict['qa_ctl_configuration'] = self.qa_ctl_configuration if 'path' in test_params: paths = test_params['path'] diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/TestLauncher.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/TestLauncher.py index 1f73d91426..c192fd9b2c 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/TestLauncher.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/run_tests/TestLauncher.py @@ -15,11 +15,13 @@ class TestLauncher: Attributes: tests (list(Test)): List containing all the tests to be executed in the remote machine ansible_inventory_path (str): path to the ansible inventory file + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. qa_framework_path (str, None): remote directory path where the qa repository will be download to Args: tests (list(Test)): List containing all the tests to be executed in the remote machine ansible_inventory_path (str): path to the ansible inventory file + qa_ctl_configuration (QACTLConfiguration): QACTL configuration. qa_framework_path (str, None): remote directory path where the qa repository will be download to """ @@ -28,10 +30,11 @@ class TestLauncher: "wazuh_modules.debug=2", "wazuh_database.interval=1", "wazuh_db.commit_time=2", "wazuh_db.commit_time_max=3", "remoted.debug=2"] - def __init__(self, tests, ansible_inventory_path, qa_framework_path=None): + def __init__(self, tests, ansible_inventory_path, qa_ctl_configuration, qa_framework_path=None): self.qa_framework_path = qa_framework_path if qa_framework_path is not None else \ os.path.join(gettempdir(), 'wazuh-qa/') self.ansible_inventory_path = ansible_inventory_path + self.qa_ctl_configuration = qa_ctl_configuration self.tests = tests @@ -57,7 +60,8 @@ def __set_local_internal_options(self, hosts): TestLauncher.LOGGER.debug(f"Setting local_internal_options configuration in {hosts} hosts") - AnsibleRunner.run_ephemeral_tasks(self.ansible_inventory_path, playbook_parameters, raise_on_error=False) + AnsibleRunner.run_ephemeral_tasks(self.ansible_inventory_path, playbook_parameters, raise_on_error=False, + output=self.qa_ctl_configuration.ansible_output) def add(self, test): """Add new test to the TestLauncher instance. diff --git a/deps/wazuh_testing/wazuh_testing/scripts/qa_ctl.py b/deps/wazuh_testing/wazuh_testing/scripts/qa_ctl.py index ac815bf19a..d146f3a7f0 100644 --- a/deps/wazuh_testing/wazuh_testing/scripts/qa_ctl.py +++ b/deps/wazuh_testing/wazuh_testing/scripts/qa_ctl.py @@ -5,12 +5,12 @@ import argparse import os import yaml -import jsonschema from jsonschema import validate from wazuh_testing.qa_ctl.deployment.QAInfraestructure import QAInfraestructure from wazuh_testing.qa_ctl.provisioning.QAProvisioning import QAProvisioning from wazuh_testing.qa_ctl.run_tests.QARunTests import RunQATests +from wazuh_testing.qa_ctl.configuration.qa_ctl_configuration import QACTLConfiguration from wazuh_testing.qa_ctl import QACTL_LOGGER from wazuh_testing.tools.logging import Logging @@ -18,11 +18,19 @@ DEPLOY_KEY = 'deployment' PROVISION_KEY = 'provision' TEST_KEY = 'tests' -LOGGER = Logging(QACTL_LOGGER, level='INFO', log_file='/home/jmv74211/test.log') + +qactl_logger = None _data_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'data') -def validate_conf(configuration): +def read_configuration_data(configuration_file_path): + with open(configuration_file_path) as config_file_fd: + configuration_data = yaml.safe_load(config_file_fd) + + return configuration_data + + +def validate_configuration_data(configuration): data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'data') schema_file = os.path.join(data_path, 'qactl_conf_validator_schema.json') @@ -32,9 +40,17 @@ def validate_conf(configuration): validate(instance=configuration, schema=schema) +def set_qactl_logging(qactl_configuration): + if not qactl_configuration.logging_enable: + qactl_logger = Logging(QACTL_LOGGER) + qactl_logger.disable() + else: + qactl_logger = Logging(QACTL_LOGGER, qactl_configuration.logging_level, True, qactl_configuration.logging_file) + + def main(): parser = argparse.ArgumentParser() - yaml_config = {} + configuration_data = {} instance_handler = None parser.add_argument('--config', '-c', type=str, action='store', required=True, @@ -45,30 +61,36 @@ def main(): arguments = parser.parse_args() + # Check configuration file path exists assert os.path.exists(arguments.config), f"{arguments.config} file doesn't exists" + # Read configuration data + configuration_data = read_configuration_data(arguments.config) + # Validate configuration schema - with open(arguments.config) as config_file_fd: - yaml_config = yaml.safe_load(config_file_fd) - LOGGER.debug('User configuration template has been read') - validate_conf(yaml_config) - LOGGER.debug('User configuration template has been validated') + validate_configuration_data(configuration_data) + + # Set QACTL configuration + qactl_configuration = QACTLConfiguration(configuration_data) + + # Set QACTL logging + set_qactl_logging(qactl_configuration) # Run QACTL modules try: - if DEPLOY_KEY in yaml_config: - deploy_dict = yaml_config[DEPLOY_KEY] - instance_handler = QAInfraestructure(deploy_dict) + if DEPLOY_KEY in configuration_data: + deploy_dict = configuration_data[DEPLOY_KEY] + instance_handler = QAInfraestructure(deploy_dict, qactl_configuration) instance_handler.run() - if PROVISION_KEY in yaml_config: - provision_dict = yaml_config[PROVISION_KEY] - qa_provisioning = QAProvisioning(provision_dict) + if PROVISION_KEY in configuration_data: + provision_dict = configuration_data[PROVISION_KEY] + qa_provisioning = QAProvisioning(provision_dict, qactl_configuration) qa_provisioning.run() - if TEST_KEY in yaml_config: - test_dict = yaml_config[TEST_KEY] - tests_runner = RunQATests(test_dict) + if TEST_KEY in configuration_data: + test_dict = configuration_data[TEST_KEY] + tests_runner = RunQATests(test_dict, qactl_configuration) tests_runner.run() finally: diff --git a/deps/wazuh_testing/wazuh_testing/tools/logging.py b/deps/wazuh_testing/wazuh_testing/tools/logging.py index 5b195a4d36..f49dd97234 100644 --- a/deps/wazuh_testing/wazuh_testing/tools/logging.py +++ b/deps/wazuh_testing/wazuh_testing/tools/logging.py @@ -37,7 +37,7 @@ def __initialize_parameters(self): 'DEBUG': logging.DEBUG, 'INFO': logging.INFO, 'WARNING': logging.WARNING, - 'ERORR': logging.ERROR, + 'ERROR': logging.ERROR, 'CRITICAL': logging.CRITICAL } @@ -84,6 +84,14 @@ def get_logger(logger_name): """ return logging.getLogger(logger_name) + def enable(self): + """Enable logger""" + self.logger.disabled = False + + def disable(self): + """Disable logger""" + self.logger.disabled = True + def debug(self, message): """Log DEBUG message""" self.logger.debug(message) From 360c36010df1335c79dd6e5b2a9c93900fa9c74a Mon Sep 17 00:00:00 2001 From: jmv74211 Date: Thu, 26 Aug 2021 15:48:58 +0200 Subject: [PATCH 6/7] fix: Fix an error when creating wazuh_net docker net in QACTL #1713 --- .../wazuh_testing/qa_ctl/deployment/docker_wrapper.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/docker_wrapper.py b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/docker_wrapper.py index b3b3c7bee4..8191062122 100644 --- a/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/docker_wrapper.py +++ b/deps/wazuh_testing/wazuh_testing/qa_ctl/deployment/docker_wrapper.py @@ -4,6 +4,7 @@ from wazuh_testing.qa_ctl.deployment.instance import Instance from wazuh_testing.qa_ctl import QACTL_LOGGER from wazuh_testing.tools.logging import Logging +from wazuh_testing.tools.exceptions import QAValueError class DockerWrapper(Instance): @@ -78,7 +79,14 @@ def run(self): remove=self.remove, detach=self.detach, stdout=self.stdout, stderr=self.stderr) if self.ip and self.network_name: - self.docker_client.networks.get(self.network_name).connect(container, ipv4_address=self.ip) + try: + self.docker_client.networks.get(self.network_name).connect(container, ipv4_address=self.ip) + except docker.errors.APIError: #requests.exceptions.HTTPError: + exception_message = f"Invalid address {self.ip} It does not belong to any of this network's " \ + 'subnets. Please check if you have already set this docker network ' \ + '(run `docker network ls`) and then remove it if it is created with ' \ + 'docker network rm ``' + raise QAValueError(exception_message, DockerWrapper.LOGGER.critical) def restart(self): """Restart the container. From 679bf8323544d311ccfde2f43c56bcb7b85ca724 Mon Sep 17 00:00:00 2001 From: jmv74211 Date: Thu, 26 Aug 2021 16:20:33 +0200 Subject: [PATCH 7/7] add: Add QACTL config schema validation #1713 --- .../data/qactl_conf_validator_schema.json | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/deps/wazuh_testing/wazuh_testing/data/qactl_conf_validator_schema.json b/deps/wazuh_testing/wazuh_testing/data/qactl_conf_validator_schema.json index f681cea9cf..1514dfc9fd 100644 --- a/deps/wazuh_testing/wazuh_testing/data/qactl_conf_validator_schema.json +++ b/deps/wazuh_testing/wazuh_testing/data/qactl_conf_validator_schema.json @@ -353,5 +353,32 @@ } } } + }, + "config": { + "$id": "#/properties/config", + "type": "object", + "patternProperties": { + "vagrant_output": { + "type": "boolean" + }, + "ansible_output": { + "type": "boolean" + }, + "logging":{ + "type": "object", + "properties": { + "enable": { + "type": "boolean" + }, + "level": { + "type": "string", + "enum": ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] + }, + "file": { + "type": "string" + } + } + } + } } }