Reputation: 129
I have written an Ansible playbook which prompts me to enter password interactively for SSH and SUDO like below.
$ ansible-playbook -i test --limit dev app_name.yml -vv --tags=stop
SSH password:
SUDO password[defaults to SSH password]:
There are various options available with Ansible like defining password in ansible_ssh_password under group_vars but it don't seem to work for me since I can't have sshpass installed in my target server nor I am allowed to make any changes to my sudoers file.
I tried to execute ansible-playbook from a little expect script below
#!/usr/bin/expect -f
set password PASSWORD
set where_to_execute [lindex $argv 0]
set which_app_to_execute [lindex $argv 1]
set what_to_execute [lindex $argv 2]
send "ansible-playbook -i test --limit $where_to_execute $which_app_to_execute -vv --tags=$what_to_execute \r"
expect "SSH password:"
send "$password \r"
expect "SUDO password*"
send "$password \r"
expect "$"
send "exit \r"
Unfortunately this is also not working may be because SSH process is not spawned by expect. Did anyone try this method and got things working. Please suggest. Thanks.
Upvotes: 2
Views: 4756
Reputation: 80931
The problem with your expect scripts is that you aren't actually running the ansible command there (or any command for that matter).
You use
send "ansible-playbook -i test --limit $where_to_execute $which_app_to_execute -vv --tags=$what_to_execute \r"
which sends that string to ... nowhere as far as I know. There's nowhere for it to go.
What you want to be doing is spawn
ing that ansible command and then using expect to communicate with it.
Something like this:
spawn ansible-playbook -i test --limit $where_to_execute $which_app_to_execute -vv --tags=$what_to_execute
You may also want to set the timeout
value if the ansible command can take a little while (to prevent expect
from killing it when it doesn't return quickly enough).
Upvotes: 3
Reputation: 3554
It works for me using the python implementation of expect. pexpect
install pexpect using pip: pip install pexpect
You can use this code as an workaround for your expect script:
#!/usr/bin/python
import pexpect
def main(args):
#Setup variables
password, where, which, what = args
cmd = "ansible-playbook -i test --limit %s %s -vv --tags=%s" % (where, which, what)
child = pexpect.spawn(cmd)
child.sendline(password)
child.expect('SSH password:')
child.sendline(password)
child.expect('SUDO password*')
child.expect(pexpect.EOF)
print child.before
if __name__ == '__main__':
main(sys.argv[1:])
This is the most simple example but it's working fine for me.
./myscript.py mypassword dev app_name.yml stop
As @Etan Reisner pointed out, the main difference between your code that isn't working and my pexpect code is the spawn
ansible command. The above code on expect also works fine:
#!/usr/bin/expect -f
spawn /usr/bin/ansible -m ping myserver --ask-pass
expect "SSH password:"
send "mypassword\r"
expect "$ "
Upvotes: 1