Repository: ansible/ansible

Issue:
Task name not templated in free strategy
<!--- Verify first that your issue/request is not already reported in GitHub -->
##### ISSUE TYPE

<!--- Pick one below and delete the rest: -->
- Bug Report
##### ANSIBLE VERSION

<!--- Paste verbatim output from “ansible --version” between quotes below -->

```
ansible 2.1.0.0
  config file = /home/.../.ansible.cfg
  configured module search path = Default w/o overrides
```
##### CONFIGURATION

<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

Using default configuration.
##### OS / ENVIRONMENT

<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->

_N/A_
##### SUMMARY

<!--- Explain the problem briefly -->

Variable are not interpreted in task names using new `free` strategy (`linear` strategy was fixed in #10347 by 7bc789ba64583fdb68e8ab9c8336dbb9b8374797)
##### STEPS TO REPRODUCE

<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
- Using `linear` strategy:

``` yaml

---
- hosts: all
  gather_facts: false
  become: false
  strategy: linear

  vars: {
    "variable": "VALUE"
  }

  tasks:
    - name: "Dynamic task name: {{ variable }}"
      debug:
        msg: "hello there"

  handlers: []
```

output is

```
PLAY [all] *********************************************************************

TASK [Dynamic task name: VALUE] ************************************************
ok: [localhost] => {
    "msg": "hello there"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0   
```
- Using the `free` strategy:

``` yaml

---
- hosts: all
  gather_facts: false
  become: false
  strategy: free

  vars: {
    "variable": "VALUE"
  }

  tasks:
    - name: "Dynamic task name: {{ variable }}"
      debug:
        msg: "hello there"

  handlers: []
```

output is:

```
PLAY [all] *********************************************************************

TASK [Dynamic task name: {{ variable }}] ***************************************
ok: [localhost] => {
    "msg": "hello there"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0   
```

<!--- You can also paste gist.github.com links for larger files -->
##### EXPECTED RESULTS

<!--- What did you expect to happen when running the steps above? -->

Same behavior in task names evaluation whatever strategy I'm using.
##### ACTUAL RESULTS

<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

`free` strategy does not replace variable in tasks names.

This bug was originally reported by @grumpycatt.



Discussion:

Resolving patch:
diff --git a/lib/ansible/plugins/strategy/free.py b/lib/ansible/plugins/strategy/free.py
--- a/lib/ansible/plugins/strategy/free.py
+++ b/lib/ansible/plugins/strategy/free.py
@@ -26,6 +26,7 @@
 from ansible.plugins import action_loader
 from ansible.plugins.strategy import StrategyBase
 from ansible.template import Templar
+from ansible.compat.six import text_type
 
 try:
     from __main__ import display
@@ -107,6 +108,15 @@ def run(self, iterator, play_context):
                         templar = Templar(loader=self._loader, variables=task_vars)
                         display.debug("done getting variables")
 
+                        try:
+                            task.name = text_type(templar.template(task.name, fail_on_undefined=False))
+                            display.debug("done templating")
+                        except:
+                            # just ignore any errors during task name templating,
+                            # we don't care if it just shows the raw name
+                            display.debug("templating failed for some reason")
+                            pass
+
                         run_once = templar.template(task.run_once) or action and getattr(action, 'BYPASS_HOST_LOOP', False)
                         if run_once:
                             if action and getattr(action, 'BYPASS_HOST_LOOP', False):


Test patch: