88
99__metaclass__ = type
1010
11+ import ipaddress
12+
1113DOCUMENTATION = r"""
1214name: scaleway
1315author:
110112try :
111113 from scaleway_core .bridge import Zone
112114 from scaleway import Client , ScalewayException
115+ from scaleway .flexibleip .v1alpha1 import FlexibleipV1Alpha1API
113116 from scaleway .applesilicon .v1alpha1 import (
114117 ApplesiliconV1Alpha1API ,
115118 ApplesiliconV1Alpha1PrivateNetworkAPI ,
116119 ServerPrivateNetworkStatus ,
117- Server as ApplesiliconServer , Server ,
120+ Server as ApplesiliconServer ,
118121)
119122 from scaleway .baremetal .v1 import (
120123 BaremetalV1API ,
139142 HAS_SCALEWAY_SDK = False
140143
141144@dataclass
142- class _Host (ABC ):
145+ class Host (ABC ):
143146 """Abstract base host object with common fields and network handling."""
144147
145148 id : str
@@ -169,6 +172,20 @@ def _populate_private_network(self, client: "Client", private_networks_id: list[
169172 self .private_ipv4 .extend (ip .address .split ("/" )[0 ] for ip in ips if not ip .is_ipv6 )
170173 self .private_ipv6 .extend (ip .address .split ("/" )[0 ] for ip in ips if ip .is_ipv6 )
171174
175+ def _populate_flexible_ip (self , client : "Client" , server : Any ) -> None :
176+ supported_types = ("InstanceServer" , "BaremetalServer" )
177+ if server .__class__ .__name__ not in supported_types :
178+ return
179+ flexible_ip_api = FlexibleipV1Alpha1API (client = client )
180+ fips = flexible_ip_api .list_flexible_i_ps_all (zone = server .zone , server_ids = [server .id ])
181+ for fip in fips :
182+ if self .get_ip_version (fip .ip_address ) == "IPv6" :
183+ self .flexible_ipv6 .extend (fip .ip_address .split ("/" )[0 ])
184+ else :
185+ self .flexible_ipv4 .extend (fip .ip_address .split ("/" )[0 ])
186+ self .public_flexible_dns .extend (fip .reverse )
187+
188+
172189 def normalized_state (self ) -> str :
173190 """Normalize server state into standard values."""
174191 mapping = {
@@ -180,14 +197,24 @@ def normalized_state(self) -> str:
180197 state_str = str (self .state ).lower ()
181198 return mapping .get (state_str , state_str )
182199
200+ def get_ip_version (self , ip : str ) -> str :
201+ """
202+ https://docs.python.org/3/library/ipaddress.html
203+ """
204+ try :
205+ parsed_ip = ipaddress .ip_network (ip )
206+ return "IPv4" if isinstance (parsed_ip , ipaddress .IPv4Network ) else "IPv6"
207+ except ValueError :
208+ return "Invalid"
209+
183210
184211
185212# ---------------------------------------------------------------------------
186213# Product-specific subclasses
187214# ---------------------------------------------------------------------------
188215
189216@dataclass
190- class _ApplesiliconHost ( _Host ):
217+ class ApplesiliconHost ( Host ):
191218 def populate_network (self , server : "ApplesiliconServer" , client : "Client" ) -> None :
192219 if server .ip :
193220 self .public_ipv4 .append (server .ip )
@@ -198,13 +225,17 @@ def populate_network(self, server: "ApplesiliconServer", client: "Client") -> No
198225 applesilicon_api = ApplesiliconV1Alpha1PrivateNetworkAPI (client = client )
199226
200227 private_networks = applesilicon_api .list_server_private_networks_all (server_id = server .id )
201- self ._populate_private_network (client , private_networks )
228+ self ._populate_private_network (client , [ pn . id for pn in private_networks ] )
202229
203230
204231@dataclass
205- class _InstanceServerHost ( _Host ):
232+ class InstanceServerHost ( Host ):
206233 public_dns : Optional [str ] = None
207234 private_dns : Optional [str ] = None
235+ flexible_ipv4 : list [str ] = field (default_factory = list )
236+ flexible_ipv6 : list [str ] = field (default_factory = list )
237+ public_flexible_dns : list [str ] = field (default_factory = list )
238+
208239
209240 def populate_network (self , server : "InstanceServer" , client : "Client" ) -> None :
210241 self .public_dns = f"{ server .id } .pub.instances.scw.cloud"
@@ -217,12 +248,18 @@ def populate_network(self, server: "InstanceServer", client: "Client") -> None:
217248 self .public_ipv6 .append (ip .address )
218249
219250 self ._populate_private_network (client , [pn .id for pn in server .private_nics ])
220-
251+ self . _populate_flexible_ip ( client , server )
221252
222253@dataclass
223- class _ElasticMetalHost (_Host ):
254+ class ElasticMetalHost (Host ):
255+ flexible_ipv4 : list [str ] = field (default_factory = list )
256+ flexible_ipv6 : list [str ] = field (default_factory = list )
257+ public_flexible_dns : list [str ] = field (default_factory = list )
258+
224259 def populate_network (self , server : "BaremetalServer" , client : "Client" ) -> None :
225- for ip in server .ips or []:
260+ if server .ips is None :
261+ return
262+ for ip in server .ips :
226263 target_list = self .public_ipv4 if ip .version .lower () == "ipv4" else self .public_ipv6
227264 target_list .append (ip .address )
228265
@@ -233,12 +270,15 @@ def populate_network(self, server: "BaremetalServer", client: "Client") -> None:
233270 baremetal_pn_api = BaremetalV1PrivateNetworkAPI (client = client )
234271
235272 private_networks = baremetal_pn_api .list_server_private_networks_all (server_id = server .id )
236- self ._populate_private_network (client , private_networks )
273+ self ._populate_private_network (client , [pn .id for pn in private_networks ])
274+ self ._populate_flexible_ip (client , server )
237275
238276
239277@dataclass
240- class _DediboxHost ( _Host ):
278+ class DediboxHost ( Host ):
241279 public_dns : list [str ] = field (default_factory = list )
280+ failover_ipv4 : list [str ] = field (default_factory = list )
281+ failover_ipv6 : list [str ] = field (default_factory = list )
242282
243283 def populate_network (self , server : "DediboxServer" , client : "Client" ) -> None :
244284 for interface in server .interfaces or []:
@@ -321,7 +361,7 @@ def get_cached_result(self, path: str, cache: bool) -> tuple[bool, Optional[Any]
321361 return True , cached_result
322362
323363 @staticmethod
324- def _host_to_dict (host : _Host ) -> dict [str , Any ]:
364+ def _host_to_dict (host : Host ) -> dict [str , Any ]:
325365 return asdict (host )
326366
327367 def _list_servers_safe (self , api , zone ):
@@ -335,16 +375,16 @@ def _list_servers_safe(self, api, zone):
335375 return []
336376 raise e
337377
338- def _get_instances (self , client : "Client" ) -> list [_InstanceServerHost ]:
378+ def _get_instances (self , client : "Client" ) -> list [InstanceServerHost ]:
339379 instance_api = InstanceV1API (client )
340380 servers : list [InstanceServer ] = []
341381 zones = self .get_option ("zones" )
342382 for zone in zones :
343383 servers .extend (instance_api .list_servers_all (zone = zone ))
344- results : list [_InstanceServerHost ] = []
384+ results : list [InstanceServerHost ] = []
345385
346386 for server in servers :
347- host = _InstanceServerHost (
387+ host = InstanceServerHost (
348388 id = server .id ,
349389 tags = ["instance" ] + server .tags ,
350390 zone = server .zone ,
@@ -355,17 +395,17 @@ def _get_instances(self, client: "Client") -> list[_InstanceServerHost]:
355395 results .append (host )
356396 return results
357397
358- def _get_elastic_metal (self , client : "Client" ) -> list [_ElasticMetalHost ]:
398+ def _get_elastic_metal (self , client : "Client" ) -> list [ElasticMetalHost ]:
359399 baremetal_api = BaremetalV1API (client )
360400 servers : list [BaremetalServer ] = []
361401 zones = self .get_option ("zones" )
362402 for zone in zones :
363403 servers .extend (self ._list_servers_safe (baremetal_api , zone ))
364404
365- results : list [_ElasticMetalHost ] = []
405+ results : list [ElasticMetalHost ] = []
366406
367407 for server in servers :
368- host = _ElasticMetalHost (
408+ host = ElasticMetalHost (
369409 id = server .id ,
370410 tags = ["elasticmetal" ] + server .tags ,
371411 zone = server .zone ,
@@ -376,15 +416,15 @@ def _get_elastic_metal(self, client: "Client") -> list[_ElasticMetalHost]:
376416 results .append (host )
377417 return results
378418
379- def _get_apple_silicon (self , client : "Client" ) -> list [_ApplesiliconHost ]:
419+ def _get_apple_silicon (self , client : "Client" ) -> list [ApplesiliconHost ]:
380420 api = ApplesiliconV1Alpha1API (client )
381421 servers = []
382422 for zone in self .get_option ("zones" ):
383423 servers .extend (self ._list_servers_safe (api , zone ))
384424
385- results : list [_ApplesiliconHost ] = []
425+ results : list [ApplesiliconHost ] = []
386426 for server in servers :
387- host = _ApplesiliconHost (
427+ host = ApplesiliconHost (
388428 id = server .id ,
389429 tags = ["applesilicon" ] + server .tags ,
390430 zone = server .zone ,
@@ -395,17 +435,17 @@ def _get_apple_silicon(self, client: "Client") -> list[_ApplesiliconHost]:
395435 results .append (host )
396436 return results
397437
398- def _get_dedibox (self , client : "Client" ) -> list [_DediboxHost ]:
438+ def _get_dedibox (self , client : "Client" ) -> list [DediboxHost ]:
399439 dedibox_api = DediboxV1API (client )
400440 servers : list [DediboxServer ] = []
401441 zones = self .get_option ("zones" )
402442 for zone in zones :
403443 servers .extend (self ._list_servers_safe (dedibox_api , zone ))
404444
405- results : list [_DediboxHost ] = []
445+ results : list [DediboxHost ] = []
406446
407447 for server in servers :
408- host = _DediboxHost (
448+ host = DediboxHost (
409449 id = str (server .id ),
410450 tags = ["dedibox" ],
411451 zone = server .zone ,
@@ -418,7 +458,7 @@ def _get_dedibox(self, client: "Client") -> list[_DediboxHost]:
418458 return results
419459
420460 @staticmethod
421- def _get_host_attribute (host : _Host , host_attributes : list [str ]):
461+ def _get_host_attribute (host : Host , host_attributes : list [str ]):
422462 host_as_dict = host .__dict__
423463
424464 for host_attribute in host_attributes :
@@ -431,7 +471,7 @@ def _get_host_attribute(host: _Host, host_attributes: list[str]):
431471 raise AnsibleError (f"{ host .id } has no attribute { host_attributes } " )
432472
433473
434- def get_host_groups (self , host : _Host ):
474+ def get_host_groups (self , host : Host ):
435475 return set (self .sanitize_tag (tag ) for tag in host .tags ).union (
436476 {self .sanitize_tag (host .zone )}
437477 )
@@ -447,23 +487,28 @@ def sanitize_tag(self, tag: str):
447487
448488 return tag
449489
450- def populate (self , all_hosts : list [_Host ]):
490+ def populate (self , all_hosts : list [Host ]):
451491 host_attributes = self .get_option ("hostnames" )
492+ print ("value of get_options(hostname): " , host_attributes )
452493 variables = self .get_option ("variables" ) or {}
494+ print ("value of get_options(variable): " , variables )
453495
454496 for host in all_hosts :
455497 groups = self .get_host_groups (host )
456498 try :
457499 hostname_value = self ._get_host_attribute (host , host_attributes )
500+ print ("value of _get_host_attribute(host, host_attributes): " , hostname_value )
458501 except AnsibleError as e :
459502 self .display .warning (f"Skipping host { host .id } : { e } " )
460503 continue
461504
462505 # If the hostname attribute is a list, create a host for each element
463506 hostnames = hostname_value if isinstance (hostname_value , list ) else [hostname_value ]
507+ print ("value of hostnames: " , hostnames )
464508
465509 for idx , hostname in enumerate (hostnames ):
466510 # Ensure hostname is a string and unique if multiple
511+ print ("vale of idx and hostnames: " , idx , hostname )
467512 if isinstance (hostname , list ):
468513 self .display .warning (f"Skipping host { host .id } : nested lists are not supported." )
469514 continue
@@ -503,10 +548,10 @@ def populate(self, all_hosts: list[_Host]):
503548 def get_inventory (self ):
504549 client = self ._get_client ()
505550
506- instances : list [_InstanceServerHost ] = self ._get_instances (client )
507- elastic_metals : list [_ElasticMetalHost ] = self ._get_elastic_metal (client )
508- apple_silicon : list [_ApplesiliconHost ] = self ._get_apple_silicon (client )
509- dedibox : list [_DediboxHost ] = self ._get_dedibox (client )
551+ instances : list [InstanceServerHost ] = self ._get_instances (client )
552+ elastic_metals : list [ElasticMetalHost ] = self ._get_elastic_metal (client )
553+ apple_silicon : list [ApplesiliconHost ] = self ._get_apple_silicon (client )
554+ dedibox : list [DediboxHost ] = self ._get_dedibox (client )
510555
511556 return instances + elastic_metals + apple_silicon + dedibox
512557
0 commit comments