diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index 4ee3480c73..3d8ed30a26 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -6,6 +6,7 @@ import hmac import json import logging import os +import re import shlex # PyYAML @@ -669,6 +670,7 @@ class Project(CommonModel): @property def playbooks(self): + valid_re = re.compile(r'^\s*?-?\s*?(?:hosts|include):\s*?.*?$') results = [] project_path = self.get_project_path() if project_path: @@ -677,17 +679,17 @@ class Project(CommonModel): if os.path.splitext(filename)[-1] != '.yml': continue playbook = os.path.join(dirpath, filename) - # Filter any invalid YAML files. - try: - data = yaml.safe_load(file(playbook).read()) - except (IOError, yaml.YAMLError): - continue # Filter files that do not have either hosts or top-level - # includes. + # includes. Use regex to allow files with invalid YAML to + # show up. + matched = False try: - if 'hosts' not in data[0] and 'include' not in data[0]: - continue - except (TypeError, IndexError, KeyError): + for line in file(playbook): + if valid_re.match(line): + matched = True + except IOError: + continue + if not matched: continue playbook = os.path.relpath(playbook, project_path) # Filter files in a roles subdirectory. diff --git a/awx/main/tests/projects.py b/awx/main/tests/projects.py index 9eea9eabd9..678c852ef3 100644 --- a/awx/main/tests/projects.py +++ b/awx/main/tests/projects.py @@ -118,11 +118,11 @@ class ProjectsTest(BaseTest): self.assertEqual(len(project.playbooks), 1) write_test_file(project, 'blah.yml', '') self.assertEqual(len(project.playbooks), 1) - # Invalid YAML + # Invalid YAML (now allowed to show) project = self.projects[4] self.assertEqual(len(project.playbooks), 1) write_test_file(project, 'blah.yml', TEST_PLAYBOOK + '----') - self.assertEqual(len(project.playbooks), 1) + self.assertEqual(len(project.playbooks), 2) # No hosts or includes project = self.projects[5] self.assertEqual(len(project.playbooks), 1)