Skip to content

Commit

Permalink
add: Add module to launch ansible tasks using the qa-ctl tool #2306
Browse files Browse the repository at this point in the history
  • Loading branch information
jmv74211 committed Dec 9, 2021
1 parent 9c9d834 commit 107dea0
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 0 deletions.
Empty file.
125 changes: 125 additions & 0 deletions deps/wazuh_testing/wazuh_testing/qa_ctl/run_tasks/qa_tasks_launcher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import os
import sys
from copy import deepcopy
from tempfile import gettempdir

from wazuh_testing.tools.file import download_text_file, remove_file
from wazuh_testing.qa_ctl.provisioning.ansible import read_ansible_instance, remove_known_host
from wazuh_testing.qa_ctl.provisioning.ansible.ansible_inventory import AnsibleInventory
from wazuh_testing.qa_ctl.provisioning.ansible.ansible_runner import AnsibleRunner
from wazuh_testing.qa_ctl import QACTL_LOGGER
from wazuh_testing.tools.logging import Logging
from wazuh_testing.tools import file
from wazuh_testing.tools.time import get_current_timestamp
from wazuh_testing.qa_ctl.provisioning.local_actions import qa_ctl_docker_run


class QATasksLauncher:
"""Class to manage and launch the tasks specified in the qa-ctl configuration module.
Args:
tasks_data (dict): Dicionary with tasks info.
qa_ctl_configuration (QACTLConfiguration): QACTL configuration info.
Attributes:
tasks_data (dict): Dicionary with tasks info.
qa_ctl_configuration (QACTLConfiguration): QACTL configuration info.
"""
LOGGER = Logging.get_logger(QACTL_LOGGER)

def __init__(self, tasks_data, qa_ctl_configuration):
self.qa_ctl_configuration = qa_ctl_configuration
self.ansible_runners = []
self.tasks_data = tasks_data

self.__process_tasks_data()

def __process_tasks_data(self):
"""Process tasks module info from the qa-ctl configuration file.
Args:
tasks_data (dict): Dicionary with tasks info.
"""
QATasksLauncher.LOGGER.debug('Processing tasks module data')

for task_id, task_data in self.tasks_data.items():
playbooks_path = []
inventory_path = ''

if 'host_info' in task_data:
instance = read_ansible_instance(task_data['host_info'])

# Remove the host IP from known host file to avoid the SSH key fingerprint error
if 'host' in task_data['host_info']:
remove_known_host(task_data['host_info']['host'], QATasksLauncher.LOGGER)

inventory_instance = AnsibleInventory(ansible_instances=[instance])
inventory_path = inventory_instance.inventory_file_path

if 'playbooks' in task_data:
for playbook_data in task_data['playbooks']:
if 'local_path' in playbook_data:
playbooks_path.append(playbook_data['local_path'])
elif 'remote_url' in playbook_data:
# If a remote url file is specified, then download it and then save the playbook path
playbook_name = os.path.split(playbook_data['remote_url'])[1]
playbook_file_name = f"{get_current_timestamp()}_{playbook_name}"
playbook_file_path = os.path.join(gettempdir(), 'wazuh_qa_ctl', playbook_file_name)

download_text_file(playbook_data['remote_url'], playbook_file_path)
playbooks_path.append(playbook_file_path)

QATasksLauncher.LOGGER.debug(f"The {playbook_name} file has been downloaded from "
f"{playbook_data['remote_url']} in {playbook_file_path} path")

# Create runner objects. One for each playbook using the same inventory for each host
for index, playbook in enumerate(playbooks_path):
self.ansible_runners.append(AnsibleRunner(inventory_path, playbook,
output=self.qa_ctl_configuration.ansible_output,
task_id=f"{task_id} - playbook_{index + 1}"))

QATasksLauncher.LOGGER.debug('Tasks module data has been processed successfully')

def run(self):
"""Run the ansible tasks specified in the tasks module."""
try:
if sys.platform == 'win32':
# If Windows, run the qa-ctl tasks in a linux container due to ansible is not compatible with Windows
tmp_config_file_name = f"config_{get_current_timestamp()}.yaml"
tmp_path = os.path.join(gettempdir(), 'wazuh_qa_ctl')
tmp_config_file = os.path.join(tmp_path, tmp_config_file_name)

# Copy the tasks data to modify
container_tasks = deepcopy(self.tasks_data)

# Copy the local playbooks to the wazuh qa-ctl path, that is shared with the container through a volume
for _, task_data in container_tasks.items():
if 'playbooks' in task_data:
for playbook_data in task_data['playbooks']:
if 'local_path' in playbook_data:
file.copy(playbook_data['local_path'], tmp_path)
playbook_file = os.path.split(playbook_data['local_path'])[1]

# Update local path to specify the playbooks path in the container
playbook_data['local_path'] = f"/wazuh_qa_ctl/{playbook_file}"

# Write a custom configuration file with tasks section modified (local paths)
file.write_yaml_file(tmp_config_file, {'tasks': container_tasks})

try:
qa_ctl_docker_run(tmp_config_file_name, self.qa_ctl_configuration.qa_ctl_launcher_branch,
self.qa_ctl_configuration.debug_level, topic='launching the custom tasks')
finally:
file.remove_file(tmp_config_file)
else:
for task_runner in self.ansible_runners:
QATasksLauncher.LOGGER.info(f"Running {task_runner.task_id}")
task_runner.run()
QATasksLauncher.LOGGER.info(f"The {task_runner.task_id} has been finished successfully")
finally:
self.destroy()

def destroy(self):
"""Remove temporarily runner files."""
for runner in self.ansible_runners:
remove_file(runner.ansible_inventory_path)
12 changes: 12 additions & 0 deletions deps/wazuh_testing/wazuh_testing/scripts/qa_ctl.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from wazuh_testing.qa_ctl.deployment.qa_infraestructure import QAInfraestructure
from wazuh_testing.qa_ctl.provisioning.qa_provisioning import QAProvisioning
from wazuh_testing.qa_ctl.run_tests.qa_test_runner import QATestRunner
from wazuh_testing.qa_ctl.run_tasks.qa_tasks_launcher import QATasksLauncher
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
Expand All @@ -28,6 +29,7 @@

DEPLOY_KEY = 'deployment'
PROVISION_KEY = 'provision'
TASKS_KEY = 'tasks'
TEST_KEY = 'tests'
WAZUH_QA_FILES = os.path.join(gettempdir(), 'wazuh_qa_ctl', 'wazuh-qa')
RUNNING_ON_DOCKER_CONTAINER = True if 'RUNNING_ON_DOCKER_CONTAINER' in os.environ else False
Expand All @@ -41,6 +43,7 @@
'config_generator': False,
'instance_handler': False,
'qa_provisioning': False,
'tasks_runner': False,
'test_runner': False
}

Expand Down Expand Up @@ -304,6 +307,9 @@ def get_script_parameters():
parser.add_argument('--skip-provisioning', action='store_true',
help='Flag to skip the provisioning phase. Set it only if -c or --config was specified.')

parser.add_argument('--skip-tasks', action='store_true',
help='Flag to skip the tasks phase. Set it only if -c or --config was specified.')

parser.add_argument('--skip-testing', action='store_true',
help='Flag to skip the testing phase. Set it only if -c or --config was specified.')

Expand Down Expand Up @@ -376,6 +382,12 @@ def main():
qa_provisioning.run()
launched['qa_provisioning'] = True

if TASKS_KEY in configuration_data and not arguments.skip_tasks:
tasks_dict = configuration_data[TASKS_KEY]
tasks_runner = QATasksLauncher(tasks_dict, qactl_configuration)
tasks_runner.run()
launched['tasks_runner'] = True

if TEST_KEY in configuration_data and not arguments.skip_testing:
test_dict = configuration_data[TEST_KEY]
tests_runner = QATestRunner(test_dict, qactl_configuration)
Expand Down

0 comments on commit 107dea0

Please sign in to comment.