summaryrefslogtreecommitdiffstats
path: root/lib/ansiblelint/rules/IncludeMissingFileRule.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansiblelint/rules/IncludeMissingFileRule.py')
-rw-r--r--lib/ansiblelint/rules/IncludeMissingFileRule.py67
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/ansiblelint/rules/IncludeMissingFileRule.py b/lib/ansiblelint/rules/IncludeMissingFileRule.py
new file mode 100644
index 0000000..57508fa
--- /dev/null
+++ b/lib/ansiblelint/rules/IncludeMissingFileRule.py
@@ -0,0 +1,67 @@
+# Copyright (c) 2020, Joachim Lusiardi
+# Copyright (c) 2020, Ansible Project
+
+import os.path
+
+import ansible.parsing.yaml.objects
+
+from ansiblelint.rules import AnsibleLintRule
+
+
+class IncludeMissingFileRule(AnsibleLintRule):
+ id = '505'
+ shortdesc = 'referenced files must exist'
+ description = (
+ 'All files referenced by by include / import tasks '
+ 'must exist. The check excludes files with jinja2 '
+ 'templates in the filename.'
+ )
+ severity = 'MEDIUM'
+ tags = ['task', 'bug']
+ version_added = 'v4.3.0'
+
+ def matchplay(self, file, data):
+ absolute_directory = file.get('absolute_directory', None)
+ results = []
+
+ # avoid failing with a playbook having tasks: null
+ for task in (data.get('tasks', []) or []):
+
+ # ignore None tasks or
+ # if the id of the current rule is not in list of skipped rules for this play
+ if not task or self.id in task.get('skipped_rules', ()):
+ continue
+
+ # collect information which file was referenced for include / import
+ referenced_file = None
+ for key, val in task.items():
+ if not (key.startswith('include_') or
+ key.startswith('import_') or
+ key == 'include'):
+ continue
+ if isinstance(val, ansible.parsing.yaml.objects.AnsibleMapping):
+ referenced_file = val.get('file', None)
+ else:
+ referenced_file = val
+ # take the file and skip the remaining keys
+ if referenced_file:
+ break
+
+ if referenced_file is None or absolute_directory is None:
+ continue
+
+ # make sure we have a absolute path here and check if it is a file
+ referenced_file = os.path.join(absolute_directory, referenced_file)
+
+ # skip if this is a jinja2 templated reference
+ if '{{' in referenced_file:
+ continue
+
+ # existing files do not produce any error
+ if os.path.isfile(referenced_file):
+ continue
+
+ results.append(({'referenced_file': referenced_file},
+ 'referenced missing file in %s:%i'
+ % (task['__file__'], task['__line__'])))
+ return results