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

var-naming warns on variables with dynamically set names #1680

Closed
joren485 opened this issue Aug 1, 2021 · 4 comments · Fixed by #1988
Closed

var-naming warns on variables with dynamically set names #1680

joren485 opened this issue Aug 1, 2021 · 4 comments · Fixed by #1988
Assignees
Labels
Milestone

Comments

@joren485
Copy link
Contributor

joren485 commented Aug 1, 2021

Summary

var-naming warns when a variable with a dynamic name is set using set_fact. For example, a variable with the name test_var can be set using {{ 'test_' }}var. Although test_var follows the naming conventions, var-naming still warns about {{ 'test_' }}var.

This is most likely because the string {{ 'test_' }}var does not pass the regex used by var-naming, even though the resulting variable name (i.e. test_var) does.

Issue Type
  • Bug Report
Ansible and Ansible Lint details
$ ansible --version
ansible [core 2.11.3] 
  config file = /home/joren/dotfiles/ansible.cfg
  configured module search path = ['/home/joren/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /home/joren/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.6 (default, Jun 30 2021, 10:22:16) [GCC 11.1.0]
  jinja version = 3.0.1
  libyaml = True

$ ansible-lint --version
ansible-lint 5.1.2 using ansible 2.11.3
  • ansible installation method: OS package
  • ansible-lint installation method: OS package
OS / ENVIRONMENT

Arch Linux 5.13.6-arch1-1

STEPS TO REPRODUCE
---

- name: "PoC"
  hosts: "localhost"
  gather_facts: no
  tasks:
    - name: "Set test_var"
      set_fact:
        "{{ 'test_' }}var": "value"

    - name: "Show that test_var is a valid variable"
      debug:
        msg: "test_var: {{ test_var }}"
Desired Behaviour

var-naming does not warn about valid variable names.

Actual Behaviour
$ ansible-lint playbook.yml
WARNING  Listing 1 violation(s) that are fatal
var-naming: Task uses 'set_fact' to define variables that violates variable naming standards
playbook.yml:9 Task/Handler: test

You can skip specific rules or tags by adding them to your configuration file:
# .ansible-lint
warn_list:  # or 'skip_list' to silence them completely
  - experimental  # all rules tagged as experimental

Finished with 0 failure(s), 1 warning(s) on 1 files.
@joren485 joren485 added bug new Triage required labels Aug 1, 2021
@ganeshrn
Copy link
Member

ganeshrn commented Sep 6, 2021

Can you please provide a valid use case for this scenario?

@ganeshrn ganeshrn added feedback-needed Divergent oppinions, additional feedback is desired in order to unblock it. and removed new Triage required labels Sep 6, 2021
@joren485
Copy link
Contributor Author

joren485 commented Sep 6, 2021

Can you please provide a valid use case for this scenario?

Let's say you want to enable some features in a template configuration file based on whether plugins/dependencies are installed or not.

You could do this by using dynamic variable names, by creating tasks like:

- name: "Check which plugin dependencies are installed"
  vars:
    dependencies:
      - "ansible"
      - "docker"
  block:
    - name: "Check if plugin dependencies are installed"
      command: "which {{ item }}"
      register: "which_output"
      loop: "{{ dependencies }}"

    - name: "Set '_installed' boolean values"
      set_fact:
        "{{ item.item }}_installed": "{{ item.rc == 0 }}"
      loop: "{{ which_output.results }}"

You can then use these variables in a template:

# global configuration
option1=value
option2=false

{% if ansible_installed %}
    # Enable ansible specific configuration
ansible_option=value
{% endif %}

@briantist
Copy link

I have used this in a role that combines a few common tasks, but needs to "return" some value (like a register on a module). Using a static value is problematic because there are times when the role is used multiple times at different points, or used by other roles implicitly, where the name will be overwritten. So I've used a pattern similar to this:

defaults/main.yml

---
rolename_register: rolename_status

tasks/main.yml

---
# do some tasks
- name: Set return values
  set_fact:
    '{{ rolename_register }}':
      thing1: value1
      thing2: value2

This allows for a default but lets you override the variable with the returned status on role invocation by setting rolename_register to unique values.

@ssbarnea ssbarnea self-assigned this Mar 9, 2022
@ssbarnea ssbarnea added this to the 6.0.0 milestone Mar 9, 2022
@ganeshrn ganeshrn removed the feedback-needed Divergent oppinions, additional feedback is desired in order to unblock it. label Mar 9, 2022
@ssbarnea
Copy link
Member

ssbarnea commented Mar 9, 2022

PR welcome here, please add a comment if you start working on it.

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

Successfully merging a pull request may close this issue.

4 participants