Skip to content

Commit 75f0190

Browse files
Adding VPC Enhanced Interfaces (#724)
## 📝 Description **What does this PR do and why is this change necessary?** Initial additions for interfaces ## ✔️ How to Test **How do I run the relevant unit/integration tests?** ```bash make test-unit ```
1 parent 134c0a4 commit 75f0190

9 files changed

+591
-0
lines changed

interfaces.go

+244
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
package linodego
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"time"
7+
8+
"github.com/linode/linodego/internal/parseabletime"
9+
)
10+
11+
type LinodeInterface struct {
12+
ID int `json:"id"`
13+
Version int `json:"version"`
14+
MACAddress string `json:"mac_address"`
15+
Created *time.Time `json:"-"`
16+
Updated *time.Time `json:"-"`
17+
DefaultRoute *InterfaceDefaultRoute `json:"default_route"`
18+
Public *PublicInterface `json:"public"`
19+
VPC *VPCInterface `json:"vpc"`
20+
VLAN *VLANInterface `json:"vlan"`
21+
}
22+
23+
type InterfaceDefaultRoute struct {
24+
IPv4 *bool `json:"ipv4,omitempty"`
25+
IPv6 *bool `json:"ipv6,omitempty"`
26+
}
27+
28+
type PublicInterface struct {
29+
IPv4 *PublicInterfaceIPv4 `json:"ipv4"`
30+
IPv6 *PublicInterfaceIPv6 `json:"ipv6"`
31+
}
32+
33+
type PublicInterfaceIPv4 struct {
34+
Addresses []PublicInterfaceIPv4Address `json:"addresses"`
35+
Shared []PublicInterfaceIPv4Shared `json:"shared"`
36+
}
37+
38+
type PublicInterfaceIPv6 struct {
39+
Ranges []PublicInterfaceIPv6Range `json:"ranges"`
40+
Shared []PublicInterfaceIPv6Range `json:"shared"`
41+
SLAAC []PublicInterfaceIPv6SLAAC `json:"slaac"`
42+
}
43+
44+
type PublicInterfaceIPv4Address struct {
45+
Address string `json:"address"`
46+
Primary bool `json:"primary"`
47+
}
48+
49+
type PublicInterfaceIPv4Shared struct {
50+
Address string `json:"address"`
51+
LinodeID string `json:"linode_id"`
52+
}
53+
54+
type PublicInterfaceIPv6Range struct {
55+
Range string `json:"range"`
56+
RouteTarget *string `json:"route_target"`
57+
}
58+
59+
type PublicInterfaceIPv6SLAAC struct {
60+
Prefix int `json:"prefix"`
61+
Address string `json:"address"`
62+
}
63+
64+
type VPCInterface struct {
65+
VPCID int `json:"vpc_id"`
66+
SubnetID int `json:"subnet_id"`
67+
IPv4 VPCInterfaceIPv4 `json:"ipv4"`
68+
}
69+
70+
type VPCInterfaceIPv4 struct {
71+
Addresses []VPCInterfaceIPv4Address `json:"addresses"`
72+
Ranges []VPCInterfaceIPv4Range `json:"ranges"`
73+
}
74+
75+
type VPCInterfaceIPv4Address struct {
76+
Address string `json:"address"`
77+
Primary bool `json:"primary"`
78+
NAT1To1Address *string `json:"nat_1_1_address"`
79+
}
80+
81+
type VPCInterfaceIPv4Range struct {
82+
Range string `json:"range"`
83+
}
84+
85+
type VLANInterface struct {
86+
Label string `json:"vlan_label"`
87+
IPAMAddress *string `json:"ipam_address,omitempty"`
88+
}
89+
90+
type LinodeInterfaceCreateOptions struct {
91+
FirewallID *int `json:"firewall_id,omitempty"`
92+
DefaultRoute *InterfaceDefaultRoute `json:"default_route,omitempty"`
93+
Public *PublicInterfaceCreateOptions `json:"public,omitempty"`
94+
VPC *VPCInterfaceCreateOptions `json:"vpc,omitempty"`
95+
VLAN *VLANInterface `json:"vlan,omitempty"`
96+
}
97+
98+
type LinodeInterfaceUpdateOptions struct {
99+
DefaultRoute *InterfaceDefaultRoute `json:"default_route,omitempty"`
100+
Public *PublicInterfaceCreateOptions `json:"public,omitempty"`
101+
VPC *VPCInterfaceCreateOptions `json:"vpc,omitempty"`
102+
VLAN *VLANInterface `json:"vlan,omitempty"`
103+
}
104+
105+
type PublicInterfaceCreateOptions struct {
106+
IPv4 []PublicInterfaceIPv4CreateOptions `json:"ipv4,omitempty"`
107+
IPv6 []PublicInterfaceIPv6CreateOptions `json:"ipv6,omitempty"`
108+
}
109+
110+
type PublicInterfaceIPv4CreateOptions struct {
111+
Addresses []PublicInterfaceIPv4AddressCreateOptions `json:"addresses,omitempty"`
112+
}
113+
114+
type PublicInterfaceIPv4AddressCreateOptions struct {
115+
Address string `json:"address"`
116+
Primary *bool `json:"primary,omitempty"`
117+
}
118+
119+
type PublicInterfaceIPv6CreateOptions struct {
120+
Ranges []PublicInterfaceIPv6RangeCreateOptions `json:"ranges,omitempty"`
121+
}
122+
123+
type PublicInterfaceIPv6RangeCreateOptions struct {
124+
Range string `json:"range"`
125+
}
126+
127+
type VPCInterfaceCreateOptions struct {
128+
SubnetID int `json:"subnet_id"`
129+
IPv4 []VPCInterfaceIPv4CreateOptions `json:"ipv4,omitempty"`
130+
}
131+
132+
type VPCInterfaceIPv4CreateOptions struct {
133+
Addresses []VPCInterfaceIPv4AddressCreateOptions `json:"addresses,omitempty"`
134+
Ranges []VPCInterfaceIPv4RangeCreateOptions `json:"ranges,omitempty"`
135+
}
136+
137+
type VPCInterfaceIPv4AddressCreateOptions struct {
138+
Address string `json:"address"`
139+
Primary *bool `json:"primary,omitempty"`
140+
NAT1To1Address *string `json:"nat_1_1_address,omitempty"`
141+
}
142+
143+
type VPCInterfaceIPv4RangeCreateOptions struct {
144+
Range string `json:"range"`
145+
}
146+
147+
type LinodeInterfacesUpgrade struct {
148+
ConfigID int `json:"config_id"`
149+
DryRun bool `json:"dry_run"`
150+
Interfaces []LinodeInterface `json:"interfaces"`
151+
}
152+
153+
type LinodeInterfacesUpgradeOptions struct {
154+
ConfigID *int `json:"config_id,omitempty"`
155+
DryRun *bool `json:"dry_run,omitempty"`
156+
}
157+
158+
type InterfaceSettings struct {
159+
NetworkHelper bool `json:"network_helper"`
160+
DefaultRoute InterfaceDefaultRouteSetting `json:"default_route"`
161+
}
162+
163+
type InterfaceSettingsUpdateOptions struct {
164+
NetworkHelper *bool `json:"network_helper,omitempty"`
165+
DefaultRoute *InterfaceDefaultRouteSettingUpdateOptions `json:"default_route,omitempty"`
166+
}
167+
168+
type InterfaceDefaultRouteSettingUpdateOptions struct {
169+
IPv4InterfaceID *int `json:"ipv4_interface_id,omitempty"`
170+
IPv6InterfaceID *int `json:"ipv6_interface_id,omitempty"`
171+
}
172+
173+
type InterfaceDefaultRouteSetting struct {
174+
IPv4InterfaceID *int `json:"ipv4_interface_id"`
175+
IPv4EligibleInterfaceIDs []int `json:"ipv4_eligible_interface_ids"`
176+
IPv6InterfaceID *int `json:"ipv6_interface_id"`
177+
IPv6EligibleInterfaceIDs []int `json:"ipv6_eligible_interface_ids"`
178+
}
179+
180+
func (i *LinodeInterface) UnmarshalJSON(b []byte) error {
181+
type Mask LinodeInterface
182+
183+
p := struct {
184+
*Mask
185+
Created *parseabletime.ParseableTime `json:"created"`
186+
Updated *parseabletime.ParseableTime `json:"updated"`
187+
}{
188+
Mask: (*Mask)(i),
189+
}
190+
191+
if err := json.Unmarshal(b, &p); err != nil {
192+
return err
193+
}
194+
195+
i.Created = (*time.Time)(p.Created)
196+
i.Updated = (*time.Time)(p.Updated)
197+
198+
return nil
199+
}
200+
201+
func (c *Client) ListInterfaces(ctx context.Context, linodeID int, opts *ListOptions) ([]LinodeInterface, error) {
202+
e := formatAPIPath("linode/instances/%d/interfaces", linodeID)
203+
return getPaginatedResults[LinodeInterface](ctx, c, e, opts)
204+
}
205+
206+
func (c *Client) GetInterface(ctx context.Context, linodeID int, interfaceID int) (*LinodeInterface, error) {
207+
e := formatAPIPath("linode/instances/%d/interfaces/%d", linodeID, interfaceID)
208+
return doGETRequest[LinodeInterface](ctx, c, e)
209+
}
210+
211+
func (c *Client) CreateInterface(ctx context.Context, linodeID int, opts LinodeInterfaceCreateOptions) (*LinodeInterface, error) {
212+
e := formatAPIPath("linode/instances/%d/interfaces", linodeID)
213+
return doPOSTRequest[LinodeInterface](ctx, c, e, opts)
214+
}
215+
216+
func (c *Client) UpdateInterface(ctx context.Context, linodeID int, interfaceID int, opts LinodeInterfaceUpdateOptions) (*LinodeInterface, error) {
217+
e := formatAPIPath("linode/instances/%d/interfaces/%d", linodeID, interfaceID)
218+
return doPUTRequest[LinodeInterface](ctx, c, e, opts)
219+
}
220+
221+
func (c *Client) DeleteInterface(ctx context.Context, linodeID int, interfaceID int) error {
222+
e := formatAPIPath("linode/instances/%d/interfaces/%d", linodeID, interfaceID)
223+
return doDELETERequest(ctx, c, e)
224+
}
225+
226+
func (c *Client) UpgradeInterfaces(ctx context.Context, linodeID int, opts LinodeInterfacesUpgradeOptions) (*LinodeInterfacesUpgrade, error) {
227+
e := formatAPIPath("linode/instances/%d/upgrade-interfaces", linodeID)
228+
return doPOSTRequest[LinodeInterfacesUpgrade](ctx, c, e, opts)
229+
}
230+
231+
func (c *Client) ListInterfaceFirewalls(ctx context.Context, linodeID int, interfaceID int, opts *ListOptions) ([]Firewall, error) {
232+
e := formatAPIPath("linode/instances/%d/interfaces/%d/firewalls", linodeID, interfaceID)
233+
return getPaginatedResults[Firewall](ctx, c, e, opts)
234+
}
235+
236+
func (c *Client) GetInterfaceSettings(ctx context.Context, linodeID int) (*InterfaceSettings, error) {
237+
e := formatAPIPath("linode/instances/%d/interfaces/settings", linodeID)
238+
return doGETRequest[InterfaceSettings](ctx, c, e)
239+
}
240+
241+
func (c *Client) UpdateInterfaceSettings(ctx context.Context, linodeID int, opts InterfaceSettingsUpdateOptions) (*InterfaceSettings, error) {
242+
e := formatAPIPath("linode/instances/%d/interfaces/settings", linodeID)
243+
return doPUTRequest[InterfaceSettings](ctx, c, e, opts)
244+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"id": 123,
3+
"mac_address": "22:00:AB:CD:EF:01",
4+
"created": "2024-01-01T00:01:01",
5+
"updated": "2024-01-01T00:01:01",
6+
"default_route": {
7+
"ipv4": true,
8+
"ipv6": false
9+
},
10+
"version": 1,
11+
"vpc": null,
12+
"public": {
13+
"ipv4": {
14+
"addresses": [
15+
{
16+
"address": "auto",
17+
"primary": true
18+
}
19+
]
20+
}
21+
},
22+
"vlan": null
23+
}

test/unit/fixtures/interface_get.json

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"id": 123,
3+
"mac_address": "22:00:AB:CD:EF:01",
4+
"created": "2024-01-01T00:01:01",
5+
"updated": "2024-01-01T00:01:01",
6+
"default_route": {
7+
"ipv4": false,
8+
"ipv6": false
9+
},
10+
"version": 1,
11+
"vpc": null,
12+
"public": null,
13+
"vlan": {
14+
"vlan_label": "my_vlan",
15+
"ipam_address": "10.0.0.1/24"
16+
}
17+
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"data": [
3+
{
4+
"id": 123,
5+
"mac_address": "22:00:AB:CD:EF:01",
6+
"created": "2024-01-01T00:01:01",
7+
"updated": "2024-01-01T00:01:01",
8+
"default_route": {
9+
"ipv4": false,
10+
"ipv6": false
11+
},
12+
"version": 1,
13+
"vpc": null,
14+
"public": null,
15+
"vlan": {
16+
"vlan_label": "my_vlan",
17+
"ipam_address": "10.0.0.1/24"
18+
}
19+
}
20+
],
21+
"page": 1,
22+
"pages": 1,
23+
"results": 1
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"network_helper": false,
3+
"default_route": {
4+
"ipv4_interface_id": 1,
5+
"ipv4_eligible_interface_ids": [1, 2],
6+
"ipv6_interface_id": 3,
7+
"ipv6_eligible_interface_ids": [3, 4]
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"network_helper": true,
3+
"default_route": {
4+
"ipv4_interface_id": 1,
5+
"ipv4_eligible_interface_ids": [1, 2],
6+
"ipv6_interface_id": 3,
7+
"ipv6_eligible_interface_ids": [3, 4]
8+
}
9+
}
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"id": 123,
3+
"mac_address": "22:00:AB:CD:EF:01",
4+
"created": "2024-01-01T00:01:01",
5+
"updated": "2024-01-01T00:01:01",
6+
"default_route": {
7+
"ipv4": false,
8+
"ipv6": true
9+
},
10+
"version": 1,
11+
"vpc": null,
12+
"public": null,
13+
"vlan": {
14+
"vlan_label": "my_vlan",
15+
"ipam_address": "10.0.0.1/24"
16+
}
17+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"config_id": 123,
3+
"dry_run": false,
4+
"interfaces": [
5+
{
6+
"id": 123,
7+
"mac_address": "22:00:AB:CD:EF:01",
8+
"created": "2024-01-01T00:01:01",
9+
"updated": "2024-01-01T00:01:01",
10+
"default_route": {
11+
"ipv4": false,
12+
"ipv6": false
13+
},
14+
"version": 1,
15+
"vpc": null,
16+
"public": null,
17+
"vlan": {
18+
"vlan_label": "my_vlan",
19+
"ipam_address": "10.0.0.1/24"
20+
}
21+
}
22+
]
23+
}

0 commit comments

Comments
 (0)