ansible / ansible-lint

ansible-lint checks playbooks for practices and behavior that could potentially be improved and can fix some of the most common ones for you
https://ansible.readthedocs.io/projects/lint/
GNU General Public License v3.0
3.49k stars 660 forks source link

ansible-lint parses documentation too aggressively in .py files #4188

Open mhjacks opened 5 months ago

mhjacks commented 5 months ago
Summary

Running recent ansible-lint in the root of the servicenow.itsm collection repo results in some errors based on documentation that seem normal for documentation and not errors.

Issue Type
OS / ENVIRONMENT
ansible-lint --version
Desired Behavior

ansible-lint should not error on the .py file

Actual Behavior
DEBUG    Logging initialized to level 10
INFO     Identified /home/martjack/gitwork/servicenow.itsm as project root due .git directory.
DEBUG    Options: Options(_skip_ansible_syntax_check=False, cache_dir=PosixPath('/home/martjack/.cache/ansible-compat/cd907e'), colored=True, configured=True, cwd=PosixPath('/home/martjack/gitwork/servicenow.itsm'), display_relative_path=True, exclude_paths=['.cache', '.git', '.hg', '.svn', '.tox'], format=None, lintables=['plugins/inventory/now.py'], list_rules=False, list_tags=False, write_list=[], parseable=False, quiet=0, rulesdirs=[PosixPath('/home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansiblelint/rules')], skip_list=[], tags=[], verbosity=5, warn_list=['experimental', 'jinja', 'fqcn'], mock_filters=[], mock_modules=[], mock_roles=[], loop_var_prefix=None, only_builtins_allow_collections=[], only_builtins_allow_modules=[], var_naming_pattern=None, offline=None, project_dir='.', extra_vars=None, enable_list=[], skip_action_validation=True, strict=False, rules={}, profile=None, task_name_prefix='{stem} | ', sarif_file=None, config_file=None, generate_ignore=False, rulesdir=[], use_default_rules=False, version=False, list_profiles=False, ignore_file=None, max_tasks=100, max_block_depth=20)
DEBUG    CWD: /home/martjack/gitwork/servicenow.itsm
DEBUG    Logging initialized to level 10
DEBUG    Effective yamllint rules used: {'anchors': {'level': 'error', 'forbid-undeclared-aliases': True, 'forbid-duplicated-anchors': False, 'forbid-unused-anchors': False}, 'braces': {'level': 'error', 'forbid': False, 'min-spaces-inside': 0, 'max-spaces-inside': 1, 'min-spaces-inside-empty': -1, 'max-spaces-inside-empty': -1}, 'brackets': {'level': 'error', 'forbid': False, 'min-spaces-inside': 0, 'max-spaces-inside': 0, 'min-spaces-inside-empty': -1, 'max-spaces-inside-empty': -1}, 'colons': {'level': 'error', 'max-spaces-before': 0, 'max-spaces-after': 1}, 'commas': {'level': 'error', 'max-spaces-before': 0, 'min-spaces-after': 1, 'max-spaces-after': 1}, 'comments': {'level': 'warning', 'require-starting-space': True, 'ignore-shebangs': True, 'min-spaces-from-content': 1}, 'comments-indentation': False, 'document-end': False, 'document-start': False, 'empty-lines': {'level': 'error', 'max': 2, 'max-start': 0, 'max-end': 0}, 'empty-values': False, 'float-values': False, 'hyphens': {'level': 'error', 'max-spaces-after': 1}, 'indentation': {'level': 'error', 'spaces': 'consistent', 'indent-sequences': True, 'check-multi-line-strings': False}, 'key-duplicates': {'level': 'error', 'forbid-duplicated-merge-keys': False}, 'key-ordering': False, 'line-length': {'level': 'error', 'max': 160, 'allow-non-breakable-words': True, 'allow-non-breakable-inline-mappings': False}, 'new-line-at-end-of-file': {'level': 'error'}, 'new-lines': {'level': 'error', 'type': 'unix'}, 'octal-values': {'forbid-implicit-octal': True, 'forbid-explicit-octal': True, 'level': 'error'}, 'quoted-strings': False, 'trailing-spaces': {'level': 'error'}, 'truthy': {'level': 'warning', 'allowed-values': ['true', 'false'], 'check-keys': True}}
INFO     Set ANSIBLE_LIBRARY=/home/martjack/.cache/ansible-compat/cd907e/modules:plugins/modules:/home/martjack/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/home/martjack/.cache/ansible-compat/cd907e/collections:/home/martjack/.ansible/collections:/usr/share/ansible/collections
INFO     Set ANSIBLE_ROLES_PATH=/home/martjack/.cache/ansible-compat/cd907e/roles:/home/martjack/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
INFO     Running from /home/martjack/gitwork/servicenow.itsm : ansible-galaxy collection install -vvv --force /home/martjack/gitwork/servicenow.itsm
DEBUG    Effective yamllint rules used: {'anchors': {'level': 'error', 'forbid-undeclared-aliases': True, 'forbid-duplicated-anchors': False, 'forbid-unused-anchors': False}, 'braces': {'level': 'error', 'forbid': False, 'min-spaces-inside': 0, 'max-spaces-inside': 1, 'min-spaces-inside-empty': -1, 'max-spaces-inside-empty': -1}, 'brackets': {'level': 'error', 'forbid': False, 'min-spaces-inside': 0, 'max-spaces-inside': 0, 'min-spaces-inside-empty': -1, 'max-spaces-inside-empty': -1}, 'colons': {'level': 'error', 'max-spaces-before': 0, 'max-spaces-after': 1}, 'commas': {'level': 'error', 'max-spaces-before': 0, 'min-spaces-after': 1, 'max-spaces-after': 1}, 'comments': {'level': 'warning', 'require-starting-space': True, 'ignore-shebangs': True, 'min-spaces-from-content': 1}, 'comments-indentation': False, 'document-end': False, 'document-start': False, 'empty-lines': {'level': 'error', 'max': 2, 'max-start': 0, 'max-end': 0}, 'empty-values': False, 'float-values': False, 'hyphens': {'level': 'error', 'max-spaces-after': 1}, 'indentation': {'level': 'error', 'spaces': 'consistent', 'indent-sequences': True, 'check-multi-line-strings': False}, 'key-duplicates': {'level': 'error', 'forbid-duplicated-merge-keys': False}, 'key-ordering': False, 'line-length': {'level': 'error', 'max': 160, 'allow-non-breakable-words': True, 'allow-non-breakable-inline-mappings': False}, 'new-line-at-end-of-file': {'level': 'error'}, 'new-lines': {'level': 'error', 'type': 'unix'}, 'octal-values': {'forbid-implicit-octal': True, 'forbid-explicit-octal': True, 'level': 'error'}, 'quoted-strings': False, 'trailing-spaces': {'level': 'error'}, 'truthy': {'level': 'warning', 'allowed-values': ['true', 'false'], 'check-keys': True}}
DEBUG    Logging initialized to level 10
DEBUG    Effective yamllint rules used: {'anchors': {'level': 'error', 'forbid-undeclared-aliases': True, 'forbid-duplicated-anchors': False, 'forbid-unused-anchors': False}, 'braces': {'level': 'error', 'forbid': False, 'min-spaces-inside': 0, 'max-spaces-inside': 1, 'min-spaces-inside-empty': -1, 'max-spaces-inside-empty': -1}, 'brackets': {'level': 'error', 'forbid': False, 'min-spaces-inside': 0, 'max-spaces-inside': 0, 'min-spaces-inside-empty': -1, 'max-spaces-inside-empty': -1}, 'colons': {'level': 'error', 'max-spaces-before': 0, 'max-spaces-after': 1}, 'commas': {'level': 'error', 'max-spaces-before': 0, 'min-spaces-after': 1, 'max-spaces-after': 1}, 'comments': {'level': 'warning', 'require-starting-space': True, 'ignore-shebangs': True, 'min-spaces-from-content': 1}, 'comments-indentation': False, 'document-end': False, 'document-start': False, 'empty-lines': {'level': 'error', 'max': 2, 'max-start': 0, 'max-end': 0}, 'empty-values': False, 'float-values': False, 'hyphens': {'level': 'error', 'max-spaces-after': 1}, 'indentation': {'level': 'error', 'spaces': 'consistent', 'indent-sequences': True, 'check-multi-line-strings': False}, 'key-duplicates': {'level': 'error', 'forbid-duplicated-merge-keys': False}, 'key-ordering': False, 'line-length': {'level': 'error', 'max': 160, 'allow-non-breakable-words': True, 'allow-non-breakable-inline-mappings': False}, 'new-line-at-end-of-file': {'level': 'error'}, 'new-lines': {'level': 'error', 'type': 'unix'}, 'octal-values': {'forbid-implicit-octal': True, 'forbid-explicit-octal': True, 'level': 'error'}, 'quoted-strings': False, 'trailing-spaces': {'level': 'error'}, 'truthy': {'level': 'warning', 'allowed-values': ['true', 'false'], 'check-keys': True}}
INFO     Set ANSIBLE_LIBRARY=/home/martjack/.cache/ansible-compat/cd907e/modules:plugins/modules:/home/martjack/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/home/martjack/.cache/ansible-compat/cd907e/collections:/home/martjack/.ansible/collections:/usr/share/ansible/collections
INFO     Set ANSIBLE_ROLES_PATH=/home/martjack/.cache/ansible-compat/cd907e/roles:/home/martjack/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
INFO     Running from /home/martjack/gitwork/servicenow.itsm : ansible-galaxy collection install -vvv --force /home/martjack/gitwork/servicenow.itsm
DEBUG    data set to None for plugins/inventory/now.py due to being 'plugin' (text/python) kind.
DEBUG    Passed 'plugins/inventory/now.py' positional argument was identified as generic 'yaml' file kind.
DEBUG    Examining plugins/inventory/now.py of type plugin
DEBUG    Running rule internal-error
DEBUG    Running rule load-failure
DEBUG    Running rule parser-error
DEBUG    Running rule warning
DEBUG    Running rule yaml
DEBUG    Running rule args
DEBUG    Running rule avoid-implicit
DEBUG    Running rule command-instead-of-module
DEBUG    Running rule command-instead-of-shell
DEBUG    Running rule complexity
DEBUG    Running rule deprecated-bare-vars
DEBUG    Running rule deprecated-local-action
DEBUG    Running rule deprecated-module
DEBUG    Running rule fqcn
DEBUG    Running rule galaxy
DEBUG    Running rule ignore-errors
DEBUG    Running rule inline-env-var
DEBUG    Running rule jinja
DEBUG    Running rule key-order
DEBUG    Running rule latest
DEBUG    Running rule literal-compare
DEBUG    Running rule loop-var-prefix
DEBUG    Running rule meta-incorrect
DEBUG    Running rule meta-no-tags
DEBUG    Running rule meta-runtime
DEBUG    Running rule meta-video-links
DEBUG    Running rule name
DEBUG    Running rule no-changed-when
DEBUG    Running rule no-free-form
DEBUG    Running rule no-handler
DEBUG    Running rule no-jinja-when
DEBUG    Running rule no-relative-paths
DEBUG    Running rule no-tabs
DEBUG    Running rule package-latest
DEBUG    Running rule partial-become
DEBUG    Running rule playbook-extension
DEBUG    Running rule risky-file-permissions
DEBUG    Running rule risky-octal
DEBUG    Running rule risky-shell-pipe
DEBUG    Running rule role-name
DEBUG    Running rule run-once
DEBUG    Running rule sanity
DEBUG    Running rule schema
DEBUG    Running rule var-naming
DEBUG    Examining /tmp/tmp04jerbjd_now.py.yaml of type yaml
DEBUG    Running rule internal-error
DEBUG    Running rule load-failure
DEBUG    Running rule parser-error
DEBUG    Running rule warning
DEBUG    Running rule yaml
DEBUG    Running rule args
DEBUG    Running rule avoid-implicit
DEBUG    Running rule command-instead-of-module
DEBUG    Running rule command-instead-of-shell
DEBUG    Running rule complexity
DEBUG    Running rule deprecated-bare-vars
DEBUG    Running rule deprecated-local-action
DEBUG    Running rule deprecated-module
DEBUG    Running rule fqcn
DEBUG    Running rule galaxy
DEBUG    Running rule ignore-errors
DEBUG    Running rule inline-env-var
DEBUG    Running rule jinja
DEBUG    Running rule key-order
DEBUG    Running rule latest
DEBUG    Running rule literal-compare
DEBUG    Running rule loop-var-prefix
DEBUG    Running rule meta-incorrect
DEBUG    Running rule meta-no-tags
DEBUG    Running rule meta-runtime
DEBUG    Running rule meta-video-links
DEBUG    Running rule name
DEBUG    Running rule no-changed-when
DEBUG    Running rule no-free-form
DEBUG    Running rule no-handler
DEBUG    Running rule no-jinja-when
DEBUG    Running rule no-relative-paths
DEBUG    Running rule no-tabs
DEBUG    Running rule package-latest
DEBUG    Running rule partial-become
DEBUG    Running rule playbook-extension
DEBUG    Running rule risky-file-permissions
DEBUG    Running rule risky-octal
DEBUG    Running rule risky-shell-pipe
DEBUG    Running rule role-name
DEBUG    Running rule run-once
DEBUG    Running rule sanity
DEBUG    Running rule schema
DEBUG    Running rule var-naming
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (plugin). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (plugin). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (keyed_groups). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (plugin). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (plugin). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (plugin). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (inventory_hostname_source). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (columns). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (compose). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (plugin). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (enhanced). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (strict). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (columns). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (compose). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (plugin). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (table). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (query). Using last defined value only.
WARNING  /home/martjack/.local/pipx/venvs/ansible-lint/lib64/python3.12/site-packages/ansible/parsing/yaml/constructor.py:76 AnsibleWarning While constructing a mapping from <unicode string>, line 6, column 1, found a duplicate dict key (keyed_groups). Using last defined value only.
WARNING  Listing 20 violation(s) that are fatal
yaml[key-duplicates]: Duplication of key "plugin" in mapping
plugins/inventory/now.py:175

yaml[key-duplicates]: Duplication of key "plugin" in mapping
plugins/inventory/now.py:193

yaml[key-duplicates]: Duplication of key "keyed_groups" in mapping
plugins/inventory/now.py:197

yaml[key-duplicates]: Duplication of key "plugin" in mapping
plugins/inventory/now.py:213

yaml[key-duplicates]: Duplication of key "plugin" in mapping
plugins/inventory/now.py:231

yaml[indentation]: Wrong indentation: expected 2 but found 4
plugins/inventory/now.py:238

yaml[key-duplicates]: Duplication of key "plugin" in mapping
plugins/inventory/now.py:252

yaml[key-duplicates]: Duplication of key "inventory_hostname_source" in mapping
plugins/inventory/now.py:255

yaml[key-duplicates]: Duplication of key "columns" in mapping
plugins/inventory/now.py:256

yaml[key-duplicates]: Duplication of key "compose" in mapping
plugins/inventory/now.py:261

yaml[indentation]: Wrong indentation: expected 2 but found 4
plugins/inventory/now.py:262

yaml[key-duplicates]: Duplication of key "plugin" in mapping
plugins/inventory/now.py:275

yaml[key-duplicates]: Duplication of key "enhanced" in mapping
plugins/inventory/now.py:276

yaml[key-duplicates]: Duplication of key "strict" in mapping
plugins/inventory/now.py:277

yaml[key-duplicates]: Duplication of key "columns" in mapping
plugins/inventory/now.py:279

yaml[key-duplicates]: Duplication of key "compose" in mapping
plugins/inventory/now.py:284

yaml[key-duplicates]: Duplication of key "plugin" in mapping
plugins/inventory/now.py:313

yaml[key-duplicates]: Duplication of key "table" in mapping
plugins/inventory/now.py:314

yaml[key-duplicates]: Duplication of key "query" in mapping
plugins/inventory/now.py:315

yaml[key-duplicates]: Duplication of key "keyed_groups" in mapping
plugins/inventory/now.py:317

DEBUG    Attempting to release lock 139627535491984 on /home/martjack/.cache/ansible-compat/cd907e/.lock
DEBUG    Lock 139627535491984 released on /home/martjack/.cache/ansible-compat/cd907e/.lock
Read documentation for instructions on how to ignore specific rule violations.

DEBUG    Determined rule-profile order: {'internal-error': (0, 'min'), 'load-failure': (1, 'min'), 'parser-error': (2, 'min'), 'syntax-check': (3, 'min'), 'command-instead-of-module': (4, 'basic'), 'command-instead-of-shell': (5, 'basic'), 'deprecated-bare-vars': (6, 'basic'), 'deprecated-local-action': (7, 'basic'), 'deprecated-module': (8, 'basic'), 'inline-env-var': (9, 'basic'), 'key-order': (10, 'basic'), 'literal-compare': (11, 'basic'), 'jinja': (12, 'basic'), 'no-free-form': (13, 'basic'), 'no-jinja-when': (14, 'basic'), 'no-tabs': (15, 'basic'), 'partial-become': (16, 'basic'), 'playbook-extension': (17, 'basic'), 'role-name': (18, 'basic'), 'schema': (19, 'basic'), 'name': (20, 'basic'), 'var-naming': (21, 'basic'), 'yaml': (22, 'basic'), 'name': (23, 'moderate'), 'name': (24, 'moderate'), 'name': (25, 'moderate'), 'spell-var-name': (26, 'moderate'), 'avoid-implicit': (27, 'safety'), 'latest': (28, 'safety'), 'package-latest': (29, 'safety'), 'risky-file-permissions': (30, 'safety'), 'risky-octal': (31, 'safety'), 'risky-shell-pipe': (32, 'safety'), 'galaxy': (33, 'shared'), 'ignore-errors': (34, 'shared'), 'layout': (35, 'shared'), 'meta-incorrect': (36, 'shared'), 'meta-no-tags': (37, 'shared'), 'meta-video-links': (38, 'shared'), 'meta-version': (39, 'shared'), 'meta-runtime': (40, 'shared'), 'no-changed-when': (41, 'shared'), 'no-changelog': (42, 'shared'), 'no-handler': (43, 'shared'), 'no-relative-paths': (44, 'shared'), 'max-block-depth': (45, 'shared'), 'max-tasks': (46, 'shared'), 'unsafe-loop': (47, 'shared'), 'avoid-dot-notation': (48, 'production'), 'sanity': (49, 'production'), 'fqcn': (50, 'production'), 'import-task-no-when': (51, 'production'), 'meta-no-dependencies': (52, 'production'), 'single-entry-point': (53, 'production'), 'use-loop': (54, 'production')}
                 Rule Violation Summary                  
 count tag                  profile rule associated tags 
     2 yaml[indentation]    basic   formatting, yaml     
    18 yaml[key-duplicates] basic   formatting, yaml

The source code in question can be found at https://raw.githubusercontent.com/ansible-collections/servicenow.itsm/2.6.0/plugins/inventory/now.py

For example, lines 157-209 represent a fairly normal documentation snippet:

EXAMPLES = r"""
# A trivial example that creates a host from every record of the
# ServiceNow cmdb_ci_server table. The ip_address column is used for
# for ansible host, and server name for inventory hostname.
# No groups will be created - all the resulting hosts are ungrouped.
plugin: servicenow.itsm.now

# `ansible-inventory -i inventory.now.yaml --graph` output:
# @all:
#  |--@ungrouped:
#  |  |--DatabaseServer1
#  |  |--DatabaseServer2
#  |  |--INSIGHT-NY-03
#  |  |--MailServerUS
#  |  |--VMWARE-SD-04

# Group hosts automatically, according to values of the manufacturer column.
plugin: servicenow.itsm.now
keyed_groups:
  - key: manufacturer
    separator: ""

# `ansible-inventory -i inventory.now.yaml --graph` output:
# @all:
#  |--@Dell Inc.:
#  |  |--DatabaseServer1
#  |  |--DatabaseServer2
#  |  |--INSIGHT-NY-03
#  |--@Lenovo:
#  |  |--FileServerFloor1
#  |  |--FileServerFloor2
#  |--@ungrouped:

# Group hosts automatically, according to values of the os column. Filtering ensures
# that we only see selected operating systems.
plugin: servicenow.itsm.now
query:
  - os: = Linux Red Hat
  - os: = Windows XP
keyed_groups:
  - key: os
    prefix: os

# `ansible-inventory -i inventory.now.yaml --graph` output:
#  |--@os_Linux_Red_Hat:
#  |  |--DatabaseServer1
#  |  |--DatabaseServer2
#  |--@os_Windows_XP:
#  |  |--FileServerFloor1
#  |  |--FileServerFloor2
#  |  |--INSIGHT-NY-03
#  |--@ungrouped:

ansible-lint fails on the repetition of plugin: and keyed_groups:. I can of course explicitly exclude this file, but maybe it would be better if ansible-lint did not error here?

ssbarnea commented 5 months ago

If you add a document separator line ---, it should probably work fine. Still, even this is acceptable, we need to update the messaging to hint plugin authors to make use of that to avoid errors.

The reality is that we assume that the entire EXAMPLES variable is a valid YAML document. Multiple keys are invalid. WDYT?

mhjacks commented 4 months ago

I think better hinting would be very helpful, and some explicit notice that EXAMPLES should use document separators if it repeats keys would make this situation much more understandable.