1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-04-01 18:06:25 +00:00

Fix unreachable hosts causing exceptions

If finish_task is never called for a host the result object stays None, which caused an exception in update_span_data. This was the case for unreachable hosts, as the callback plugin did not implement v2_runner_on_unreachable.
This commit is contained in:
Alexander Freiherr von Buddenbrock 2026-01-23 16:04:28 +01:00
parent 81873ea059
commit fd178d4c28
No known key found for this signature in database
2 changed files with 23 additions and 6 deletions

View file

@ -196,7 +196,7 @@ class HostData:
Data about an individual host.
"""
def __init__(self, uuid, name, status, result):
def __init__(self, uuid, name, status, result=None):
self.uuid = uuid
self.name = name
self.status = status
@ -234,7 +234,7 @@ class OpenTelemetrySource:
uuid = task._uuid
if uuid in tasks_data:
tasks_data[uuid].add_host(HostData(host._uuid, host.name, "started", None))
tasks_data[uuid].add_host(HostData(host._uuid, host.name, "started"))
return
name = task.get_name().strip()
@ -246,7 +246,7 @@ class OpenTelemetrySource:
args = task.args
tasks_data[uuid] = TaskData(uuid, name, path, play_name, action, args)
tasks_data[uuid].add_host(HostData(host._uuid, host.name, "started", None))
tasks_data[uuid].add_host(HostData(host._uuid, host.name, "started"))
def finish_task(self, tasks_data, status, result, dump):
"""record the results of a task for a single host"""
@ -337,13 +337,13 @@ class OpenTelemetrySource:
if host_data.status != "included":
# Support loops
enriched_error_message = None
if "results" in host_data.result._result:
if host_data.result and "results" in host_data.result._result:
if host_data.status == "failed":
message = self.get_error_message_from_results(host_data.result._result["results"], task_data.action)
enriched_error_message = self.enrich_error_message_from_results(
host_data.result._result["results"], task_data.action
)
else:
elif host_data.result:
res = host_data.result._result
rc = res.get("rc", 0)
if host_data.status == "failed":
@ -593,6 +593,12 @@ class CallbackModule(CallbackBase):
self.tasks_data, "skipped", result, self.dump_results(self.tasks_data[result._task._uuid], result)
)
def v2_runner_on_unreachable(self, result):
self.errors += 1
self.opentelemetry.finish_task(
self.tasks_data, "failed", result, self.dump_results(self.tasks_data[result._task._uuid], result)
)
def v2_playbook_on_include(self, included_file):
self.opentelemetry.finish_task(self.tasks_data, "included", included_file, "")

View file

@ -11,7 +11,7 @@ from unittest.mock import MagicMock, Mock, patch
from ansible.executor.task_result import TaskResult
from ansible.playbook.task import Task
from ansible_collections.community.general.plugins.callback.opentelemetry import OpenTelemetrySource, TaskData
from ansible_collections.community.general.plugins.callback.opentelemetry import OpenTelemetrySource, TaskData, HostData
class TestOpentelemetry(unittest.TestCase):
@ -36,6 +36,10 @@ class TestOpentelemetry(unittest.TestCase):
self.my_task_result = TaskResult(
host=self.mock_host, task=self.mock_task, return_data={}, task_fields=self.task_fields
)
self.mock_span = Mock("MockSpan")
self.mock_span.set_status = MagicMock()
self.mock_span.set_attributes = MagicMock()
self.mock_span.end = MagicMock()
def test_run_task_with_host(self):
tasks_data = OrderedDict()
@ -83,6 +87,13 @@ class TestOpentelemetry(unittest.TestCase):
self.assertEqual(host_data.name, "include")
self.assertEqual(host_data.status, "ok")
@patch("ansible_collections.community.general.plugins.callback.opentelemetry.Status", create=True)
@patch("ansible_collections.community.general.plugins.callback.opentelemetry.StatusCode", create=True)
def test_update_span_data(self, mock_status_code, mock_status):
unfinished_host = HostData("myhost_uuid", "myhost", "unreachable")
self.opentelemetry.update_span_data(self.mock_task, unfinished_host, self.mock_span, True, True)
self.mock_span.end.assert_called()
def test_get_error_message(self):
test_cases = (
("my-exception", "my-msg", None, "my-exception"),