
    VhaV                        d Z dZdZddlmZ ddlmZ ddlmZ ddlmZ ddlmZ dd	lm	Z	 dd
l
mZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ dee   dee   deeee	eeeeef      f   f      fdZ	 d0deeeef      dededee   fdZ 	 d1ded eeeef      d!ee   d"ed#eeeef      d$ee   deeeef   ef   fd%Zdededeeeef      fd&Z!d'edeeeef      fd(Z"d'edefd)Z#d*ed'edeeeef      dedeeef   f
d+Z$d'edeeeef      dedeeef   fd,Z%d'efd-Z&d. Z'e(d/k(  r e'        yy)2a/  
---
module: ec2_eip
version_added: 5.0.0
short_description: manages EC2 elastic IP (EIP) addresses.
description:
  - This module can allocate or release an EIP.
  - This module can associate/disassociate an EIP with instances or network interfaces.
  - This module was originally added to C(community.aws) in release 1.0.0.
options:
  device_id:
    description:
      - The id of the device for the EIP.
      - Can be an EC2 Instance id or Elastic Network Interface (ENI) id.
      - When specifying an ENI id, O(in_vpc) must be V(true).
      - The C(instance_id) alias was removed in release 6.0.0.
    required: false
    type: str
  public_ip:
    description:
      - The IP address of a previously allocated EIP.
      - When O(state=present) and device is specified, the EIP is associated with the device.
      - When O(state=absent) and device is specified, the EIP is disassociated from the device.
    aliases: [ ip ]
    type: str
  state:
    description:
      - When O(state=present), allocate an EIP or associate an existing EIP with a device.
      - When O(state=absent), disassociate the EIP from the device and optionally release it.
    choices: ['present', 'absent']
    default: present
    type: str
  in_vpc:
    description:
      - Allocate an EIP inside a VPC or not.
      - Required if specifying an ENI with O(device_id).
    default: false
    type: bool
  reuse_existing_ip_allowed:
    description:
      - Reuse an EIP that is not associated to a device (when available), instead of allocating a new one.
    default: false
    type: bool
  release_on_disassociation:
    description:
      - Whether or not to automatically release the EIP when it is disassociated.
    default: false
    type: bool
  private_ip_address:
    description:
      - The primary or secondary private IP address to associate with the Elastic IP address.
    type: str
  allow_reassociation:
    description:
      -  Specify this option to allow an Elastic IP address that is already associated with another
         network interface or instance to be re-associated with the specified instance or interface.
    default: false
    type: bool
  tag_name:
    description:
      - When O(reuse_existing_ip_allowed=true), supplement with this option to only reuse
        an Elastic IP if it is tagged with O(tag_name).
    type: str
  tag_value:
    description:
      - Supplements O(tag_name) but also checks that the value of the tag provided in O(tag_name) matches O(tag_value).
    type: str
  public_ipv4_pool:
    description:
      - Allocates the new Elastic IP from the provided public IPv4 pool (BYOIP)
        only applies to newly allocated Elastic IPs, isn't validated when O(reuse_existing_ip_allowed=true).
    type: str
  domain_name:
    description: The domain name to attach to the IP address.
    required: false
    type: str
    version_added: 9.0.0
extends_documentation_fragment:
  - amazon.aws.common.modules
  - amazon.aws.region.modules
  - amazon.aws.tags
  - amazon.aws.boto3

author:
  - "Rick Mendes (@rickmendes) <rmendes@illumina.com>"
notes:
  - There may be a delay between the time the EIP is assigned and when
    the cloud instance is reachable via the new address. Use wait_for and
    pause to delay further playbook execution until the instance is reachable,
    if necessary.
  - This module returns multiple changed statuses on disassociation or release.
    It returns an overall status based on any changes occurring. It also returns
    individual changed statuses for disassociation and release.
  - Support for O(tags) and O(purge_tags) was added in release 2.1.0.
a  
# Note: These examples do not set authentication details, see the AWS Guide for details.

- name: associate an elastic IP with an instance
  amazon.aws.ec2_eip:
    device_id: i-1212f003
    ip: 93.184.216.119

- name: associate an elastic IP with a device
  amazon.aws.ec2_eip:
    device_id: eni-c8ad70f3
    ip: 93.184.216.119

- name: associate an elastic IP with a device and allow reassociation
  amazon.aws.ec2_eip:
    device_id: eni-c8ad70f3
    public_ip: 93.184.216.119
    allow_reassociation: true

- name: disassociate an elastic IP from an instance
  amazon.aws.ec2_eip:
    device_id: i-1212f003
    ip: 93.184.216.119
    state: absent

- name: disassociate an elastic IP with a device
  amazon.aws.ec2_eip:
    device_id: eni-c8ad70f3
    ip: 93.184.216.119
    state: absent

- name: allocate a new elastic IP and associate it with an instance
  amazon.aws.ec2_eip:
    device_id: i-1212f003

- name: allocate a new elastic IP without associating it to anything
  amazon.aws.ec2_eip:
    state: present
  register: eip

- name: output the IP
  ansible.builtin.debug:
    msg: "Allocated IP is {{ eip.public_ip }}"

- name: provision new instances with ec2
  amazon.aws.ec2:
    keypair: mykey
    instance_type: c1.medium
    image: ami-40603AD1
    wait: true
    group: webserver
    count: 3
  register: ec2

- name: associate new elastic IPs with each of the instances
  amazon.aws.ec2_eip:
    device_id: "{{ item }}"
  loop: "{{ ec2.instance_ids }}"

- name: allocate a new elastic IP inside a VPC in us-west-2
  amazon.aws.ec2_eip:
    region: us-west-2
    in_vpc: true
  register: eip

- name: output the IP
  ansible.builtin.debug:
    msg: "Allocated IP inside a VPC is {{ eip.public_ip }}"

- name: allocate eip - reuse unallocated ips (if found) with FREE tag
  amazon.aws.ec2_eip:
    region: us-east-1
    in_vpc: true
    reuse_existing_ip_allowed: true
    tag_name: FREE

- name: allocate eip - reuse unallocated ips if tag reserved is nope
  amazon.aws.ec2_eip:
    region: us-east-1
    in_vpc: true
    reuse_existing_ip_allowed: true
    tag_name: reserved
    tag_value: nope

- name: allocate new eip - from servers given ipv4 pool
  amazon.aws.ec2_eip:
    region: us-east-1
    in_vpc: true
    public_ipv4_pool: ipv4pool-ec2-0588c9b75a25d1a02

- name: allocate eip - from a given pool (if no free addresses where dev-servers tag is dynamic)
  amazon.aws.ec2_eip:
    region: us-east-1
    in_vpc: true
    reuse_existing_ip_allowed: true
    tag_name: dev-servers
    public_ipv4_pool: ipv4pool-ec2-0588c9b75a25d1a02

- name: allocate eip from pool - check if tag reserved_for exists and value is our hostname
  amazon.aws.ec2_eip:
    region: us-east-1
    in_vpc: true
    reuse_existing_ip_allowed: true
    tag_name: reserved_for
    tag_value: "{{ inventory_hostname }}"
    public_ipv4_pool: ipv4pool-ec2-0588c9b75a25d1a02

- name: create new IP and modify it's reverse DNS record
  amazon.aws.ec2_eip:
    state: present
    domain_name: test-domain.xyz

- name: Modify reverse DNS record of an existing EIP
  amazon.aws.ec2_eip:
    public_ip: 44.224.84.105
    domain_name: test-domain.xyz
    state: present

- name: Remove reverse DNS record of an existing EIP
  amazon.aws.ec2_eip:
    public_ip: 44.224.84.105
    domain_name: ""
    state: present
a  
allocation_id:
  description: Allocation id of the elastic ip.
  returned: on success
  type: str
  sample: eipalloc-51aa3a6c
public_ip:
  description: An elastic ip address.
  returned: on success
  type: str
  sample: 52.88.159.209
update_reverse_dns_record_result:
  description: Information about result of update reverse dns record operation.
  returned: When O(domain_name) is specified.
  type: dict
  contains:
    address:
      description: Information about the Elastic IP address.
      returned: always
      type: dict
      contains:
        allocation_id:
          description: The allocation ID.
          returned: always
          type: str
          sample: "eipalloc-00a11aa111aaa1a11"
        ptr_record:
          description: The pointer (PTR) record for the IP address.
          returned: always
          type: str
          sample: "ec2-11-22-33-44.us-east-2.compute.amazonaws.com."
        ptr_record_update:
          description: The updated PTR record for the IP address.
          returned: always
          type: dict
          contains:
            status:
              description: The status of the PTR record update.
              returned: always
              type: str
              sample: "PENDING"
            value:
              description: The value for the PTR record update.
              returned: always
              type: str
              sample: "example.com"
        public_ip:
          description: The public IP address.
          returned: always
          type: str
          sample: "11.22.33.44"
    )Any)Dict)List)Optional)Tuple)Union)camel_dict_to_snake_dict)AnsibleEC2Error)allocate_address)associate_address)describe_addresses)describe_instances)describe_network_interfaces)disassociate_address)ensure_ec2_tags)release_address)AnsibleAWSModule)boto3_tag_specifications)!ansible_dict_to_boto3_filter_list	public_ip	device_idreturnc                     d}|s|sy|rd|gi}n|rd|gdg}nd|gdg}d|i}d}t        | fi |}|r$t        |      dkD  rt        d| d	|       |d
   }|S )z#Find an existing Elastic IP addressN	PublicIpszinstance-idNameValuesznetwork-interface-idFilters   z'Found more than one address using args z Addresses found: r   )r   lenr
   )ec2r   r   is_instancefiltersparamsresult	addressess           f/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/amazon/aws/plugins/modules/ec2_eip.pyfind_addressr(   0  s     GY	{+ -)EFG 69+NOGW%F"31&1Iy>A!$KF8Sefoep"qrr1M    addressr"   c                     |sdn|j                  d      }t        | |||      }d}|r:|r|j                  d      n|j                  d      }||k(  r|j                  d      }|S )z]Check if the elastic IP is currently associated with the device and return the association IdNPublicIp
InstanceIdNetworkInterfaceIdAssociationId)getr(   )r!   r*   r   r"   r   r%   association_idinstance_ids           r'   !address_is_associated_with_devicer3   K  sf     $Z)@I#y)[AFN2=fjj.6::NbCc)##ZZ8Nr)   N
check_modesearch_tagsdomainreuse_existing_ip_allowedtagspublic_ipv4_poolc                    |sd}|rzg }|j                  d|gd       ||t        |      z  }t        | |      }|dk(  r#|D 	cg c]  }	|	j                  dd      r|	 }
}	n|D 	cg c]
  }	|	d   r	|	 }
}	|
r|
d	   d
fS d|i}|r|j	                  d|i       |rt        |d      |d<   d}|st        | fi |}|dfS c c}	w c c}	w )z=Allocate a new elastic IP address (when needed) and return itstandardr6   r   N)r   vpcr/   r-   r   FDomainPublicIpv4Pool
elastic-ip)typesTagSpecificationsT)appendr   r   r0   updater   allocate_ip_address)clientr4   r5   r6   r7   r8   r9   r#   all_addressesaunassociated_addressesr$   r*   s                r'   r   r   \  s      VH=>"8EEG*67CU?1>%cAaeeO]aFba%c"%c1>%VAaoa%V"%V!)!,e33F')9:;&>t<&X"#G%f77D= &d%Vs   C C '
C2Cc                     d}|r9t        | |g      }t        |      dk(  r|d   d   }t        |      dk(  r|d   }|S t        | |g      }t        |      dk(  r|d   }|S )z.Attempt to find the EC2 instance and return itN)InstanceIdsr   r   	Instances)NetworkInterfaceIds)r   r    r   )rE   r   r"   r%   reservations	instances
interfacess          r'   find_devicerP     s{     F)&ykJ|!$Q4I9~""1
 M 1i[Y
z?a]FMr)   modulec                    | j                   j                  d      }| j                   j                  d      }d}|s|S |s(|j                  d      r|j                  d      }d|i}|S |j                  d      sd|z   }||i}|S )z9Generates a dictionary to be passed as a filter to Amazontag_name	tag_valueNztag:ztag-key)r$   r0   
startswithstrip)rQ   rS   rT   r%   s       r'   generate_tag_dictrW     s    }}  ,H!!+.IFv&~~f-HX& M	 ""6*(HI&Mr)   c                     | j                   j                  d      }| j                   j                  d      }|sy|j                  d      ry|j                  d      r|s| j                  d      y)Nr   in_vpcFzi-Tzeni-z1If you are specifying an ENI, in_vpc must be true)r$   r0   rU   	fail_json)rQ   r   rY   s      r'   check_is_instancer[     sf    !!+.I]]x(FD!F#FRSSr)   rE   c                 0   d}d}|j                   j                  d      }|j                   j                  d      }|rQ|r+t        | |||      }|rd}|j                  st	        | |      }|r|r |rd}|j                  st        | |d         }|xs |||dS )	NFr   release_on_disassociationT)r1   AllocationId)allocation_id)changeddisassociatedreleased)r$   r0   r3   r4   r   r   )	rE   rQ   r*   r"   ra   rb   r   r]   r1   s	            r'   ensure_absentrc     s     MH!!+.I & 1 12M N>vwPY[fgN $(($8P^$_M]/HH$$*6AXY$0=^fggr)   c           	         |j                   j                  d      }|j                   j                  d      }|j                   j                  d      }|rdnd }|j                   j                  d      }|j                   j                  d      }	|j                   j                  d      }
|j                   j                  d      }|j                   j                  d	      }|j                   j                  d
      }t        |      }i }d}|st        | |j                  |||||
      \  }}|$t        | |||      \  }}|j                  d|i       |rt        | ||      }|r%|r#|d   rt        |d         dkD  r|t        d      t        | |||      }|s{d}|j                  sm|rC||	d}|j                  d      dk(  r|j                  d      |d<   n*|j                  d      |d<   n||j                  d      |	d}|r||d<   t        | fi | |r1|t        | ||d   d||      z  }|j                  |d   |d   d       ||d<   |S )Nr   private_ip_addressrY   r<   r7   allow_reassociationr9   r8   
purge_tagsdomain_nameF update_reverse_dns_record_resultVpcIdr   zSYou must set 'in_vpc' to true to associate an instance with an existing ip in a vpcT)r-   AllowReassociationr=   r^   r,   )r.   r^   rk   PrivateIpAddressr?   )resource_typer8   rg   )r   r_   r`   )r$   r0   rW   r   r4    update_reverse_dns_record_of_eiprC   rP   r    r
   r3   r   r   )rE   rQ   r*   r"   r   re   rY   r6   r7   rf   r9   r8   rg   rh   r5   r%   r`   ri   instancer1   r$   s                        r'   ensure_presentrp     s    !!+.I**+?@]]x(FU$F & 1 12M N --++,AB}}(();<==V$D""<0J--##M2K $F+KFG +F%%{F<UW[]m
 4TFG[5
11 	9;[\] vy+>4 S'):%;a%?FN%i 
 ;67IWbcG$$,5M`aF{{8,518^1L~.-4[[-Dz* /8(/N(C.AF &1CF-.!&3F3 ?FGN3<VZgq
 	
 	GJ$7'R`JabcF9Mr)   c                    |j                   rdi fS | j                  |d   gd      }|d   r|d   d   d   |dz   k(  r	d	d
|dz   ifS t        |      dk(  r!	 | j                  |d   d      }d}dv r$|d= n 	 | j                  |d   |      }d}dv r|d= t        |      fS # t        $ r}|j                  |       Y d }~Td }~ww xY w# t        $ r}|j                  |       Y d }~Zd }~ww xY w)NTr^   zdomain-name)AllocationIds	Attribute	Addressesr   	PtrRecord.F
ptr_record)r^   rs   ResponseMetadata)r^   
DomainName)r4   describe_addresses_attributer    reset_address_attributer
   fail_json_aws_errormodify_address_attributer	   )rE   rQ   r*   rh   current_ptr_record_domainri   r`   es           r'   rn   rn     sZ   Rx & C C~./= !D !
 	"+.%k215kBkTWFWW|[3%6777
;1	*/5/M/M$^4 0N 0, G !AA01CD	*/5/N/N$^4 0O 0, G !AA01CD,-MNNN#  	*&&q))	*  	*&&q))	*s0   B# 7C
 #	C,CC
	C.C))C.c                  8   t        t        d      t        dd      t        ddg      t        ddddg	      t        dd
d      t        dd
d      t        dd
d      t        d
d      t               t        dddg      t        dd
d      t               t               t                     } t        | ddgdgd      }|j                  d      }|j                  j	                  d      }|j                  j	                  d      }|j                  j	                  d      }t        |      }	 t        ||||      }|dk(  rt        ||||      }nt        ||||      } |j                  di  y # t        $ r}	|j                  |	       Y d }	~	2d }	~	ww xY w)NF)requiredstr)r   typeip)r   aliasespresentabsent)r   defaultchoicesbool)r   r   r   )r   r   dictresource_tags)r   r   r   T)r   rh   r   staterY   r7   r]   rf   re   r8   rg   rS   rT   r9   r   rS   )re   rT   )argument_specsupports_check_moderequired_byr!   r   r    )r   r   rE   r$   r0   r[   r(   rp   rc   r
   r|   	exit_json)
r   rQ   r!   r   r   r   r"   r*   r%   r   s
             r'   mainr   E  s   &%e4v6E9y(>STU?"&FE"R"&FE"R fe<65v7HIVTB&M" # #.-$
F --
C!!+.I!!+.IMMg&E#F+K	&sIy+FI#C+FF"3EF
 Fv  &""1%%&s   20E5 5	F>FF__main__)T)N))DOCUMENTATIONEXAMPLESRETURNtypingr   r   r   r   r   r   0ansible.module_utils.common.dict_transformationsr	   7ansible_collections.amazon.aws.plugins.module_utils.ec2r
   r   rD   r   r   r   r   r   r   r   ;ansible_collections.amazon.aws.plugins.module_utils.modulesr   ;ansible_collections.amazon.aws.plugins.module_utils.taggingr   Bansible_collections.amazon.aws.plugins.module_utils.transformationr   r   r(   r   r3   rP   rW   r[   rc   rp   rn   r   __name__r   r)   r'   <module>r      sx  ^@{z3
j       U S k U V V _ X S S X ` pSM.6smd3c4S#X#77889:> 	d38n%  	
 c]0 (,%% $sCx.)% SM	%
  $% 4S>
"% tn% 4S>4 %P3 T htCQTH~>V ". 8DcN3K *
. 
4 
hh)h4<T#s(^4Lh[_h	#t)_h4I$I/7S#X/GIVZI	#s(^IX%O5E %OP.b zF r)   