mlist
mlist

Reputation: 31

ansible module amazon.aws.ec2_instance - can't get public IP

I created the following playbook using "old" EC2 Ansible module:

---
- name: Create Ec2 instances
  hosts: localhost
  become: False
  # import the secret file
  vars_files:
    - secrets.yml
  gather_facts: false
  tasks:

  # Block is a Group of Tasks combined together
  - name: Get Info Block
    block:
      - name: Get Running instance Info

        ec2_instance_info:
        register: ec2info

      - name: Print info
        debug: var="ec2info.instances"

  - name: Create EC2 Block
    block:

      - name: Launch ec2 instances
        tags: create_ec2
        ec2:
          region: eu-west-1
          key_name: ec2-tutorial
          group: launch-wizard-1
          instance_type: t2.micro
          image: ami-04dd4500af104442f
          wait: yes
          wait_timeout: 500
          count: 1
          instance_tags:
            name: appservers
            os: ubuntu
          monitoring: no
          vpc_subnet_id: subnet-049055a2c1633c0eb
          assign_public_ip: yes
          aws_access_key: XXXX
          aws_secret_key: YYYYYYY
        register: ec2
        delegate_to: localhost

      - name : Add instance to host group
        add_host:
          hostname: "{{ item.public_ip }}"
          groupname: launched
        loop: "{{ ec2.instances }}"

      - name: Wait for SSH to come up
        local_action:
          module: wait_for
          host: "{{ item.public_ip }}"
          port: 22
          delay: 10
          timeout: 120
        loop: "{{ ec2.instances }}"
    # By specifying never on the tag of this block,
    # I let this block to run only when explicitely being called
    tags: ['never', 'ec2-create']

It works correctly and I'm able to create and EC2 instance testing also the connection retrieving its public IP.

The problem is that EC2 is deprecated, so; I rewrote the same playbook using the new module ec2_instance that doesn't return the public IP.
Since, I'm not able to test the connection, I temporarily put a - meta: end_play, so that I can deploy instance.
This is the new playbook

---
- name: Create Ec2 instances
  hosts: localhost
  become: False
  # import the secret file
  vars_files:
    - secrets.yml
  gather_facts: false
  tasks:

  # Block is a Group of Tasks combined together
  - name: Get Info Block
    block:
      - name: Get Running instance Info

        ec2_instance_info:
        register: ec2info

      - name: Print info
        debug: var="ec2info.instances"

    # By specifying always on the tag,
    #     # I let this block to run all the time by module_default
    #         # this is for security to net create ec2 instances accidentally
    tags: ['always', 'getinfoonly']

  - name: Create EC2 Block
    block:

      - name: Launch ec2 instances
        tags: create_ec2
        ec2_instance:
          name: "Test new Ansible ec2 module"
          region: eu-west-1
          #Availability zone is mutually excluded with vpc_subnet_id
          #availability_zone: eu-west-1c
          #key_name: ec2-tutorial
          key_name: testec2key
          security_group: launch-wizard-1
          instance_type: t2.micro
          image_id: ami-04dd4500af104442f
          wait: yes
          volumes:
            - device_name: /dev/sdb
              ebs:
                volume_size: 8
                delete_on_termination: true
            #- device_name: /dev/sdb
            #  volume_type: gp2
            #  volume_size: 5
            #  delete_on_termination: true
          wait_timeout: 500
          # count not available is this new module
          #count: 1
          tags:
            name: "Test"
            os: AwsAmi
          #vpc_subnet_id: subnet-049055a2c1633c0eb
          vpc_subnet_id: subnet-08a394b8718bbff45
          network:
            assign_public_ip: true
          #termination_protection: yes
          #aws_access_key: XXXXXXX
          #aws_secret_key: YYYYYYYYYYY
        register: ec2
        delegate_to: localhost

      #- meta: end_play

      - name: Add instance to host group
        add_host:
          hostname: "{{ item.public_ip }}"
          groupname: launched
        loop: "{{ ec2.instances }}"
               
      - name: Wait for SSH to come up
        local_action:
          module: wait_for
          host: "{{ item.public }}"
          port: 22
          delay: 10
          timeout: 120
        loop: "{{ ec2.instances }}"
    # By specifying never on the tag of this block,
    # I let this block to run only when explicitely being called
    tags: ['never', 'ec2-create']

This is the error I get running playbook, commenting - meta: end_play (that makes the playbook go on):

ansible-playbook aws-ec2-creationtst3.yml --connection=local --tags=ec2-create -e "ansible_python_interpreter=/home/marcoreale/aws-venv/bin/python3" --ask-vault-pass -vvvv

TASK [Add instance to host group] **************************************************************************************
task path: /home/xxx/aws-venv/playbook/aws-ec2-create/aws-ec2-creationtst3.yml:70
fatal: [localhost]: FAILED! => {
   "msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'public_ip'\n\nThe error appears to be in '/home/marcoreale/aws-venv/playbook/aws-ec2-create/aws-ec2-creationtst3.yml': line 70, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n      - name: Add instance to host group\n        ^ here\n"
}

error

Note: replacing item.public_ip with item.private_ip works but I need to test connection using the public IP.
Do you have any suggestion? How should I change my playbook to test the connection using the public IP?

Upvotes: 3

Views: 1539

Answers (2)

Chaffelson
Chaffelson

Reputation: 1269

You want to set state: running in your ec2_instance invocation. Basically what is happening is your wait is only until it achieves the state defined, and the default state does not wait for the public_ip to be assigned.

Upvotes: 5

β.εηοιτ.βε
β.εηοιτ.βε

Reputation: 39129

The documentation is pointing at the fact that the public IP address is now nested via the public_ip_address property.

So, your task should work with

- name: Add instance to host group
  add_host:
    hostname: "{{ item.public_ip_address }}"
    groupname: launched
  loop: "{{ ec2.instances }}"

Upvotes: 0

Related Questions