Skip to content

Commit

Permalink
Merge commit 'pull/origin/672'
Browse files Browse the repository at this point in the history
This change implements support for path expansion in rulesdirs
and exclude paths configs.

Resolves #541
  • Loading branch information
webknjaz committed Feb 27, 2020
2 parents 9b1c30b + 3aad8cb commit 5765765
Show file tree
Hide file tree
Showing 14 changed files with 80 additions and 24 deletions.
15 changes: 7 additions & 8 deletions lib/ansiblelint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,13 @@ def matchyaml(self, file, text):

class RulesCollection(object):

def __init__(self):
def __init__(self, rulesdirs=None):
if rulesdirs is None:
rulesdirs = []
self.rulesdirs = ansiblelint.utils.expand_paths_vars(rulesdirs)
self.rules = []
for rulesdir in self.rulesdirs:
self.extend(ansiblelint.utils.load_plugins(rulesdir))

def register(self, obj):
self.rules.append(obj)
Expand Down Expand Up @@ -193,12 +198,6 @@ def listtags(self):
results.append("{0} {1}".format(tag, tags[tag]))
return "\n".join(results)

@classmethod
def create_from_directory(cls, rulesdir):
result = cls()
result.rules = ansiblelint.utils.load_plugins(os.path.expanduser(rulesdir))
return result


class Match(object):

Expand Down Expand Up @@ -239,7 +238,7 @@ def __init__(self, rules, playbook, tags, skip_list, exclude_paths,
def _update_exclude_paths(self, exclude_paths):
if exclude_paths:
# These will be (potentially) relative paths
paths = [s.strip() for s in exclude_paths]
paths = ansiblelint.utils.expand_paths_vars(exclude_paths)
# Since ansiblelint.utils.find_children returns absolute paths,
# and the list of files we create in `Runner.run` can contain both
# relative and absolute paths, we need to cover both bases.
Expand Down
5 changes: 1 addition & 4 deletions lib/ansiblelint/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,7 @@ def main():
rulesdirs = options.rulesdir + [default_rulesdir]
else:
rulesdirs = options.rulesdir or [default_rulesdir]

rules = RulesCollection()
for rulesdir in rulesdirs:
rules.extend(RulesCollection.create_from_directory(rulesdir))
rules = RulesCollection(rulesdirs)

if options.listrules:
print(rules)
Expand Down
14 changes: 14 additions & 0 deletions lib/ansiblelint/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -863,3 +863,17 @@ def get_playbooks_and_roles(options=None):
print('Found playbooks: ' + ' '.join(playbooks))

return role_dirs + playbooks


def expand_path_vars(path):
"""Expand the environment or ~ variables in a path string."""
path = path.strip()
path = os.path.expanduser(path)
path = os.path.expandvars(path)
return path


def expand_paths_vars(paths):
"""Expand the environment or ~ variables in a list."""
paths = [expand_path_vars(p) for p in paths]
return paths
2 changes: 1 addition & 1 deletion test/TestDependenciesInMeta.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class TestDependenciesInMeta(unittest.TestCase):

def setUp(self):
rulesdir = os.path.join('lib', 'ansiblelint', 'rules')
self.rules = RulesCollection.create_from_directory(rulesdir)
self.rules = RulesCollection([rulesdir])

def test_bitbucket_in_meta_dependency_is_ok(self):
filename = 'test/dependency-in-meta/bitbucket.yml'
Expand Down
2 changes: 1 addition & 1 deletion test/TestImportIncludeRole.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
class TestImportIncludeRole(unittest.TestCase):
def setUp(self):
rulesdir = os.path.join('lib', 'ansiblelint', 'rules')
self.rules = RulesCollection.create_from_directory(rulesdir)
self.rules = RulesCollection([rulesdir])

# make dir and write role tasks to import or include
self.play_root = tempfile.mkdtemp()
Expand Down
2 changes: 1 addition & 1 deletion test/TestPretaskIncludePlaybook.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class TestTaskIncludes(unittest.TestCase):

def setUp(self):
rulesdir = os.path.join('lib', 'ansiblelint', 'rules')
self.rules = RulesCollection.create_from_directory(rulesdir)
self.rules = RulesCollection([rulesdir])

def test_pre_task_include_playbook(self):
filename = 'test/playbook-include/playbook_pre.yml'
Expand Down
2 changes: 1 addition & 1 deletion test/TestRuleProperties.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class TestAlwaysRun(unittest.TestCase):

def setUp(self):
self.collection.extend(
RulesCollection.create_from_directory(default_rulesdir)
RulesCollection([default_rulesdir])
)

def test_serverity_valid(self):
Expand Down
18 changes: 16 additions & 2 deletions test/TestRulesCollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import collections
import unittest
import os

from ansiblelint import RulesCollection

Expand All @@ -31,7 +32,7 @@ class TestRulesCollection(unittest.TestCase):
bracketsmatchtestfile = dict(path='test/bracketsmatchtest.yml', type='playbook')

def setUp(self):
self.rules = RulesCollection.create_from_directory('./test/rules')
self.rules = RulesCollection(['./test/rules'])

def test_load_collection_from_directory(self):
self.assertEqual(len(self.rules), 2)
Expand Down Expand Up @@ -75,6 +76,19 @@ def test_skip_non_existent_id(self):
self.assertEqual(len(matches), 3)

def test_no_duplicate_rule_ids(self):
real_rules = RulesCollection.create_from_directory('./lib/ansiblelint/rules')
real_rules = RulesCollection(['./lib/ansiblelint/rules'])
rule_ids = [rule.id for rule in real_rules]
self.assertEqual([x for x, y in collections.Counter(rule_ids).items() if y > 1], [])


def test_rulesdir_var_expansion(monkeypatch):
test_path = '/test/path'
monkeypatch.setenv('TEST_PATH', test_path)
test_rulesdirs = ['$TEST_PATH']
expansion_rules = RulesCollection(test_rulesdirs)
assert test_path in expansion_rules.rulesdirs


def test_rulesdir_user_expansion():
expansion_rules = RulesCollection(['~'])
assert os.path.expanduser('~') in expansion_rules.rulesdirs
21 changes: 19 additions & 2 deletions test/TestRunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@
import unittest

import ansiblelint
from ansiblelint import Runner, RulesCollection
from ansiblelint import default_rulesdir, Runner, RulesCollection
import ansiblelint.formatters


class TestRule(unittest.TestCase):

def setUp(self):
rulesdir = os.path.join('lib', 'ansiblelint', 'rules')
self.rules = RulesCollection.create_from_directory(rulesdir)
self.rules = RulesCollection([rulesdir])

def test_runner_count(self):
filename = 'test/nomatchestest.yml'
Expand Down Expand Up @@ -118,3 +118,20 @@ def test_files_not_scanned_twice(self):
run2 = runner.run()

assert ((len(run1) + len(run2)) == 1)


def test_runner_exclude_var_expansion(monkeypatch):
rules = RulesCollection([default_rulesdir])
filename = 'example/lots_of_warnings.yml'
monkeypatch.setenv('EXCLUDE_PATH', filename)
excludes = ['$EXCLUDE_PATH']
runner = Runner(rules, filename, [], [], excludes)
assert filename in runner.exclude_paths


def test_runner_exclude_user_expansion():
rules = RulesCollection([default_rulesdir])
filename = 'example/lots_of_warnings.yml'
excludes = ['~']
runner = Runner(rules, filename, [], [], excludes)
assert os.path.expanduser('~') in runner.exclude_paths
2 changes: 1 addition & 1 deletion test/TestSkipImportPlaybook.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
class TestSkipBeforeImport(unittest.TestCase):
def setUp(self):
rulesdir = os.path.join('lib', 'ansiblelint', 'rules')
self.rules = RulesCollection.create_from_directory(rulesdir)
self.rules = RulesCollection([rulesdir])

# make dir and write role tasks to import or include
self.play_root = tempfile.mkdtemp()
Expand Down
2 changes: 1 addition & 1 deletion test/TestSkipInsideYaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@

class TestSkipInsideYaml(unittest.TestCase):
rulesdir = os.path.join('lib', 'ansiblelint', 'rules')
collection = RulesCollection.create_from_directory(rulesdir)
collection = RulesCollection([rulesdir])

def setUp(self):
self.runner = RunFromText(self.collection)
Expand Down
2 changes: 1 addition & 1 deletion test/TestSkipPlaybookItems.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@

class TestSkipPlaybookItems(unittest.TestCase):
rulesdir = os.path.join('lib', 'ansiblelint', 'rules')
collection = RulesCollection.create_from_directory(rulesdir)
collection = RulesCollection([rulesdir])

def setUp(self):
self.runner = RunFromText(self.collection)
Expand Down
2 changes: 1 addition & 1 deletion test/TestTaskIncludes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class TestTaskIncludes(unittest.TestCase):

def setUp(self):
rulesdir = os.path.join('lib', 'ansiblelint', 'rules')
self.rules = RulesCollection.create_from_directory(rulesdir)
self.rules = RulesCollection([rulesdir])

def test_block_included_tasks(self):
filename = 'test/blockincludes.yml'
Expand Down
15 changes: 15 additions & 0 deletions test/TestUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# THE SOFTWARE.

import unittest
import os
try:
from pathlib import Path
except ImportError:
Expand Down Expand Up @@ -154,3 +155,17 @@ def test_normpath_with_string(self):
self.assertEqual(
utils.normpath("a/b/../"),
"a")


def test_expand_path_vars(monkeypatch):
test_path = '/test/path'
monkeypatch.setenv('TEST_PATH', test_path)
assert utils.expand_path_vars('~') == os.path.expanduser('~')
assert utils.expand_path_vars('$TEST_PATH') == test_path


def test_expand_paths_vars(monkeypatch):
test_path = '/test/path'
monkeypatch.setenv('TEST_PATH', test_path)
assert utils.expand_paths_vars(['~']) == [os.path.expanduser('~')]
assert utils.expand_paths_vars(['$TEST_PATH']) == [test_path]

0 comments on commit 5765765

Please sign in to comment.