Use consolidated ignore.txt in ansible-test. (#59618)

pull/58954/head
Matt Clay 5 years ago committed by GitHub
parent c1ee1f142d
commit db7e9aa051
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,99 @@
Sanity Tests » ignores
======================
Sanity tests for individual files can be skipped, and specific errors can be ignored.
When to Ignore Errors
---------------------
Sanity tests are designed to improve code quality and identify common issues with content.
When issues are identified during development, those issues should be corrected.
As development of Ansible continues, sanity tests are expanded to detect issues that previous releases could not.
To allow time for existing content to be updated to pass newer tests, ignore entries can be added.
New content should not use ignores for existing sanity tests.
When code is fixed to resolve sanity test errors, any relevant ignores must also be removed.
If the ignores are not removed, this will be reported as an unnecessary ignore error.
This is intended to prevent future regressions due to the same error recurring after being fixed.
When to Skip Tests
------------------
Although rare, there are reasons for skipping a sanity test instead of ignoring the errors it reports.
If a sanity test results in a traceback when processing content, that error cannot be ignored.
If this occurs, open a new `bug report <https://github.com/ansible/ansible/issues/new?template=bug_report.md>`_ for the issue so it can be fixed.
If the traceback occurs due to an issue with the content, that issue should be fixed.
If the content is correct, the test will need to be skipped until the bug in the sanity test is fixed.
Caution should be used when skipping sanity tests instead of ignoring them.
Since the test is skipped entirely, resolution of the issue will not be automatically detected.
This will prevent prevent regression detection from working once the issue has been resolved.
For this reason it is a good idea to periodically review skipped entries manually to verify they are required.
Ignore File Location
--------------------
The location of the ignore file depends on the type of content being tested.
Ansible Collections
~~~~~~~~~~~~~~~~~~~
Since sanity tests change between Ansible releases, a separate ignore file is needed for each Ansible major release.
The filename is ``test/sanity/ignore-X.Y.txt`` where ``X.Y`` is the Ansible release being used to test the collection.
Maintaining a separate file for each Ansible release allows a collection to pass tests for multiple versions of Ansible.
Ansible
~~~~~~~
When testing Ansible, all ignores are placed in the ``test/sanity/ignore.txt`` file.
Only a single file is needed because ``ansible-test`` is developed and released as a part of Ansible itself.
Ignore File Format
------------------
The ignore file contains one entry per line.
Each line consists of two columns, separated by a single space.
Comments may be added at the end of an entry, started with a hash (``#``) character, which can be proceeded by zero or more spaces.
Blank and comment only lines are not allowed.
The first column specifies the file path that the entry applies to.
File paths must be relative to the root of the content being tested.
This is either the Ansible source or an Ansible collection.
File paths cannot contain a space or the hash (``#``) character.
The second column specifies the sanity test that the entry applies to.
This will be the name of the sanity test.
If the sanity test is specific to a version of Python, the name will include a dash (``-``) and the relevant Python version.
If the named test uses error codes then the error code to ignore must be appended to the name of the test, separated by a colon (``:``).
Below are some example ignore entries for an Ansible collection::
roles/my_role/files/my_script.sh shellcheck:SC2154 # ignore undefined variable
plugins/modules/my_module.py validate-modules:E105 # ignore license check
plugins/modules/my_module.py import-3.8 # needs update to support collections.abc on Python 3.8+
It is also possible to skip a sanity test for a specific file.
This is done by adding ``!skip`` after the sanity test name in the second column.
When this is done, no error code is included, even if the sanity test uses error codes.
Below are some example skip entries for an Ansible collection::
plugins/module_utils/my_util.py validate-modules!skip # waiting for bug fix in module validator
plugins/lookup/my_plugin.py compile-2.6!skip # Python 2.6 is not supported on the controller
Ignore File Errors
------------------
There are various errors that can be reported for the ignore file itself:
- syntax errors parsing the ignore file
- references a file path that does not exist
- references to a sanity test that does not exist
- ignoring an error that does not occur
- ignoring a file which is skipped
- duplicate entries

@ -57,13 +57,16 @@ from lib.test import (
TestSkipped, TestSkipped,
TestMessage, TestMessage,
calculate_best_confidence, calculate_best_confidence,
calculate_confidence,
) )
from lib.data import ( from lib.data import (
data_context, data_context,
) )
from lib.env import (
get_ansible_version,
)
COMMAND = 'sanity' COMMAND = 'sanity'
@ -174,6 +177,258 @@ def sanity_get_tests():
return SANITY_TESTS return SANITY_TESTS
class SanityIgnoreParser:
"""Parser for the consolidated sanity test ignore file."""
NO_CODE = '_'
def __init__(self, args): # type: (SanityConfig) -> None
if data_context().content.collection:
ansible_version = '%s.%s' % tuple(get_ansible_version(args).split('.')[:2])
ansible_label = 'Ansible %s' % ansible_version
file_name = 'ignore-%s.txt' % ansible_version
else:
ansible_label = 'Ansible'
file_name = 'ignore.txt'
self.args = args
self.relative_path = os.path.join('test/sanity', file_name)
self.path = os.path.join(data_context().content.root, self.relative_path)
self.ignores = collections.defaultdict(lambda: collections.defaultdict(dict)) # type: t.Dict[str, t.Dict[str, t.Dict[str, int]]]
self.skips = collections.defaultdict(lambda: collections.defaultdict(int)) # type: t.Dict[str, t.Dict[str, int]]
self.parse_errors = [] # type: t.List[t.Tuple[int, int, str]]
self.file_not_found_errors = [] # type: t.List[t.Tuple[int, str]]
lines = read_lines_without_comments(self.path, optional=True)
paths = set(data_context().content.all_files())
tests_by_name = {} # type: t.Dict[str, SanityTest]
versioned_test_names = set() # type: t.Set[str]
unversioned_test_names = {} # type: t.Dict[str, str]
display.info('Read %d sanity test ignore line(s) for %s from: %s' % (len(lines), ansible_label, self.relative_path), verbosity=1)
for test in sanity_get_tests():
if isinstance(test, SanityMultipleVersion):
versioned_test_names.add(test.name)
tests_by_name.update(dict(('%s-%s' % (test.name, python_version), test) for python_version in SUPPORTED_PYTHON_VERSIONS))
else:
unversioned_test_names.update(dict(('%s-%s' % (test.name, python_version), test.name) for python_version in SUPPORTED_PYTHON_VERSIONS))
tests_by_name[test.name] = test
for line_no, line in enumerate(lines, start=1):
if not line:
self.parse_errors.append((line_no, 1, "Line cannot be empty or contain only a comment"))
continue
parts = line.split(' ')
path = parts[0]
codes = parts[1:]
if not path:
self.parse_errors.append((line_no, 1, "Line cannot start with a space"))
continue
if path not in paths:
self.file_not_found_errors.append((line_no, path))
continue
if not codes:
self.parse_errors.append((line_no, len(path), "Error code required after path"))
continue
code = codes[0]
if not code:
self.parse_errors.append((line_no, len(path) + 1, "Error code after path cannot be empty"))
continue
if len(codes) > 1:
self.parse_errors.append((line_no, len(path) + len(code) + 2, "Error code cannot contain spaces"))
continue
parts = code.split('!')
code = parts[0]
commands = parts[1:]
parts = code.split(':')
test_name = parts[0]
error_codes = parts[1:]
test = tests_by_name.get(test_name)
if not test:
unversioned_name = unversioned_test_names.get(test_name)
if unversioned_name:
self.parse_errors.append((line_no, len(path) + len(unversioned_name) + 2, "Sanity test '%s' cannot use a Python version like '%s'" % (
unversioned_name, test_name)))
elif test_name in versioned_test_names:
self.parse_errors.append((line_no, len(path) + len(test_name) + 1, "Sanity test '%s' requires a Python version like '%s-%s'" % (
test_name, test_name, args.python_version)))
else:
self.parse_errors.append((line_no, len(path) + 2, "Sanity test '%s' does not exist" % test_name))
continue
if commands and error_codes:
self.parse_errors.append((line_no, len(path) + len(test_name) + 2, "Error code cannot contain both '!' and ':' characters"))
continue
if commands:
command = commands[0]
if len(commands) > 1:
self.parse_errors.append((line_no, len(path) + len(test_name) + len(command) + 3, "Error code cannot contain multiple '!' characters"))
continue
if command == 'skip':
if not test.can_skip:
self.parse_errors.append((line_no, len(path) + len(test_name) + 2, "Sanity test '%s' cannot be skipped" % test_name))
continue
existing_line_no = self.skips.get(test_name, {}).get(path)
if existing_line_no:
self.parse_errors.append((line_no, 1, "Duplicate '%s' skip for path '%s' first found on line %d" % (test_name, path, existing_line_no)))
continue
self.skips[test_name][path] = line_no
continue
self.parse_errors.append((line_no, len(path) + len(test_name) + 2, "Command '!%s' not recognized" % command))
continue
if not test.can_ignore:
self.parse_errors.append((line_no, len(path) + 1, "Sanity test '%s' cannot be ignored" % test_name))
continue
if test.error_code:
if not error_codes:
self.parse_errors.append((line_no, len(path) + len(test_name) + 1, "Sanity test '%s' requires an error code" % test_name))
continue
error_code = error_codes[0]
if len(error_codes) > 1:
self.parse_errors.append((line_no, len(path) + len(test_name) + len(error_code) + 3, "Error code cannot contain multiple ':' characters"))
continue
else:
if error_codes:
self.parse_errors.append((line_no, len(path) + len(test_name) + 2, "Sanity test '%s' does not support error codes" % test_name))
continue
error_code = self.NO_CODE
existing = self.ignores.get(test_name, {}).get(path, {}).get(error_code)
if existing:
if test.error_code:
self.parse_errors.append((line_no, 1, "Duplicate '%s' ignore for error code '%s' for path '%s' first found on line %d" % (
test_name, error_code, path, existing)))
else:
self.parse_errors.append((line_no, 1, "Duplicate '%s' ignore for path '%s' first found on line %d" % (
test_name, path, existing)))
continue
self.ignores[test_name][path][error_code] = line_no
@staticmethod
def load(args): # type: (SanityConfig) -> SanityIgnoreParser
"""Return the current SanityIgnore instance, initializing it if needed."""
try:
return SanityIgnoreParser.instance
except AttributeError:
pass
SanityIgnoreParser.instance = SanityIgnoreParser(args)
return SanityIgnoreParser.instance
class SanityIgnoreProcessor:
"""Processor for sanity test ignores for a single run of one sanity test."""
def __init__(self,
args, # type: SanityConfig
name, # type: str
code, # type: t.Optional[str]
python_version, # type: t.Optional[str]
): # type: (...) -> None
if python_version:
full_name = '%s-%s' % (name, python_version)
else:
full_name = name
self.args = args
self.code = code
self.parser = SanityIgnoreParser.load(args)
self.ignore_entries = self.parser.ignores.get(full_name, {})
self.skip_entries = self.parser.skips.get(full_name, {})
self.used_line_numbers = set() # type: t.Set[int]
def filter_skipped_paths(self, paths): # type: (t.List[str]) -> t.List[str]
"""Return the given paths, with any skipped paths filtered out."""
return sorted(set(paths) - set(self.skip_entries.keys()))
def filter_skipped_targets(self, targets): # type: (t.List[TestTarget]) -> t.List[TestTarget]
"""Return the given targets, with any skipped paths filtered out."""
return sorted(target for target in targets if target.path not in self.skip_entries)
def process_errors(self, errors, paths): # type: (t.List[SanityMessage], t.List[str]) -> t.List[SanityMessage]
"""Return the given errors filtered for ignores and with any settings related errors included."""
errors = self.filter_messages(errors)
errors.extend(self.get_errors(paths))
errors = sorted(set(errors))
return errors
def filter_messages(self, messages): # type: (t.List[SanityMessage]) -> t.List[SanityMessage]
"""Return a filtered list of the given messages using the entries that have been loaded."""
filtered = []
for message in messages:
path_entry = self.ignore_entries.get(message.path)
if path_entry:
code = message.code if self.code else SanityIgnoreParser.NO_CODE
line_no = path_entry.get(code)
if line_no:
self.used_line_numbers.add(line_no)
continue
filtered.append(message)
return filtered
def get_errors(self, paths): # type: (t.List[str]) -> t.List[SanityMessage]
"""Return error messages related to issues with the file."""
messages = []
# unused errors
unused = [] # type: t.List[t.Tuple[int, str, str]]
for path in paths:
path_entry = self.ignore_entries.get(path)
if not path_entry:
continue
unused.extend((line_no, path, code) for code, line_no in path_entry.items() if line_no not in self.used_line_numbers)
messages.extend(SanityMessage(
code=self.code,
message="Ignoring '%s' on '%s' is unnecessary" % (code, path) if self.code else "Ignoring '%s' is unnecessary" % path,
path=self.parser.relative_path,
line=line,
column=1,
confidence=calculate_best_confidence(((self.parser.path, line), (path, 0)), self.args.metadata) if self.args.metadata.changes else None,
) for line, path, code in unused)
return messages
class SanitySuccess(TestSuccess): class SanitySuccess(TestSuccess):
"""Sanity test success.""" """Sanity test success."""
def __init__(self, test, python_version=None): def __init__(self, test, python_version=None):
@ -233,6 +488,21 @@ class SanityTest(ABC):
self.name = name self.name = name
self.enabled = True self.enabled = True
@property
def error_code(self): # type: () -> t.Optional[str]
"""Error code for ansible-test matching the format used by the underlying test program, or None if the program does not use error codes."""
return None
@property
def can_ignore(self): # type: () -> bool
"""True if the test supports ignore entries."""
return True
@property
def can_skip(self): # type: () -> bool
"""True if the test supports skip entries."""
return True
class SanityCodeSmellTest(SanityTest): class SanityCodeSmellTest(SanityTest):
"""Sanity test script.""" """Sanity test script."""
@ -277,6 +547,10 @@ class SanityCodeSmellTest(SanityTest):
pattern = None pattern = None
data = None data = None
settings = self.load_processor(args)
paths = []
if self.config: if self.config:
output = self.config.get('output') output = self.config.get('output')
extensions = self.config.get('extensions') extensions = self.config.get('extensions')
@ -317,6 +591,8 @@ class SanityCodeSmellTest(SanityTest):
if files: if files:
paths = [p for p in paths if os.path.basename(p) in files] paths = [p for p in paths if os.path.basename(p) in files]
paths = settings.filter_skipped_paths(paths)
if not paths and not always: if not paths and not always:
return SanitySkipped(self.name) return SanitySkipped(self.name)
@ -344,14 +620,28 @@ class SanityCodeSmellTest(SanityTest):
column=int(m.get('column', 0)), column=int(m.get('column', 0)),
) for m in matches] ) for m in matches]
messages = settings.process_errors(messages, paths)
if not messages:
return SanitySuccess(self.name)
return SanityFailure(self.name, messages=messages) return SanityFailure(self.name, messages=messages)
if stderr or status: if stderr or status:
summary = u'%s' % SubprocessError(cmd=cmd, status=status, stderr=stderr, stdout=stdout) summary = u'%s' % SubprocessError(cmd=cmd, status=status, stderr=stderr, stdout=stdout)
return SanityFailure(self.name, summary=summary) return SanityFailure(self.name, summary=summary)
messages = settings.process_errors([], paths)
if messages:
return SanityFailure(self.name, messages=messages)
return SanitySuccess(self.name) return SanitySuccess(self.name)
def load_processor(self, args): # type: (SanityConfig) -> SanityIgnoreProcessor
"""Load the ignore processor for this sanity test."""
return SanityIgnoreProcessor(args, self.name, self.error_code, None)
class SanityFunc(SanityTest): class SanityFunc(SanityTest):
"""Base class for sanity test plugins.""" """Base class for sanity test plugins."""
@ -373,9 +663,9 @@ class SanitySingleVersion(SanityFunc):
:rtype: TestResult :rtype: TestResult
""" """
def load_settings(self, args, code): # type: (SanityConfig, t.Optional[str]) -> SanitySettings def load_processor(self, args): # type: (SanityConfig) -> SanityIgnoreProcessor
"""Load settings for this sanity test.""" """Load the ignore processor for this sanity test."""
return SanitySettings(args, self.name, code, None) return SanityIgnoreProcessor(args, self.name, self.error_code, None)
class SanityMultipleVersion(SanityFunc): class SanityMultipleVersion(SanityFunc):
@ -389,222 +679,9 @@ class SanityMultipleVersion(SanityFunc):
:rtype: TestResult :rtype: TestResult
""" """
def load_settings(self, args, code, python_version): # type: (SanityConfig, t.Optional[str], t.Optional[str]) -> SanitySettings def load_processor(self, args, python_version): # type: (SanityConfig, str) -> SanityIgnoreProcessor
"""Load settings for this sanity test.""" """Load the ignore processor for this sanity test."""
return SanitySettings(args, self.name, code, python_version) return SanityIgnoreProcessor(args, self.name, self.error_code, python_version)
class SanitySettings:
"""Settings for sanity tests."""
def __init__(self,
args, # type: SanityConfig
name, # type: str
code, # type: t.Optional[str]
python_version, # type: t.Optional[str]
): # type: (...) -> None
self.args = args
self.code = code
self.ignore_settings = SanitySettingsFile(args, name, 'ignore', code, python_version)
self.skip_settings = SanitySettingsFile(args, name, 'skip', code, python_version)
def filter_skipped_paths(self, paths): # type: (t.List[str]) -> t.List[str]
"""Return the given paths, with any skipped paths filtered out."""
return sorted(set(paths) - set(self.skip_settings.entries.keys()))
def filter_skipped_targets(self, targets): # type: (t.List[TestTarget]) -> t.List[TestTarget]
"""Return the given targets, with any skipped paths filtered out."""
return sorted(target for target in targets if target.path not in self.skip_settings.entries)
def process_errors(self, errors, paths): # type: (t.List[SanityMessage], t.List[str]) -> t.List[SanityMessage]
"""Return the given errors filtered for ignores and with any settings related errors included."""
errors = self.ignore_settings.filter_messages(errors)
errors.extend(self.ignore_settings.get_errors(paths))
errors.extend(self.skip_settings.get_errors([]))
for ignore_path, ignore_entry in self.ignore_settings.entries.items():
skip_entry = self.skip_settings.entries.get(ignore_path)
if not skip_entry:
continue
skip_line_no = skip_entry[SanitySettingsFile.NO_CODE]
for ignore_line_no in ignore_entry.values():
candidates = ((self.ignore_settings.path, ignore_line_no), (self.skip_settings.path, skip_line_no))
errors.append(SanityMessage(
code=self.code,
message="Ignoring '%s' is unnecessary due to skip entry on line %d of '%s'" % (ignore_path, skip_line_no, self.skip_settings.relative_path),
path=self.ignore_settings.relative_path,
line=ignore_line_no,
column=1,
confidence=calculate_best_confidence(candidates, self.args.metadata) if self.args.metadata.changes else None,
))
errors = sorted(set(errors))
return errors
class SanitySettingsFile:
"""Interface to sanity ignore or sanity skip file settings."""
NO_CODE = '_'
def __init__(self,
args, # type: SanityConfig
name, # type: str
mode, # type: str
code, # type: t.Optional[str]
python_version, # type: t.Optional[str]
): # type: (...) -> None
"""
:param mode: must be either "ignore" or "skip"
:param code: a code for ansible-test to use for internal errors, using a style that matches codes used by the test, or None if codes are not used
"""
if mode == 'ignore':
self.parse_codes = bool(code)
elif mode == 'skip':
self.parse_codes = False
else:
raise Exception('Unsupported mode: %s' % mode)
if name == 'compile':
filename = 'python%s-%s' % (python_version, mode)
else:
filename = '%s-%s' % (mode, python_version) if python_version else mode
self.args = args
self.code = code
self.relative_path = 'test/sanity/%s/%s.txt' % (name, filename)
self.path = os.path.join(data_context().content.root, self.relative_path)
self.entries = collections.defaultdict(dict) # type: t.Dict[str, t.Dict[str, int]]
self.parse_errors = [] # type: t.List[t.Tuple[int, int, str]]
self.file_not_found_errors = [] # type: t.List[t.Tuple[int, str]]
self.used_line_numbers = set() # type: t.Set[int]
lines = read_lines_without_comments(self.path, optional=True)
paths = set(data_context().content.all_files())
for line_no, line in enumerate(lines, start=1):
if not line:
continue
if line.startswith(' '):
self.parse_errors.append((line_no, 1, 'Line cannot start with a space'))
continue
if line.endswith(' '):
self.parse_errors.append((line_no, len(line), 'Line cannot end with a space'))
continue
parts = line.split(' ')
path = parts[0]
if path not in paths:
self.file_not_found_errors.append((line_no, path))
continue
if self.parse_codes:
if len(parts) < 2:
self.parse_errors.append((line_no, len(line), 'Code required after path'))
continue
code = parts[1]
if not code:
self.parse_errors.append((line_no, len(path) + 1, 'Code after path cannot be empty'))
continue
if len(parts) > 2:
self.parse_errors.append((line_no, len(path) + len(code) + 2, 'Code cannot contain spaces'))
continue
existing = self.entries.get(path, {}).get(code)
if existing:
self.parse_errors.append((line_no, 1, "Duplicate code '%s' for path '%s' first found on line %d" % (code, path, existing)))
continue
else:
if len(parts) > 1:
self.parse_errors.append((line_no, len(path) + 1, 'Path cannot contain spaces'))
continue
code = self.NO_CODE
existing = self.entries.get(path)
if existing:
self.parse_errors.append((line_no, 1, "Duplicate path '%s' first found on line %d" % (path, existing[code])))
continue
self.entries[path][code] = line_no
def filter_messages(self, messages): # type: (t.List[SanityMessage]) -> t.List[SanityMessage]
"""Return a filtered list of the given messages using the entries that have been loaded."""
filtered = []
for message in messages:
path_entry = self.entries.get(message.path)
if path_entry:
code = message.code if self.code else self.NO_CODE
line_no = path_entry.get(code)
if line_no:
self.used_line_numbers.add(line_no)
continue
filtered.append(message)
return filtered
def get_errors(self, paths): # type: (t.List[str]) -> t.List[SanityMessage]
"""Return error messages related to issues with the file."""
messages = []
# parse errors
messages.extend(SanityMessage(
code=self.code,
message=message,
path=self.relative_path,
line=line,
column=column,
confidence=calculate_confidence(self.path, line, self.args.metadata) if self.args.metadata.changes else None,
) for line, column, message in self.parse_errors)
# file not found errors
messages.extend(SanityMessage(
code=self.code,
message="File '%s' does not exist" % path,
path=self.relative_path,
line=line,
column=1,
confidence=calculate_best_confidence(((self.path, line), (path, 0)), self.args.metadata) if self.args.metadata.changes else None,
) for line, path in self.file_not_found_errors)
# unused errors
unused = [] # type: t.List[t.Tuple[int, str, str]]
for path in paths:
path_entry = self.entries.get(path)
if not path_entry:
continue
unused.extend((line_no, path, code) for code, line_no in path_entry.items() if line_no not in self.used_line_numbers)
messages.extend(SanityMessage(
code=self.code,
message="Ignoring '%s' on '%s' is unnecessary" % (code, path) if self.code else "Ignoring '%s' is unnecessary" % path,
path=self.relative_path,
line=line,
column=1,
confidence=calculate_best_confidence(((self.path, line), (path, 0)), self.args.metadata) if self.args.metadata.changes else None,
) for line, path, code in unused)
return messages
SANITY_TESTS = ( SANITY_TESTS = (

@ -48,7 +48,7 @@ class AnsibleDocTest(SanitySingleVersion):
:type targets: SanityTargets :type targets: SanityTargets
:rtype: TestResult :rtype: TestResult
""" """
settings = self.load_settings(args, None) settings = self.load_processor(args)
targets_include = [target for target in targets.include if os.path.splitext(target.path)[1] == '.py'] targets_include = [target for target in targets.include if os.path.splitext(target.path)[1] == '.py']
targets_include = settings.filter_skipped_targets(targets_include) targets_include = settings.filter_skipped_targets(targets_include)

@ -38,7 +38,7 @@ class CompileTest(SanityMultipleVersion):
:type python_version: str :type python_version: str
:rtype: TestResult :rtype: TestResult
""" """
settings = self.load_settings(args, None, python_version) settings = self.load_processor(args, python_version)
paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] == '.py' or i.path.startswith('bin/')) paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] == '.py' or i.path.startswith('bin/'))
paths = settings.filter_skipped_paths(paths) paths = settings.filter_skipped_paths(paths)

@ -0,0 +1,87 @@
"""Sanity test for the sanity ignore file."""
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from lib.sanity import (
SanityFailure,
SanityIgnoreParser,
SanitySingleVersion,
SanitySuccess,
SanityMessage,
)
from lib.test import (
calculate_confidence,
calculate_best_confidence,
)
from lib.config import (
SanityConfig,
)
class IgnoresTest(SanitySingleVersion):
"""Sanity test for sanity test ignore entries."""
@property
def can_ignore(self): # type: () -> bool
"""True if the test supports ignore entries."""
return False
@property
def can_skip(self): # type: () -> bool
"""True if the test supports skip entries."""
return False
# noinspection PyUnusedLocal
def test(self, args, targets): # pylint: disable=locally-disabled, unused-argument
"""
:type args: SanityConfig
:type targets: SanityTargets
:rtype: TestResult
"""
sanity_ignore = SanityIgnoreParser.load(args)
messages = []
# parse errors
messages.extend(SanityMessage(
message=message,
path=sanity_ignore.relative_path,
line=line,
column=column,
confidence=calculate_confidence(sanity_ignore.path, line, args.metadata) if args.metadata.changes else None,
) for line, column, message in sanity_ignore.parse_errors)
# file not found errors
messages.extend(SanityMessage(
message="File '%s' does not exist" % path,
path=sanity_ignore.relative_path,
line=line,
column=1,
confidence=calculate_best_confidence(((sanity_ignore.path, line), (path, 0)), args.metadata) if args.metadata.changes else None,
) for line, path in sanity_ignore.file_not_found_errors)
# conflicting ignores and skips
for test_name, ignores in sanity_ignore.ignores.items():
for ignore_path, ignore_entry in ignores.items():
skip_line_no = sanity_ignore.skips.get(test_name, {}).get(ignore_path)
if not skip_line_no:
continue
for ignore_line_no in ignore_entry.values():
messages.append(SanityMessage(
message="Ignoring '%s' is unnecessary due to skip entry on line %d" % (ignore_path, skip_line_no),
path=sanity_ignore.relative_path,
line=ignore_line_no,
column=1,
confidence=calculate_confidence(sanity_ignore.path, ignore_line_no, args.metadata) if args.metadata.changes else None,
))
if messages:
return SanityFailure(self.name, messages=messages)
return SanitySuccess(self.name)

@ -58,7 +58,7 @@ class ImportTest(SanityMultipleVersion):
:type python_version: str :type python_version: str
:rtype: TestResult :rtype: TestResult
""" """
settings = self.load_settings(args, None, python_version) settings = self.load_processor(args, python_version)
paths = sorted( paths = sorted(
i.path i.path

@ -88,6 +88,16 @@ class IntegrationAliasesTest(SanitySingleVersion):
self._shippable_yml_lines = [] # type: t.List[str] self._shippable_yml_lines = [] # type: t.List[str]
self._shippable_test_groups = {} # type: t.Dict[str, t.Set[int]] self._shippable_test_groups = {} # type: t.Dict[str, t.Set[int]]
@property
def can_ignore(self): # type: () -> bool
"""True if the test supports ignore entries."""
return False
@property
def can_skip(self): # type: () -> bool
"""True if the test supports skip entries."""
return False
@property @property
def shippable_yml_lines(self): def shippable_yml_lines(self):
""" """

@ -2,9 +2,10 @@
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
__metaclass__ = type __metaclass__ = type
import json
import os import os
import lib.types as t
from lib.sanity import ( from lib.sanity import (
SanitySingleVersion, SanitySingleVersion,
SanityMessage, SanityMessage,
@ -30,6 +31,10 @@ from lib.config import (
class Pep8Test(SanitySingleVersion): class Pep8Test(SanitySingleVersion):
"""Sanity test for PEP 8 style guidelines using pycodestyle.""" """Sanity test for PEP 8 style guidelines using pycodestyle."""
def error_code(self): # type: () -> t.Optional[str]
"""Error code for ansible-test matching the format used by the underlying test program, or None if the program does not use error codes."""
return 'A100'
def test(self, args, targets): def test(self, args, targets):
""" """
:type args: SanityConfig :type args: SanityConfig
@ -39,7 +44,7 @@ class Pep8Test(SanitySingleVersion):
current_ignore_file = os.path.join(ANSIBLE_ROOT, 'test/sanity/pep8/current-ignore.txt') current_ignore_file = os.path.join(ANSIBLE_ROOT, 'test/sanity/pep8/current-ignore.txt')
current_ignore = sorted(read_lines_without_comments(current_ignore_file, remove_blank_lines=True)) current_ignore = sorted(read_lines_without_comments(current_ignore_file, remove_blank_lines=True))
settings = self.load_settings(args, 'A100') settings = self.load_processor(args)
paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] == '.py' or i.path.startswith('bin/')) paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] == '.py' or i.path.startswith('bin/'))
paths = settings.filter_skipped_paths(paths) paths = settings.filter_skipped_paths(paths)

@ -6,6 +6,8 @@ import json
import os import os
import re import re
import lib.types as t
from lib.sanity import ( from lib.sanity import (
SanitySingleVersion, SanitySingleVersion,
SanityMessage, SanityMessage,
@ -35,13 +37,17 @@ from lib.data import (
class PslintTest(SanitySingleVersion): class PslintTest(SanitySingleVersion):
"""Sanity test using PSScriptAnalyzer.""" """Sanity test using PSScriptAnalyzer."""
def error_code(self): # type: () -> t.Optional[str]
"""Error code for ansible-test matching the format used by the underlying test program, or None if the program does not use error codes."""
return 'AnsibleTest'
def test(self, args, targets): def test(self, args, targets):
""" """
:type args: SanityConfig :type args: SanityConfig
:type targets: SanityTargets :type targets: SanityTargets
:rtype: TestResult :rtype: TestResult
""" """
settings = self.load_settings(args, 'AnsibleTest') settings = self.load_processor(args)
paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] in ('.ps1', '.psm1', '.psd1')) paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] in ('.ps1', '.psm1', '.psd1'))
paths = settings.filter_skipped_paths(paths) paths = settings.filter_skipped_paths(paths)

@ -50,6 +50,10 @@ UNSUPPORTED_PYTHON_VERSIONS = (
class PylintTest(SanitySingleVersion): class PylintTest(SanitySingleVersion):
"""Sanity test using pylint.""" """Sanity test using pylint."""
def error_code(self): # type: () -> t.Optional[str]
"""Error code for ansible-test matching the format used by the underlying test program, or None if the program does not use error codes."""
return 'ansible-test'
def test(self, args, targets): def test(self, args, targets):
""" """
:type args: SanityConfig :type args: SanityConfig
@ -64,7 +68,7 @@ class PylintTest(SanitySingleVersion):
plugin_names = sorted(p[0] for p in [ plugin_names = sorted(p[0] for p in [
os.path.splitext(p) for p in os.listdir(plugin_dir)] if p[1] == '.py' and p[0] != '__init__') os.path.splitext(p) for p in os.listdir(plugin_dir)] if p[1] == '.py' and p[0] != '__init__')
settings = self.load_settings(args, 'ansible-test') settings = self.load_processor(args)
paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] == '.py' or is_subdir(i.path, 'bin/')) paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] == '.py' or is_subdir(i.path, 'bin/'))
paths = settings.filter_skipped_paths(paths) paths = settings.filter_skipped_paths(paths)

@ -48,7 +48,7 @@ class RstcheckTest(SanitySingleVersion):
ignore_file = os.path.join(ANSIBLE_ROOT, 'test/sanity/rstcheck/ignore-substitutions.txt') ignore_file = os.path.join(ANSIBLE_ROOT, 'test/sanity/rstcheck/ignore-substitutions.txt')
ignore_substitutions = sorted(set(read_lines_without_comments(ignore_file, remove_blank_lines=True))) ignore_substitutions = sorted(set(read_lines_without_comments(ignore_file, remove_blank_lines=True)))
settings = self.load_settings(args, None) settings = self.load_processor(args)
paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] in ('.rst',)) paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] in ('.rst',))
paths = settings.filter_skipped_paths(paths) paths = settings.filter_skipped_paths(paths)

@ -25,6 +25,16 @@ class SanityDocsTest(SanitySingleVersion):
"""Sanity test for documentation of sanity tests.""" """Sanity test for documentation of sanity tests."""
ansible_only = True ansible_only = True
@property
def can_ignore(self): # type: () -> bool
"""True if the test supports ignore entries."""
return False
@property
def can_skip(self): # type: () -> bool
"""True if the test supports skip entries."""
return False
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
def test(self, args, targets): # pylint: disable=locally-disabled, unused-argument def test(self, args, targets): # pylint: disable=locally-disabled, unused-argument
""" """

@ -9,6 +9,8 @@ from xml.etree.ElementTree import (
Element, Element,
) )
import lib.types as t
from lib.sanity import ( from lib.sanity import (
SanitySingleVersion, SanitySingleVersion,
SanityMessage, SanityMessage,
@ -34,6 +36,10 @@ from lib.config import (
class ShellcheckTest(SanitySingleVersion): class ShellcheckTest(SanitySingleVersion):
"""Sanity test using shellcheck.""" """Sanity test using shellcheck."""
def error_code(self): # type: () -> t.Optional[str]
"""Error code for ansible-test matching the format used by the underlying test program, or None if the program does not use error codes."""
return 'AT1000'
def test(self, args, targets): def test(self, args, targets):
""" """
:type args: SanityConfig :type args: SanityConfig
@ -43,7 +49,7 @@ class ShellcheckTest(SanitySingleVersion):
exclude_file = os.path.join(ANSIBLE_ROOT, 'test/sanity/shellcheck/exclude.txt') exclude_file = os.path.join(ANSIBLE_ROOT, 'test/sanity/shellcheck/exclude.txt')
exclude = set(read_lines_without_comments(exclude_file, remove_blank_lines=True, optional=True)) exclude = set(read_lines_without_comments(exclude_file, remove_blank_lines=True, optional=True))
settings = self.load_settings(args, 'AT1000') settings = self.load_processor(args)
paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] == '.sh') paths = sorted(i.path for i in targets.include if os.path.splitext(i.path)[1] == '.sh')
paths = settings.filter_skipped_paths(paths) paths = settings.filter_skipped_paths(paths)

@ -5,6 +5,8 @@ __metaclass__ = type
import json import json
import os import os
import lib.types as t
from lib.sanity import ( from lib.sanity import (
SanitySingleVersion, SanitySingleVersion,
SanityMessage, SanityMessage,
@ -43,6 +45,10 @@ UNSUPPORTED_PYTHON_VERSIONS = (
class ValidateModulesTest(SanitySingleVersion): class ValidateModulesTest(SanitySingleVersion):
"""Sanity test using validate-modules.""" """Sanity test using validate-modules."""
def error_code(self): # type: () -> t.Optional[str]
"""Error code for ansible-test matching the format used by the underlying test program, or None if the program does not use error codes."""
return 'A100'
def test(self, args, targets): def test(self, args, targets):
""" """
:type args: SanityConfig :type args: SanityConfig
@ -62,7 +68,7 @@ class ValidateModulesTest(SanitySingleVersion):
env = ansible_environment(args, color=False) env = ansible_environment(args, color=False)
settings = self.load_settings(args, 'A100') settings = self.load_processor(args)
paths = sorted(i.path for i in targets.include if i.module) paths = sorted(i.path for i in targets.include if i.module)
paths = settings.filter_skipped_paths(paths) paths = settings.filter_skipped_paths(paths)

@ -5,6 +5,8 @@ __metaclass__ = type
import json import json
import os import os
import lib.types as t
from lib.sanity import ( from lib.sanity import (
SanitySingleVersion, SanitySingleVersion,
SanityMessage, SanityMessage,
@ -35,13 +37,17 @@ from lib.data import (
class YamllintTest(SanitySingleVersion): class YamllintTest(SanitySingleVersion):
"""Sanity test using yamllint.""" """Sanity test using yamllint."""
def error_code(self): # type: () -> t.Optional[str]
"""Error code for ansible-test matching the format used by the underlying test program, or None if the program does not use error codes."""
return 'ansible-test'
def test(self, args, targets): def test(self, args, targets):
""" """
:type args: SanityConfig :type args: SanityConfig
:type targets: SanityTargets :type targets: SanityTargets
:rtype: TestResult :rtype: TestResult
""" """
settings = self.load_settings(args, 'ansible-test') settings = self.load_processor(args)
paths = [i.path for i in targets.include if os.path.splitext(i.path)[1] in ('.yml', '.yaml')] paths = [i.path for i in targets.include if os.path.splitext(i.path)[1] in ('.yml', '.yaml')]

@ -1,42 +0,0 @@
lib/ansible/modules/utilities/logic/async_wrapper.py
lib/ansible/modules/utilities/helper/_accelerate.py
lib/ansible/modules/network/aos/_aos_asn_pool.py
lib/ansible/modules/network/aos/_aos_blueprint.py
lib/ansible/modules/network/aos/_aos_blueprint_param.py
lib/ansible/modules/network/aos/_aos_blueprint_virtnet.py
lib/ansible/modules/network/aos/_aos_device.py
lib/ansible/modules/network/aos/_aos_external_router.py
lib/ansible/modules/network/aos/_aos_ip_pool.py
lib/ansible/modules/network/aos/_aos_logical_device.py
lib/ansible/modules/network/aos/_aos_logical_device_map.py
lib/ansible/modules/network/aos/_aos_login.py
lib/ansible/modules/network/aos/_aos_rack_type.py
lib/ansible/modules/network/aos/_aos_template.py
lib/ansible/modules/cloud/azure/_azure.py
lib/ansible/modules/network/cumulus/_cl_bond.py
lib/ansible/modules/network/cumulus/_cl_bridge.py
lib/ansible/modules/network/cumulus/_cl_img_install.py
lib/ansible/modules/network/cumulus/_cl_interface.py
lib/ansible/modules/network/cumulus/_cl_interface_policy.py
lib/ansible/modules/network/cumulus/_cl_license.py
lib/ansible/modules/network/cumulus/_cl_ports.py
lib/ansible/modules/cloud/cloudstack/_cs_nic.py
lib/ansible/modules/cloud/docker/_docker.py
lib/ansible/modules/cloud/amazon/_ec2_ami_find.py
lib/ansible/modules/cloud/amazon/_ec2_ami_search.py
lib/ansible/modules/cloud/amazon/_ec2_facts.py
lib/ansible/modules/cloud/amazon/_ec2_remote_facts.py
lib/ansible/modules/cloud/amazon/_ec2_vpc.py
lib/ansible/modules/clustering/k8s/_kubernetes.py
lib/ansible/modules/network/citrix/_netscaler.py
lib/ansible/modules/network/nxos/_nxos_ip_interface.py
lib/ansible/modules/network/nxos/_nxos_mtu.py
lib/ansible/modules/network/nxos/_nxos_portchannel.py
lib/ansible/modules/network/nxos/_nxos_switchport.py
lib/ansible/modules/clustering/openshift/_oc.py
lib/ansible/modules/cloud/openstack/_os_server_actions.py
lib/ansible/modules/network/panos/_panos_nat_policy.py
lib/ansible/modules/network/panos/_panos_security_policy.py
lib/ansible/modules/cloud/amazon/_s3.py
lib/ansible/modules/cloud/vmware/_vsphere_guest.py
lib/ansible/modules/windows/_win_msi.py

@ -1,6 +0,0 @@
hacking/build_library/build_ansible/command_plugins/porting_guide.py # release process only, 3.6+ required
hacking/build_library/build_ansible/command_plugins/release_announcement.py # release process only, 3.6+ required
hacking/build_library/build_ansible/command_plugins/dump_config.py # docs build only, 2.7+ required
hacking/build_library/build_ansible/command_plugins/dump_keywords.py # docs build only, 2.7+ required
hacking/build_library/build_ansible/command_plugins/generate_man.py # docs build only, 2.7+ required
hacking/build_library/build_ansible/command_plugins/plugin_formatter.py # docs build only, 2.7+ required

@ -1,2 +0,0 @@
hacking/build_library/build_ansible/command_plugins/porting_guide.py # release process only, 3.6+ required
hacking/build_library/build_ansible/command_plugins/release_announcement.py # release process only, 3.6+ required

@ -1,2 +0,0 @@
hacking/build_library/build_ansible/command_plugins/porting_guide.py # release process only, 3.6+ required
hacking/build_library/build_ansible/command_plugins/release_announcement.py # release process only, 3.6+ required

File diff suppressed because it is too large Load Diff

@ -1 +0,0 @@
lib/ansible/module_utils/distro/_distro.py # bundled code we don't want to modify

@ -1,106 +0,0 @@
examples/scripts/ConfigureRemotingForAnsible.ps1 PSCustomUseLiteralPath
examples/scripts/upgrade_to_ps3.ps1 PSCustomUseLiteralPath
examples/scripts/upgrade_to_ps3.ps1 PSUseApprovedVerbs
lib/ansible/executor/powershell/async_watchdog.ps1 PSCustomUseLiteralPath
lib/ansible/executor/powershell/async_wrapper.ps1 PSCustomUseLiteralPath
lib/ansible/executor/powershell/exec_wrapper.ps1 PSCustomUseLiteralPath
lib/ansible/module_utils/powershell/Ansible.ModuleUtils.ArgvParser.psm1 PSUseApprovedVerbs
lib/ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 PSProvideCommentHelp # need to agree on best format for comment location
lib/ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 PSUseApprovedVerbs
lib/ansible/module_utils/powershell/Ansible.ModuleUtils.FileUtil.psm1 PSCustomUseLiteralPath
lib/ansible/module_utils/powershell/Ansible.ModuleUtils.FileUtil.psm1 PSProvideCommentHelp
lib/ansible/module_utils/powershell/Ansible.ModuleUtils.Legacy.psm1 PSCustomUseLiteralPath
lib/ansible/module_utils/powershell/Ansible.ModuleUtils.Legacy.psm1 PSUseApprovedVerbs
lib/ansible/module_utils/powershell/Ansible.ModuleUtils.LinkUtil.psm1 PSUseApprovedVerbs
lib/ansible/modules/windows/async_status.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/setup.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_acl_inheritance.ps1 PSAvoidTrailingWhitespace
lib/ansible/modules/windows/win_audit_rule.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_chocolatey.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_chocolatey_config.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_chocolatey_facts.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_chocolatey_source.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_copy.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_credential.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_dns_client.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_dns_client.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_domain.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_domain_controller.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_domain_controller.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_domain_membership.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_domain_membership.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_dotnet_ngen.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_dsc.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_eventlog.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_feature.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_file_version.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_firewall_rule.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_hotfix.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_hotfix.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_iis_virtualdirectory.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_iis_webapplication.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_iis_webapppool.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_iis_webbinding.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_iis_webbinding.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_iis_website.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_lineinfile.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_mapped_drive.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_package.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_package.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_pagefile.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_pagefile.ps1 PSUseSupportsShouldProcess
lib/ansible/modules/windows/win_pester.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_product_facts.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_rabbitmq_plugin.ps1 PSAvoidUsingInvokeExpression
lib/ansible/modules/windows/win_rabbitmq_plugin.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_rds_cap.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_rds_rap.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_rds_settings.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_regedit.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_region.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_regmerge.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_robocopy.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_security_policy.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_security_policy.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_share.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_shell.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_shortcut.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_snmp.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_say.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_unzip.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_unzip.ps1 PSUseApprovedVerbs
lib/ansible/modules/windows/win_updates.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_user_profile.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_wait_for.ps1 PSCustomUseLiteralPath
lib/ansible/modules/windows/win_webpicmd.ps1 PSAvoidUsingInvokeExpression
lib/ansible/modules/windows/win_xml.ps1 PSCustomUseLiteralPath
test/integration/targets/collections/collection_root_user/ansible_collections/testns/testcoll/plugins/module_utils/MyPSMU.psm1 PSUseApprovedVerbs
test/integration/targets/win_audit_rule/library/test_get_audit_rule.ps1 PSCustomUseLiteralPath
test/integration/targets/win_chocolatey/files/tools/chocolateyUninstall.ps1 PSCustomUseLiteralPath
test/integration/targets/win_chocolatey_source/library/choco_source.ps1 PSCustomUseLiteralPath
test/integration/targets/win_csharp_utils/library/ansible_basic_tests.ps1 PSCustomUseLiteralPath
test/integration/targets/win_csharp_utils/library/ansible_basic_tests.ps1 PSUseDeclaredVarsMoreThanAssignments # test setup requires vars to be set globally and not referenced in the same scope
test/integration/targets/win_csharp_utils/library/ansible_become_tests.ps1 PSCustomUseLiteralPath
test/integration/targets/win_exec_wrapper/library/test_fail.ps1 PSCustomUseLiteralPath
test/integration/targets/win_iis_webbinding/library/test_get_webbindings.ps1 PSUseApprovedVerbs
test/integration/targets/win_module_utils/library/argv_parser_test.ps1 PSUseApprovedVerbs
test/integration/targets/win_module_utils/library/backup_file_test.ps1 PSCustomUseLiteralPath
test/integration/targets/win_module_utils/library/command_util_test.ps1 PSCustomUseLiteralPath
test/integration/targets/win_psmodule/files/setup_modules.ps1 PSCustomUseLiteralPath
test/integration/targets/win_reboot/templates/post_reboot.ps1 PSCustomUseLiteralPath
test/integration/targets/win_script/files/test_script_creates_file.ps1 PSAvoidUsingCmdletAliases
test/integration/targets/win_script/files/test_script_removes_file.ps1 PSCustomUseLiteralPath
test/integration/targets/win_stat/library/test_symlink_file.ps1 PSCustomUseLiteralPath
test/integration/targets/win_user_right/library/test_get_right.ps1 PSCustomUseLiteralPath
test/runner/setup/windows-httptester.ps1 PSCustomUseLiteralPath
test/integration/targets/win_script/files/test_script.ps1 PSAvoidUsingWriteHost # Keep
test/integration/targets/win_script/files/test_script_with_args.ps1 PSAvoidUsingWriteHost # Keep
test/integration/targets/win_script/files/test_script_with_splatting.ps1 PSAvoidUsingWriteHost # Keep
lib/ansible/modules/windows/win_domain.ps1 PSAvoidUsingEmptyCatchBlock # Keep
lib/ansible/modules/windows/win_dsc.ps1 PSAvoidUsingEmptyCatchBlock # Keep
lib/ansible/modules/windows/win_find.ps1 PSAvoidUsingEmptyCatchBlock # Keep
lib/ansible/modules/windows/win_region.ps1 PSAvoidUsingEmptyCatchBlock # Keep
lib/ansible/modules/windows/win_uri.ps1 PSAvoidUsingEmptyCatchBlock # Keep
lib/ansible/modules/windows/win_domain_membership.ps1 PSAvoidGlobalVars # New PR
lib/ansible/modules/windows/win_domain_controller.ps1 PSAvoidGlobalVars # New PR
lib/ansible/modules/windows/win_pagefile.ps1 PSUseDeclaredVarsMoreThanAssignments # New PR - bug test_path should be testPath

@ -1,8 +0,0 @@
test/integration/targets/win_ping/library/win_ping_syntax_error.ps1
test/integration/targets/win_dsc/files/xTestDsc/1.0.0/DSCResources/ANSIBLE_xSetReboot/ANSIBLE_xSetReboot.psm1
test/integration/targets/win_dsc/files/xTestDsc/1.0.0/xTestDsc.psd1
test/integration/targets/win_dsc/files/xTestDsc/1.0.0/DSCResources/ANSIBLE_xTestResource/ANSIBLE_xTestResource.psm1
test/integration/targets/win_dsc/files/xTestDsc/1.0.1/xTestDsc.psd1
test/integration/targets/win_dsc/files/xTestDsc/1.0.1/DSCResources/ANSIBLE_xTestResource/ANSIBLE_xTestResource.psm1
test/integration/targets/win_psmodule/files/module/template.psd1
test/integration/targets/win_psmodule/files/module/template.psm1

@ -1,97 +0,0 @@
contrib/inventory/gce.py blacklisted-name
lib/ansible/cli/console.py blacklisted-name
lib/ansible/compat/selectors/_selectors2.py blacklisted-name
lib/ansible/executor/playbook_executor.py blacklisted-name
lib/ansible/executor/task_queue_manager.py blacklisted-name
lib/ansible/module_utils/facts/network/linux.py blacklisted-name
lib/ansible/module_utils/network/edgeswitch/edgeswitch_interface.py duplicate-string-formatting-argument
lib/ansible/module_utils/urls.py blacklisted-name
lib/ansible/modules/cloud/amazon/data_pipeline.py blacklisted-name
lib/ansible/modules/cloud/amazon/ec2_vpc_nat_gateway.py blacklisted-name
lib/ansible/modules/cloud/amazon/ec2_vpc_vpn.py blacklisted-name
lib/ansible/modules/cloud/amazon/efs.py blacklisted-name
lib/ansible/modules/cloud/amazon/efs_facts.py blacklisted-name
lib/ansible/modules/cloud/amazon/kinesis_stream.py blacklisted-name
lib/ansible/modules/cloud/amazon/s3_sync.py blacklisted-name
lib/ansible/modules/cloud/google/_gce.py blacklisted-name
lib/ansible/modules/cloud/google/gce_eip.py blacklisted-name
lib/ansible/modules/cloud/google/gce_img.py blacklisted-name
lib/ansible/modules/cloud/google/gce_instance_template.py blacklisted-name
lib/ansible/modules/cloud/google/gce_lb.py blacklisted-name
lib/ansible/modules/cloud/google/gce_mig.py blacklisted-name
lib/ansible/modules/cloud/google/gce_net.py blacklisted-name
lib/ansible/modules/cloud/google/gce_pd.py blacklisted-name
lib/ansible/modules/cloud/google/gce_snapshot.py blacklisted-name
lib/ansible/modules/cloud/google/gce_tag.py blacklisted-name
lib/ansible/modules/cloud/google/_gcp_backend_service.py blacklisted-name
lib/ansible/modules/cloud/google/_gcp_healthcheck.py blacklisted-name
lib/ansible/modules/cloud/lxc/lxc_container.py blacklisted-name
lib/ansible/modules/files/copy.py blacklisted-name
lib/ansible/modules/files/patch.py blacklisted-name
lib/ansible/modules/files/synchronize.py blacklisted-name
lib/ansible/modules/monitoring/statusio_maintenance.py blacklisted-name
lib/ansible/modules/monitoring/zabbix/zabbix_maintenance.py blacklisted-name
lib/ansible/modules/net_tools/basics/uri.py blacklisted-name
lib/ansible/modules/network/cloudengine/ce_command.py blacklisted-name
lib/ansible/modules/network/cloudengine/ce_dldp_interface.py blacklisted-name
lib/ansible/modules/network/cloudengine/ce_mlag_interface.py blacklisted-name
lib/ansible/modules/network/cloudvision/cv_server_provision.py blacklisted-name
lib/ansible/modules/network/illumos/dladm_etherstub.py blacklisted-name
lib/ansible/modules/network/illumos/dladm_iptun.py blacklisted-name
lib/ansible/modules/network/illumos/dladm_linkprop.py blacklisted-name
lib/ansible/modules/network/illumos/dladm_vlan.py blacklisted-name
lib/ansible/modules/network/illumos/dladm_vnic.py blacklisted-name
lib/ansible/modules/network/illumos/flowadm.py blacklisted-name
lib/ansible/modules/network/illumos/ipadm_addr.py blacklisted-name
lib/ansible/modules/network/illumos/ipadm_addrprop.py blacklisted-name
lib/ansible/modules/network/illumos/ipadm_if.py blacklisted-name
lib/ansible/modules/network/illumos/ipadm_ifprop.py blacklisted-name
lib/ansible/modules/network/illumos/ipadm_prop.py blacklisted-name
lib/ansible/modules/network/vyos/vyos_command.py blacklisted-name
lib/ansible/modules/packaging/language/pip.py blacklisted-name
lib/ansible/modules/packaging/os/yum.py blacklisted-name
lib/ansible/modules/source_control/git.py blacklisted-name
lib/ansible/modules/system/alternatives.py blacklisted-name
lib/ansible/modules/system/beadm.py blacklisted-name
lib/ansible/modules/system/cronvar.py blacklisted-name
lib/ansible/modules/system/dconf.py blacklisted-name
lib/ansible/modules/system/filesystem.py blacklisted-name
lib/ansible/modules/system/gconftool2.py blacklisted-name
lib/ansible/modules/system/interfaces_file.py blacklisted-name
lib/ansible/modules/system/iptables.py blacklisted-name
lib/ansible/modules/system/java_cert.py blacklisted-name
lib/ansible/modules/system/lvg.py blacklisted-name
lib/ansible/modules/system/lvol.py blacklisted-name
lib/ansible/modules/system/parted.py blacklisted-name
lib/ansible/modules/system/timezone.py blacklisted-name
lib/ansible/modules/utilities/logic/wait_for.py blacklisted-name
lib/ansible/modules/web_infrastructure/rundeck_acl_policy.py blacklisted-name
lib/ansible/parsing/vault/__init__.py blacklisted-name
lib/ansible/playbook/base.py blacklisted-name
lib/ansible/playbook/helpers.py blacklisted-name
lib/ansible/playbook/role/__init__.py blacklisted-name
lib/ansible/plugins/callback/hipchat.py blacklisted-name
lib/ansible/plugins/connection/lxc.py blacklisted-name
lib/ansible/plugins/lookup/sequence.py blacklisted-name
lib/ansible/plugins/strategy/__init__.py blacklisted-name
lib/ansible/plugins/strategy/linear.py blacklisted-name
lib/ansible/vars/hostvars.py blacklisted-name
test/integration/targets/module_utils/module_utils/bar0/foo.py blacklisted-name
test/integration/targets/module_utils/module_utils/foo.py blacklisted-name
test/integration/targets/module_utils/module_utils/sub/bar/__init__.py blacklisted-name
test/integration/targets/module_utils/module_utils/sub/bar/bar.py blacklisted-name
test/integration/targets/module_utils/module_utils/yak/zebra/foo.py blacklisted-name
test/legacy/cleanup_gce.py blacklisted-name
test/legacy/gce_credentials.py blacklisted-name
test/units/contrib/inventory/test_vmware_inventory.py blacklisted-name
test/units/executor/test_play_iterator.py blacklisted-name
test/units/module_utils/basic/test_run_command.py blacklisted-name
test/units/modules/cloud/amazon/test_ec2_vpc_nat_gateway.py blacklisted-name
test/units/modules/cloud/amazon/test_ec2_vpc_vpn.py blacklisted-name
test/units/modules/packaging/os/test_apt.py blacklisted-name
test/units/modules/system/interfaces_file/test_interfaces_file.py blacklisted-name
test/units/modules/system/test_known_hosts.py ansible-bad-function
test/units/parsing/vault/test_vault.py blacklisted-name
test/units/playbook/role/test_role.py blacklisted-name
test/units/plugins/test_plugins.py blacklisted-name
test/units/template/test_templar.py blacklisted-name

File diff suppressed because it is too large Load Diff

@ -1 +0,0 @@
lib/ansible/modules/utilities/logic/async_status.py
Loading…
Cancel
Save