Matthew Daly Matthew Daly - 3 months ago 90
YAML Question

Variable does not seem to be defined in Ansible playbook

The following Ansible playbook for setting up a server for a Laravel app works fine:

---
- name: Set up a standard Laravel install
hosts: localhost
vars_prompt:
- name: "domain"
prompt: "Domain name"
private: no
- name: "dbname"
prompt: "Database name"
private: no
- name: "dbuser"
prompt: "Database username"
private: no
- name: "dbpassword"
prompt: "Database password"
private: yes
roles:
- create_droplet
- create_domain
- name: Install dependencies
hosts: launched
roles:
- upgrade
- utilities
- users
- nginx-php
- composer
- nginx_firewall
- redis
- postgres
- git


The following similar one for setting up a Wordpress install doesn't:

---
- name: Set up Wordpress with Apache, Memcached and Varnish
hosts: localhost
vars_prompt:
- name: "domain"
prompt: "Domain name"
private: no
- name: "title"
prompt: "Wordpress title"
private: no
- name: "email"
prompt: "Wordpress email"
private: no
- name: "user"
prompt: "Admin username"
private: no
- name: "pass"
prompt: "Admin password"
private: yes
roles:
- create_droplet
- create_domain
- name: Install dependencies
hosts: launched
roles:
- upgrade
- utilities
- users
- apache
- varnish
- memcached
- mysql
- wordpress


Both playbooks set up a new droplet on Digital Ocean using the
create_droplet
and
create_domain
roles, and add it to the
launched
group. However, the variables prompted for in the second playbook don't appear to be defined, as in this error message:

TASK [wordpress : Add user "wordpress", belonging to group "wordpress" and having a home dir of /var/www] ***
fatal: [<IP_ADDRESS_REDACTED>]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'pass' is undefined\n\nThe error appears to have been in '/home/matthew/Projects/ansible-setup/playbooks/roles/wordpress/tasks/main.yml': line 28, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Add user \"wordpress\", belonging to group \"wordpress\" and having a home dir of /var/www\n ^ here\nWe could be wrong, but this one looks like it might be an issue with\nunbalanced quotes. If starting a value with a quote, make sure the\nline ends with the same set of quotes. For instance this arbitrary\nexample:\n\n foo: \"bad\" \"wolf\"\n\nCould be written as:\n\n foo: '\"bad\" \"wolf\"'\n"}


Use of debug statements has confirmed that in none of the roles called in the second playbook does the
domain
variable appear to be defined. I'm not sure why that is. However, if I remove the part that creates the droplet and run it against an existing droplet, it seems to work OK.

Can anyone see why this is showing up as undefined? Is it something to do with the scope of these variables?

Answer

Is it something to do with the scope of these variables?

Yes, your variables are play-bound, so they are available for the first play (where you prompt them) and unavailable for the second one.

If you need variable to survive between plays, you need to convert it to host fact.
For example add post_tasks to your first play:

post_tasks:
  - set_fact:
      domain: '{{ domain }}'
    delegate_to: '{{ item }}'
    delegate_facts: true
    with_inventory_hostnames: launched

This will add domain fact to every host in launched group.