mirror of
https://github.com/thegeeklab/ansible-later.git
synced 2024-11-25 14:20:45 +00:00
90 lines
2.5 KiB
Python
90 lines
2.5 KiB
Python
# Original code written by the authors of ansible-lint
|
|
|
|
import functools
|
|
|
|
from ansiblelater.rule import RuleBase
|
|
|
|
SORTER_TASKS = (
|
|
"name",
|
|
# "__module__",
|
|
# "action",
|
|
# "args",
|
|
None, # <-- None include all modules that not using action and *
|
|
# "when",
|
|
# "notify",
|
|
# "tags",
|
|
"block",
|
|
"rescue",
|
|
"always",
|
|
)
|
|
|
|
|
|
class CheckKeyOrder(RuleBase):
|
|
rid = "ANS129"
|
|
description = "Check for recommended key order"
|
|
helptext = "{type} key order can be improved to `{sorted_keys}`"
|
|
types = ["playbook", "task", "handler"]
|
|
|
|
def check(self, candidate, settings):
|
|
errors = []
|
|
tasks, err = self.get_normalized_tasks(candidate, settings)
|
|
|
|
if err:
|
|
return self.Result(candidate.path, err)
|
|
|
|
for task in tasks:
|
|
is_sorted, keys = self._sort_keys(task.get("__raw_task__"))
|
|
if not is_sorted:
|
|
errors.append(
|
|
self.Error(
|
|
task["__line__"],
|
|
self.helptext.format(type="task", sorted_keys=", ".join(keys)),
|
|
)
|
|
)
|
|
|
|
if candidate.kind == "playbook":
|
|
tasks, err = self.get_tasks(candidate, settings)
|
|
|
|
if err:
|
|
return self.Result(candidate.path, err)
|
|
|
|
for task in tasks:
|
|
is_sorted, keys = self._sort_keys(task)
|
|
if not is_sorted:
|
|
errors.append(
|
|
self.Error(
|
|
task["__line__"],
|
|
self.helptext.format(type="play", sorted_keys=", ".join(keys)),
|
|
)
|
|
)
|
|
|
|
return self.Result(candidate.path, errors)
|
|
|
|
@staticmethod
|
|
def _sort_keys(task):
|
|
if not task:
|
|
return True, []
|
|
|
|
keys = [str(key) for key in task if not key.startswith("_")]
|
|
sorted_keys = sorted(keys, key=functools.cmp_to_key(_task_property_sorter))
|
|
|
|
return (keys == sorted_keys), sorted_keys
|
|
|
|
|
|
def _task_property_sorter(property1, property2):
|
|
"""Sort task properties based on SORTER."""
|
|
v_1 = _get_property_sort_index(property1)
|
|
v_2 = _get_property_sort_index(property2)
|
|
return (v_1 > v_2) - (v_1 < v_2)
|
|
|
|
|
|
def _get_property_sort_index(name):
|
|
"""Return the index of the property in the sorter."""
|
|
a_index = -1
|
|
for i, v in enumerate(SORTER_TASKS):
|
|
if v == name:
|
|
return i
|
|
if v is None:
|
|
a_index = i
|
|
return a_index
|