diff --git a/module_build_service/utils.py b/module_build_service/utils.py index 64e052ad..47b810ce 100644 --- a/module_build_service/utils.py +++ b/module_build_service/utils.py @@ -786,8 +786,11 @@ def get_reusable_component(session, module, component_name): def validate_koji_tag(tag_arg_names, pre='', post='-', dict_key='name'): """ - Used as a decorator validates koji tag arg value (which may be str or list) + Used as a decorator validates koji tag arg(s)' value(s) against configurable list of koji tag prefixes. + Supported arg value types are: dict, list, str + + :param tag_arg_names: Str or list of parameters to validate. :param pre: Prepend this optional string (e.g. '.' in case of disttag validation) to each koji tag prefix. :param post: Append this string/delimiter ('-' by default) to each koji @@ -803,26 +806,34 @@ def validate_koji_tag(tag_arg_names, pre='', post='-', dict_key='name'): call_args = inspect.getcallargs(function, *args, **kwargs) for tag_arg_name in tag_arg_names: + err_subject = "Koji tag validation:" # If any of them don't appear in the function, then fail. if tag_arg_name not in call_args: raise ProgrammingError( - 'Koji tag validation: Inspected argument {} is not within function args.' + '{} Inspected argument {} is not within function args.' ' The function was: {}.' - .format(tag_arg_name, function.__name__)) + .format(err_subject, tag_arg_name, function.__name__)) + + tag_arg_val = call_args[tag_arg_name] + + # First, check that we have some value + if not tag_arg_val: + raise ValidationError('{} Can not validate {}. No value provided.' + .format(err_subject, tag_arg_name)) # If any of them are a dict, then use the provided dict_key - if isinstance(call_args[tag_arg_name], dict): - if dict_key not in call_args[tag_arg_name]: + if isinstance(tag_arg_val, dict): + if dict_key not in tag_arg_val: raise ProgrammingError( - 'Koji tag validation: Inspected dict arg {} does not contain {} key.' + '{} Inspected dict arg {} does not contain {} key.' ' The function was: {}.' - .format(call_args[tag_arg_name], dict_key, function.__name__)) - tag_list = [call_args[tag_arg_name][dict_key]] - elif isinstance(call_args[tag_arg_name], list): - tag_list = call_args[tag_arg_name] + .format(err_subject, tag_arg_name, dict_key, function.__name__)) + tag_list = [tag_arg_val[dict_key]] + elif isinstance(tag_arg_val, list): + tag_list = tag_arg_val else: - tag_list = [call_args[tag_arg_name]] + tag_list = [tag_arg_val] # Check to make sure the provided values match our whitelist. for allowed_prefix in conf.koji_tag_prefixes: diff --git a/tests/test_utils/test_utils.py b/tests/test_utils/test_utils.py index 3fec6159..f122176c 100644 --- a/tests/test_utils/test_utils.py +++ b/tests/test_utils/test_utils.py @@ -169,6 +169,8 @@ class TestUtils(unittest.TestCase): self.assertEqual(tangerine_rv, None) def test_validate_koji_tag_wrong_tag_arg_during_programming(self): + """ Test that we fail on a wrong param name (non-existing one) due to + programming error. """ @module_build_service.utils.validate_koji_tag('wrong_tag_arg') def validate_koji_tag_programming_error(good_tag_arg, other_arg): @@ -178,6 +180,7 @@ class TestUtils(unittest.TestCase): validate_koji_tag_programming_error('dummy', 'other_val') def test_validate_koji_tag_bad_tag_value(self): + """ Test that we fail on a bad tag value. """ @module_build_service.utils.validate_koji_tag('tag_arg') def validate_koji_tag_bad_tag_value(tag_arg): @@ -187,6 +190,7 @@ class TestUtils(unittest.TestCase): validate_koji_tag_bad_tag_value('forbiddentagprefix-foo') def test_validate_koji_tag_bad_tag_value_in_list(self): + """ Test that we fail on a list containing bad tag value. """ @module_build_service.utils.validate_koji_tag('tag_arg') def validate_koji_tag_bad_tag_value_in_list(tag_arg): @@ -197,6 +201,7 @@ class TestUtils(unittest.TestCase): 'module-foo', 'forbiddentagprefix-bar']) def test_validate_koji_tag_good_tag_value(self): + """ Test that we pass on a good tag value. """ @module_build_service.utils.validate_koji_tag('tag_arg') def validate_koji_tag_good_tag_value(tag_arg): @@ -206,6 +211,7 @@ class TestUtils(unittest.TestCase): validate_koji_tag_good_tag_value('module-foo'), True) def test_validate_koji_tag_good_tag_values_in_list(self): + """ Test that we pass on a list of good tag values. """ @module_build_service.utils.validate_koji_tag('tag_arg') def validate_koji_tag_good_tag_values_in_list(tag_arg): @@ -216,6 +222,8 @@ class TestUtils(unittest.TestCase): 'module-bar']), True) def test_validate_koji_tag_good_tag_value_in_dict(self): + """ Test that we pass on a dict arg with default key + and a good value. """ @module_build_service.utils.validate_koji_tag('tag_arg') def validate_koji_tag_good_tag_value_in_dict(tag_arg): @@ -225,6 +233,8 @@ class TestUtils(unittest.TestCase): validate_koji_tag_good_tag_value_in_dict({'name': 'module-foo'}), True) def test_validate_koji_tag_good_tag_value_in_dict_nondefault_key(self): + """ Test that we pass on a dict arg with non-default key + and a good value. """ @module_build_service.utils.validate_koji_tag('tag_arg', dict_key='nondefault') @@ -256,3 +266,15 @@ class TestUtils(unittest.TestCase): with self.assertRaises(ValidationError): validate_koji_tag_double_trouble('module-1', 'BADNEWS-2') + + def test_validate_koji_tag_is_None(self): + """ Test that we fail on a tag which is None. """ + + @module_build_service.utils.validate_koji_tag('tag_arg') + def validate_koji_tag_is_None(tag_arg): + pass + + with self.assertRaises(ValidationError) as cm: + validate_koji_tag_is_None(None) + + self.assertTrue(str(cm.exception).endswith(' No value provided.'))