Ejemplo n.º 1
0
    def check(self, paths):  # type: (t.List[str]) -> None
        """Check the specified paths."""
        config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                   'config')

        yaml_conf = YamlLintConfig(
            file=os.path.join(config_path, 'default.yml'))
        module_conf = YamlLintConfig(
            file=os.path.join(config_path, 'modules.yml'))
        plugin_conf = YamlLintConfig(
            file=os.path.join(config_path, 'plugins.yml'))

        for path in paths:
            extension = os.path.splitext(path)[1]

            with open(path, encoding='utf-8') as file:
                contents = file.read()

            if extension in ('.yml', '.yaml'):
                self.check_yaml(yaml_conf, path, contents)
            elif extension == '.py':
                if path.startswith('lib/ansible/modules/') or path.startswith(
                        'plugins/modules/'):
                    conf = module_conf
                else:
                    conf = plugin_conf

                self.check_module(conf, path, contents)
            else:
                raise Exception('unsupported extension: %s' % extension)
Ejemplo n.º 2
0
    def check(self, paths):
        """
        :type paths: str
        """
        config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                   'config')

        yaml_conf = YamlLintConfig(
            file=os.path.join(config_path, 'default.yml'))
        module_conf = YamlLintConfig(
            file=os.path.join(config_path, 'modules.yml'))
        plugin_conf = YamlLintConfig(
            file=os.path.join(config_path, 'plugins.yml'))

        for path in paths:
            extension = os.path.splitext(path)[1]

            with open(path) as f:
                contents = f.read()

            if extension in ('.yml', '.yaml'):
                self.check_yaml(yaml_conf, path, contents)
            elif extension == '.py':
                if path.startswith('lib/ansible/modules/') or path.startswith(
                        'plugins/modules/'):
                    conf = module_conf
                else:
                    conf = plugin_conf

                self.check_module(conf, path, contents)
            else:
                raise Exception('unsupported extension: %s' % extension)
Ejemplo n.º 3
0
    def check(self, paths):
        """
        :type paths: str
        """
        yaml_conf = YamlLintConfig(
            file='test/sanity/yamllint/config/default.yml')
        module_conf = YamlLintConfig(
            file='test/sanity/yamllint/config/modules.yml')
        plugin_conf = YamlLintConfig(
            file='test/sanity/yamllint/config/plugins.yml')

        for path in paths:
            extension = os.path.splitext(path)[1]

            with open(path) as f:
                contents = f.read()

            if extension in ('.yml', '.yaml'):
                self.check_yaml(yaml_conf, path, contents)
            elif extension == '.py':
                if path.startswith('lib/ansible/plugins/'):
                    conf = plugin_conf
                else:
                    conf = module_conf

                self.check_module(conf, path, contents)
            else:
                raise Exception('unsupported extension: %s' % extension)
Ejemplo n.º 4
0
class YamllintRule(AnsibleLintRule):
    id = 'yaml'
    shortdesc = 'Violations reported by yamllint'
    description = DESCRIPTION
    severity = 'VERY_LOW'
    tags = ['formatting', 'yaml']
    version_added = 'v5.0.0'
    config = None
    has_dynamic_tags = True
    if "yamllint.config" in sys.modules:
        config = YamlLintConfig(content=YAMLLINT_CONFIG)
        # if we detect local yamllint config we use it but raise a warning
        # as this is likely to get out of sync with our internal config.
        for file in ['.yamllint', '.yamllint.yaml', '.yamllint.yml']:
            if os.path.isfile(file):
                _logger.warning(
                    "Loading custom %s config file, this extends our "
                    "internal yamllint config.",
                    file,
                )
                config_override = YamlLintConfig(file=file)
                config_override.extend(config)
                break
        _logger.debug("Effective yamllint rules used: %s", config.rules)

    def __init__(self) -> None:
        """Construct a rule instance."""
        # customize id by adding the one reported by yamllint
        self.id = self.__class__.id

    def matchyaml(self, file: Lintable) -> List["MatchError"]:
        """Return matches found for a specific YAML text."""
        matches: List["MatchError"] = []
        filtered_matches = []
        if file.kind == 'role':
            return matches

        if YamllintRule.config:
            for p in run_yamllint(file.content, YamllintRule.config):
                matches.append(
                    self.create_matcherror(
                        message=p.desc,
                        linenumber=p.line,
                        details="",
                        filename=str(file.path),
                        tag=p.rule,
                    )
                )

        if matches:
            lines = file.content.splitlines()
            for match in matches:
                # rule.linenumber starts with 1, not zero
                skip_list = get_rule_skips_from_line(lines[match.linenumber - 1])
                # print(skip_list)
                if match.rule.id not in skip_list and match.tag not in skip_list:
                    filtered_matches.append(match)
        return filtered_matches
Ejemplo n.º 5
0
    def test_disabled_with_changes(self):
        config_content = '{"extends": "default", "rules": {"key-ordering": "disable"}}'

        expected = """---
key 3:
    something: 456
    else: 45
key 2: v
key 1: val
lst:
    - {first_name: something, age: 42, last_name: else}
    - {age: 41, first_name: already, last_name: in_order}
"""

        content = """---
key 3:
    something: 456
    else: 45
key 2: v
key 1: val
lst:
    - {first_name: something, age: 42, last_name: else}
    - {age: 41, first_name: already, last_name: in_order}
"""
        output = read_and_format_text(content, YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 6
0
    def test_dos_lines_in_the_middle_with_comments(self):
        config_content = (
            '{"extends": "default", '
            '"rules": {"empty-lines": {"max": 5}, "new-lines": {"type": "dos"}}}'
        )

        expected = """---\r
test:\r
  key: value\r
\r
\r
# some test\r
\r
# some test\r
\r
  lst:\r
    - item1\r
"""

        content = """---\r
test:\r
  key: value\r
\r
\r
# some test\r
\r
# some test\r
\r
  lst:\r
    - item1\r
"""
        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 7
0
def lint_yaml_files(input_filepaths, file=sys.stderr):
    """
    Performs glinter YAML lint on a set of files.

    :param input_filepaths: List of input files to lint.
    :param file: The stream to write errors to.
    :returns: List of nits.
    """

    nits = []
    for path in input_filepaths:
        # yamllint needs both the file content and the path.
        file_content = None
        with path.open("r") as fd:
            file_content = fd.read()

        problems = linter.run(file_content, YamlLintConfig("extends: default"), path)
        nits.extend(p for p in problems)

    if len(nits):
        print("Sorry, Glean found some glinter nits:", file=file)
        for p in nits:
            print("{} ({}:{}) - {}".format(path, p.line, p.column, p.message))
        print("", file=file)
        print("Please fix the above nits to continue.", file=file)

    return nits
Ejemplo n.º 8
0
 def build_fake_config(self, conf):
     if conf is None:
         conf = {}
     else:
         conf = yaml.safe_load(conf)
     conf = {'extends': 'default', 'rules': conf}
     return YamlLintConfig(yaml.safe_dump(conf))
Ejemplo n.º 9
0
    def run(self):
        ''' run command '''
        if self.excludes is not None:
            print("Excludes:\n{0}".format(
                yaml.dump(self.excludes, default_flow_style=False)))

        config = YamlLintConfig(file=self.config_file)

        has_errors = False
        has_warnings = False

        if self.format == 'parsable':
            format_method = Format.parsable
        else:
            format_method = Format.standard_color

        for yaml_file in find_files(os.getcwd(), self.excludes, None,
                                    r'^[^\.].*\.ya?ml$'):
            first = True
            with open(yaml_file, 'r') as contents:
                for problem in linter.run(contents, config):
                    if first and self.format != 'parsable':
                        print('\n{0}:'.format(os.path.relpath(yaml_file)))
                        first = False

                    print(format_method(problem, yaml_file))
                    if problem.level == linter.PROBLEM_LEVELS[2]:
                        has_errors = True
                    elif problem.level == linter.PROBLEM_LEVELS[1]:
                        has_warnings = True

        if has_errors or has_warnings:
            print('yamllint issues found')
            raise SystemExit(1)
Ejemplo n.º 10
0
    def test_disabled_present(self):
        config_content = '{"extends": "default", "rules": {"empty-lines": "disable"}}'

        expected = """

---
test:
  key: value
  lst:
    - item1

"""

        content = """

---
test:
  key: value
  lst:
    - item1

"""
        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 11
0
 def test_ignore_file(self):
     config = YamlLintConfig('{"extends": "default", "ignore": "something.yml"}')
     self.assertTrue(is_matching_path("something.yaml", yaml_config=config))
     self.assertFalse(is_matching_path("folder/something.yml", yaml_config=config))
     self.assertTrue(is_matching_path(".yamllint", yaml_config=config))
     self.assertTrue(is_matching_path(".somefolder/test.yaml", yaml_config=config))
     self.assertFalse(is_matching_path("ghdfshs.fadsg", yaml_config=config))
Ejemplo n.º 12
0
    def test_any_quote_if_needed(self):
        config_content = "{extends: default, rules: {quoted-strings: {quote-type: any, required: only-when-needed}}}"

        expected = """---
test42: {something469: value}
test43:
    hey879: someothervalue
    hey880: somevalue
    required: "{this: needsquotes}"
    lst:
        - someitem
        - someotheritem
        - somefinalitem
        - item4
"""

        content = """---
test42: {something469: 'value'}
test43:
    hey879: "someothervalue"
    hey880: somevalue
    required: "{this: needsquotes}"
    lst:
        - 'someitem'
        - someotheritem
        - "somefinalitem"
        - item4
"""

        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 13
0
    def test_disabled(self):
        config_content = '{extends: default, rules: {quoted-strings: "disable"}}'

        expected = """---
test42: {something469: 'value'}
test43:
    hey879: "someothervalue"
    hey880: somevalue
    lst:
        - 'someitem'
        - someotheritem
        - "somefinalitem"
        - item4
"""

        content = """---
test42: {something469: 'value'}
test43:
    hey879: "someothervalue"
    hey880: somevalue
    lst:
        - 'someitem'
        - someotheritem
        - "somefinalitem"
        - item4
"""

        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 14
0
def lint_yaml_files(input_filepaths: Iterable[Path], file=sys.stderr) -> List:
    """
    Performs glinter YAML lint on a set of files.

    :param input_filepaths: List of input files to lint.
    :param file: The stream to write errors to.
    :returns: List of nits.
    """

    # Generic type since the actual type comes from yamllint, which we don't
    # control.
    nits: List = []
    for path in input_filepaths:
        # yamllint needs both the file content and the path.
        file_content = None
        with path.open("r", encoding="utf-8") as fd:
            file_content = fd.read()

        problems = linter.run(file_content, YamlLintConfig("extends: default"),
                              path)
        nits.extend((path, p) for p in problems)

    if len(nits):
        print("Sorry, Glean found some glinter nits:", file=file)
        for (path, p) in nits:
            print(f"{path} ({p.line}:{p.column}) - {p.message}")
        print("", file=file)
        print("Please fix the above nits to continue.", file=file)

    return [x[1] for x in nits]
Ejemplo n.º 15
0
def main():
    yaml_path = os.environ["INPUT_PATH"]
    strict = os.environ["INPUT_STRICT"] == "true"
    conf = YamlLintConfig("extends: default")
    warning_count = 0

    with open(yaml_path) as f:
        problems = linter.run(f, conf, yaml_path)

    for problem in problems:

        if problem.level == "warning" and strict:
            problem.level = "error"

        print(
            f"::{problem.level} file={yaml_path},line={problem.line},"
            f"col={problem.column}::{problem.desc} ({problem.rule})"
        )

        if problem.level == "warning":
            warning_count = warning_count + 1

        if problem.level == "error":
            sys.exit(1)

    print(f"::set-output name=warnings::{warning_count}")

    sys.exit(0)
Ejemplo n.º 16
0
    def test_allowed(self):
        config_content = (
            '{"extends": "default",'
            '"rules": {"empty-values": {"forbid-in-block-mappings": false, "forbid-in-flow-mappings": false}}}'
        )

        expected = """---
test42: {something469: }
test43:
    hey879:
    hey880:
    lst: [key: ]
    lst2:
        - key2:
"""

        content = """---
test42: {something469: }
test43:
    hey879:
    hey880: null
    lst: [key: null]
    lst2:
        - key2: null
"""
        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 17
0
    def test_default_enabled(self):
        config_content = '{"extends": "default", "rules": {"empty-values": "enable"}}'

        expected = """---
test42: {something469: null}
test43:
    hey879: null
    hey880: null
    lst: [key: null]
    lst2:
        - key2: null
"""

        content = """---
test42: {something469: }
test43:
    hey879:
    hey880: null
    lst: [key: null]
    lst2:
        - key2: null
"""
        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 18
0
    def test_double_quote(self):
        config_content = (
            "{extends: default,"
            " rules: {truthy: enable, quoted-strings: {quote-type: double, required: false}}}"
        )

        expected = """---
test42: {something469: true}
test43:
    noquote: TRuE
    hey879: "TRuE"
    "off": "FALSE"
"""

        content = """---
test42: {something469: true}
test43:
    noquote: TRuE
    hey879: 'TRuE'
    off: FALSE
"""

        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 19
0
    def test_any_quote_extra_required(self):
        config_content = (
            "{extends: default,"
            " rules: {quoted-strings: {quote-type: any, required: false, extra-required: [some]}}}"
        )

        expected = """---
test42: {something469: 'value'}
test43:
    hey879: "someothervalue"
    hey880: "somevalue"
    required: "{this: needsquotes}"
    lst:
        - 'someitem'
        - "someotheritem"
        - "somefinalitem"
        - item4
"""

        content = """---
test42: {something469: 'value'}
test43:
    hey879: "someothervalue"
    hey880: somevalue
    required: "{this: needsquotes}"
    lst:
        - 'someitem'
        - someotheritem
        - "somefinalitem"
        - item4
"""

        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 20
0
    def test_enabled(self):
        config_content = '{extends: default, rules: {colons: "enable"}}'

        expected = """---
test42: {something469: true}
test43:
    'with_colon:': TRuE
    hey879: 'TRuE'
    "off": "FALSE"
    lst:
        - somelist
        - something_else
"""

        content = """---
test42     :   {something469 :    true}
test43 :
    'with_colon:' :  TRuE
    hey879 : 'TRuE'
    "off" :  "FALSE"
    lst:
        - somelist
        - something_else
"""
        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 21
0
    def test_double_quote_required(self):
        config_content = "{extends: default, rules: {quoted-strings: {quote-type: double, required: true}}}"

        expected = """---
test42: {something469: "value"}
test43:
    hey879: "someothervalue"
    hey880: "somevalue"
    lst:
        - "someitem"
        - "someotheritem"
        - "somefinalitem"
        - "item4"
"""

        content = """---
test42: {something469: 'value'}
test43:
    hey879: "someothervalue"
    hey880: somevalue
    lst:
        - 'someitem'
        - someotheritem
        - "somefinalitem"
        - item4
"""

        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 22
0
    def test_disabled_dos_newline(self):
        config_content = (
            "{extends: default, rules: {colons: disable, new-lines: {type: dos}}}"
        )

        expected = """---\r
test42     :   {something469 :    true}\r
test43 :\r
    'with_colon:' :  TRuE\r
    hey879 : 'TRuE'\r
    "off" :  "FALSE"\r
    lst:\r
        - somelist\r
        - something_else\r
"""

        content = """---
test42     :   {something469 :    true}
test43 :
    'with_colon:' :  TRuE
    hey879 : 'TRuE'
    "off" :  "FALSE"
    lst:
        - somelist
        - something_else
"""

        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 23
0
    def test_max_space_after_is_3(self):
        config_content = "{extends: default, rules: {colons: {max-spaces-after: 3}}}"

        expected = """---
test42:   {something469:   true}
test43:
    'with_colon:':  TRuE
    hey879: 'TRuE'
    "off":  "FALSE"
    lst:
        - somelist
        - something_else
"""

        content = """---
test42     :   {something469 :    true}
test43 :
    'with_colon:' :  TRuE
    hey879 : 'TRuE'
    "off" :  "FALSE"
    lst:
        - somelist
        - something_else
"""
        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 24
0
    def test_default_no_seq_indent(self):
        config_content = ('{"extends": "default", "rules": {'
                          '"comments-indentation": "enable",'
                          '"indentation": {"indent-sequences": false}'
                          "}}")

        expected = """---
##############################
## Some text
# Fix me
test:  # First key
# thing
  key: value
  # valid
  lst:
  - item1
  # here too
"""

        content = """---
##############################
## Some text
# Fix me
test:  # First key
# thing
  key: value
# valid
  lst:
  - item1
    # here too
"""
        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 25
0
 def test_yaml_files_and_ignore(self):
     config = YamlLintConfig('{"yaml-files": ["*.yaml"], "ignore": "test.yaml"}')
     self.assertTrue(is_matching_path("something.yaml", yaml_config=config))
     self.assertFalse(is_matching_path("folder/something.yml", yaml_config=config))
     self.assertFalse(is_matching_path(".yamllint", yaml_config=config))
     self.assertFalse(is_matching_path(".somefolder/test.yaml", yaml_config=config))
     self.assertFalse(is_matching_path("ghdfshs.fadsg", yaml_config=config))
Ejemplo n.º 26
0
    def test_default_enabled_present(self):
        config_content = (
            '{"extends": "default", "rules": {"comments-indentation": "enable"}}'
        )

        expected = """---
##############################
## Some text
# Fix me
test:  # First key
# thing
  key: value
  # valid
  lst:
    - item1
"""

        content = """---
##############################
## Some text
# Fix me
test:  # First key
# thing
  key: value
  # valid
  lst:
    - item1
"""
        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)
Ejemplo n.º 27
0
def read_and_format_text(
    text: str,
    config: Optional[YamlLintConfig] = YamlLintConfig("extends: default")
) -> str:
    """
    Using getlocale and setlocale makes this function thread-unsafe
    """
    default_locale = getlocale(LC_COLLATE)
    if config and config.locale:
        setlocale(LC_COLLATE, config.locale)

    dumping_config = {}
    loading_config = {}
    rules = config.rules if config else {}
    for rule_id, rule in RULES.items():
        result = rule.apply_before_load(text, rules.get(rule_id), rules)

        text = result.text
        dumping_config.update(result.dumping_config)
        loading_config.update(result.loading_config)

    data = load(text, Loader, **loading_config)

    for rule_id, rule in RULES.items():
        data = rule.apply_before_dump(data, rules.get(rule_id), text, rules)

    result = dump(data, Dumper=RoundTripDumper, **dumping_config)

    for rule_id, rule in RULES.items():
        result = rule.apply_on_result(result, text, rules.get(rule_id), rules)

    if config and config.locale:
        setlocale(LC_COLLATE, default_locale)

    return result
Ejemplo n.º 28
0
def yaml_checker(path):
    """Read all yaml files in the directory and verify structure.

    :param str path: Path to test cases.

    :return: Number of errors.
    :rtype: int
    """
    path_for_check = Path(path)
    if path_for_check.is_dir():
        file_list = chain(path_for_check.glob('**/*.yaml'),
                          path_for_check.glob('**/*.yml'))
    else:
        file_list = [path_for_check]
    error_count = 0
    for file_name in file_list:
        with open(str(file_name)) as file:
            text = file.read()
        conf = YamlLintConfig(
            'document-start:\n'
            '  present: false\n'
            'rules:\n'
            '  line-length:\n'
            '    max: 250\n'
            '    allow-non-breakable-words: false\n'
            '    allow-non-breakable-inline-mappings: true\n')
        for err in linter.run(text, conf):
            print(Format.parsable(err, file_name))
            error_count += 1
        try:
            test_case = yaml.load(text)
        except Exception:
            error_count += 1
            print('{}: Error load YAML with PyYAML library'.format(file_name))
        else:
            error_count += check_section(test_case,
                                         'Description',
                                         file_name,
                                         is_markdown=True)
            error_count += check_section(test_case,
                                         'Requirements',
                                         file_name,
                                         section_type=list)
            if not check_section(
                    test_case, 'Steps', file_name, section_type=list):
                for step_count, step in enumerate(test_case['Steps'], 1):
                    error_count += check_section(step,
                                                 'Description',
                                                 file_name,
                                                 step_count,
                                                 is_markdown=True)
                    error_count += check_section(step,
                                                 'Expected result',
                                                 file_name,
                                                 step_count,
                                                 is_markdown=True)
            else:
                error_count += 1
    print('\n\t{} errors were found'.format(error_count))
    return error_count
Ejemplo n.º 29
0
def validate_yaml(yaml_in, yaml_fn):
    """Check with yamllint the yaml syntaxes
    Looking for duplicate keys."""
    try:
        import yamllint.linter as linter
        from yamllint.config import YamlLintConfig
    except ImportError:
        return
    conf = """{"extends": "relaxed",
               "rules": {"trailing-spaces": {"level": "warning"},
                         "new-lines": {"level": "warning"},
                         "new-line-at-end-of-file": {"level": "warning"}}}"""
    if utils.file_exists(yaml_in):
        with open(yaml_in) as in_handle:
            yaml_in = in_handle.read()
    out = linter.run(yaml_in, YamlLintConfig(conf))

    for problem in out:
        msg = '%(fn)s:%(line)s:%(col)s: [%(level)s] %(msg)s' % {
            'fn': yaml_fn,
            'line': problem.line,
            'col': problem.column,
            'level': problem.level,
            'msg': problem.message
        }
        if problem.level == "error":
            raise ValueError(msg)
Ejemplo n.º 30
0
    def test_dos_max_start_end(self):
        config_content = (
            '{"extends": "default", '
            '"rules": {"empty-lines": {"max-start": 2, "max-end": 1}, "new-lines": {"type": "dos"}}}'
        )

        expected = """\r
\r
---\r
test:\r
  key: value\r
  lst:\r
    - item1\r
\r
"""

        content = """\r
\r
\r
\r
---\r
test:\r
  key: value\r
  lst:\r
    - item1\r
\r
\r
\r
\r
\r
"""
        output = read_and_format_text(content,
                                      YamlLintConfig(content=config_content))
        self.assertEqual(expected, output)