mirror of
https://pagure.io/fm-orchestrator.git
synced 2026-06-14 22:17:34 +08:00
Allow passing in multiple tag names to the validation decorator.
We have problems when we try to wrap one decorator around another. There are ways to do that with the [decorator](https://pypi.python.org/pypi/decorator) module nicely, however.. they are ugly. Take a look at this: https://github.com/micheles/decorator/blob/master/src/decorator.py#L217-L218 And this: https://github.com/micheles/decorator/blob/master/src/decorator.py#L185-L188 The approach in this PR is.. simpler.
This commit is contained in:
@@ -691,8 +691,7 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
|
|||||||
raise SystemError("Unknown tag: %s" % tag)
|
raise SystemError("Unknown tag: %s" % tag)
|
||||||
return taginfo
|
return taginfo
|
||||||
|
|
||||||
@module_build_service.utils.validate_koji_tag('tag_name')
|
@module_build_service.utils.validate_koji_tag(['tag_name', 'parent_tags'])
|
||||||
@module_build_service.utils.validate_koji_tag('parent_tags')
|
|
||||||
def _koji_add_many_tag_inheritance(self, tag_name, parent_tags):
|
def _koji_add_many_tag_inheritance(self, tag_name, parent_tags):
|
||||||
tag = self._get_tag(tag_name)
|
tag = self._get_tag(tag_name)
|
||||||
# highest priority num is at the end
|
# highest priority num is at the end
|
||||||
@@ -826,8 +825,7 @@ chmod 644 %buildroot/%_rpmconfigdir/macros.d/macros.modules
|
|||||||
|
|
||||||
self.koji_session.packageListAdd(self.module_tag['name'], package, owner)
|
self.koji_session.packageListAdd(self.module_tag['name'], package, owner)
|
||||||
|
|
||||||
@module_build_service.utils.validate_koji_tag('build_tag')
|
@module_build_service.utils.validate_koji_tag(['build_tag', 'dest_tag'])
|
||||||
@module_build_service.utils.validate_koji_tag('dest_tag')
|
|
||||||
def _koji_add_target(self, name, build_tag, dest_tag):
|
def _koji_add_target(self, name, build_tag, dest_tag):
|
||||||
"""
|
"""
|
||||||
:param name: target name
|
:param name: target name
|
||||||
|
|||||||
@@ -784,7 +784,7 @@ def get_reusable_component(session, module, component_name):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def validate_koji_tag(tag_arg_name, pre='', post='-', dict_key='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 value (which may be str or list)
|
||||||
against configurable list of koji tag prefixes.
|
against configurable list of koji tag prefixes.
|
||||||
@@ -794,33 +794,56 @@ def validate_koji_tag(tag_arg_name, pre='', post='-', dict_key='name'):
|
|||||||
tag prefix.
|
tag prefix.
|
||||||
:param dict_key: In case of a dict arg, inspect this key ('name' by default).
|
:param dict_key: In case of a dict arg, inspect this key ('name' by default).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if not isinstance(tag_arg_names, list):
|
||||||
|
tag_arg_names = [tag_arg_names]
|
||||||
|
|
||||||
def validation_decorator(function):
|
def validation_decorator(function):
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
call_args = inspect.getcallargs(function, *args, **kwargs)
|
call_args = inspect.getcallargs(function, *args, **kwargs)
|
||||||
if tag_arg_name not in call_args:
|
|
||||||
raise ProgrammingError(
|
for tag_arg_name in tag_arg_names:
|
||||||
'Koji tag validation: Inspected argument {} is not within function args.'
|
|
||||||
' The function was: {}.'
|
# If any of them don't appear in the function, then fail.
|
||||||
.format(tag_arg_name, function.__name__))
|
if tag_arg_name not in call_args:
|
||||||
if isinstance(call_args[tag_arg_name], dict):
|
|
||||||
if dict_key not in call_args[tag_arg_name]:
|
|
||||||
raise ProgrammingError(
|
raise ProgrammingError(
|
||||||
'Koji tag validation: Inspected dict arg {} does not contain {} key.'
|
'Koji tag validation: Inspected argument {} is not within function args.'
|
||||||
' The function was: {}.'
|
' The function was: {}.'
|
||||||
.format(call_args[tag_arg_name], dict_key, function.__name__))
|
.format(tag_arg_name, function.__name__))
|
||||||
tag_list = [call_args[tag_arg_name][dict_key]]
|
|
||||||
elif isinstance(call_args[tag_arg_name], list):
|
# If any of them are a dict, then use the provided dict_key
|
||||||
tag_list = call_args[tag_arg_name]
|
if isinstance(call_args[tag_arg_name], dict):
|
||||||
else:
|
if dict_key not in call_args[tag_arg_name]:
|
||||||
tag_list = [call_args[tag_arg_name]]
|
raise ProgrammingError(
|
||||||
for tag_prefix in conf.koji_tag_prefixes:
|
'Koji tag validation: Inspected dict arg {} does not contain {} key.'
|
||||||
if all([t.startswith(pre + tag_prefix + post) for t in tag_list]):
|
' The function was: {}.'
|
||||||
break
|
.format(call_args[tag_arg_name], dict_key, function.__name__))
|
||||||
else:
|
tag_list = [call_args[tag_arg_name][dict_key]]
|
||||||
raise ValidationError(
|
elif isinstance(call_args[tag_arg_name], list):
|
||||||
'Koji tag validation: {} does not satisfy any of allowed prefixes: {}'
|
tag_list = call_args[tag_arg_name]
|
||||||
.format(tag_list,
|
else:
|
||||||
[pre + p + post for p in conf.koji_tag_prefixes]))
|
tag_list = [call_args[tag_arg_name]]
|
||||||
|
|
||||||
|
# Check to make sure the provided values match our whitelist.
|
||||||
|
for allowed_prefix in conf.koji_tag_prefixes:
|
||||||
|
if all([t.startswith(pre + allowed_prefix + post) for t in tag_list]):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# Only raise this error if the given tags don't start with
|
||||||
|
# *any* of our allowed prefixes.
|
||||||
|
raise ValidationError(
|
||||||
|
'Koji tag validation: {} does not satisfy any of allowed prefixes: {}'
|
||||||
|
.format(tag_list,
|
||||||
|
[pre + p + post for p in conf.koji_tag_prefixes]))
|
||||||
|
|
||||||
|
# Finally.. after all that validation, call the original function
|
||||||
|
# and return its value.
|
||||||
return function(*args, **kwargs)
|
return function(*args, **kwargs)
|
||||||
|
|
||||||
|
# We're replacing the original function with our synthetic wrapper,
|
||||||
|
# but dress it up to make it look more like the original function.
|
||||||
|
wrapper.__name__ = function.__name__
|
||||||
|
wrapper.__doc__ = function.__doc__
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return validation_decorator
|
return validation_decorator
|
||||||
|
|||||||
@@ -233,3 +233,25 @@ class TestUtils(unittest.TestCase):
|
|||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
validate_koji_tag_good_tag_value_in_dict_nondefault_key(
|
validate_koji_tag_good_tag_value_in_dict_nondefault_key(
|
||||||
{'nondefault': 'module-foo'}), True)
|
{'nondefault': 'module-foo'}), True)
|
||||||
|
|
||||||
|
def test_validate_koji_tag_double_trouble_good(self):
|
||||||
|
""" Test that we pass on a list of tags that are good. """
|
||||||
|
|
||||||
|
expected = 'foo'
|
||||||
|
|
||||||
|
@module_build_service.utils.validate_koji_tag(['tag_arg1', 'tag_arg2'])
|
||||||
|
def validate_koji_tag_double_trouble(tag_arg1, tag_arg2):
|
||||||
|
return expected
|
||||||
|
|
||||||
|
actual = validate_koji_tag_double_trouble('module-1', 'module-2')
|
||||||
|
self.assertEquals(actual, expected)
|
||||||
|
|
||||||
|
def test_validate_koji_tag_double_trouble_bad(self):
|
||||||
|
""" Test that we fail on a list of tags that are bad. """
|
||||||
|
|
||||||
|
@module_build_service.utils.validate_koji_tag(['tag_arg1', 'tag_arg2'])
|
||||||
|
def validate_koji_tag_double_trouble(tag_arg1, tag_arg2):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
validate_koji_tag_double_trouble('module-1', 'BADNEWS-2')
|
||||||
|
|||||||
Reference in New Issue
Block a user