From 6da0313d59c2c05f887e8a1a5d8aee2a7c4db8ef Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Thu, 13 Apr 2023 10:36:03 +0100 Subject: [PATCH] Use temporary playbooks to check role syntax (#3280) --- .config/dictionary.txt | 1 + .gitignore | 3 ++ src/ansiblelint/rules/syntax_check.py | 44 ++++++++++++++++----------- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/.config/dictionary.txt b/.config/dictionary.txt index 1b9bb1b491..4ad0accd09 100644 --- a/.config/dictionary.txt +++ b/.config/dictionary.txt @@ -167,6 +167,7 @@ isdir isdisjoint iskeyword isort +isorted jsonfile jsonschema junitxml diff --git a/.gitignore b/.gitignore index e082ca2b0c..63f20da7c2 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ __pycache__ *.py[co] *$py.class +# Temporary ruff file +*.isorted + # Packages .Python env/ diff --git a/src/ansiblelint/rules/syntax_check.py b/src/ansiblelint/rules/syntax_check.py index 84a6a5af5e..8fda69fae8 100644 --- a/src/ansiblelint/rules/syntax_check.py +++ b/src/ansiblelint/rules/syntax_check.py @@ -5,6 +5,7 @@ import re import subprocess import sys +import tempfile from dataclasses import dataclass from typing import Any @@ -72,6 +73,7 @@ class AnsibleSyntaxCheckRule(AnsibleLintRule): def _get_ansible_syntax_check_matches(lintable: Lintable) -> list[MatchError]: """Run ansible syntax check and return a list of MatchError(s).""" default_rule: BaseRule = AnsibleSyntaxCheckRule() + fh = None results = [] if lintable.kind not in ("playbook", "role"): return [] @@ -79,26 +81,32 @@ def _get_ansible_syntax_check_matches(lintable: Lintable) -> list[MatchError]: with timed_info( "Executing syntax check on %s %s", lintable.kind, lintable.path ): + if lintable.kind == "role": + playbook_text = f""" +--- +- name: Temporary playbook for role syntax check + hosts: localhost + tasks: + - ansible.builtin.import_role: + name: {str(lintable.path.expanduser())} +""" + # pylint: disable=consider-using-with + fh = tempfile.NamedTemporaryFile(mode="w", suffix=".yml", prefix="play") + fh.write(playbook_text) + fh.flush() + playbook_path = fh.name + else: + playbook_path = str(lintable.path.expanduser()) # To avoid noisy warnings we pass localhost as current inventory: # [WARNING]: No inventory was parsed, only implicit localhost is available # [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' - if lintable.kind == "playbook": - cmd = [ - "ansible-playbook", - "-i", - "localhost,", - "--syntax-check", - str(lintable.path.expanduser()), - ] - else: # role - cmd = [ - "ansible", - "localhost", - "--syntax-check", - "--module-name=include_role", - "--args", - f"name={str(lintable.path.expanduser())}", - ] + cmd = [ + "ansible-playbook", + "-i", + "localhost,", + "--syntax-check", + playbook_path, + ] if options.extra_vars: cmd.extend(["--extra-vars", json.dumps(options.extra_vars)]) @@ -178,6 +186,8 @@ def _get_ansible_syntax_check_matches(lintable: Lintable) -> list[MatchError]: ) ) + if fh: + fh.close() return results