Validate new blocks during copy
It is possible that a block is copied prior to validation, in which case some fields (like when) which should be something other than a string might not be. Using validate() in copy() is relatively harmless and ensures the blocks are in the proper structure. This also cleans up some of the finalized logic from an earlier commit and adds similar logic for validated. Fixes #17018
This commit is contained in:
parent
543f266801
commit
57fca2dde2
2 changed files with 26 additions and 19 deletions
|
@ -65,9 +65,6 @@ class Base:
|
||||||
_ignore_errors = FieldAttribute(isa='bool')
|
_ignore_errors = FieldAttribute(isa='bool')
|
||||||
_check_mode = FieldAttribute(isa='bool')
|
_check_mode = FieldAttribute(isa='bool')
|
||||||
|
|
||||||
# other internal params
|
|
||||||
_finalized = False
|
|
||||||
|
|
||||||
# param names which have been deprecated/removed
|
# param names which have been deprecated/removed
|
||||||
DEPRECATED_ATTRIBUTES = [
|
DEPRECATED_ATTRIBUTES = [
|
||||||
'sudo', 'sudo_user', 'sudo_pass', 'sudo_exe', 'sudo_flags',
|
'sudo', 'sudo_user', 'sudo_pass', 'sudo_exe', 'sudo_flags',
|
||||||
|
@ -81,9 +78,12 @@ class Base:
|
||||||
self._loader = None
|
self._loader = None
|
||||||
self._variable_manager = None
|
self._variable_manager = None
|
||||||
|
|
||||||
|
# other internal params
|
||||||
|
self._validated = False
|
||||||
|
self._finalized = False
|
||||||
|
|
||||||
# every object gets a random uuid:
|
# every object gets a random uuid:
|
||||||
self._uuid = uuid.uuid4()
|
self._uuid = uuid.uuid4()
|
||||||
#self._uuid = 1
|
|
||||||
|
|
||||||
# and initialize the base attributes
|
# and initialize the base attributes
|
||||||
self._initialize_base_attributes()
|
self._initialize_base_attributes()
|
||||||
|
@ -272,20 +272,25 @@ class Base:
|
||||||
def validate(self, all_vars=dict()):
|
def validate(self, all_vars=dict()):
|
||||||
''' validation that is done at parse time, not load time '''
|
''' validation that is done at parse time, not load time '''
|
||||||
|
|
||||||
# walk all fields in the object
|
if not self._validated:
|
||||||
for (name, attribute) in iteritems(self._get_base_attributes()):
|
# walk all fields in the object
|
||||||
|
for (name, attribute) in iteritems(self._get_base_attributes()):
|
||||||
|
|
||||||
# run validator only if present
|
# run validator only if present
|
||||||
method = getattr(self, '_validate_%s' % name, None)
|
method = getattr(self, '_validate_%s' % name, None)
|
||||||
if method:
|
if method:
|
||||||
method(attribute, name, getattr(self, name))
|
method(attribute, name, getattr(self, name))
|
||||||
else:
|
else:
|
||||||
# and make sure the attribute is of the type it should be
|
# and make sure the attribute is of the type it should be
|
||||||
value = getattr(self, name)
|
value = getattr(self, name)
|
||||||
if value is not None:
|
if value is not None:
|
||||||
if attribute.isa == 'string' and isinstance(value, (list, dict)):
|
if attribute.isa == 'string' and isinstance(value, (list, dict)):
|
||||||
raise AnsibleParserError("The field '%s' is supposed to be a string type,"
|
raise AnsibleParserError(
|
||||||
" however the incoming data structure is a %s" % (name, type(value)), obj=self.get_ds())
|
"The field '%s' is supposed to be a string type,"
|
||||||
|
" however the incoming data structure is a %s" % (name, type(value)), obj=self.get_ds()
|
||||||
|
)
|
||||||
|
|
||||||
|
self._validated = True
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
'''
|
'''
|
||||||
|
@ -303,9 +308,10 @@ class Base:
|
||||||
else:
|
else:
|
||||||
setattr(new_me, name, attr_val)
|
setattr(new_me, name, attr_val)
|
||||||
|
|
||||||
new_me._loader = self._loader
|
new_me._loader = self._loader
|
||||||
new_me._variable_manager = self._variable_manager
|
new_me._variable_manager = self._variable_manager
|
||||||
|
new_me._validated = self._validated
|
||||||
|
new_me._finalized = self._finalized
|
||||||
new_me._uuid = self._uuid
|
new_me._uuid = self._uuid
|
||||||
|
|
||||||
# if the ds value was set on the object, copy it to the new copy too
|
# if the ds value was set on the object, copy it to the new copy too
|
||||||
|
|
|
@ -192,6 +192,7 @@ class Block(Base, Become, Conditional, Taggable):
|
||||||
if self._role:
|
if self._role:
|
||||||
new_me._role = self._role
|
new_me._role = self._role
|
||||||
|
|
||||||
|
new_me.validate()
|
||||||
return new_me
|
return new_me
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
|
|
Loading…
Reference in a new issue