@@ -300,10 +300,83 @@ def _populate(self, json):
300
300
301
301
@dataclass
302
302
class ConfigInterfaceIPv4 (JSONObject ):
303
+ """
304
+ ConfigInterfaceIPv4 represents the IPv4 configuration of a VPC interface.
305
+ """
306
+
303
307
vpc : str = ""
304
308
nat_1_1 : str = ""
305
309
306
310
311
+ @dataclass
312
+ class ConfigInterfaceIPv6SLAACOptions (JSONObject ):
313
+ """
314
+ ConfigInterfaceIPv6SLAACOptions is used to set a single IPv6 SLAAC configuration of a VPC interface.
315
+ """
316
+
317
+ range : str = ""
318
+
319
+
320
+ @dataclass
321
+ class ConfigInterfaceIPv6RangeOptions (JSONObject ):
322
+ """
323
+ ConfigInterfaceIPv6RangeOptions is used to set a single IPv6 range configuration of a VPC interface.
324
+ """
325
+
326
+ range : str = ""
327
+
328
+
329
+ @dataclass
330
+ class ConfigInterfaceIPv6Options (JSONObject ):
331
+ """
332
+ ConfigInterfaceIPv6Options is used to set the IPv6 configuration of a VPC interface.
333
+ """
334
+
335
+ slaac : List [ConfigInterfaceIPv6SLAACOptions ] = field (
336
+ default_factory = lambda : []
337
+ )
338
+ ranges : List [ConfigInterfaceIPv6RangeOptions ] = field (
339
+ default_factory = lambda : []
340
+ )
341
+ is_public : bool = False
342
+
343
+
344
+ @dataclass
345
+ class ConfigInterfaceIPv6SLAAC (JSONObject ):
346
+ """
347
+ ConfigInterfaceIPv6SLAAC represents a single SLAAC address under a VPC interface's IPv6 configuration.
348
+ """
349
+
350
+ put_class = ConfigInterfaceIPv6SLAACOptions
351
+
352
+ range : str = ""
353
+ address : str = ""
354
+
355
+
356
+ @dataclass
357
+ class ConfigInterfaceIPv6Range (JSONObject ):
358
+ """
359
+ ConfigInterfaceIPv6Range represents a single IPv6 address under a VPC interface's IPv6 configuration.
360
+ """
361
+
362
+ put_class = ConfigInterfaceIPv6RangeOptions
363
+
364
+ range : str = ""
365
+
366
+
367
+ @dataclass
368
+ class ConfigInterfaceIPv6 (JSONObject ):
369
+ """
370
+ ConfigInterfaceIPv6 represents the IPv6 configuration of a VPC interface.
371
+ """
372
+
373
+ put_class = ConfigInterfaceIPv6Options
374
+
375
+ slaac : List [ConfigInterfaceIPv6SLAAC ] = field (default_factory = lambda : [])
376
+ ranges : List [ConfigInterfaceIPv6Range ] = field (default_factory = lambda : [])
377
+ is_public : bool = False
378
+
379
+
307
380
class NetworkInterface (DerivedBase ):
308
381
"""
309
382
This class represents a Configuration Profile's network interface object.
@@ -329,6 +402,7 @@ class NetworkInterface(DerivedBase):
329
402
"vpc_id" : Property (id_relationship = VPC ),
330
403
"subnet_id" : Property (),
331
404
"ipv4" : Property (mutable = True , json_object = ConfigInterfaceIPv4 ),
405
+ "ipv6" : Property (mutable = True , json_object = ConfigInterfaceIPv6 ),
332
406
"ip_ranges" : Property (mutable = True ),
333
407
}
334
408
@@ -400,7 +474,10 @@ class ConfigInterface(JSONObject):
400
474
# VPC-specific
401
475
vpc_id : Optional [int ] = None
402
476
subnet_id : Optional [int ] = None
477
+
403
478
ipv4 : Optional [Union [ConfigInterfaceIPv4 , Dict [str , Any ]]] = None
479
+ ipv6 : Optional [Union [ConfigInterfaceIPv6 , Dict [str , Any ]]] = None
480
+
404
481
ip_ranges : Optional [List [str ]] = None
405
482
406
483
# Computed
@@ -409,7 +486,7 @@ class ConfigInterface(JSONObject):
409
486
def __repr__ (self ):
410
487
return f"Interface: { self .purpose } "
411
488
412
- def _serialize (self , * args , ** kwargs ):
489
+ def _serialize (self , is_put : bool = False ):
413
490
purpose_formats = {
414
491
"public" : {"purpose" : "public" , "primary" : self .primary },
415
492
"vlan" : {
@@ -421,11 +498,8 @@ def _serialize(self, *args, **kwargs):
421
498
"purpose" : "vpc" ,
422
499
"primary" : self .primary ,
423
500
"subnet_id" : self .subnet_id ,
424
- "ipv4" : (
425
- self .ipv4 .dict
426
- if isinstance (self .ipv4 , ConfigInterfaceIPv4 )
427
- else self .ipv4
428
- ),
501
+ "ipv4" : self .ipv4 ,
502
+ "ipv6" : self .ipv6 ,
429
503
"ip_ranges" : self .ip_ranges ,
430
504
},
431
505
}
@@ -435,11 +509,14 @@ def _serialize(self, *args, **kwargs):
435
509
f"Unknown interface purpose: { self .purpose } " ,
436
510
)
437
511
438
- return {
439
- k : v
440
- for k , v in purpose_formats [self .purpose ].items ()
441
- if v is not None
442
- }
512
+ return _flatten_request_body_recursive (
513
+ {
514
+ k : v
515
+ for k , v in purpose_formats [self .purpose ].items ()
516
+ if v is not None
517
+ },
518
+ is_put = is_put ,
519
+ )
443
520
444
521
445
522
class Config (DerivedBase ):
@@ -580,6 +657,7 @@ def interface_create_vpc(
580
657
subnet : Union [int , VPCSubnet ],
581
658
primary = False ,
582
659
ipv4 : Union [Dict [str , Any ], ConfigInterfaceIPv4 ] = None ,
660
+ ipv6 : Union [Dict [str , Any ], ConfigInterfaceIPv6Options ] = None ,
583
661
ip_ranges : Optional [List [str ]] = None ,
584
662
) -> NetworkInterface :
585
663
"""
@@ -593,6 +671,8 @@ def interface_create_vpc(
593
671
:type primary: bool
594
672
:param ipv4: The IPv4 configuration of the interface for the associated subnet.
595
673
:type ipv4: Dict or ConfigInterfaceIPv4
674
+ :param ipv6: The IPv6 configuration of the interface for the associated subnet.
675
+ :type ipv6: Dict or ConfigInterfaceIPv6Options
596
676
:param ip_ranges: A list of IPs or IP ranges in the VPC subnet.
597
677
Packets to these CIDRs are routed through the
598
678
VPC network interface.
@@ -603,19 +683,16 @@ def interface_create_vpc(
603
683
"""
604
684
params = {
605
685
"purpose" : "vpc" ,
606
- "subnet_id" : subnet . id if isinstance ( subnet , VPCSubnet ) else subnet ,
686
+ "subnet_id" : subnet ,
607
687
"primary" : primary ,
688
+ "ipv4" : ipv4 ,
689
+ "ipv6" : ipv6 ,
690
+ "ip_ranges" : ip_ranges ,
608
691
}
609
692
610
- if ipv4 is not None :
611
- params ["ipv4" ] = (
612
- ipv4 .dict if isinstance (ipv4 , ConfigInterfaceIPv4 ) else ipv4
613
- )
614
-
615
- if ip_ranges is not None :
616
- params ["ip_ranges" ] = ip_ranges
617
-
618
- return self ._interface_create (params )
693
+ return self ._interface_create (
694
+ drop_null_keys (_flatten_request_body_recursive (params ))
695
+ )
619
696
620
697
def interface_reorder (self , interfaces : List [Union [int , NetworkInterface ]]):
621
698
"""
@@ -2018,6 +2095,7 @@ def linode_interfaces(self) -> Optional[list[LinodeInterface]]:
2018
2095
2019
2096
if self .interface_generation != InterfaceGeneration .LINODE :
2020
2097
return None
2098
+
2021
2099
if not hasattr (self , "_interfaces" ):
2022
2100
result = self ._client .get (
2023
2101
"{}/interfaces" .format (Instance .api_endpoint ),
0 commit comments