Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schema[playbook] report a warning about invalid schema if 'var_files' is used #2474

Closed
laurent-indermuehle opened this issue Sep 21, 2022 · 8 comments · Fixed by ansible/schemas#404 or #2528
Assignees
Labels
Milestone

Comments

@laurent-indermuehle
Copy link

Summary

When a playbook uses the option 'var_files', ansible-lint report a warning about invalid schema

Issue Type
  • Bug Report
Ansible and Ansible Lint details
ansible --version

ansible [core 2.13.4]
  config file = /home/indermue/src/ansible-mysql/ansible.cfg
  configured module search path = ['/home/indermue/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/indermue/python-venv/ansible-6.4.0/lib/python3.10/site-packages/ansible
  ansible collection location = /home/indermue/src/ansible-mysql/local_collections:/home/indermue/src/ansible-mysql/collections:/home/indermue/python-venv/ansible-4.2.0/lib/python3.8/site-packages:/var/lib/awx/projects/ansible-mysql-manual/collections:/opt/my-tower-venv/ansible-4.2.0/lib/python3.8/site-packages:/var/lib/awx/projects/ansible-mysql-manual/collections
  executable location = /home/indermue/python-venv/ansible-6.4.0/bin/ansible
  python version = 3.10.6 (main, Aug  2 2022, 00:00:00) [GCC 12.1.1 20220507 (Red Hat 12.1.1-1)]
  jinja version = 3.1.2
  libyaml = True

ansible-lint --version

ansible-lint 6.6.1 using ansible 2.13.4
  • ansible installation method: pip
  • ansible-lint installation method: pip
OS / ENVIRONMENT

Fedora

STEPS TO REPRODUCE

run `ansible-lint -v playbooks/test.yml

- name: Test Playbook with var_files
  hosts: all
  gather_facts: false
  vars_files: vars/main.yml
  tasks:

    - name: Test
      ansible.builtin.debug:
        msg: "This is a test"
Desired Behavior

I expect the playbook to be valid.

Actual Behavior
  • output of running ansible-lint
schema: {'name': 'Test Playbook with var_files', 'hosts': 'all', 'gather_facts': False, 'vars_files': 'vars/main.yml', 'tasks': [{'name': 'Test', 'ansible.builtin.debug': {'msg': 'This is a test'}}]} is not valid under any of the given schemas (schema[playbook])
  • if you're getting a stack trace, output of
    ansible-playbook --syntax-check playbook

ansible-playbook --syntax-check passes

  • Full command output:
DEBUG    Logging initialized to level 10
DEBUG    Options: Namespace(cache_dir='/home/indermue/.cache/ansible-compat/4ba8de', colored=True, configured=True, cwd=PosixPath('/home/indermue/src/ansible-mysql'), display_relative_path=True, exclude_paths=['.cache', '.git', '.hg', '.svn', '.tox'], format='rich', lintables=['playbooks/test.yml'], listrules=False, listtags=False, write_list=None, parseable=False, quiet=0, rulesdirs=['/home/indermue/python-venv/ansible-6.4.0/lib/python3.10/site-packages/ansiblelint/rules'], skip_list=[], tags=[], verbosity=4, warn_list=['experimental', 'jinja[spacing]', 'name[casing]', 'name[play]', 'role-name'], kinds=[{'jinja2': '**/*.j2'}, {'jinja2': '**/*.j2.*'}, {'yaml': '.github/**/*.{yaml,yml}'}, {'text': '**/templates/**/*.*'}, {'execution-environment': '**/execution-environment.yml'}, {'ansible-lint-config': '**/.ansible-lint'}, {'ansible-lint-config': '**/.config/ansible-lint.yml'}, {'ansible-navigator-config': '**/ansible-navigator.{yaml,yml}'}, {'inventory': '**/inventory/**.{yaml,yml}'}, {'requirements': '**/meta/requirements.{yaml,yml}'}, {'galaxy': '**/galaxy.yml'}, {'reno': '**/releasenotes/*/*.{yaml,yml}'}, {'tasks': '**/tasks/**/*.{yaml,yml}'}, {'playbook': '**/playbooks/*.{yml,yaml}'}, {'playbook': '**/*playbook*.{yml,yaml}'}, {'role': '**/roles/*/'}, {'handlers': '**/handlers/*.{yaml,yml}'}, {'vars': '**/{host_vars,group_vars,vars,defaults}/**/*.{yaml,yml}'}, {'test-meta': '**/tests/integration/targets/*/meta/main.{yaml,yml}'}, {'meta': '**/meta/main.{yaml,yml}'}, {'meta-runtime': '**/meta/runtime.{yaml,yml}'}, {'arg_specs': '**/meta/argument_specs.{yaml,yml}'}, {'yaml': '.config/molecule/config.{yaml,yml}'}, {'requirements': '**/molecule/*/{collections,requirements}.{yaml,yml}'}, {'yaml': '**/molecule/*/{base,molecule}.{yaml,yml}'}, {'requirements': '**/requirements.{yaml,yml}'}, {'playbook': '**/molecule/*/*.{yaml,yml}'}, {'yaml': '**/{.ansible-lint,.yamllint}'}, {'yaml': '**/*.{yaml,yml}'}, {'yaml': '**/.*.{yaml,yml}'}], mock_filters=[], mock_modules=[], mock_roles=[], loop_var_prefix=None, var_naming_pattern=None, offline=None, project_dir='.', extra_vars=None, enable_list=[], skip_action_validation=True, rules={}, profile=None, progressive=False, rulesdir=[], use_default_rules=False, config_file=None, version=False, cache_dir_lock=<filelock._unix.UnixFileLock object at 0x7f9603d0b7f0>)
DEBUG    /home/indermue/src/ansible-mysql
INFO     Running ansible-galaxy role install -vr roles/requirements.yml --roles-path /home/indermue/.cache/ansible-compat/4ba8de/roles
INFO     Running ansible-galaxy collection install -vr collections/requirements.yml -p /home/indermue/.cache/ansible-compat/4ba8de/collections
INFO     Set ANSIBLE_LIBRARY=/home/indermue/.cache/ansible-compat/4ba8de/modules:/home/indermue/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/home/indermue/.cache/ansible-compat/4ba8de/collections:/home/indermue/src/ansible-mysql/local_collections:/home/indermue/src/ansible-mysql/collections:/home/indermue/python-venv/ansible-4.2.0/lib/python3.8/site-packages:/var/lib/awx/projects/ansible-mysql-manual/collections:/opt/my-tower-venv/ansible-4.2.0/lib/python3.8/site-packages:/var/lib/awx/projects/ansible-mysql-manual/collections
INFO     Set ANSIBLE_ROLES_PATH=/home/indermue/.cache/ansible-compat/4ba8de/roles:roles:/home/indermue/src/ansible-mysql/roles:/home/indermue/src/ansible-mysql/galaxy_roles
INFO     Set ANSIBLE_LIBRARY=/home/indermue/.cache/ansible-compat/4ba8de/modules:/home/indermue/.ansible/plugins/modules:/usr/share/ansible/plugins/modules
INFO     Set ANSIBLE_COLLECTIONS_PATH=/home/indermue/.cache/ansible-compat/4ba8de/collections:/home/indermue/src/ansible-mysql/local_collections:/home/indermue/src/ansible-mysql/collections:/home/indermue/python-venv/ansible-4.2.0/lib/python3.8/site-packages:/var/lib/awx/projects/ansible-mysql-manual/collections:/opt/my-tower-venv/ansible-4.2.0/lib/python3.8/site-packages:/var/lib/awx/projects/ansible-mysql-manual/collections
INFO     Set ANSIBLE_ROLES_PATH=/home/indermue/.cache/ansible-compat/4ba8de/roles:roles:/home/indermue/src/ansible-mysql/roles:/home/indermue/src/ansible-mysql/galaxy_roles
DEBUG    Effective yamllint rules used: {'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'}, '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': False, 'quoted-strings': False, 'trailing-spaces': {'level': 'error'}, 'truthy': {'level': 'warning', 'allowed-values': ['true', 'false'], 'check-keys': True}}
INFO     Executing syntax check on playbooks/test.yml (0.68s)
DEBUG    Examining playbooks/test.yml of type playbook
WARNING  Listing 1 violation(s) that are fatal
schema: {'name': 'Test Playbook with var_files', 'hosts': 'all', 'gather_facts': False, 'vars_files': 'vars/main.yml', 'tasks': [{'name': 'Test', 'ansible.builtin.debug': {'msg': 'This is a test'}}]} is not valid under any of the given schemas (schema[playbook])
playbooks/test.yml:1  Returned errors will not include exact line numbers, but they will mention
the schema name being used as a tag, like ``schema``,
``schema``.

This rule is not skippable and stops further processing of the file.

Schema bugs should be reported towards (https://github.com/ansible/schemas) project instead of ansible-lint.

If incorrect schema was picked, you might want to either:

* move the file to standard location, so its file is detected correctly.
* use ``kinds:`` option in linter config to help it pick correct file type.
@laurent-indermuehle laurent-indermuehle added bug new Triage required labels Sep 21, 2022
@ssbarnea
Copy link
Member

Current schema implementation for vars_files only allows array of strings, not a single sting.

Even the official ansible meta-datadump reports the keyword as:

            "vars_files": {
                "applies_to": [
                    "Play"
                ],
                "description": "List of files that contain vars to include in the play.",
                "priority": 99,
                "template": "explicit",
                "type": "list"

This makes me believe that this is not a bug. The fact that Ansible might let you feed it something else might count as an accidental/undocumented behavior.

I will double check before closing as wontfix as changing it to allow simple tring is easy, but easy is not necessarily good in longer term.

@bcoca
Copy link
Member

bcoca commented Sep 21, 2022

all 'list' types in ansible allow single string as they get 'auto magically' converted into list of single element

@laurent-indermuehle
Copy link
Author

I failed to find both the documentation and the meta-data about vars_files parameters. I wasn't aware it is waiting for a list. Sorry about that.
When using a list instead of a string, ansible-test "schema[playbook]" passes.

I'm not sure what ansible-lint should do, either accept a string or not, but a more verbose output would make a long way in making our lives easier. My playbook is invalid, ok, but why? Using -vvv doesn't help.

@ssbarnea
Copy link
Member

Yep, this bug is open to remind me that I need to update our schemas to always allow a string for fields that allow lists. It is not only var_files that is affected by this undocumented behavior. It would be much easier if the metadata would be explicit about what it allows, but at the same time we can also feed null for most fields and Ansible will not complain, taking it as an empty list too. The ideal way to expose what is allow should more look like string, list[string], null or something similar.

@laurent-indermuehle
Copy link
Author

@ssbarnea sound reasoning. Thanks for your work. And thanks for the solution (convert string to list). I leave this issue open as a reminder then.

@bcoca
Copy link
Member

bcoca commented Sep 22, 2022

it is documented, the problem is you are equating 'Ansible types' to JSON ones and they are not the same. When you have 'type: list' also can also have an 'elements:' keyword that describe the allowed elements for the list (if omitted 'any/raw' is assumed).

None/null is allowed for all types.

@ssbarnea
Copy link
Member

@bcoca Here is a related on https://github.com/ansible/schemas/issues/401 -- and for this I was not able to find any documentation or examples stating that for vars you can feed it a list of dictionaries.

@bcoca
Copy link
Member

bcoca commented Sep 29, 2022

no list of lists (of paths), vars/vars_prompt are list of dictionaries, also vars_files when it is a list of lists uses a 'first found' logic

The original example vars_files: vars/main.yml is cast into vars_files: [[vars/main.yml]] (one auto cast into list for vars_files being list type, another for the elements of that list being list) at no point is this a dict

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
3 participants