Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying a custom name for a host

I have an Ansible play-book for working with EC2 instances. I'm using dynamic inventory (ec2.py) to get the group of instances that I want to work with (hosts: tag_Service_Foo). When I run it, it produces output like:

GATHERING FACTS ***************************************************************
ok: [54.149.9.198]
ok: [52.11.22.29]
ok: [52.11.0.3]

However, I can fetch the "Name" tag for a particular instance from Amazon (I do this and store it in a variable for use in a couple parts of the playbook).

Is there a way to get Ansible to use this string for the hostname when displaying progress? I'd like to see something more descriptive (since I don't have the IPs memorized):

GATHERING FACTS ***************************************************************
ok: [main-server]
ok: [extra-server]
ok: [my-cool-server]

The output of the ec2.py inventory script looks like this (truncated; it's very long).

{
  "_meta": {
    "hostvars": {
      "54.149.9.198": {
        "ec2__in_monitoring_element": false,
        "ec2_ami_launch_index": "0",
        "ec2_architecture": "x86_64",
        "ec2_client_token": "xxx",
        "ec2_dns_name": "xxx",
        "ec2_ebs_optimized": false,
        "ec2_eventsSet": "",
        "ec2_group_name": "",
        "ec2_hypervisor": "xen",
        "ec2_id": "i-xxx",
        "ec2_image_id": "ami-xxx",
        "ec2_instance_type": "xxx",
        "ec2_ip_address": "xxx",
        "ec2_item": "",
        "ec2_kernel": "",
        "ec2_key_name": "xxx",
        "ec2_launch_time": "xxx",
        "ec2_monitored": xxx,
        "ec2_monitoring": "",
        "ec2_monitoring_state": "xxx",
        "ec2_persistent": false,
        "ec2_placement": "xxx",
        "ec2_platform": "",
        "ec2_previous_state": "",
        "ec2_previous_state_code": 0,
        "ec2_private_dns_name": "xxx",
        "ec2_private_ip_address": "xxx",
        "ec2_public_dns_name": "xxx",
        "ec2_ramdisk": "",
        "ec2_reason": "",
        "ec2_region": "xxx",
        "ec2_requester_id": "",
        "ec2_root_device_name": "/dev/xvda",
        "ec2_root_device_type": "ebs",
        "ec2_security_group_ids": "xxx",
        "ec2_security_group_names": "xxx",
        "ec2_sourceDestCheck": "true",
        "ec2_spot_instance_request_id": "",
        "ec2_state": "running",
        "ec2_state_code": 16,
        "ec2_state_reason": "",
        "ec2_subnet_id": "subnet-xxx",
        "ec2_tag_Name": "main-server",
        "ec2_tag_aws_autoscaling_groupName": "xxx",
        "ec2_virtualization_type": "hvm",
        "ec2_vpc_id": "vpc-xxx"
      }
    }
  }
  "tag_Service_Foo": [
    "54.149.9.198",
    "52.11.22.29",
    "52.11.0.3"
  ],
}
like image 482
Nathaniel Waisbrot Avatar asked Oct 24 '25 09:10

Nathaniel Waisbrot


2 Answers

What you need to do is create your own wrapper (say my_ec2.py) over the ec2.py that would post process the output. Idea is to use the behavioral hostvar ansible_ssh_host. You can use any language not only python. As long as it prints valid json on stdout you're good to go. Reference if needed.

It'll be a tiny bit of work. But hope the sudo code would help:

output_json_map = new map
for each group in <ec2_output>: # e.g. tag_Service_Foo, I think there would be another 
                                # key in the output that contains list of group names.
  for each ip_address in group:
    hname = ec2_output._meta.hostvars.find(ip_address).find(ec2_tag_Name)

    # Add new host to the group member list
    output_json_map.add(key=group, value=hname)
    copy all vars from ec2_output._meta.hostvars.<ip_address>
                  to output_json_map._meta.hostvars.<hname>
    # Assign the IP address of this host to the ansible_ssh_host
    # in hostvars for this host
    output_json_map.add(key=_meta.hostvars.<hname>.ansible_ssh_host,
                        value=ip_address)
    output_json_map.add(key=_meta.hostvars.find(ip_address).ansible_ssh_host,
                        value=ip_address)

print output_json_map to stdout

E.g. for your example the output of my_ec2.py should be:

{
  "_meta": {
    "hostvars": {
      "main-server": {
        "ansible_ssh_host": "54.149.9.198"
        --- snip ---
        "ec2_tag_Name": "main-server",
        --- snip ---
      },
      "extra-server": {
        "ansible_ssh_host": "52.11.22.29"
        --- snip ---
        "ec2_tag_Name": "extra-server",
        --- snip ---
      },
      <other hosts from all groups>
    }
  }
  "tag_Service_Foo": [
    "main-server",
    "extra-server",
    <other hosts in this group>
  ],
  "some other group": [
    <hosts in this group>,
    ...
  ],
}

and obviously, use this my_ec2.py instead of ec2.py as the inventory file. :-)

-- edit --

1) In the groups, can I only refer to things by one name? 2) There's no notion of an alias? 3) I'm wondering if I could use the IP addr in the groups and just modify the _meta part or if I need to do it all?

Yes*, No and no.


* Technically first yes should be no. Let me explain.

What we are doing here can be done with static inventory file like this:

Original ec2.py was returning json equivalent of following inventory file:

[tag_Service_Foo]
54.149.9.198 ec2_tag_Name="main-server"  ec2_previous_state_code="0" ...
52.11.22.29  ec2_tag_Name="extra-server" ec2_previous_state_code="0" ...

our new my_ec2.py returns this:

[tag_Service_Foo]
main-server  ansible_ssh_host="54.149.9.198" ec2_tag_Name="main-server"  ec2_previous_state_code="0" ...
extra-server ansible_ssh_host="52.11.22.29"  ec2_tag_Name="extra-server" ec2_previous_state_code="0" ...

# Technically it's possible to create "an alias" for main-server like this:
main-server-alias  ansible_ssh_host="54.149.9.198" ec2_tag_Name="main-server"  ec2_previous_state_code="0" ...

Now you would be able to run a play with main-server-alias in the host list and ansible would execute it on 54.149.9.198.

BUT, and this is a big BUT, when you run a play with 'all' as the host pattern ansible would run the task on main-server-alias as well as main-server. So what you created is an alias in one context and a new host in another. I've not tested this BUT part so do come back and correct me if you find out otherwise.

HTH

like image 53
Kashyap Avatar answered Oct 26 '25 05:10

Kashyap


If you put

vpc_destination_variable = Name

in your ec2.ini file, that should work too.

like image 45
Josh Smift Avatar answered Oct 26 '25 04:10

Josh Smift



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!