Ansible loop control

How has it taken me this long?! Sometimes I feel tremendously silly for overlooking the simplest of answers.

I've used loop_control to change the default loop variable, but I've never noticed loop_control can also change the loop label. This is a game changer! Previously, I've mangled data objects to trim them down, or just set no_log: true when loops get to chatty, but all that extra effort was for naught. There's a far simpler answer!

- name: query AWS inventory
  tags: aws
  ec2_instance_info:
    region: "{{ aws_region }}"
    filters:
      instance-state-name: running
      "tag:Platform":
        - Some-Platform
        - Some-Other-Platform
  register: res_ec2_info
- name: Add controller to hosts
  tags: aws
  changed_when: false
  no_log: true #Very chatty with little benefit.
  add_host:
    name: "{{ item.tags.Name |lower |regex_replace('^(.+?) .+', '\\1') }}"
    groups: runtime
    ansible_host : "{{ item.private_ip_address }}"
    platform     : "{{ item.tags.Platform }}"
  loop: "{{ res_ec2_info.instances }}"

The resulting output would be:

TASK [Add controller to hosts] **************************************
ok: [localhost] => (item=None)
ok: [localhost] => (item=None)
ok: [localhost] => (item=None)
ok: [localhost] => (item=None)
ok: [localhost] => (item=None)
ok: [localhost] => (item=None)
...

See – not ideal. I just shut off the log because it was too verbose as it iterated over ec2 instances and spammed out all their details. Just look at how much bloat we don't want to see:

TASK [Add controller to hosts] *****************************************
ok: [localhost] => (item={'ami_launch_index': 0, 'image_id': 'ami-1234',
'instance_id': 'i-1234', 'instance_type': 't2.small', 'key_name': 'a_key', 
'launch_time': '2019-11-04T19:44:24+00:00', 'monitoring': {'state': 'disabled'}, 
'placement': {'availability_zone': 'aws-zone', 'group_name': '', 'tenancy': 'default'}, 
'private_dns_name': 'ip-1.2.3.4.ec2.internal', 'private_ip_address': '1.2.3.4',
'product_codes': [], 'public_dns_name': '', 'state': {'code': 16, 'name': 'running'},
'state_transition_reason': '', 'subnet_id': 'subnet-1234', 'vpc_id': 'vpc-1234',
'architecture': 'x86_64', 'block_device_mappings': [{'device_name': '/dev/sda1',
'ebs': {'attach_time': '2019-11-04T19:44:25+00:00', 'delete_on_termination': False,
'status': 'attached', 'volume_id': 'vol-1234'}}], 'client_token': '', 'ebs_optimized': False, 
'ena_support': False, 'hypervisor': 'xen', 'network_interfaces': [{'attachment': {'attach_time': '2019-11-04T19:44:24+00:00', 
'attachment_id': 'eni-attach-1234', 'delete_on_termination': False, 'device_index': 0,
'status': 'attached', 'network_card_index': 0}, 'description': 'P0000 - A Description', 
'groups': [{'group_name': 'AGroup', 'group_id': 'sg-1234'}, 
{'group_name': 'AnotherGroup', 'group_id': 'sg-5678'}], 'ipv6_addresses': [],
'mac_address': '00:11:22:33:44:55', 'network_interface_id': 'eni-1234',
'owner_id': '012345678', 'private_ip_address': '1.2.3.4', 
'private_ip_addresses': [{'primary': True, 'private_ip_address': '1.2.3.4'}],
'source_dest_check': False, 'status': 'in-use', 'subnet_id': 'subnet-1234', 
'vpc_id': 'vpc-1234', 'interface_type': 'interface'}],
'root_device_name': '/dev/sda1', 'root_device_type': 'ebs',
'security_groups': [{'group_name': 'AGroup', 'group_id': 'sg-1234'},
{'group_name': 'AnotherGroup', 'group_id': 'sg-5678'}], 'source_dest_check': True,
'tags': {'Platform': 'Some-Platform', 'Name': 'P0000 - A Description'},
'virtualization_type': 'hvm', 'cpu_options': {'core_count': 1, 'threads_per_core': 1}, 
'capacity_reservation_specification': {'capacity_reservation_preference': 'open'}, 'hibernation_options': {'configured': False}, 
'metadata_options': {'state': 'applied', 'http_tokens': 'optional', 'http_put_response_hop_limit': 1,
'http_endpoint': 'enabled'}, 'enclave_options': {'enabled': False}})
...

Consider the above in comparison to the below!

- name: query AWS inventory
  tags: aws
  ec2_instance_info:
    region: "{{ aws_region }}"
    filters:
      instance-state-name: running
      "tag:Platform":
        - Some-Platform
        - Some-Other-Platform
  register: res_ec2_info
- name: Add controller to hosts
  tags: aws
  changed_when: false
  loop_control:
    label: "{{ item.tags.Name }}"
  add_host:
    name: "{{ item.tags.Name |lower |regex_replace('^(.+?) .+', '\\1') }}"
    groups: runtime
    ansible_host : "{{ item.private_ip_address }}"
    platform     : "{{ item.tags.Platform }}"
  loop: "{{ res_ec2_info.instances }}"

So much nicer output:

TASK [Add controller to hosts] *****************************************
ok: [localhost] => (item=P0000 - A Description)
ok: [localhost] => (item=P0001 - B Description)
ok: [localhost] => (item=P0002 - C Description)
ok: [localhost] => (item=P0003 - D Description)
ok: [localhost] => (item=P0004 - E Description)
ok: [localhost] => (item=P0005 - F Description)
...

Reference