Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change: add file: Lintable argument to <rule_class>.match{,task} methods #1535

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 9 additions & 2 deletions examples/rules/TaskHasTag.py
@@ -1,8 +1,13 @@
"""Example implementation of a rule requiring tasks to have tags set."""
from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class TaskHasTag(AnsibleLintRule):
"""Tasks must have tag."""
Expand All @@ -12,7 +17,9 @@ class TaskHasTag(AnsibleLintRule):
description = 'Tasks must have tag'
tags = ['productivity', 'tags']

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
"""Task matching method."""
if isinstance(task, str):
return False
Expand Down
6 changes: 5 additions & 1 deletion src/ansiblelint/_internal/rules.py
Expand Up @@ -2,6 +2,8 @@
from typing import TYPE_CHECKING, Any, Dict, List, Union

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.constants import odict
from ansiblelint.errors import MatchError
from ansiblelint.file_utils import Lintable
Expand Down Expand Up @@ -43,7 +45,9 @@ def matchlines(self, file: "Lintable") -> List["MatchError"]:
"""Return matches found for a specific line."""
return []

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: "Optional[Lintable]" = None
) -> Union[bool, str]:
"""Confirm if current rule is matching a specific task."""
return False

Expand Down
11 changes: 9 additions & 2 deletions src/ansiblelint/rules/CommandHasChangesCheckRule.py
Expand Up @@ -18,10 +18,15 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class CommandHasChangesCheckRule(AnsibleLintRule):
id = 'no-changed-when'
Expand All @@ -38,7 +43,9 @@ class CommandHasChangesCheckRule(AnsibleLintRule):

_commands = ['command', 'shell', 'raw']

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
if task["__ansible_action_type__"] == 'task':
if task["action"]["__ansible_module__"] in self._commands:
return (
Expand Down
11 changes: 9 additions & 2 deletions src/ansiblelint/rules/CommandsInsteadOfArgumentsRule.py
Expand Up @@ -19,11 +19,16 @@
# THE SOFTWARE.

import os
from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule
from ansiblelint.utils import convert_to_boolean, get_first_cmd_arg

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class CommandsInsteadOfArgumentsRule(AnsibleLintRule):
id = 'deprecated-command-syntax'
Expand All @@ -47,7 +52,9 @@ class CommandsInsteadOfArgumentsRule(AnsibleLintRule):
'rm': 'state=absent',
}

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
if task["action"]["__ansible_module__"] in self._commands:
first_cmd_arg = get_first_cmd_arg(task)
if not first_cmd_arg:
Expand Down
11 changes: 9 additions & 2 deletions src/ansiblelint/rules/CommandsInsteadOfModulesRule.py
Expand Up @@ -19,11 +19,16 @@
# THE SOFTWARE.

import os
from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule
from ansiblelint.utils import convert_to_boolean, get_first_cmd_arg

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class CommandsInsteadOfModulesRule(AnsibleLintRule):
id = 'command-instead-of-module'
Expand Down Expand Up @@ -59,7 +64,9 @@ class CommandsInsteadOfModulesRule(AnsibleLintRule):
'yum': 'yum',
}

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
if task['action']['__ansible_module__'] not in self._commands:
return False

Expand Down
11 changes: 9 additions & 2 deletions src/ansiblelint/rules/ComparisonToEmptyStringRule.py
Expand Up @@ -3,11 +3,16 @@

import re
import sys
from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule
from ansiblelint.utils import nested_items

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class ComparisonToEmptyStringRule(AnsibleLintRule):
id = 'empty-string-compare'
Expand All @@ -22,7 +27,9 @@ class ComparisonToEmptyStringRule(AnsibleLintRule):

empty_string_compare = re.compile("[=!]= ?(\"{2}|'{2})")

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
for k, v, _ in nested_items(task):
if k == 'when':
if isinstance(v, str):
Expand Down
11 changes: 9 additions & 2 deletions src/ansiblelint/rules/ComparisonToLiteralBoolRule.py
Expand Up @@ -2,11 +2,16 @@
# Copyright (c) 2018-2021, Ansible Project

import re
from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule
from ansiblelint.utils import nested_items

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class ComparisonToLiteralBoolRule(AnsibleLintRule):
id = 'literal-compare'
Expand All @@ -21,7 +26,9 @@ class ComparisonToLiteralBoolRule(AnsibleLintRule):

literal_bool_compare = re.compile("[=!]= ?(True|true|False|false)")

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
for k, v, _ in nested_items(task):
if k == 'when':
if isinstance(v, str):
Expand Down
11 changes: 9 additions & 2 deletions src/ansiblelint/rules/DeprecatedModuleRule.py
@@ -1,9 +1,14 @@
# Copyright (c) 2018, Ansible Project

from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class DeprecatedModuleRule(AnsibleLintRule):
id = 'deprecated-module'
Expand Down Expand Up @@ -60,7 +65,9 @@ class DeprecatedModuleRule(AnsibleLintRule):
'include',
]

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
module = task["action"]["__ansible_module__"]
if module in self._modules:
message = '{0} {1}'
Expand Down
11 changes: 9 additions & 2 deletions src/ansiblelint/rules/EnvVarsInCommandRule.py
Expand Up @@ -18,11 +18,16 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule
from ansiblelint.utils import FILENAME_KEY, LINE_NUMBER_KEY, get_first_cmd_arg

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class EnvVarsInCommandRule(AnsibleLintRule):
id = 'inline-env-var'
Expand Down Expand Up @@ -51,7 +56,9 @@ class EnvVarsInCommandRule(AnsibleLintRule):
FILENAME_KEY,
]

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
if task["action"]["__ansible_module__"] in ['command']:
first_cmd_arg = get_first_cmd_arg(task)
if not first_cmd_arg:
Expand Down
11 changes: 9 additions & 2 deletions src/ansiblelint/rules/GitHasVersionRule.py
Expand Up @@ -18,10 +18,15 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class GitHasVersionRule(AnsibleLintRule):
id = 'git-latest'
Expand All @@ -34,7 +39,9 @@ class GitHasVersionRule(AnsibleLintRule):
tags = ['idempotency']
version_added = 'historic'

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
return bool(
task['action']['__ansible_module__'] == 'git'
and task['action'].get('version', 'HEAD') == 'HEAD'
Expand Down
11 changes: 9 additions & 2 deletions src/ansiblelint/rules/MercurialHasRevisionRule.py
Expand Up @@ -18,10 +18,15 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class MercurialHasRevisionRule(AnsibleLintRule):
id = 'hg-latest'
Expand All @@ -34,7 +39,9 @@ class MercurialHasRevisionRule(AnsibleLintRule):
tags = ['idempotency']
version_added = 'historic'

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
return bool(
task['action']['__ansible_module__'] == 'hg'
and task['action'].get('revision', 'default') == 'default'
Expand Down
12 changes: 10 additions & 2 deletions src/ansiblelint/rules/MissingFilePermissionsRule.py
Expand Up @@ -17,10 +17,16 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


# Despite documentation mentioning 'preserve' only these modules support it:
_modules_with_preserve = (
'copy',
Expand Down Expand Up @@ -60,7 +66,9 @@ class MissingFilePermissionsRule(AnsibleLintRule):
'lineinfile': False,
}

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
module = task["action"]["__ansible_module__"]
mode = task['action'].get('mode', None)

Expand Down
12 changes: 9 additions & 3 deletions src/ansiblelint/rules/NestedJinjaRule.py
Expand Up @@ -22,10 +22,15 @@
# THE SOFTWARE.

import re
from typing import Any, Dict, Union
from typing import TYPE_CHECKING, Any, Dict, Union

from ansiblelint.rules import AnsibleLintRule

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.file_utils import Lintable


class NestedJinjaRule(AnsibleLintRule):
id = 'no-jinja-nesting'
Expand All @@ -42,8 +47,9 @@ class NestedJinjaRule(AnsibleLintRule):

pattern = re.compile(r"{{(?:[^{}]*)?[^'\"]{{")

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:

def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
command = "".join(
str(value)
# task properties are stored in the 'action' key
Expand Down
8 changes: 6 additions & 2 deletions src/ansiblelint/rules/NoFormattingInWhenRule.py
Expand Up @@ -3,6 +3,8 @@
from ansiblelint.rules import AnsibleLintRule

if TYPE_CHECKING:
from typing import Optional

from ansiblelint.constants import odict
from ansiblelint.errors import MatchError
from ansiblelint.file_utils import Lintable
Expand Down Expand Up @@ -31,7 +33,7 @@ def matchplay(
if 'roles' not in data or data['roles'] is None:
return errors
for role in data['roles']:
if self.matchtask(role):
if self.matchtask(role, file=file):
errors.append(self.create_matcherror(details=str({'when': role})))
if isinstance(data, list):
for play_item in data:
Expand All @@ -40,5 +42,7 @@ def matchplay(
errors = errors + sub_errors
return errors

def matchtask(self, task: Dict[str, Any]) -> Union[bool, str]:
def matchtask(
self, task: Dict[str, Any], file: 'Optional[Lintable]' = None
) -> Union[bool, str]:
return 'when' in task and not self._is_valid(task['when'])