Skip to content

Commit f6f8393

Browse files
Jkhall81ssbarneaalisonlhart
authored
fix: allow valid tabs in lineinfile nested in blocks (#4719) (#4881)
Co-authored-by: Sorin Sbarnea <[email protected]> Co-authored-by: Alison Hart <[email protected]>
1 parent fd89ca2 commit f6f8393

File tree

2 files changed

+36
-14
lines changed

2 files changed

+36
-14
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
- name: Example playbook
3+
hosts: localhost
4+
tasks:
5+
- name: Example block
6+
block:
7+
- name: This should now pass linting
8+
ansible.builtin.lineinfile:
9+
path: some.txt
10+
regexp: "^\t$" # Tab inside allowed key
11+
line: "string with \t inside"

src/ansiblelint/rules/no_tabs.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ def matchtask(
5454
file: Lintable | None = None,
5555
) -> list[MatchError]:
5656
result = []
57-
action = task["action"]["__ansible_module__"]
58-
for k, v, _ in nested_items_path(task):
57+
# Check the key/value pairs found by the nested pathing
58+
for k, v, _path in nested_items_path(task):
59+
# Check if the Key itself has a tab (almost never allowed)
5960
if isinstance(k, str) and "\t" in k and not has_jinja(k):
6061
result.append(
6162
self.create_matcherror(
@@ -64,19 +65,20 @@ def matchtask(
6465
filename=file,
6566
)
6667
)
67-
if (
68-
isinstance(v, str)
69-
and "\t" in v
70-
and (action, k) not in self.allow_list
71-
and not has_jinja(v)
72-
):
73-
result.append(
74-
self.create_matcherror(
75-
message=self.shortdesc,
76-
data=v,
77-
filename=file,
68+
69+
# Check if the Value has a tab
70+
if isinstance(v, str) and "\t" in v and not has_jinja(v):
71+
# We check if 'k' is in our allow_list for ANY of the modules
72+
is_allowed = any(k == allowed_key for _, allowed_key in self.allow_list)
73+
74+
if not is_allowed:
75+
result.append(
76+
self.create_matcherror(
77+
message=self.shortdesc,
78+
data=v,
79+
filename=file,
80+
)
7881
)
79-
)
8082
return result
8183

8284

@@ -102,3 +104,12 @@ def test_no_tabs_rule(default_rules_collection: RulesCollection) -> None:
102104
# 2.19 has more precise line:columns numbers so the effective result
103105
# is different.
104106
assert lines == [10, 13] or lines == [12, 15, 15], lines
107+
108+
@pytest.mark.libyaml
109+
def test_no_tabs_block_pass(default_rules_collection: RulesCollection) -> None:
110+
"""Verify that tabs are allowed in lineinfile even inside blocks."""
111+
results = Runner(
112+
"examples/playbooks/rule-no-tabs-block-pass.yml",
113+
rules=default_rules_collection,
114+
).run()
115+
assert len(results) == 0

0 commit comments

Comments
 (0)