Passing register variable to a role called by playbook?

353 views
Skip to first unread message

ji...@pristine.io

unread,
Dec 10, 2014, 3:11:41 PM12/10/14
to ansible...@googlegroups.com
I am launching one-off ec2 instance for development purposes and in the main playbook I am launching an EC2 instance then assigning an elastic IP. Once all of that is done I am configuring the server via a role. I am able to capture the elastic IP via register but how do I call it from the role? Or more specifically how can I call it in a configuration template from within the role that is applied?

Here's an example:

launch-server.yml:

- name: Launch ec2 instance
  hosts: localhost
  gather_facts: False
  vars:
    key_name: ssh-key
    instance_type: t2.medium
    group_id: sg-f834234
    image: ami-b234234
    region: us-east-1
    vpc_subnet_id: subnet-65wer234
  tasks:

    - name: Launch instance
      local_action: ec2 key_name={{ key_name }} group_id={{ group_id }} instance_type={{ instance_type }} image={{ image }} wait=true region={{ region }} vpc_subnet_id={{ vpc_subnet_id }} instance_tags='{"Name":"ec2-instance"}'
      register: ec2

    - name: allocate a new elastic IP without associating it to anything
      action: ec2_eip region=us-east-1
      register: eiptest

    - name: output the IP
      debug: msg="Allocated IP is {{ eiptest.public_ip }}" <--- this prints the elastic IP to the screen.

    - name: Add new instance to host group
      local_action: add_host hostname={{ item.private_ip }} groupname=launched
      with_items: ec2.instances

    - name: Wait for SSH to come up
      local_action: wait_for host={{ item.private_ip }} port=22 delay=60 timeout=320 state=started
      with_items: ec2.instances

- name: Configure instance
  hosts: launched
  sudo: True
  gather_facts: True
  roles:
    - myrole

In the template from within the role it doesn't know about eiptest.public_ip so it fails and reading the docs it seems that var will be destroyed at the end of the play that calls the role. If I run ansible hostname -m setup I don't see any entries for the elastic IP assigned to the instance.

I've tried a number of things and read through the docs but not having much luck. I would like to keep the roles separate from the plays that launch the instances if at all possible.

Thanks!

ji...@pristine.io

unread,
Dec 10, 2014, 3:18:53 PM12/10/14
to ansible...@googlegroups.com
Quick correction on this. I pasted the wrong data where it says "name: allocate a new elastic IP without associating it to anything" The play actually looks like this:

    - name: Associate a new Elastic IP to instance
      ec2_eip: region=us-east-1 in_vpc=yes "instance_id={{ item }}"
      with_items: ec2.instance_ids
      register: eiptest

Michael DeHaan

unread,
Dec 11, 2014, 7:25:42 PM12/11/14
to ansible...@googlegroups.com
Perhaps I'm not completely following the question:

" I am able to capture the elastic IP via register but how do I call it from the role?"

Basically any variable already registered can be used like "{{ foo }}" in subsequent roles/tasks/whatever -- so maybe you could help me understand where the point of confusion is?

Want to help, just a bit unclear on it.  Thanks!



--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/6613e7b0-3be9-40f1-9eb9-4fbe685297ea%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

ji...@pristine.io

unread,
Dec 12, 2014, 10:29:51 AM12/12/14
to ansible...@googlegroups.com
Hi Michael,

Thanks for the reply. 

I have a playbook that launches an EC2 instance and associates an elastic IP to that instance I then use register to capture that IP:

    - name: Associate a new Elastic IP to instance
      ec2_eip: region=us-east-1 in_vpc=yes "instance_id={{ item }}"
      with_items: ec2.instance_ids
      register: eiptest

I used the debug technique to print out the IP just to make sure it was working:

    - name: Output the IP
      debug: msg="The elastic IP is {{ eiptest }}"

Here's the output:

TASK: [Output the IP] *********************************************************
ok: [localhost] => {
    "msg": "The elastic IP is {'msg': 'All items completed', 'changed': True, 'results': [{u'public_ip': u'255.100.104.57', 'item': u'i-32d230d2', u'changed': True, 'invocation': {'module_name': u'ec2_eip', 'module_args': u'region=us-east-1 in_vpc=yes \"instance_id=asdfadf\"'}}]}"
}

I tried a number of things and for some reason I can't get it to print "The elastic IP is 255.100.104.57" using "The elastic IP is {{ eiptest.public_ip }}". I had it working before but now I can only get it to dump the full dict above. 

In any case at the end of the play I call the role which attempts to use a j2 template to put a config in place. From the configuration file:

external-ip="{{ eiptest.public_ip }}"

And the error message:

ASK: [boom | Copy boom configuration] ****************************************
fatal: [10.10.10.10] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'eiptest' is undefined", 'failed': True}

Hope all of this makes sense. I am using version 1.7.2 currently. 

Thanks!

On Wednesday, December 10, 2014 2:11:41 PM UTC-6, ji...@pristine.io wrote:

ji...@pristine.io

unread,
Dec 12, 2014, 3:09:05 PM12/12/14
to ansible...@googlegroups.com
Okay I fixed the first issue in my previous post so:

- name: Output the IP
  debug: msg="The elastic IP is {{ eiptest.results[0].public_ip }}"

Now displays:

TASK: [Output the IP] *********************************************************
ok: [localhost] => {
    "msg": "The elastic IP is 255.10.10.10"
}

But it doesnt carry over when the role is run. I tried turning off gather_facts before the role is called thinking maybe it was being overwritten or discarded but that didn't work either.

I am also having a similar issue where we run a script that generates an API key and I save the output to a register: but I can't get the nested value of "key". But I'll save that for another post :)

Once I wrap my head around the best way to access data in lists / dicts properly via Ansible I'll be off and running. 

Toshio Kuratomi

unread,
Dec 12, 2014, 4:30:05 PM12/12/14
to ansible...@googlegroups.com
I tried to simplify this down and replicate it but wasn't able to.
Here's my playbooks and role, maybe you can spot an important
difference:


$ cat var.yml
---
- name: first
hosts: localhost
tasks:
- name: set a variable
action: ping
register: eiptest

- name: second
sudo: True
gather_facts: True
hosts: localhost
roles:
- var


$ tree roles
roles
└── var
├── tasks
│ └── main.yml
└── templates
└── test.j2

$ cat roles/var/tasks/main.yml
---
# tasks file for var
- name: use a variable in a template from a role
template:
src: 'test.j2'
dest: /var/tmp/var-test

$ cat roles/var/templates/test.j2
{{ eiptest.ping }}

$ ansible-playbook var.yml -K
[...]
$ cat /var/tmp/var-test
pong

-Toshio
> --
> You received this message because you are subscribed to the Google Groups
> "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to ansible-proje...@googlegroups.com.
> To post to this group, send email to ansible...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/ansible-project/fe986fd4-0b22-4799-a827-724b54f3426e%40googlegroups.com.

ji...@pristine.io

unread,
Dec 14, 2014, 3:01:26 PM12/14/14
to ansible...@googlegroups.com
Looks good to me. But I am still fighting through this on my end.

It seems like it should be pretty straightforward. 

- Launch the instance
- Allocate elastic IP then use the register keyword to save it to a var. (I even tried set_fact with no luck)
- In the template add {{ var.public_ip }}.

It will print the correct IP during a playbook run using debug but when it gets to the point of building the config from the template it seems the variable no longer exists.

I am going to try some other things or just put everything in the same one-off play.

Thanks for the replies.


On Wednesday, December 10, 2014 2:11:41 PM UTC-6, ji...@pristine.io wrote:

ji...@pristine.io

unread,
Dec 15, 2014, 4:48:39 PM12/15/14
to ansible...@googlegroups.com
Alright I have no idea what I am missing here but this is not working.

I added everything from the role into the same playbook that launches the server and it still has no clue what the variable is when I try to use it in a j2 template.

Keep in mind here there are two stages to this playbook. The local actions that LAUNCH the ec2 instance and then I configure the remote instance that was launched. All in the same play. Whereas before I was just launching then calling a role to run on it. I create groupname=launched then when it comes time to configure I use hosts: launched and everything else works but my vars don't carry over.

Here are the relevant bits:

    - name: Associate a new Elastic IP to instance
      ec2_eip: region=us-east-1 in_vpc=yes "instance_id={{ item }}"
      with_items: ec2.instance_ids
      register: eiptest

    - name: Set elastic IP fact
      set_fact: elasticIP="{{ eiptest.results[0].public_ip }}"

    - name: Output the IP
      debug: msg="The elastic IP is {{ elasticIP }}"  <--- This prints out the IP properly. No problem. Example: "msg": "The elastic IP is 104.104.104.104"

    - name: Add new instance to host group
      local_action: add_host hostname={{ item.private_ip }} groupname=launched
      with_items: ec2.instances

    - name: Wait for SSH to come up
      local_action: wait_for host={{ item.private_ip }} port=22 delay=60 timeout=320 state=started
      with_items: ec2.instances

After SSH comes up the play continues with the following:

- name: Install and configure server
  hosts: launched
  remote_user: ec2-user
  sudo: yes
  tasks:
        - name: Copy rpm packages for installation
        copy: src=packages/{{ item }} dest=/tmp/{{ item }}
        with_items:
        - a-linux-rpm-el6.x86_64.rpm
        - another-rpm-el6.x86_64.rpm

      - name: Copy configuration file
        template: src=config.conf.j2 dest=/etc/linuxstuff/config.conf
        notify:
        - restart server

And finally IN the config file itself is this line:

external-ip="{{ elasticIP }}"  NOTE: I have tried many different quote styles here

And I get this error:

TASK: [Copy server configuration] ***********************************************
fatal: [10.10.10.10 => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'elasticIP' is undefined", 'failed': True}
fatal: [10.10.10.10] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'elasticIP' is undefined", 'failed': True}

ji...@pristine.io

unread,
Dec 16, 2014, 10:06:13 AM12/16/14
to ansible...@googlegroups.com
I resolved this by doing the following:

Instance launch stage:

- Setting the fact for the elastic IP
- Writing the IP to a file using shell:

After calling the role when SSH is available:

- cat the same file and register result to a new variable (delegate_to: localhost)
- Set a new fact
- great success

On Wednesday, December 10, 2014 2:11:41 PM UTC-6, ji...@pristine.io wrote:
Reply all
Reply to author
Forward
0 new messages