diff options
author | James Cammarata <jimi@sngx.net> | 2016-11-07 16:10:51 -0600 |
---|---|---|
committer | James Cammarata <jimi@sngx.net> | 2016-11-07 16:10:51 -0600 |
commit | b03fed804d41382a5e4002db08d56789244ed0a9 (patch) | |
tree | ecf8a2e39e7a5966cd4f53e58fd6a02311bade41 | |
parent | a0f27d552c4bee9374ab224cb969119e5d9c0cc5 (diff) | |
download | ansible-issue_18378_handler_environment_inheritance.tar.gz |
Add flag to Attributes to allow forcing parent inheritenceissue_18378_handler_environment_inheritance
In some situations, where the Base class defines an Attribute, the
BaseMeta class doesn't properly see the _get_parent_attribute or
_get_attr_<whatever> methods because of multiple layers of subclasses
(ie. Handler, which subclasses Task).
Fixes #18378
-rw-r--r-- | lib/ansible/playbook/attribute.py | 27 | ||||
-rw-r--r-- | lib/ansible/playbook/base.py | 21 |
2 files changed, 37 insertions, 11 deletions
diff --git a/lib/ansible/playbook/attribute.py b/lib/ansible/playbook/attribute.py index 3f55936ff6..f401eee3d7 100644 --- a/lib/ansible/playbook/attribute.py +++ b/lib/ansible/playbook/attribute.py @@ -23,17 +23,42 @@ from copy import deepcopy class Attribute: - def __init__(self, isa=None, private=False, default=None, required=False, listof=None, priority=0, class_type=None, always_post_validate=False, inherit=True): + def __init__( + self, + isa=None, + private=False, + default=None, + required=False, + listof=None, + priority=0, + class_type=None, + always_post_validate=False, + inherit=True, + force_parent=False, + ): + # the type of the field (string, bool, int, etc.) self.isa = isa + # whether the value of the attribute is private self.private = private + # the default value of the attribute, if not specified in the YAML self.default = default + # if required and not set, an error will be raised self.required = required + # if isa == 'list', this field can be used to control the types + # of each element in the list for validation purposes self.listof = listof + # the loading priority of the attribute self.priority = priority + # the class type of the attribute when isa == 'class' self.class_type = class_type + # whether or not the attribute should be post validated self.always_post_validate = always_post_validate + # whether or not the attribute should be inherited from the parent self.inherit = inherit + # force inheritence from the parent, even if _get_parent_attribute + # is not found in the class + self.force_parent = force_parent if default is not None and self.isa in ('list', 'dict', 'set'): self.default = deepcopy(default) diff --git a/lib/ansible/playbook/base.py b/lib/ansible/playbook/base.py index 77fd6890b5..f76927653f 100644 --- a/lib/ansible/playbook/base.py +++ b/lib/ansible/playbook/base.py @@ -111,7 +111,7 @@ class BaseMeta(type): method = "_get_attr_%s" % attr_name if method in src_dict or method in dst_dict: getter = partial(_generic_g_method, attr_name) - elif '_get_parent_attribute' in dst_dict and value.inherit: + elif '_get_parent_attribute' in dst_dict and value.inherit or value.force_parent: getter = partial(_generic_g_parent, attr_name) else: getter = partial(_generic_g, attr_name) @@ -148,20 +148,20 @@ class BaseMeta(type): class Base(with_metaclass(BaseMeta, object)): # connection/transport - _connection = FieldAttribute(isa='string') - _port = FieldAttribute(isa='int') - _remote_user = FieldAttribute(isa='string') + _connection = FieldAttribute(isa='string', force_parent=True) + _port = FieldAttribute(isa='int', force_parent=True) + _remote_user = FieldAttribute(isa='string', force_parent=True) # variables _vars = FieldAttribute(isa='dict', priority=100, inherit=False) # flags and misc. settings - _environment = FieldAttribute(isa='list') - _no_log = FieldAttribute(isa='bool') - _always_run = FieldAttribute(isa='bool') - _run_once = FieldAttribute(isa='bool') - _ignore_errors = FieldAttribute(isa='bool') - _check_mode = FieldAttribute(isa='bool') + _environment = FieldAttribute(isa='list', force_parent=True) + _no_log = FieldAttribute(isa='bool', force_parent=True) + _always_run = FieldAttribute(isa='bool', force_parent=True) + _run_once = FieldAttribute(isa='bool', force_parent=True) + _ignore_errors = FieldAttribute(isa='bool', force_parent=True) + _check_mode = FieldAttribute(isa='bool', force_parent=True) # param names which have been deprecated/removed DEPRECATED_ATTRIBUTES = [ @@ -535,3 +535,4 @@ class Base(with_metaclass(BaseMeta, object)): setattr(self, '_uuid', data.get('uuid')) self._finalized = data.get('finalized', False) self._squashed = data.get('squashed', False) + |