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

jinja[invalid] incorrectly fires for missing mandatory var when defined in loop_var #3048

Closed
Tompage1994 opened this issue Feb 16, 2023 · 1 comment · Fixed by #3056 or redhat-cop/infra.aap_configuration#515
Assignees
Labels

Comments

@Tompage1994
Copy link
Contributor

Summary

Recent changes have meant that jinja[invalid] is firing for mandatory values where the variable is defined in loop control. I've included my slimmed down playbook below which should make things clearer.

There are no errors on v6.12.2 and I cannot see anything that would directly have affected this in the changelog. I believe this to be a regression.

Issue Type
  • Bug Report
OS / ENVIRONMENT
ansible-lint --version
ansible-lint 6.13.0 using ansible 2.12.1
  • ansible installation method:pip
  • ansible-lint installation method: pip
STEPS TO REPRODUCE
---
- name: Test
  hosts: localhost
  tasks:
    - name: Test Test
      ansible.builtin.debug:
        msg: "{{ __my_var | mandatory }}"
      loop: "{{ a_var }}"
      loop_control:
        loop_var: __my_var
      vars:
        a_var:
          - one
          - two
          - three
...
Desired Behavior

Expected no linting errors to show as per previous ansible-lint version.

Actual Behavior

There is a linting error on junja[invalid] when the above should be

$ ansible-lint --profile=production test
WARNING  Listing 1 violation(s) that are fatal
test/playbook.yml:7: jinja[invalid]: Mandatory variable '__my_var'  not defined.
Read documentation for instructions on how to ignore specific rule violations.

              Rule Violation Summary               
 count tag            profile rule associated tags 
     1 jinja[invalid] basic   formatting           

Failed after min profile: 1 failure(s), 0 warning(s) on 2 files.
@nre-ableton
Copy link
Contributor

nre-ableton commented Feb 16, 2023

It's not just loops, there are other false positives that emit jinja[invalid] in 6.13.0. Here's a few (condensed) examples.

  1. Using set_fact:
---
- name: Update Jenkins plugins
  hosts: "all"

  tasks:
    - name: Initialize plugins_list fact
      ansible.builtin.set_fact:
        plugins_list: []

    # Add plugins etc; these tasks have been omitted

    - name: Generate jenkins-plugins.yml file
      delegate_to: localhost
      ansible.builtin.copy:
        dest: "{{ plugins_file }}"
        content: >
          {{ {'plugins': plugins_list} | to_nice_yaml(indent=2) }}
        mode: "0644"

This causes jinja[invalid]: to_nice_yaml - 'plugins_list' is undefined. 'plugins_list' is undefined

  1. Using a variable defined elsewhere:
# group_vars/all.yml
host_info_keys:
  cpus: "{{ vsphere_guest_cpu_sockets }}"
  memory: "{{ vsphere_guest_memory_mb }}"
# A task file that belongs to a role
- name: Write host info file
  delegate_to: localhost
  ansible.builtin.copy:  # noqa template-instead-of-copy
    dest: "{{ host_info_dir }}/{{ inventory_name }}/{{ inventory_hostname }}.yml"
    content: "{{ host_info_keys | to_nice_yaml(explicit_start=True, sort_keys=False) }}"
    mode: "0644"

Again, fails with jinja[invalid]: to_nice_yaml - 'host_info_keys' is undefined. 'host_info_keys' is undefined.

Another frustrating part of this bug is that it can't be suppressed on the exact line with a multi-line YAML statement. So in second example above, this suppression does not work:

- name: Write host info file
  delegate_to: localhost
  ansible.builtin.copy:  # noqa template-instead-of-copy
    dest: "{{ host_info_dir }}/{{ inventory_name }}/{{ inventory_hostname }}.yml"
    content: >-  # noqa jinja[invalid]
      {{ host_info_keys | to_nice_yaml(explicit_start=True, sort_keys=False) }}
    mode: "0644"

The only way to suppress it in this case is on the task level, like so:

- name: Write host info file  # noqa jinja[invalid]
  delegate_to: localhost
  ansible.builtin.copy:  # noqa template-instead-of-copy
    dest: "{{ host_info_dir }}/{{ inventory_name }}/{{ inventory_hostname }}.yml"
    content: "{{ host_info_keys | to_nice_yaml(explicit_start=True, sort_keys=False) }}"
    mode: "0644"

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