2

Here is a Linode playbook to spin a cloud server instance:

---
- hosts: 127.0.0.1
  connection: local
  tasks:
   - name: Create Linode Machine
     linode:
      api_key: 'blablabla'
      name: test
      plan: 1
      datacenter: 7
      distribution: 124
      password: 'blabla'
      swap: 768
      wait: yes
      wait_timeout: 600
      state: started
     register: result

If I do that, the instance gets created, however this is not that great of an advantage if I can't get an ip from the output to pass to another playbook and automate a build fully.

When you run the above the module gives no output whatsoever, however if you run the playbook with the -v option, you can see that the following output is reported. How can I fetch this

changed: [127.0.0.1] => {"changed": true, "instance": {"fqdn": "xxxx.members.linode.com", "id": 2342234, "ipv4": "185.x.x.x", "name": "1902695_test", "password": "blabla", "private": [], "public": [{"fqdn": "xxxx.members.linode.com", "ip_id": 324324, "ipv4": "185.x.x.x"}], "status": "Running"}}

How can I just save the ipv4 to a variable to use in another playbook or whatever?

EDIT: I've added the following code under the one above to test the answer given but it didn't work:

- hosts: "{{ result['instance']['ipv4'] }}"
  remote_user: root
  tasks:
   - name: "test"
     command: ls -la
   - apt: upgrade=dist update_cache=yes

I get the following error message:

ERROR! 'result' is undefined

Ive also tried set_fact and that didn't work either.

1 Answer 1

2

You can register the output of any task as a variable like so:

- name: Create Linode Machine
  linode:
     api_key: 'blablabla'
     ...
  register: result

Now you have the tasks result stored in the variable result and should be able to access the IP via result['instance']['ipv4'].

If not, the debug module is your friend and you can inspect the content of the variable:

- debug: var=result

If your really want to make it available to another playbook which is not part of the current execution, fact-caching might be an option for you. With fact-caching enabled you can use set_fact:

- set_fact:
    myInstanceIp: "{{ result['instance']['ipv4'] }}"

Another complication is that variables/facts are stored per host. In above case you stored the variable for localhost. So it will only be directly available on tasks which run in context of localhost.

The hosts section of the playbook though is not evaluated in context of any host, so you can not directly access this variable.

I see three possible options:

1) Execute the second play also on localhost and then delegate the tasks to another host. Since now the task is executed in context of localhost you should be able to access the registered result.

- hosts: localhost
  delegate_to: "{{ result['instance']['ipv4'] }}"
  remote_user: root
  tasks:
     ...

According to the docs delegate_to will work on tasks, but I guess it should work on play level as well which then will pass it on to every contained task. If not, you'll need to add it to every single task then.

- hosts: localhost
  remote_user: root
  tasks:
    - name: "test"
      command: ls -la
      delegate_to: "{{ result['instance']['ipv4'] }}"
    - apt: upgrade=dist update_cache=yes
      delegate_to: "{{ result['instance']['ipv4'] }}"

2) Even though not executed in the context of localhost you should be able to access the related vars through the hostvars dict:

- hosts: "{{ hostvars['localhost']['result']['instance']['ipv4'] }}"
  remote_user: root
  ...

3) Dynamically create a new group with the add_host module:

- add_host:
    name: "{{ result['instance']['ipv4'] }}"
    groups: just_created

And then use the group just_created in the next play:

- hosts: just_created
  tasks: ...
10
  • Why would result['instance']['ipv4'] ? know exactly to fetch the ip? Is it because of the json formatting? Where is that documented?
    – Ulukai
    May 18, 2016 at 16:55
  • The result of any task is a dictionary. There are some default keys in there like changed, failed. Other keys are depending on the module. The JSON you got from the verbose output should be this result. It is not documented what each module returns. The debug module is therefore very important to inspect the registered content.
    – udondan
    May 18, 2016 at 17:02
  • Thank you udondan. The debug does display the right content, but when doing what you suggested to parse the ipv4 it didn't work as explained in the edit.
    – Ulukai
    May 19, 2016 at 9:15
  • - hosts: "result['instance']['ipv4']" would only be a string. Try - hosts: "{{ result['instance']['ipv4'] }}". But I'm not sure this is going to work like this, because variables/facts are stored per host. Not sure how this would be accessible at this position in the playbook, since that's not related to any host... I got an idea how to do it if above notation won't work.
    – udondan
    May 19, 2016 at 9:28
  • Yes, I realised that, and corrected before you mentioned it. However it still doesn't work like you said... I am finding ansible really frustrating, something that should be so simple is such a pain and I keep going around in circles with the documentation... maybe I am missing something. If you think of something let me know. Thank you for all your help until now either way, I've learned something, even if it didn't fully solved my issue.
    – Ulukai
    May 19, 2016 at 9:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .