Ansible: variable interpolation in task name

2020-06-01 07:33发布

问题:

I cannot get this seemingly simple example to work in Ansible 1.8.3. The variable interpolation does not kick in the task name. All examples I have seen seem to suggest this should work. Given that the variable is defined in the vars section I expected the task name to print the value of the variable. Why doesn't this work?

Even the example from the Ansible documentation seems to not print the variable value.

---
- hosts: 127.0.0.1
  gather_facts: no
  vars:
    vhost: "foo"
  tasks:
    - name: create a virtual host file for {{ vhost }}
      debug: msg="{{ vhost }}"

This results in the following output:

PLAY [127.0.0.1]     
************************************************************** 

TASK: [create a virtual host file for {{ vhost }}] 
**************************** 
ok: [127.0.0.1] => {
   "msg": "foo"
}

PLAY RECAP 
******************************************************************** 
127.0.0.1                  : ok=1    changed=0    unreachable=0    failed=0   

Update This works with 1.7.2 but does not work with 1.8.3. So either this is a bug or a feature.

回答1:

Variables are not resolved inside the name. Only inside the actual tasks/conditions etc. the placeholders will be resolved. I guess this is by design. Imagine you have a with_items loop and use the {{ item }}in the name. The tasks name will only be printed once, but the {{ item }} would change in every iteration.

I see the examples, even the one in the doc you linked to, use variables in the name. But that doesn't mean the result would be like you expected it. The docs are community managed. It might be someone just put that line there w/o testing it - or maybe it used to work like that in a previous version of Ansible and the docs have not been updated then. (I'm only using Ansible since about one year). But even though it doesn't work like we wish it would, I'm still using variables in my name's, just to indicate that the task is based on dynamic parameters. Might be the examples have been written with the same intention.

An interesting observation I recently made (Ansible 1.9.4) is, default values are written out in the task name.

- name: create a virtual host file for {{ vhost | default("foo") }}

When executed, Ansible would show the task title as:

TASK: [create a virtual host file for foo]

This way you can avoid ugly task names in the output.



回答2:

Explanation

Whether the variable gets interpolated depends on where it has been declared.

Imagine You have two hosts: A and B.

  • If variable foo has only per-host values, when Ansible runs the play, it cannot decide which value to use.
  • On the other hand, if it has a global value (global in a sense of host invariance), there is no confusion which value to use.

Source: https://github.com/ansible/ansible/issues/3103#issuecomment-18835432

Hands on playbook

  • ansible_user is an inventory variable
  • greeting is an invariant variable
- name: Test variable substitution in names
  hosts: localhost
  connection: local
  vars:
    greeting: Hello
  tasks:
    - name: Sorry {{ ansible_user }}
      debug:
        msg: this won't work
    - name: You say '{{ greeting }}'
      debug:
        var: ansible_user


回答3:

I experienced the same problem today in one of my Ansible roles and I noticed something interesting.
When I use the set_fact module before I use the vars in the task name, they actually get translated to their correct values.

In this example I wanted to set the password for a remote user:
Notice that I use the vars test_user and user_password that I set as facts before.

- name: Prepare to set user password
  set_fact:
    user_password: "{{ linux_pass }}"
    user_salt: "s0m3s4lt"
    test_user: "{{ ansible_user }}"

- name: "Changing password for user {{ test_user }} to {{ user_password }}"
  user:
   name: "{{ ansible_user }}"
   password: "{{ user_password | password_hash('sha512', user_salt) }}"
   state: present
   shell: /bin/bash
   update_password: always

This gives me the following output:

TASK [install : Changing password for user linux to LiNuXuSeRPaSs#]

So this solved my problem.



回答4:

You have to surround the string in quotation marks.

tasks:
    - name: "create a virtual host file for {{ vhost }}"
      debug: msg="{{ vhost }}"

From ansible documentation:

YAML syntax requires that if you start a value with {{ foo }} you quote the whole line, since it wants to be sure you aren’t trying to start a YAML dictionary. This is covered on the YAML Syntax page.