1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
"""Implementation of no-prompting rule."""
from __future__ import annotations
import sys
from typing import TYPE_CHECKING, Any
from ansiblelint.constants import LINE_NUMBER_KEY
from ansiblelint.rules import AnsibleLintRule
if TYPE_CHECKING:
from ansiblelint.errors import MatchError
from ansiblelint.file_utils import Lintable
from ansiblelint.utils import Task
class NoPromptingRule(AnsibleLintRule):
"""Disallow prompting."""
id = "no-prompting"
description = (
"Disallow the use of vars_prompt or ansible.builtin.pause to better"
"accommodate unattended playbook runs and use in CI pipelines."
)
tags = ["opt-in"]
severity = "VERY_LOW"
version_added = "v6.0.3"
def matchplay(self, file: Lintable, data: dict[str, Any]) -> list[MatchError]:
"""Return matches found for a specific playbook."""
# If the Play uses the 'vars_prompt' section to set variables
if file.kind != "playbook": # pragma: no cover
return []
vars_prompt = data.get("vars_prompt", None)
if not vars_prompt:
return []
return [
self.create_matcherror(
message="Play uses vars_prompt",
lineno=vars_prompt[0][LINE_NUMBER_KEY],
filename=file,
),
]
def matchtask(
self,
task: Task,
file: Lintable | None = None,
) -> bool | str:
"""Return matches for ansible.builtin.pause tasks."""
# We do not want to trigger this rule if pause has either seconds or
# minutes defined, as that does not make it blocking.
return task["action"]["__ansible_module_original__"] in [
"pause",
"ansible.builtin.pause",
] and not (
task["action"].get("minutes", None) or task["action"].get("seconds", None)
)
if "pytest" in sys.modules:
from ansiblelint.config import options
from ansiblelint.rules import RulesCollection # pylint: disable=ungrouped-imports
from ansiblelint.runner import Runner # pylint: disable=ungrouped-imports
def test_no_prompting_fail() -> None:
"""Negative test for no-prompting."""
# For testing we want to manually enable opt-in rules
options.enable_list = ["no-prompting"]
rules = RulesCollection(options=options)
rules.register(NoPromptingRule())
results = Runner("examples/playbooks/rule-no-prompting.yml", rules=rules).run()
assert len(results) == 2
for result in results:
assert result.rule.id == "no-prompting"
|