
    Vh9D                    F   d dl mZ dZdZd dl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mZmZ d d
lmZ d dlmZ ddlmZmZmZmZ ddlmZ ddlmZ ddlmZ ddl m!Z! ejD                  dk\  rd dl#m$Z$m%Z%  G d de%      Z& G d de%      Z'ne(Z'ddZ) G d deee      Z*y)    )annotationsa>  
name: hcloud
short_description: Ansible dynamic inventory plugin for the Hetzner Cloud.

description:
  - Reads inventories from the Hetzner Cloud API.
  - Uses a YAML configuration file that ends with C(hcloud.yml) or C(hcloud.yaml).

author:
  - Lukas Kaemmerling (@lkaemmerling)

requirements:
  - python-dateutil >= 2.7.5
  - requests >=2.20

extends_documentation_fragment:
  - constructed
  - inventory_cache

options:
  plugin:
    description: Mark this as an P(hetzner.hcloud.hcloud#inventory) inventory instance.
    required: true
    choices: [hcloud, hetzner.hcloud.hcloud]

  api_token:
    description:
      - The API Token for the Hetzner Cloud.
    type: str
    required: true
    aliases: [token]
    env:
      - name: HCLOUD_TOKEN
  api_endpoint:
    description:
      - The API Endpoint for the Hetzner Cloud.
    type: str
    default: https://api.hetzner.cloud/v1
    env:
      - name: HCLOUD_ENDPOINT

  group:
    description: The group all servers are automatically added to.
    default: hcloud
    type: str
    required: false
  connect_with:
    description: |
      Connect to the server using the value from this field. This sets the C(ansible_host)
      variable to the value indicated, if that value is available. If you need further
      customization, like falling back to private ipv4 if the server has no public ipv4,
      you can use O(compose) top-level key.
    default: public_ipv4
    type: str
    choices:
      - public_ipv4
      - public_ipv6
      - hostname
      - ipv4_dns_ptr
      - private_ipv4

  locations:
    description: Populate inventory with instances in this location.
    default: []
    type: list
    elements: str
    required: false
  types:
    description: Populate inventory with instances with this type.
    default: []
    type: list
    elements: str
    required: false
  images:
    description: Populate inventory with instances with this image name, only available for system images.
    default: []
    type: list
    elements: str
    required: false
  label_selector:
    description: Populate inventory with instances with this label.
    default: ""
    type: str
    required: false
  network:
    description: Populate inventory with instances which are attached to this network name or ID.
    default: ""
    type: str
    required: false
  status:
    description: Populate inventory with instances with this status.
    default: []
    type: list
    elements: str
    required: false

  hostvars_prefix:
    description:
      - The prefix for host variables names coming from Hetzner Cloud.
    type: str
    version_added: 2.5.0
  hostvars_suffix:
    description:
      - The suffix for host variables names coming from Hetzner Cloud.
    type: str
    version_added: 2.5.0

  hostname:
    description:
      - A template for the instances hostname, if not provided the Hetzner Cloud server name will be used.
      - Available variables are the Hetzner Cloud host variables.
      - The available variables names are provide with the O(hostvars_prefix) or O(hostvars_suffix) modifications.
    type: str
    version_added: 3.0.0
aR  
# Minimal example. 'HCLOUD_TOKEN' is exposed in environment.
plugin: hetzner.hcloud.hcloud

---
# Example with templated token, e.g. provided through extra vars.
plugin: hetzner.hcloud.hcloud
api_token: "{{ _vault_hetzner_cloud_token }}"

---
# Example with locations, types, status
plugin: hetzner.hcloud.hcloud
locations:
  - nbg1
types:
  - cx22
status:
  - running

---
# Group by a location with prefix e.g. "hcloud_location_nbg1"
# and image_os_flavor without prefix and separator e.g. "ubuntu"
# and status with prefix e.g. "server_status_running"
plugin: hetzner.hcloud.hcloud
keyed_groups:
  - key: location
    prefix: hcloud_location
  - key: image_os_flavor
    separator: ""
  - key: status
    prefix: server_status

---
# Use a custom hostname template.
plugin: hetzner.hcloud.hcloud

# Available variables are for example:
## Server
#   id: 42984895
#   name: "my-server"
#   labels:
#     foo: "bar"
#   status: "running"
## Server Type
#   type: "cx22"
#   server_type: "cx22"
#   architecture: "x86"
## Image
#   image_id: 114690387
#   image_name: "debian-12"
#   image_os_flavor: "debian"
## Datacenter
#   datacenter: "hel1-dc2"
#   location: "hel1"
## Network
#   ipv4: "65.109.140.95" # Value is optional!
#   ipv6: "2a01:4f9:c011:b83f::1" # Value is optional!
#   ipv6_network: 2a01:4f9:c011:b83f::" # Value is optional!
#   ipv6_network_mask: "64" # Value is optional!
#   private_ipv4: "10.0.0.3" # Value is optional!
#   private_networks:
#     - id: 114690387
#       name: "my-private-network"
#       ip: "10.0.0.3"
#
hostname: "my-prefix-{{ datacenter }}-{{ name }}-{{ server_type }}"
N)IPv6Network)AnsibleError)InventoryData)	to_native)BaseInventoryPlugin	CacheableConstructable)Display)combine_vars   )ClientClientExceptionclient_check_required_libclient_get_by_name_or_id)APIException)Network)Server)version)      )NotRequired	TypedDictc                  ,    e Zd ZU ded<   ded<   ded<   y)InventoryPrivateNetworkintidstrnameipN__name__
__module____qualname____annotations__     k/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/hetzner/hcloud/plugins/inventory/hcloud.pyr   r      s    	r'   r   c                      e Zd ZU ded<   ded<   ded<   ded<   ded<   ded<   ded	<   ded
<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   ded<   y)InventoryServerr   r   r   r   statustypeserver_typearchitecture
datacenterlocationzdict[str, str]labelszNotRequired[str]ipv4ipv6ipv6_networkipv6_network_maskprivate_ipv4zlist[InventoryPrivateNetwork]private_networksimage_id
image_nameimage_os_flavoransible_hostNr!   r&   r'   r(   r*   r*      sx    	 	   &&++&&77  r'   r*   c                X    t        t        t        |       j                                     S )zY
    Return the first address for a ipv6 network.

    :param network: IPv6 Network.
    )r   nextr   hosts)networks    r(   first_ipv6_addressr@     s"     tK(..0122r'   c                       e Zd ZU dZded<   ded<   ded<   ded	<   d
 ZddZddZddZddZ	 fdZ
ddZddZd fd	Z xZS )InventoryModulezhetzner.hcloud.hcloudr   	inventoryr   displayr   clientzNetwork | Noner?   c                2   | j                  d      }| j                  d      }| j                  j                  |      }t        ||dt              | _        	 | j
                  j                  j                          y # t        $ r}t        d      |d }~ww xY w)N	api_tokenapi_endpointzansible-inventory)tokenrH   application_nameapplication_versionz Invalid Hetzner Cloud API Token.)

get_optiontemplartemplater   r   rE   	locationsget_listr   r   )selfrG   rH   	exceptions       r(   _configure_hcloud_clientz(InventoryModule._configure_hcloud_client  s    OOK0	~6 LL)))4	%0 '	
	RKK!!**, 	RAB	Q	Rs   $A< <	BBBc                   | j                  d      rJ| j                  d      }| j                  j                  |      }	 t        | j                  d|      | _        y y # t        t        f$ r}t        t        |            |d }~ww xY w)Nr?   networks)
rL   rM   rN   r   rE   r?   r   r   r   r   )rQ   network_paramrR   s      r(   _validate_optionsz!InventoryModule._validate_options)  s{    ??9%!%!;M LL11-@MH7ZQ^_ & $\2 H"9Y#78iGHs   A B,BBc           	        | j                          i }| j                  d      r| j                  d      |d<   | j                  d      r| j                  d      |d<    | j                  j                  j                  di |}| j                  d      rV|D cg c]I  }| j
                  j                  |j                  D cg c]  }|j
                  j                   c}v sH|K }}}| j                  d      rC| j                  d      }|D cg c]'  }|j                  j                  j                  |v s&|) }}| j                  d      r9| j                  d      }|D cg c]  }|j                  j                  |v s| }}| j                  d      rF| j                  d      }|D cg c]*  }|j                  |j                  j                  |v s)|, }}|S c c}w c c}}w c c}w c c}w c c}w )Nlabel_selectorr+   r?   rO   typesimagesr&   )rW   rL   rE   serversget_allr?   r   private_netr/   r0   r   r-   image	os_flavor)rQ   get_servers_paramsr\   sprO   server_typesr[   s           r(   _fetch_serverszInventoryModule._fetch_servers3  s    ??+,37??CS3T/0??8$+/??8+Dx(-$++%%--C0BC??9%")fQT\\__WXWdWd@eRS@e-eqfGf??;'#'??;#?I")UQQ\\-B-B-G-G9-TqUGU??7#&*oog&>L")PQQ]]-?-?<-OqPGP??8$ $ 9F")aQQWW-@QWWEVEVZ`E`qaGa Aff V Q bsH   (G&G!G&#G&'G,8G,$G1G1.G6 G6G6!G&c                   i }|j                   |d<   |j                  |d<   |j                  |d<   |j                  j                  |d<   |j                  j                  |d<   |j                  j                  |d<   |j
                  j                  r#|j
                  j                  j                  |d<   |j
                  j                  rrt        |j
                  j                  j                        |d<   |j
                  j                  j                  |d	<   |j
                  j                  j                  |d
<   |j                  D cg c]:  }|j                  j                   |j                  j                  |j                  d< c}|d<   | j                  d      rO|j                  D ]@  }|j                  j                   | j                  j                   k(  s1|j                  |d<    n |j                  j                  |d<   |j                  j                  j                  |d<   |j                   c|j                   j                   |d<   |j                   j"                  |d<   |j                   j                  xs |j                   j$                  |d<   t'        |j(                        |d<   	 | j+                  |      |d<   |S c c}w # t,        $ r4}| j.                  j1                  d| |j                         Y d }~|S d }~ww xY w)Nr   r   r+   r,   r-   r.   r2   r3   r4   r5   )r   r   r    r7   r?   r6   r/   r0   r8   r:   r9   r1   r;   z	[hcloud] )r   r   r+   r-   r.   
public_netr2   r    r3   r@   r?   network_maskr^   rL   r/   r0   r_   r`   descriptiondictr1   _get_server_ansible_hostr   rD   v)rQ   serverserver_dictrl   r^   rR   s         r(   _build_inventory_serverz'InventoryModule._build_inventory_serverP  s   ')"IID$kkF &H %0055F%+%7%7%<%<M"&,&8&8&E&EN# !!"("3"3"8"8";";K!!"4V5F5F5K5K5N5N"OK*0*;*;*@*@*H*HK'/5/@/@/E/E/R/RK+, OUN`N`+
IJ199<<qttD+
&' ??9%%11 &&))T\\__<2=..K/	 %+$5$5$:$:L!"("3"3"<"<"A"AJ <<#&,llooK
#-3\\-C-CK)*(.(9(9(UV\\=U=UK% !%V]] 3H	A*.*G*G*OK' C+
4  	A
 LLNNYyk2FKK@@	As   
?K	3K 	L)LLc                N   | j                  d      dk(  rA|j                  j                  r |j                  j                  j                  S t	        d      | j                  d      dk(  rJ|j                  j
                  r)t        |j                  j
                  j                        S t	        d      | j                  d      dk(  r|j                  S | j                  d      dk(  rA|j                  j                  r |j                  j                  j                  S t	        d      | j                  d      d	k(  ri| j                  d
      rM|j                  D ]=  }|j                  j                  | j                  j                  k(  s1|j                  c S  y t	        d      y )Nconnect_withpublic_ipv4zEServer has no public ipv4, but connect_with=public_ipv4 was specifiedpublic_ipv6zEServer has no public ipv6, but connect_with=public_ipv6 was specifiedhostnameipv4_dns_ptrzFServer has no public ipv4, but connect_with=ipv4_dns_ptr was specifiedr6   r?   z>You can only connect via private IPv4 if you specify a network)rL   rg   r2   r    r   r3   r@   r   dns_ptrr^   r?   r   )rQ   rm   r^   s      r(   rk   z(InventoryModule._get_server_ansible_host  sY   ??>*m;  %%((--000fgg??>*m;  %%)&*;*;*@*@*C*CDDfgg??>*j8;;??>*n<  %%((--555ghh??>*n<y)#)#5#5 .K"**--@*~~-.
 ##cdd =r'   c                H    t         |   |      xr |j                  d      S )z>Return the possibly of a file being consumable by this plugin.)zhcloud.yamlz
hcloud.yml)superverify_fileendswith)rQ   path	__class__s     r(   ry   zInventoryModule.verify_file  s"    w"4(YT]];X-YYr'   c                    |sg dfS | j                  d      sg dfS | j                  |      }	 | j                  |   }|dfS # t        $ r g dfcY S w xY w)NFcacheT)rL   get_cache_key_cacheKeyError)rQ   r{   r~   	cache_keycached_results        r(   _get_cached_resultz"InventoryModule._get_cached_result  sr    u9 w'u9&&t,		 KK	2M
 d""	  	u9	s   A AAc                    | j                  d      sy | j                  |      }|r|| j                  v ry || j                  |<   y )Nr~   )rL   r   r   )rQ   r{   r~   resultr   s        r(   _update_cached_resultz%InventoryModule._update_cached_result  sB    w'&&t,	 Y$++-!'Ir'   c                   t         |   ||||       	 t                | j                  | j                  _        | j                  |       | j                          | j                  ||      \  }}|sO| j                  j                         5  | j                         D cg c]  }| j                  |       }}d d d        | j                   j#                  | j%                  d             | j%                  d      }	| j%                  d      }
| j%                  d      }|D ]}  }i }|j'                         D ]   \  }}|	s|
r|dvr|	r|	|z   }|
r||
z   }|||<   " |r9| j                  }t)        || j                        |_        |j+                  |      }n|d   }| j                   j-                  || j%                  d             |j'                         D ]"  \  }}| j                   j/                  |||       $ | j%                  d      }| j1                  | j%                  d	      | j                   j3                  |      j5                         ||
       | j7                  | j%                  d      i ||
       | j9                  | j%                  d      i ||
        | j;                  |||       y # t        $ r}t	        t        |            |d }~ww xY wc c}w # 1 sw Y   *xY w)Ngroup)r   hostvars_prefixhostvars_suffixrt   )r;   r   strictcompose)r   groupskeyed_groups)rx   parser   r   r   r   _varsrM   available_variables_read_config_datarS   r   rE   cached_sessionre   ro   rC   	add_grouprL   itemsr   rN   add_hostset_variable_set_composite_varsget_hostget_vars_add_host_to_composed_groups_add_host_to_keyed_groupsr   )rQ   rC   loaderr{   r~   rR   r\   cachedrb   r   r   hostname_templaterm   hostvarskeyvaluerM   rt   r   r|   s                      r(   r   zInventoryModule.parse  s   iu5	D%' ,0::(t$%%'11$>++- [DHDWDWDYZq477:ZZ[ 	  tw'? @//*;<//*;< OOJ7 1	FH$lln 	&
U"o"33*"1C"7C*"%"7C %	& !,,.:8TZZ.P+"++,=>!&>NN##HDOOG4L#M&nn. B
U++Hc5AB __X.F $$	*''1::<	 %  --)	 .  **/	 + Y1	f 	""48S  	Dy34)C	D [[ [s5   
J6 K!K7K!6	K?KKK!!K+)returnNone)r   zlist[Server])rm   r   r   r*   )rm   r   )r   z"tuple[list[InventoryServer], bool])r   zlist[InventoryServer])T)r"   r#   r$   NAMEr%   rS   rW   re   ro   rk   ry   r   r   r   __classcell__)r|   s   @r(   rB   rB     sX    "DNR(H:5ne:Z#$(N9 N9r'   rB   )r?   r   r   r   )+
__future__r   DOCUMENTATIONEXAMPLESsys	ipaddressr   ansible.errorsr   ansible.inventory.managerr   +ansible.module_utils.common.text.convertersr   ansible.plugins.inventoryr   r	   r
   ansible.utils.displayr   ansible.utils.varsr   module_utils.clientr   r   r   r   module_utils.vendor.hcloudr   #module_utils.vendor.hcloud.networksr   "module_utils.vendor.hcloud.serversr   module_utils.versionr   version_infotypingr   r   r   r*   rj   r@   rB   r&   r'   r(   <module>r      s    #rhBH  ! ' 3 A S S ) +  6 9 7 *w .) 
) D O3J9)=) J9r'   