Skip to content

Commit 6428eed

Browse files
NichtJensSven Augustin
andauthored
facts: add FactProcessError to log, not explode, issues processing facts
Co-authored-by: Sven Augustin <[email protected]>
1 parent fb5724f commit 6428eed

File tree

4 files changed

+39
-2
lines changed

4 files changed

+39
-2
lines changed

src/pyinfra/api/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
FactError,
1515
FactTypeError,
1616
FactValueError,
17+
FactProcessError,
1718
InventoryError,
1819
OperationError,
1920
OperationTypeError,

src/pyinfra/api/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ class FactValueError(FactError, ValueError):
2929
"""
3030

3131

32+
class FactProcessError(FactError, RuntimeError):
33+
"""
34+
Exception raised when the data gathered for a fact cannot be processed.
35+
"""
36+
37+
3238
class OperationError(PyinfraError):
3339
"""
3440
Exception raised during fact gathering staging if an operation is unable to

src/pyinfra/api/facts.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from pyinfra import logger
2525
from pyinfra.api import StringCommand
2626
from pyinfra.api.arguments import all_global_arguments, pop_global_arguments
27+
from pyinfra.api.exceptions import FactProcessError
2728
from pyinfra.api.util import (
2829
get_kwargs_str,
2930
log_error_or_warning,
@@ -269,7 +270,22 @@ def _get_fact(
269270

270271
if status:
271272
if stdout_lines:
272-
data = fact.process(stdout_lines)
273+
try:
274+
data = fact.process(stdout_lines)
275+
except FactProcessError as e:
276+
log_error_or_warning(
277+
host,
278+
global_kwargs["_ignore_errors"],
279+
description=("could not process fact: {0} {1}").format(
280+
name, get_kwargs_str(fact_kwargs)
281+
),
282+
exception=e,
283+
)
284+
285+
# Check we've not failed
286+
if apply_failed_hosts and not global_kwargs["_ignore_errors"]:
287+
state.fail_hosts({host})
288+
273289
elif stderr_lines:
274290
# If we have error output and that error is sudo or su stating the user
275291
# does not exist, do not fail but instead return the default fact value.

src/pyinfra/api/util.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,11 @@ def log_operation_start(
222222

223223

224224
def log_error_or_warning(
225-
host: "Host", ignore_errors: bool, description: str = "", continue_on_error: bool = False
225+
host: "Host",
226+
ignore_errors: bool,
227+
description: str = "",
228+
continue_on_error: bool = False,
229+
exception: Exception | None = None,
226230
) -> None:
227231
log_func = logger.error
228232
log_color = "red"
@@ -237,6 +241,16 @@ def log_error_or_warning(
237241
if description:
238242
log_text = f"{log_text}: "
239243

244+
if exception:
245+
exc = exception.__cause__ or exception
246+
exc_text = "{0}: {1}".format(type(exc).__name__, exc)
247+
log_func(
248+
"{0}{1}".format(
249+
host.print_prefix,
250+
click.style(exc_text, log_color),
251+
),
252+
)
253+
240254
log_func(
241255
"{0}{1}{2}".format(
242256
host.print_prefix,

0 commit comments

Comments
 (0)