Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Launch multiple volumes with ec2 instance using ansible

I am provisioning an ec2 instance with number of volumes attached to it. Following is my playbook to do the same.

---
- hosts: localhost
  connection: local
  gather_facts: false
  vars:
    instance_type: 't2.micro'
    region: 'my-region'
    aws_zone: 'myzone'
    security_group: my-sg
    image: ami-sample
    keypair: my-keypair
    vpc_subnet_id: my-subnet
  tasks:
  - name: Launch instance
    ec2:
      image: "{{ image }}"
      instance_type: "{{ instance_type }}"
      keypair: "{{ keypair}}"
      instance_tags: '{"Environment":"test","Name":"test-provisioning"}'
      region: "{{region}}"
      aws_zone: "{{ region }}{{ aws_zone }}"
      group: "{{ security_group }}"
      vpc_subnet_id: "{{vpc_subnet_id}}"
      wait: true
      volumes:
        - device_name: "{{ item }}"
          with_items:
             - /dev/sdb
             - /dev/sdc
          volume_type: gp2
          volume_size: 100
          delete_on_termination: true
          encrypted: true
    register: ec2_info

But getting following error

fatal: [localhost]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'item' is undefined

If I replace the {{item}} with /dev/sdb the instance gets launched with the specific volume easily. But I want to create more than one volume with the specified list of items - /dev/sdb, /dev/sdc etc Any possible way to achieve this?

like image 203
drishti ahuja Avatar asked Oct 18 '22 01:10

drishti ahuja


1 Answers

You can't use with_items with vars and parameters – it's just for tasks.
You need to construct your volumes list in advance:

- name: Populate volumes list
  set_fact:
    vol:
      device_name: "{{ item }}"
      volume_type: gp2
      volume_size: 100
      delete_on_termination: true
      encrypted: true
  with_items:
     - /dev/sdb
     - /dev/sdc
  register: volumes

And then exec ec2 module with:

volumes: "{{ volumes.results | map(attribute='ansible_facts.vol') | list }}"

Update: another approach without set_fact:

Define a variable – kind of template dictionary for volume (without device_name):

vol_default:
  volume_type: gp2
  volume_size: 100
  delete_on_termination: true
  encrypted: true

Then in your ec2 module you can use:

volumes: "{{ [{'device_name': '/dev/sdb'},{'device_name': '/dev/sdc'}] | map('combine',vol_default) | list }}"
like image 103
Konstantin Suvorov Avatar answered Oct 21 '22 05:10

Konstantin Suvorov