From 72063d087e110dbd27165b6140be3c18894fa29e Mon Sep 17 00:00:00 2001 From: Edward Hope-Morley Date: Thu, 3 Oct 2024 10:39:46 +0100 Subject: [PATCH] Use local project functional test template Need to make sure we use the local functional test template when looking up voting info in zosci-config. Falls back to default charm-functional-jobs if no local one found. --- .../charmed_openstack_functest_runner.sh | 5 +- openstack/tools/func_test_tools/common.py | 40 +++++------- .../tools/func_test_tools/test_is_voting.py | 65 ++++++++++++------- 3 files changed, 60 insertions(+), 50 deletions(-) diff --git a/openstack/tools/charmed_openstack_functest_runner.sh b/openstack/tools/charmed_openstack_functest_runner.sh index 5ebd157..2a6fcf9 100755 --- a/openstack/tools/charmed_openstack_functest_runner.sh +++ b/openstack/tools/charmed_openstack_functest_runner.sh @@ -116,10 +116,11 @@ which yq &>/dev/null || sudo snap install yq get_and_update_repo https://github.com/openstack-charmers/zosci-config TOOLS_PATH=$(realpath $(dirname $0))/func_test_tools -CHARM_PATH=$PWD +# This is used generally to identify the charm root. +export CHARM_ROOT_PATH=$PWD # Get commit we are running tests against. -COMMIT_ID=$(git -C $CHARM_PATH rev-parse --short HEAD) +COMMIT_ID=$(git -C $CHARM_ROOT_PATH rev-parse --short HEAD) CHARM_NAME=$(awk '/^name: .+/{print $2}' metadata.yaml) echo "Running functional tests for charm $CHARM_NAME commit $COMMIT_ID" diff --git a/openstack/tools/func_test_tools/common.py b/openstack/tools/func_test_tools/common.py index 23a1c45..1a556d8 100644 --- a/openstack/tools/func_test_tools/common.py +++ b/openstack/tools/func_test_tools/common.py @@ -56,13 +56,11 @@ def get_branch_jobs(self, branch, project_templates): class OSCIConfig(): """ Extract information from osci.yaml """ def __init__(self): - if not os.path.exists('osci.yaml'): - self._osci_config = {} - else: - with open('osci.yaml', encoding='utf-8') as fd: - self._osci_config = yaml.safe_load(fd) + path = os.path.join(os.environ.get('CHARM_ROOT_PATH', ''), 'osci.yaml') + with open(path, encoding='utf-8') as fd: + self._osci_config = yaml.safe_load(fd) - @property + @cached_property def project_templates(self): """ Returns all project templates. """ for item in self._osci_config: @@ -73,7 +71,7 @@ def project_templates(self): return [] - @property + @cached_property def project_check_jobs(self): """ Generator returning all project check jobs defined. """ for item in self._osci_config: @@ -103,21 +101,17 @@ def get_job(self, name): return None + def get_project_check_job(self, name): + """ Get job by name from project.check.jobs. Return can be string name + or dict. -class ProjectTemplatesConfig(): - """ Extract information from project_templates.yaml """ - def __init__(self, path): - if not os.path.exists(path): - self._config = {} - else: - with open(path, encoding='utf-8') as fd: - self._config = yaml.safe_load(fd) - - @property - def project_templates(self): - """ Generator returning all project check jobs defined. """ - for item in self._config: - if 'project-template' not in item: - continue + @param name: string name + """ + for job in self.project_check_jobs: + if isinstance(job, dict): + if name in job: + return job + elif job == name: + return job - yield item['project-template'] + return None diff --git a/openstack/tools/func_test_tools/test_is_voting.py b/openstack/tools/func_test_tools/test_is_voting.py index b92c7e2..f735c31 100644 --- a/openstack/tools/func_test_tools/test_is_voting.py +++ b/openstack/tools/func_test_tools/test_is_voting.py @@ -9,42 +9,57 @@ from common import ( # pylint: disable=import-error OSCIConfig, - ProjectTemplatesConfig, + ZOSCIConfig, ) -if __name__ == "__main__": - test_job = sys.argv[1] - zosci_path = os.path.join(os.environ['HOME'], "zosci-config") - project_templates = os.path.join(zosci_path, - "zuul.d/project-templates.yaml") +def is_job_voting(job, name): + """ + Jobs are voting by default so only return False if there is a match and it + is a dict with voting=False. + """ + if isinstance(job, dict): + if name in job: + return job[name].get('voting', True) + + return True + + +def is_test_voting(): """ - First look for the func-target in osci + Exit with 1 if test is non-voting otherwise 0. """ + test_job = sys.argv[1] + # First look for the func-target in osci if os.path.exists('osci.yaml'): osci_config = OSCIConfig() try: - jobs = osci_config.project_check_jobs - for job in jobs: - if isinstance(job, dict) and test_job in job: - if not job[test_job]['voting']: - sys.exit(1) - else: - # default is true - sys.exit(0) + job = osci_config.get_project_check_job(test_job) + if not is_job_voting(job, test_job): + sys.exit(1) + # default is true except KeyError as exc: sys.stderr.write(f"ERROR: failed to process osci.yaml - assuming " f"{test_job} is voting (key {exc} not found)." "\n") - # If the target was not found in osci.yaml then osci will fallback to - # looking at https://github.com/openstack-charmers/zosci-config/blob/master/zuul.d/project-templates.yaml # noqa, pylint: disable=line-too-long - if os.path.exists(project_templates): - config = ProjectTemplatesConfig(project_templates) - for project in config.project_templates: - if project['name'] == "charm-functional-jobs": - for job in project['check']['jobs']: - if test_job in job: - if not job[test_job].get('voting', True): - sys.exit(1) + # If the target was not found in osci.yaml then osci will fallback to zosci + project_template = 'charm-functional-jobs' + for template in osci_config.project_templates: + if 'functional' in template: + project_template = template + + path = os.path.join(os.environ['HOME'], 'zosci-config') + for project in ZOSCIConfig(path).project_templates: + t = project['project-template'] + if ('functional' not in t['name'] or t['name'] != project_template): + continue + + for job in t['check']['jobs']: + if not is_job_voting(job, test_job): + sys.exit(1) + + +if __name__ == "__main__": + is_test_voting()