From 35b69edb48b2f85bce8f647248727be60c5c2dc3 Mon Sep 17 00:00:00 2001 From: Giulia Naponiello Date: May 29 2018 13:13:43 +0000 Subject: waiverdb-cli: guessing the product version The waiverdb-cli is trying to guess the product version based on the subject. If it is not possible to determinate it, it will just ask for it from the user. Issue link: https://pagure.io/waiverdb/issue/111 --- diff --git a/tests/test_cli.py b/tests/test_cli.py index d3a6054..8737d6e 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -4,6 +4,7 @@ import json from mock import Mock, patch from click.testing import CliRunner from waiverdb.cli import cli as waiverdb_cli +from waiverdb.cli import guess_product_version def test_misconfigured_auth_method(tmpdir): @@ -89,10 +90,11 @@ oidc_scopes= openid """) runner = CliRunner() - args = ['-C', p.strpath] + args = ['-C', p.strpath, '-s', '{"subject.test": "test", "s": "t"}', '-t', 'testcase', + '-c', 'comment'] result = runner.invoke(waiverdb_cli, args) assert result.exit_code == 1 - assert result.output == 'Error: Please specify product version\n' + assert result.output == 'Error: Please specify product version using --product-version\n' def test_no_subject(tmpdir): @@ -292,17 +294,17 @@ Created waiver 15 for result with id 456\n' def test_malformed_submission_with_id_and_subject_and_testcase(tmpdir): - runner = CliRunner() - p = tmpdir.join('client.conf') - p.write(""" + runner = CliRunner() + p = tmpdir.join('client.conf') + p.write(""" [waiverdb] auth_method=dummy api_url=http://localhost:5004/api/v1.0 - """) - args = ['-C', p.strpath, '-p', 'Parrot', '-r', '123', '-s', - '{"subject.test": "test", "s": "t"}', '-c', "This is fine"] - result = runner.invoke(waiverdb_cli, args) - assert result.output == 'Error: Please specify result_id or subject/testcase. Not both\n' + """) + args = ['-C', p.strpath, '-p', 'Parrot', '-r', '123', '-s', + '{"subject.test": "test", "s": "t"}', '-c', "This is fine"] + result = runner.invoke(waiverdb_cli, args) + assert result.output == 'Error: Please specify result_id or subject/testcase. Not both\n' def test_submit_waiver_for_original_spec_nvr_result(tmpdir): @@ -331,3 +333,59 @@ api_url=http://localhost:5004/api/v1.0 result = runner.invoke(waiverdb_cli, args) mock_request.assert_called() assert result.output == 'Created waiver 15 for result with id 123\n' + + +def test_create_waiver_no_product_version(tmpdir): + with patch('requests.request') as mock_request: + mock_rv = Mock() + mock_rv.json.return_value = { + "comment": "This is fine", + "id": 15, + "subject": {"type": "koji_build", "item": "setup-2.8.71-7.el7_4"}, + "testcase": "test.testcase", + "timestamp": "2017-010-16T17:42:04.209638", + "username": "foo", + "waived": True + } + mock_request.return_value = mock_rv + p = tmpdir.join('client.conf') + p.write(""" +[waiverdb] +auth_method=dummy +api_url=http://localhost:5004/api/v1.0 +koji_base_url=https://koji.fedoraproject.org/kojihub + """) + runner = CliRunner() + args = ['-C', p.strpath, '-s', '{"type": "koji_build", "item": "setup-2.8.71-7.el7_4"}', + '-t', 'test.testcase', '-c', "This is fine"] + result = runner.invoke(waiverdb_cli, args) + mock_request.assert_called() + assert result.output.startswith('Created waiver 15 for result with subject ') + assert result.output.endswith(' and testcase test.testcase\n') + assert any(['{"type": "koji_build", "item": "setup-2.8.71-7.el7_4"}' in result.output, + '{"item": "setup-2.8.71-7.el7_4", "type": "koji_build"}' in result.output]) + + args = ['-C', p.strpath, '-s', '{"type": "koji_build", "item": "this-will-not-work"}', + '-t', 'test.testcase', '-c', "This is fine"] + result = runner.invoke(waiverdb_cli, args) + assert result.output == 'Error: Please specify product version using --product-version\n' + + args = ['-C', p.strpath, '-s', ('{"productmd.compose.id": "Fedora-Rawhide-20180526.n.1",' + '"type": "compose",' + '"item": "Fedora-Rawhide-20180526.n.1"}'), + '-t', 'test.testcase', '-c', "This is fine"] + result = runner.invoke(waiverdb_cli, args) + mock_request.assert_called() + assert result.output == ('Created waiver 15 for result with subject ' + '{"productmd.compose.id": "Fedora-Rawhide-20180526.n.1", "type": ' + '"compose", "item": "Fedora-Rawhide-20180526.n.1"} and testcase ' + 'test.testcase\n') + + +def test_guess_product_version(): + # some more tests for checking "guess_product_version" + assert guess_product_version('epel7-infra-mailman') == 'epel-7' + assert guess_product_version('f26-infra', koji_build=True) == 'fedora-26' + assert guess_product_version('Fedora-28-20180423.n.0') == 'fedora-28' + assert guess_product_version('Fedora-Rawhide-20180524.n.0') == 'fedora-rawhide' + assert guess_product_version('Fedora-Atomic-28-20180424.4') is None diff --git a/waiverdb/cli.py b/waiverdb/cli.py index 493cfba..ea42345 100644 --- a/waiverdb/cli.py +++ b/waiverdb/cli.py @@ -6,6 +6,8 @@ import click import requests import json import configparser +import re +from xmlrpc import client requests_session = requests.Session() @@ -51,6 +53,32 @@ def check_response(resp, data, result_id=None): resp.json()['id'], msg)) +def guess_product_version(toparse, koji_build=False): + if toparse == 'rawhide' or toparse.startswith('Fedora-Rawhide'): + return 'fedora-rawhide' + else: + product_version = None + if (toparse.startswith('f') and koji_build): + product_version = 'fedora-' + elif toparse.startswith('epel'): + product_version = 'epel-' + elif toparse.startswith('el'): + product_version = 'rhel-' + elif toparse.startswith('fc') or toparse.startswith('Fedora'): + product_version = 'fedora-' + if product_version: + # seperate the prefix from the number + result = list(filter(None, '-'.join(re.split(r'(\d+)', toparse)).split('-'))) + if len(result) >= 2: + try: + int(result[1]) + product_version += result[1] + return product_version + except ValueError: + pass + return None + + @click.command(context_settings={'help_option_names': ['-h', '--help']}) @click.option('--config-file', '-C', default='/etc/waiverdb/client.conf', type=click.Path(exists=True), @@ -80,7 +108,6 @@ def cli(comment, waived, product_version, testcase, subject, result_id, config_f waiverdb-cli -t dist.rpmdeplint \\ -s '{"item": "qclib-1.3.1-3.fc28", "type": "koji_build"}' \\ -p "fedora-28" -c "This is expected for non-x86 packages" - """ config = configparser.SafeConfigParser() @@ -88,8 +115,6 @@ def cli(comment, waived, product_version, testcase, subject, result_id, config_f validate_config(config) result_ids = result_id - if not product_version: - raise click.ClickException('Please specify product version') if not comment: raise click.ClickException('Please specify comment') if result_ids and (subject or testcase): @@ -99,6 +124,36 @@ def cli(comment, waived, product_version, testcase, subject, result_id, config_f if not result_ids and not testcase: raise click.ClickException('Please specify testcase') + if not product_version and not result_ids: + # trying to guess the product_version + if json.loads(subject).get('type', None) == 'koji_build': + try: + short_prod_version = json.loads(subject)['item'].split('.')[-1] + product_version = guess_product_version(short_prod_version, koji_build=True) + except KeyError: + pass + + # try to call koji + if config.has_option('waiverdb', 'koji_base_url'): + koji_base_url = config.get('waiverdb', 'koji_base_url') + proxy = client.ServerProxy(koji_base_url) + try: + build = proxy.getBuild(json.loads(subject)['item']) + if build: + target = proxy.getTaskRequest(build['task_id'])[1] + product_version = guess_product_version(target, koji_build=True) + except KeyError: + pass + except client.Fault: + pass + + if "productmd.compose.id" in json.loads(subject): + product_version = guess_product_version( + json.loads(subject)["productmd.compose.id"]) + + if not product_version: + raise click.ClickException('Please specify product version using --product-version') + auth_method = config.get('waiverdb', 'auth_method') data_list = [] if not result_ids: