Run a role in loop for multiple Elastic Ips

I have written a global role to spin-up ec2 instance at the address: playbook/aws/spin-up-ec2/tasks/main.yaml and i am calling the role in a main file at the location playbook/servers/cluster/tasks/main.yaml to deploy three servers by calling the role in a loop for elastic_ips in the below fashion.
playbook/aws/spin-up-ec2/tasks/main.yaml

- name: test 
  hosts: localhost
  become: false
  gather_facts: false
  vars_files:
   - "vars/{{ env }}/main.yaml"

  pre_tasks:
  - name: Set all
    add_host: hostname={{ item }} groupname=all-servers
    with_items: '{{ elastic_ips }}'

  - name: add new instance to host group at runtime
    add_host: hostname={{ item }} groupname=nodes
    with_items: '{{ elastic_ips[1:] }}'
  tasks:
    - name: Run the role for each elastic IP
      include_role:
        name: ../../roles/aws/spin-up-ec2-instance
      vars:
         elastic_ip: "{{ elastic_ips }}"
      loop: "{{ elastic_ips }}"

- name: On all servers
  hosts: all-servers
  become: false
  gather_facts: false

  roles:
   - install-dependencies
   - install-package
   - configure-package

- name: On all nodes
  hosts: nodes
  become: false
  gather_facts: false
  
  roles:
    - setup-cluster

I am using the variable file at the below location: playbook/servers/cluster/vars/<prod/uat>/main.yaml
The var file contains the some variables which are common for all the three servers. But there are some variables which are different for different instances. So i want these variables to be passed in the loop. I am not able to achieve this. The variables which are different for different instances are mentioned below;

ebs_tags:
  Name: server-1/2/3
  customer: abc
  cost_center: abc
  env_type: prod/uat
ec2_tags:
  Name: server-1/2/3
  customer: abc
  cost_center: abc
  env_type: prod/uat
server_name: "server-1/2/3"
elastic_ips:
  - 4.8.9.7
  - 4.6.6.3
  - 2.5.3.0

I have tried different approaches but i get errors like item is undefined or we were unable to convert to dict: dictionary requested, could not parse JSON or key=value.

Please help me resolve this issue and optimize the approach.
Note: I can’t use the host/inventory file also the playbook/aws/spin-up-ec2/tasks/main.yaml role is a global role and uses variables as defined in the var file. No changes can be made in the variable key parameter.

You are using a loop, but not actually looping through? You would reference the current loop variable by using item

An easy example from Loops — Ansible Documentation

- name: Add several users
  ansible.builtin.user:
    name: "{{ item }}"
    state: present
    groups: "wheel"
  loop: "{{ somelist }}"

So maybe this section needs to be changed like so?

    - name: Run the role for each elastic IP
      include_role:
        name: ../../roles/aws/spin-up-ec2-instance
      vars:
         #elastic_ip: "{{ elastic_ips }}"
         elastic_ip: "{{ item }}"
      loop: "{{ elastic_ips }}"
1 Like

@jrglynn2 I tried this as well, but it gives me the below mentioned error.

TASK [../../roles/aws/spin-up-ec2-instance : Spin up the EC2 instance] *************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "argument 'tags' is of type <class 'list'> and we were unable to convert to dict: <class 'list'> cannot be converted to a dict"}

Hi,

What is your argument ‘tags’ ? What are you trying to do with it in your role ?

You obviously have a type mismatch, trying to pass a list to something expecting a dict, but it’s hard to debug without seeing what your role is doing. Could you share you role’s relevant task(s) ? Also, how was your playbook changed exactly for you to get this error ?

Same questions as @ptn … we don’t see tags in your initial code, so we don’t know where the issue is happening.

When you run the command as -vvv and get this error, do you see that the task is trying to run against one of your {{ elastic_ips }} values?

That would confirm whether the initial issue is resolved - the loop issue.

This tags seems like an issue with a different part of code.

1 Like

Hi @jrglynn2 @ptn thanks i got the solution i was looping elastic ip only now i modified the loop to use all the tags.

---
- name: test 
  hosts: localhost
  become: false
  gather_facts: false
  vars_files:
   - "vars/{{ env }}/main.yml"

  tasks:  
    - name: Run the role for each elastic IP
      include_role:
        name: ../../roles/aws/spin-up-ec2-instance
      loop: "{{ server_variable }}"
      loop_control:
        loop_var: server_item
      vars:
        elastic_ip: "{{ server_item.elastic_ip }}"
        ec2_tags: "{{ server_item.ec2_tags }}"
        ebs_tags: "{{ server_item.ebs_tags }}"
        server_name: "{{ server_item.server_name }}"

var file

server_variable:
  - ec2_tags:
      Name: RabbitMQ-1
      customer: hsbc
      cost_center: hsbc
      env_type: prod
    ebs_tags:
      Name: RabbitMQ-1
      customer: hsbc
      cost_center: hsbc
      env_type: prod
    server_name: RabbitMQ-1
    elastic_ip: "34.198.209.77"
  - ec2_tags:
      Name: RabbitMQ-2
      customer: hsbc
      cost_center: hsbc
      env_type: prod
    ebs_tags:
      Name: RabbitMQ-2
      customer: hsbc
      cost_center: hsbc
      env_type: prod
    server_name: RabbitMQ-2
    elastic_ip: "44.196.206.193"
  - ec2_tags:
      Name: RabbitMQ-3
      customer: hsbc
      cost_center: hsbc
      env_type: prod
    ebs_tags:
      Name: RabbitMQ-3
      customer: hsbc
      cost_center: hsbc
      env_type: prod
    server_name: RabbitMQ-3
    elastic_ip: "52.45.63.110"

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.