and_apo
and_apo

Reputation: 1297

Ansible expect module not working

This has been irritating me for the past hour, I use Ansible's expect module to answer to a command prompt, namely:

Re-format filesystem in Storage Directory /mnt/ephemeral-hdfs/dfs/name ? (Y or N)

for which I want to reply

Y

This should work according to standard regex matching and this other stackoverflow question

 - name: Run Spark Cluster script
    expect:
       command: /home/ubuntu/cluster_setup/scripts/shell/utils-cluster_launcher-start_spark.sh
       responses:
          "Re-format filesystem": "Y"
       timeout: 600
       echo: yes

The issue I am facing is that when it reaches the point where it expects keyboard input it doesn't get anything, therefore it hangs. There is no error output as such; it just stays still.

Any ideas how to fix this?

Upvotes: 1

Views: 8619

Answers (3)

Martin
Martin

Reputation: 2591

I know this is old but I had the same trouble with this module and these answers didn't help, however I did find my own solutions eventually and thought I'd save people some time.

First the timeout in the poster's example is 10 minutes. Though this makes sense for a reformat, it means that you need to wait 10 minutes before the script will fail. e.g. If it is stopped waiting for a response to "Are you sure?". When debugging keep that timeout low and if you can't then wait patiently.

Second the fields in the responses are listed alphabetically so

responses:
  "Test a specific string": "Specific"
  "Test": "General"

Will always respond to ALL messages containing Test with General as that is the first alphabetically in the responses map.

Third (following on) this caught me out because in my case expect was simply hitting enter at the prompt and the script asked again for valid data. The problem then is that my timeout never fires and nothing gets returned so I don't see any response from the module, it just hangs. The solution in this case is to go to the server you are provisioning with Ansible, find the command Ansible is running with ps and kill it. This allows Ansible to collect the output and show you where it is stuck in an infinite loop.

Upvotes: 0

techraf
techraf

Reputation: 68529

The task from the question works properly on the data included in the question:

---
- hosts: localhost
  gather_facts: no
  connection: local
  tasks:
    - name: Run script producing the same prompt as Spark Cluster script
      expect:
        command: ./prompt.sh
        responses:
          "Re-format filesystem": "Y"
        timeout: 600
        echo: yes
      register: prompt
    - debug:
        var: prompt.stdout_lines

Contents of the ./prompt.sh:

#!/bin/bash

read -p "Re-format filesystem in Storage Directory /mnt/ephemeral-hdfs/dfs/name ? (Y or N) " response
echo pressed: $response

Result:

PLAY [localhost] ***************************************************************

TASK [Run script producing the same prompt as Spark Cluster script] ************
changed: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "prompt.stdout_lines": [
        "Re-format filesystem in Storage Directory /mnt/ephemeral-hdfs/dfs/name ? (Y or N) Y",
        "pressed: Y"
    ]
}

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

Upvotes: 2

Will Barnwell
Will Barnwell

Reputation: 4089

The Ansible documentation for expect does not have quotes around the regex in the example.

# Case insensitve password string match
- expect:
    command: passwd username
    responses:
      (?i)password: "MySekretPa$$word"

Maybe try:

Re-format\sfilesystem: "Y"

Upvotes: 1

Related Questions