From a5c3106eebcac92c55da3d20aa119b0306f2bd42 Mon Sep 17 00:00:00 2001 From: Adam Williamson Date: Mar 15 2018 19:11:03 +0000 Subject: Allow filtering by arch when scheduling compose jobs Sometimes it's useful to run/re-run compose jobs only for one or more specific arches, so let's allow this both via API and CLI. `jobs_from_compose` has a new kwarg which is a list of arches to schedule jobs for, and the CLI has a `--arches` arg that feeds it (with a comma-separated list). Signed-off-by: Adam Williamson --- diff --git a/fedora_openqa/cli.py b/fedora_openqa/cli.py index 8af9bae..bfbdb06 100644 --- a/fedora_openqa/cli.py +++ b/fedora_openqa/cli.py @@ -47,9 +47,13 @@ def command_compose(args): extraparams = None if args.updates: extraparams = {'GRUBADD': "inst.updates={0}".format(args.updates)} + arches = None + if args.arches: + arches = args.arches.split(',') try: (_, jobs) = schedule.jobs_from_compose( - args.location, force=args.force, extraparams=extraparams, openqa_hostname=args.openqa_hostname) + args.location, force=args.force, extraparams=extraparams, + openqa_hostname=args.openqa_hostname, arches=arches) except schedule.TriggerException as err: logger.warning("No jobs run! %s", err) sys.exit(1) @@ -152,7 +156,7 @@ def parse_args(args=None): 'location', help="The URL of the compose (for Pungi 4 composes, the /compose directory)", metavar="COMPOSE_URL") parser_compose.add_argument( - "--openqa-hostname", help="openQA host to schedule jobs on (default: client library " + '--openqa-hostname', help="openQA host to schedule jobs on (default: client library " "default)", metavar='HOSTNAME') parser_compose.add_argument( '--force', '-f', help="For each ISO/flavor combination, schedule jobs even if there " @@ -161,6 +165,9 @@ def parse_args(args=None): '--updates', '-u', help="URL to an updates image to load for all tests. The tests that " "test updates image loading will fail when you use this", metavar='UPDATE_IMAGE_URL') parser_compose.set_defaults(func=command_compose) + parser_compose.add_argument( + "--arches", '-a', help="Comma-separated list of arches to schedule jobs for (if not specified, " + "all arches will be scheduled)", metavar='ARCH') parser_update = subparsers.add_parser('update', description="Schedule jobs for a specific update.") parser_update.add_argument('update', help="The update ID (e.g. 'FEDORA-2017-b07d628952')", metavar='UPDATE') diff --git a/fedora_openqa/schedule.py b/fedora_openqa/schedule.py index af678c1..f6bab47 100644 --- a/fedora_openqa/schedule.py +++ b/fedora_openqa/schedule.py @@ -214,7 +214,7 @@ def run_openqa_jobs(param_urls, flavor, arch, subvariant, imagetype, build, vers return output["ids"] -def jobs_from_compose(location, wanted=None, force=False, extraparams=None, openqa_hostname=None): +def jobs_from_compose(location, wanted=None, force=False, extraparams=None, openqa_hostname=None, arches=None): """Schedule jobs against a specific compose. Returns a 2-tuple of the compose ID and the list of job IDs. @@ -242,9 +242,15 @@ def jobs_from_compose(location, wanted=None, force=False, extraparams=None, open openqa_hostname is passed through as well. It specifies which openQA host to schedule the jobs on. If not set, the client lib will choose. + + arches is a list of arches to schedule jobs for; if specified, + the image list will be filtered by the arches listed. If not + specified, jobs are scheduled for all arches in the image list. """ if not wanted: wanted = WANTED + if not arches: + arches = [] try: rel = fedfind.release.get_release(url=location) except ValueError: @@ -260,6 +266,9 @@ def jobs_from_compose(location, wanted=None, force=False, extraparams=None, open return ('', []) logger.debug("Finding images for compose %s in location %s", rel.cid, location) images = _get_images(rel, wanted=wanted) + if arches: + logger.debug("Only scheduling jobs for arches %s", ' '.join(arches)) + images = [img for img in images if img[1] in arches] if len(images) == 0: raise TriggerException("Compose found, but no available images") jobs = [] diff --git a/tests/test_cli.py b/tests/test_cli.py index cf6fb40..46ae5f8 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -53,6 +53,8 @@ class TestCommandCompose: assert not excinfo.value.code # shouldn't force assert fakejfc.call_args[1]['force'] is False + # should pass arches as 'None' + assert fakejfc.call_args[1]['arches'] is None def test_force(self, fakejfc): """Test with -f (force).""" @@ -80,6 +82,31 @@ class TestCommandCompose: # should add extra params assert fakejfc.call_args[1]['extraparams'] == {'GRUBADD': "inst.updates=https://www.foo.com/updates.img"} + def test_arch(self, fakejfc): + """Test with --arches.""" + args = cli.parse_args([ + 'compose', + 'https://kojipkgs.fedoraproject.org/compose/rawhide/Fedora-24-20160113.n.1/compose', + '--arches=x86_64' + ]) + with pytest.raises(SystemExit) as excinfo: + cli.command_compose(args) + # should exit 0 + assert not excinfo.value.code + # should specify arch as single-item list + assert fakejfc.call_args[1]['arches'] == ['x86_64'] + args = cli.parse_args([ + 'compose', + 'https://kojipkgs.fedoraproject.org/compose/rawhide/Fedora-24-20160113.n.1/compose', + '--arches=i386,armhfp' + ]) + with pytest.raises(SystemExit) as excinfo: + cli.command_compose(args) + # should exit 0 + assert not excinfo.value.code + # should specify arch as multi-item list + assert fakejfc.call_args[1]['arches'] == ['i386', 'armhfp'] + def test_nojobs(self, fakejfc): """Test exits 1 when no jobs are run.""" # adjust mock return value to say no jobs run diff --git a/tests/test_schedule.py b/tests/test_schedule.py index 3e00943..eedbc85 100644 --- a/tests/test_schedule.py +++ b/tests/test_schedule.py @@ -363,6 +363,12 @@ def test_jobs_from_compose(fakerun, ffmock02): assert argtup[1]['extraparams'] == {'EXTRA': 'here'} assert argtup[1]['openqa_hostname'] == 'somehost' + # check arches is handled properly + fakerun.reset_mock() + ret = schedule.jobs_from_compose(COMPURL, arches=['i386', 'armhfp']) + # 7 images (6 i386, 1 armhfp), 1 universal arch (i386) + assert fakerun.call_count == 8 + # check triggerexception is raised when appropriate with mock.patch('fedfind.release.get_release', side_effect=ValueError("Oops!")): with pytest.raises(schedule.TriggerException):