Skip to content

Commit

Permalink
Fix transform exception with local_action with old syntax
Browse files Browse the repository at this point in the history
Fixes: #3740
  • Loading branch information
ssbarnea committed Sep 18, 2023
1 parent 0fa2929 commit 2c6c31b
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
WSLENV: FORCE_COLOR:PYTEST_REQPASS:TOXENV:GITHUB_STEP_SUMMARY
# Number of expected test passes, safety measure for accidental skip of
# tests. Update value if you add/remove tests.
PYTEST_REQPASS: 823
PYTEST_REQPASS: 824
steps:
- name: Activate WSL1
if: "contains(matrix.shell, 'wsl')"
Expand Down
5 changes: 5 additions & 0 deletions examples/playbooks/tasks/local_action.transformed.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
- name: Sample
# not fixable because we expect a dict instead of a str as value. This should
# be fix fixed by no-free-form before deprecated-local-action can fix it.
local_action: command echo 123
5 changes: 5 additions & 0 deletions examples/playbooks/tasks/local_action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
- name: Sample
# not fixable because we expect a dict instead of a str as value. This should
# be fix fixed by no-free-form before deprecated-local-action can fix it.
local_action: command echo 123
60 changes: 56 additions & 4 deletions src/ansiblelint/rules/deprecated_local_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,29 @@
# Copyright (c) 2018, Ansible Project
from __future__ import annotations

import copy
import logging
import sys
from typing import TYPE_CHECKING

from ansiblelint.rules import AnsibleLintRule, TransformMixin
from ansiblelint.runner import _get_matches
from ansiblelint.transformer import Transformer

if TYPE_CHECKING:
from pathlib import Path

from ruamel.yaml.comments import CommentedMap, CommentedSeq

from ansiblelint.config import Options
from ansiblelint.errors import MatchError
from ansiblelint.file_utils import Lintable
from ansiblelint.utils import Task


_logger = logging.getLogger(__name__)


class TaskNoLocalAction(AnsibleLintRule, TransformMixin):
"""Do not use 'local_action', use 'delegate_to: localhost'."""

Expand Down Expand Up @@ -45,16 +55,26 @@ def transform(
data: CommentedMap | CommentedSeq | str,
) -> None:
if match.tag == self.id:
target_task = self.seek(match.yaml_path, data)
# we do not want perform a partial modification accidentally
original_target_task = self.seek(match.yaml_path, data)
target_task = copy.deepcopy(original_target_task)
for _ in range(len(target_task)):
k, v = target_task.popitem(False)
if k == "local_action":
module_name = v["module"]
target_task[module_name] = None
target_task["delegate_to"] = "localhost"
if isinstance(v, dict):
module_name = v["module"]
target_task[module_name] = None
target_task["delegate_to"] = "localhost"
else:
_logger.debug(
"Ignored unexpected data inside %s transform.",
self.id,
)
return
else:
target_task[k] = v
match.fixed = True
original_target_task = target_task


# testing code to be loaded only with pytest or when executed the rule file
Expand All @@ -71,3 +91,35 @@ def test_local_action(default_rules_collection: RulesCollection) -> None:

assert len(results) == 1
assert results[0].tag == "deprecated-local-action"

def test_local_action_transform(
config_options: Options,
copy_examples_dir: tuple[Path, Path],
default_rules_collection: RulesCollection,
) -> None:
"""Test transform functionality for no-log-password rule."""
playbook: str = "examples/playbooks/tasks/local_action.yml"
config_options.write_list = ["all"]

config_options.lintables = [playbook]
runner_result = _get_matches(
rules=default_rules_collection,
options=config_options,
)
transformer = Transformer(result=runner_result, options=config_options)
transformer.run()

matches = runner_result.matches
assert len(matches) == 3

orig_dir, tmp_dir = copy_examples_dir
orig_playbook = orig_dir / playbook
expected_playbook = orig_dir / playbook.replace(".yml", ".transformed.yml")
transformed_playbook = tmp_dir / playbook

orig_playbook_content = orig_playbook.read_text()
expected_playbook_content = expected_playbook.read_text()
transformed_playbook_content = transformed_playbook.read_text()

assert orig_playbook_content == transformed_playbook_content
assert transformed_playbook_content == expected_playbook_content

0 comments on commit 2c6c31b

Please sign in to comment.