---
# tasks file for test_ec2_ami

- block:

    # ============================================================

    # SETUP: vpc, ec2 key pair, subnet, security group, ec2 instance, snapshot

    - name: create a VPC to work in
      ec2_vpc_net:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        cidr_block: 10.0.0.0/24
        state: present
        name: '{{ ec2_ami_name }}_setup'
        resource_tags:
          Name: '{{ ec2_ami_name }}_setup'
      register: setup_vpc

    - name: create a key pair to use for creating an ec2 instance
      ec2_key:
        name: '{{ ec2_ami_name }}_setup'
        state: present
        ec2_region: '{{ ec2_region }}'
        ec2_access_key: '{{ ec2_access_key }}'
        ec2_secret_key: '{{ ec2_secret_key }}'
        security_token: '{{ security_token }}'
      register: setup_key

    - name: create a subnet to use for creating an ec2 instance
      ec2_vpc_subnet:
        ec2_region: '{{ ec2_region }}'
        ec2_access_key: '{{ ec2_access_key }}'
        ec2_secret_key: '{{ ec2_secret_key }}'
        security_token: '{{ security_token }}'
        az: '{{ ec2_region }}a'
        tags: '{{ ec2_ami_name }}_setup'
        vpc_id: '{{ setup_vpc.vpc.id }}'
        cidr: 10.0.0.0/24
        state: present
        resource_tags:
          Name: '{{ ec2_ami_name }}_setup'
      register: setup_subnet

    - name: create a security group to use for creating an ec2 instance
      ec2_group:
        name: '{{ ec2_ami_name }}_setup'
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        description: 'created by Ansible integration tests'
        state: present
        vpc_id: '{{ setup_vpc.vpc.id }}'
      register: setup_sg

    - name: provision ec2 instance to create an image
      ec2:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        key_name: '{{ setup_key.key.name }}'
        instance_type: t2.micro
        state: present
        image: '{{ ec2_ami_image[ec2_region] }}'
        wait: yes
        instance_tags:
          '{{ec2_ami_name}}_instance_setup': 'integration_tests'
        group_id: '{{ setup_sg.group_id }}'
        vpc_subnet_id: '{{ setup_subnet.subnet.id }}'
      register: setup_instance

    - name: take a snapshot of the instance to create an image
      ec2_snapshot:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        instance_id: '{{ setup_instance.instance_ids[0] }}'
        device_name: /dev/xvda
        state: present
      register: setup_snapshot

    # ============================================================

    - name: create an image from the instance
      ec2_ami:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        instance_id: '{{ setup_instance.instance_ids[0] }}'
        state: present
        name: '{{ ec2_ami_name }}_ami'
        description: '{{ ec2_ami_description }}'
        tags:
          Name: '{{ ec2_ami_name }}_ami'
        wait: yes
        root_device_name: /dev/xvda
      ignore_errors: true
      register: result

    - name: assert that image has been created
      assert:
        that:
          - "result.changed"
          - "result.image_id.startswith('ami-')"
          # FIXME: tags are not currently shown in the results
          #- "result.tags == '{Name: {{ ec2_ami_name }}_ami}'"

    - name: set image id fact for deletion later
      set_fact:
        ec2_ami_image_id: "{{ result.image_id }}"

    # ============================================================

    - name: delete the image
      ec2_ami:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        instance_id: '{{ setup_instance.instance_ids[0] }}'
        state: absent
        delete_snapshot: yes
        name: '{{ ec2_ami_name }}_ami'
        description: '{{ ec2_ami_description }}'
        image_id: '{{ result.image_id }}'
        tags:
          Name: '{{ ec2_ami_name }}_ami'
        wait: yes
      ignore_errors: true
      register: result

    - name: assert that the image has been deleted
      assert:
        that:
          - "result.changed"
          - "'image_id' not in result"

    # ============================================================

    - name: test removing an ami if no image ID is provided (expected failed=true)
      ec2_ami:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        state: absent
      register: result
      ignore_errors: yes

    - name: assert that an image ID is required
      assert:
        that:
          - "result.failed"
          - "result.msg == 'image_id needs to be an ami image to registered/delete'"

    # ============================================================

    - name: create an image from the snapshot
      ec2_ami:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        name: '{{ ec2_ami_name }}_ami'
        description: '{{ ec2_ami_description }}'
        state: present
        tags:
          Name: '{{ ec2_ami_name }}_ami'
        root_device_name: /dev/xvda
        device_mapping:
          - device_name: /dev/xvda
            volume_type: gp2
            size: 8
            delete_on_termination: true
            snapshot_id: '{{ setup_snapshot.snapshot_id }}'
      register: result
      ignore_errors: true

    - name: assert a new ami has been created
      assert:
        that:
          - "result.changed"
          - "result.image_id.startswith('ami-')"

    - name: set image id fact for deletion later
      set_fact:
        ec2_ami_image_id: "{{ result.image_id }}"
        ec2_ami_snapshot: "{{ result.block_device_mapping['/dev/xvda'].snapshot_id }}"

    # ============================================================

# FIXME: this only works if launch permissions are specified and if they are not an empty list
#    - name: test idempotence
#      ec2_ami:
#        ec2_region: '{{ec2_region}}'
#        ec2_access_key: '{{ec2_access_key}}'
#        ec2_secret_key: '{{ec2_secret_key}}'
#        security_token: '{{security_token}}'
#        description: '{{ ec2_ami_description }}'
#        state: present
#        tags:
#          Name: '{{ ec2_ami_name }}_ami'
#        root_device_name: /dev/xvda
#        image_id: '{{ result.image_id }}'
#        launch_permissions:
#          user_ids:
#            -
#        device_mapping:
#          - device_name: /dev/xvda
#            volume_type: gp2
#            size: 8
#            delete_on_termination: true
#            snapshot_id: '{{ setup_snapshot.snapshot_id }}'
#      register: result

#    - name: assert a new ami has been created
#      assert:
#        that:
#          - "not result.changed"
#          - "result.image_id.startswith('ami-')"

    # ============================================================

# FIXME: tags are not currently shown in the results
    - name: add a tag to the AMI
      ec2_ami:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        state: present
        description: '{{ ec2_ami_description }}'
        image_id: '{{ result.image_id }}'
        name: '{{ ec2_ami_name }}_ami'
        tags:
          New: Tag
        launch_permissions:
          group_names: ['all']
      register: result
#
#    - name: assert a tag was added
#      assert:
#        that:
#          - "result.tags == '{Name: {{ ec2_ami_name }}_ami}, New: Tag'"

    # ============================================================

    - name: update AMI launch permissions
      ec2_ami:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        state: present
        image_id: '{{ result.image_id }}'
        name: '{{ ec2_ami_name }}_ami'
        description: '{{ ec2_ami_description }}'
        tags:
          Name: '{{ ec2_ami_name }}_ami'
        launch_permissions:
          group_names: ['all']
      register: result

    - name: assert launch permissions were updated
      assert:
        that:
          - "result.changed"

    # ============================================================

    - name: modify the AMI description
      ec2_ami:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        state: present
        image_id: '{{ result.image_id }}'
        name: '{{ ec2_ami_name }}_ami'
        description: '{{ ec2_ami_description }}CHANGED'
        tags:
          Name: '{{ ec2_ami_name }}_ami'
        launch_permissions:
          group_names: ['all']
      register: result

    - name: assert the description changed
      assert:
        that:
          - "result.changed"

    # ============================================================

# FIXME: currently the module doesn't remove launch permissions correctly
#    - name: remove public launch permissions
#      ec2_ami:
#        ec2_region: '{{ec2_region}}'
#        ec2_access_key: '{{ec2_access_key}}'
#        ec2_secret_key: '{{ec2_secret_key}}'
#        security_token: '{{security_token}}'
#        state: present
#        image_id: '{{ result.image_id }}'
#        name: '{{ ec2_ami_name }}_ami'
#        tags:
#          Name: '{{ ec2_ami_name }}_ami'
#        launch_permissions:
#          group_names:
#            -
#
#      register: result
#      ignore_errors: true
#
#    - name: assert launch permissions were updated
#      assert:
#        that:
#          - "result.changed"

    # ============================================================

    - name: delete ami without deleting the snapshot (default is not to delete)
      ec2_ami:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        instance_id: '{{ setup_instance.instance_ids[0] }}'
        state: absent
        name: '{{ ec2_ami_name }}_ami'
        image_id: '{{ ec2_ami_image_id }}'
        tags:
          Name: '{{ ec2_ami_name }}_ami'
        wait: yes
      ignore_errors: true
      register: result

    - name: assert that the image has been deleted
      assert:
        that:
          - "result.changed"
          - "'image_id' not in result"

    - name: ensure the snapshot still exists
      ec2_snapshot_facts:
        snapshot_ids:
          - '{{ ec2_ami_snapshot }}'
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
      register: snapshot_result

    - name: assert the snapshot wasn't deleted
      assert:
        that:
          - "snapshot_result.snapshots[0].snapshot_id == ec2_ami_snapshot"

    - name: delete ami for a second time
      ec2_ami:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        instance_id: '{{ setup_instance.instance_ids[0] }}'
        state: absent
        name: '{{ ec2_ami_name }}_ami'
        image_id: '{{ ec2_ami_image_id }}'
        tags:
          Name: '{{ ec2_ami_name }}_ami'
        wait: yes
      ignore_errors: true
      register: result

# FIXME: currently deleting an already deleted image fails
# It should succeed, with changed: false
#    - name: assert that image does not exist
#      assert:
#        that:
#          - not result.changed
#          - not result.failed


    # ============================================================

  always:

    # ============================================================

    # TEAR DOWN: snapshot, ec2 instance, ec2 key pair, security group, vpc
    - name: Announce teardown start
      debug:
        msg: "***** TESTING COMPLETE. COMMENCE TEARDOWN *****"

    - name: delete ami
      ec2_ami:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        state: absent
        image_id: "{{ ec2_ami_image_id }}"
        name: '{{ ec2_ami_name }}_ami'
        wait: yes
      ignore_errors: yes

    - name: remove setup snapshot of ec2 instance
      ec2_snapshot:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        state: absent
        snapshot_id: '{{ setup_snapshot.snapshot_id }}'
      ignore_errors: yes

    - name: remove setup ec2 instance
      ec2:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        instance_type: t2.micro
        instance_ids: '{{ setup_instance.instance_ids }}'
        state: absent
        wait: yes
        instance_tags:
          '{{ec2_ami_name}}_instance_setup': 'integration_tests'
        group_id: '{{ setup_sg.group_id }}'
        vpc_subnet_id: '{{ setup_subnet.subnet.id }}'
      ignore_errors: yes

    - name: remove setup keypair
      ec2_key:
        name: '{{ec2_ami_name}}_setup'
        state: absent
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
      ignore_errors: yes

    - name: remove setup security group
      ec2_group:
        name: '{{ ec2_ami_name }}_setup'
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        description: 'created by Ansible integration tests'
        state: absent
        vpc_id: '{{ setup_vpc.vpc.id }}'
      ignore_errors: yes

    - name: remove setup subnet
      ec2_vpc_subnet:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        az: '{{ ec2_region }}a'
        tags: '{{ec2_ami_name}}_setup'
        vpc_id: '{{ setup_vpc.vpc.id }}'
        cidr: 10.0.0.0/24
        state: absent
        resource_tags:
          Name: '{{ ec2_ami_name }}_setup'
      ignore_errors: yes

    - name: remove setup VPC
      ec2_vpc_net:
        ec2_region: '{{ec2_region}}'
        ec2_access_key: '{{ec2_access_key}}'
        ec2_secret_key: '{{ec2_secret_key}}'
        security_token: '{{security_token}}'
        cidr_block: 10.0.0.0/24
        state: absent
        name: '{{ ec2_ami_name }}_setup'
        resource_tags:
          Name: '{{ ec2_ami_name }}_setup'
      ignore_errors: yes
