More informative playbook attribute errors (#77082)

* More informative playbook attribute errors

Co-authored-by: Sloane Hertel <19572925+s-hertel@users.noreply.github.com>
pull/77127/head
Brian Coca 3 years ago committed by GitHub
parent 8cbe1435c2
commit 143904f49b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
bugfixes:
- playbook/strategy have more informative 'attribute' based errors for playbook objects and handlers.

@ -16,10 +16,9 @@ from jinja2.exceptions import UndefinedError
from ansible import constants as C
from ansible import context
from ansible.errors import AnsibleError
from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleAssertionError
from ansible.module_utils.six import string_types
from ansible.module_utils.parsing.convert_bool import boolean
from ansible.errors import AnsibleParserError, AnsibleUndefinedVariable, AnsibleAssertionError
from ansible.module_utils._text import to_text, to_native
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.attribute import Attribute, FieldAttribute
@ -36,7 +35,7 @@ def _generic_g(prop_name, self):
try:
value = self._attributes[prop_name]
except KeyError:
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, prop_name))
raise AttributeError("'%s' does not have the keyword '%s'" % (self.__class__.__name__, prop_name))
if value is Sentinel:
value = self._attr_defaults[prop_name]
@ -51,7 +50,7 @@ def _generic_g_method(prop_name, self):
method = "_get_attr_%s" % prop_name
return getattr(self, method)()
except KeyError:
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, prop_name))
raise AttributeError("'%s' does not support the keyword '%s'" % (self.__class__.__name__, prop_name))
def _generic_g_parent(prop_name, self):
@ -64,7 +63,7 @@ def _generic_g_parent(prop_name, self):
except AttributeError:
value = self._attributes[prop_name]
except KeyError:
raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, prop_name))
raise AttributeError("'%s' nor it's parents support the keyword '%s'" % (self.__class__.__name__, prop_name))
if value is Sentinel:
value = self._attr_defaults[prop_name]
@ -146,12 +145,15 @@ class BaseMeta(type):
# method, or if the attribute is marked as not inheriting
# its value from a parent object
method = "_get_attr_%s" % attr_name
try:
if method in src_dict or method in dst_dict:
getter = partial(_generic_g_method, attr_name)
elif ('_get_parent_attribute' in dst_dict or '_get_parent_attribute' in src_dict) and value.inherit:
getter = partial(_generic_g_parent, attr_name)
else:
getter = partial(_generic_g, attr_name)
except AttributeError as e:
raise AnsibleParserError("Invalid playbook definition: %s" % to_native(e), orig_exc=e)
setter = partial(_generic_s, attr_name)
deleter = partial(_generic_d, attr_name)

@ -26,6 +26,7 @@ import pprint
import sys
import threading
import time
import traceback
from collections import deque
from multiprocessing import Lock
@ -42,7 +43,7 @@ from ansible.executor.process.worker import WorkerProcess
from ansible.executor.task_result import TaskResult
from ansible.executor.task_queue_manager import CallbackSend
from ansible.module_utils.six import string_types
from ansible.module_utils._text import to_text
from ansible.module_utils._text import to_text, to_native
from ansible.module_utils.connection import Connection, ConnectionError
from ansible.playbook.conditional import Conditional
from ansible.playbook.handler import Handler
@ -1037,10 +1038,14 @@ class StrategyBase:
# but this may take some work in the iterator and gets tricky when
# we consider the ability of meta tasks to flush handlers
for handler in handler_block.block:
try:
if handler.notified_hosts:
result = self._do_handler_run(handler, handler.get_name(), iterator=iterator, play_context=play_context)
if not result:
break
except AttributeError as e:
display.vvv(traceback.format_exc())
raise AnsibleParserError("Invalid handler definition for '%s'" % (handler.get_name()), orig_exc=e)
return result
def _do_handler_run(self, handler, handler_name, iterator, play_context, notified_hosts=None):

Loading…
Cancel
Save