ansible/ansible — pull request #9151 by ahamilton55 (2014-09-25 18:32:44+00:00)
Title: Template delegate private key

##### Issue Type:
Bugfix Pull Requiest

##### Ansible Version:
ansible 1.8 (devel 19703617b8) last updated 2014/09/25 10:53:31 (GMT -700)

##### Environment:
Running from: Mac OS X 10.9, Fedora 20
Running against: Debian 7, Centos 6/7

##### Summary:
When using the "local_action" module or "delegate_to" with a private key filename that includes variables such as, "~/.ssh/{{ key_name | default(group) }}.pem," Ansible will throw a OSError exception when looking up the key. `template.template()` is called on the private key filename when delegation is not used but not when it is.

The following line is used in `group_vars/all` for the private key filename:
```ansible_ssh_private_key_file: ~/.ssh/{{ key_name | default(group) }}.pem```

The stacktrace given is the following:
```
fatal: [ip-10-X-Y-Z..compute -> 127.0.0.1] => Traceback (most recent call last):
File "/Users/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 563, in _executor
exec_rc = self._executor_internal(host, new_stdin)
File "/Users/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 713, in _executor_internal
return self._executor_internal_inner(host, self.module_name, self.module_args, inject, port, complex_args=complex_args)
File "/Users/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 875, in _executor_internal_inner
conn = self.connector.connect(actual_host, actual_port, actual_user, actual_pass, actual_transport, actual_private_key_file)
File "/Users/andrew/workspace/ansible/lib/ansible/runner/connection.py", line 39, in connect
st = os.stat(private_key_file)
OSError: [Errno 2] No such file or directory: '/Users/andrew/.ssh/{{ key_name | default(group) }}.pem'
```

##### Steps To Reproduce:
1. Add `ansible_ssh_private_key_file` in a `group_vars` file such as `group_vars/all` and have it use a variable in the file path such as:
```ansible_ssh_private_key_file: ~/.ssh/{{ service_name }}.pem
service_name: test```

2. Make sure that the path is to an actual file and that the proper permissions are set (`chmod 0600 `)

3. Use "local_action" or delegate to with any module. For example, you can create a playbook such as `test.yml` with the following gist: https://gist.github.com/ahamilton55/d081087abaa6399b3487

4. Run with something like `ansible-playbook -i hosts.yml test.yml`.

##### Expected Results:
```
% ansible-playbook -i hosts.yml test.yml

PLAY [test] *******************************************************************

TASK: [Pause for a bit] *******************************************************
(^C-c = continue early, ^C-a = abort)
[testhost]
Pausing for 4 seconds
ok: [testhost -> 127.0.0.1]

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

##### Actual Results:
```
% ansible-playbook -i hosts.yml

PLAY [test] *******************************************************************

TASK: [Pause for a bit] *******************************************************
fatal: [testhost -> 127.0.0.1] => Traceback (most recent call last):
File "/home/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 563, in _executor
exec_rc = self._executor_internal(host, new_stdin)
File "/home/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 713, in _executor_internal
return self._executor_internal_inner(host, self.module_name, self.module_args, inject, port, complex_args=complex_args)
File "/home/andrew/workspace/ansible/lib/ansible/runner/__init__.py", line 875, in _executor_internal_inner
conn = self.connector.connect(actual_host, actual_port, actual_user, actual_pass, actual_transport, actual_private_key_file)
File "/home/andrew/workspace/ansible/lib/ansible/runner/connection.py", line 39, in connect
st = os.stat(private_key_file)
OSError: [Errno 2] No such file or directory: '/home/andrew/.ssh/{{ service_name }}.pem'

FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************
to retry, use: --limit @/home/andrew/test.retry

testhost : ok=0 changed=0 unreachable=0 failed=1
```