Skip to content

Commit 923cc42

Browse files
zliang-akamaiezilber-akamaijriddle-linodevshanthelgarber-akamai
authored
Project: Linode Interfaces (#735)
* Implement changes for account APIs (#715) * Implement changes for account APIs * Cleanup and re-add tests * gofumpt * Add availability notice * Added support for `networking/` and `vpcs/` endpoint changs for VPC Linodes Enhanced Interfaces (#727) * Added support for networking/firewalls related changes * Added support for Networking IPs and VPC changes * Addressed PR comments * Add support for firewall template (#726) * Add firewall template functions * Add integration tests * Fix inline doc * 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 ``` * Linode instance changes for Linode Interfaces (#723) * Add linode instance changes for linode interfaces * Fix interface structs * Add tests * go work sum * Make default firewall IDs pointers (#765) * Add DoublePointer helper function * Remove duplicated DoublePointer in test * Fix * Add DoublePointerNull * lint * Make nullable default firewall IDs pointer * Make default firewall IDs in update options double pointers * Update unit test to utilize DoublePointer helper func * Firewall Related integration tests (#760) * firewall_tests * fix * fix * fix_format * fixPRcomments * fix * Linode Interfaces: Consolidate InterfaceGeneration and LinodeInterfaces fields into InstanceCreateOptions (#759) * Consolidate InterfaceGeneration and LinodeInterfaces fields into InstanceCreateOptions * Add network_helper to create opts * Add unmarshal * Re-run fixtures * Fix various issues * Fix firewall settings tests (#772) * Make interface optional fields pointers (#773) * Fix firewall settings tests * Make optional fields pointers for Linode interface structs * Rename Label field to VLANLabel to align with API attribute naming * golangci-lint run --fix * fix a comment * Nullable default firewall ids (#776) * Make default_firewall_ids nullable * Fix unit test * Add future breaking change notice for ConfigID in VPC IP (#775) * Add future breaking change notice for ConfigID in VPC IP * Update wording * Make FirewallID in linode interface creation options a double ptr (#792) * Make FirewallID in linode interface creation options a double ptr * golangci-lint fmt * Refresh the monthly transfer test fixture * Make `address` of interface ipv4 optional (#804) * Make `address` of interface ipv4 optional * Update test * Add omitempty --------- Co-authored-by: Erik Zilber <[email protected]> Co-authored-by: Jacob Riddle <[email protected]> Co-authored-by: Vinay <[email protected]> Co-authored-by: Lena Garber <[email protected]>
1 parent 967aacd commit 923cc42

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+4190
-1725
lines changed

account_settings.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ import (
44
"context"
55
)
66

7+
type InterfacesForNewLinodes string
8+
9+
const (
10+
LegacyConfigOnly InterfacesForNewLinodes = "legacy_config_only"
11+
LegacyConfigDefaultButLinodeAllowed InterfacesForNewLinodes = "legacy_config_default_but_linode_allowed"
12+
LinodeDefaultButLegacyConfigAllowed InterfacesForNewLinodes = "linode_default_but_legacy_config_allowed"
13+
LinodeOnly InterfacesForNewLinodes = "linode_only"
14+
)
15+
716
// AccountSettings are the account wide flags or plans that effect new resources
817
type AccountSettings struct {
918
// The default backups enrollment status for all new Linodes for all users on the account. When enabled, backups are mandatory per instance.
@@ -21,6 +30,10 @@ type AccountSettings struct {
2130
// A string like "disabled", "suspended", or "active" describing the status of this account’s Object Storage service enrollment.
2231
ObjectStorage *string `json:"object_storage"`
2332

33+
// NOTE: Interfaces for new linode setting may not currently be available to all users.
34+
// A new configuration flag defines whether new Linodes can use Linode and/or legacy config interfaces.
35+
InterfacesForNewLinodes InterfacesForNewLinodes `json:"interfaces_for_new_linodes"`
36+
2437
// The slug of the maintenance policy associated with the account.
2538
// NOTE: MaintenancePolicy can only be used with v4beta.
2639
MaintenancePolicy string `json:"maintenance_policy"`
@@ -34,6 +47,10 @@ type AccountSettingsUpdateOptions struct {
3447
// The default network helper setting for all new Linodes and Linode Configs for all users on the account.
3548
NetworkHelper *bool `json:"network_helper,omitempty"`
3649

50+
// NOTE: Interfaces for new linode setting may not currently be available to all users.
51+
// A new configuration flag defines whether new Linodes can use Linode and/or legacy config interfaces.
52+
InterfacesForNewLinodes *InterfacesForNewLinodes `json:"interfaces_for_new_linodes"`
53+
3754
// The slug of the maintenance policy to set the account to.
3855
// NOTE: MaintenancePolicy can only be used with v4beta.
3956
MaintenancePolicy *string `json:"maintenance_policy,omitempty"`

firewall_devices.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type FirewallDeviceType string
1515
const (
1616
FirewallDeviceLinode FirewallDeviceType = "linode"
1717
FirewallDeviceNodeBalancer FirewallDeviceType = "nodebalancer"
18+
FirewallDeviceInterface FirewallDeviceType = "interface"
1819
)
1920

2021
// FirewallDevice represents a device governed by a Firewall

firewall_templates.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package linodego
2+
3+
import (
4+
"context"
5+
)
6+
7+
type FirewallTemplate struct {
8+
Slug string `json:"slug"`
9+
Rules FirewallRuleSet `json:"rules"`
10+
}
11+
12+
// NOTE: This feature may not currently be available to all users.
13+
// GetFirewallTemplate gets a FirewallTemplate given a slug.
14+
func (c *Client) GetFirewallTemplate(ctx context.Context, slug string) (*FirewallTemplate, error) {
15+
e := formatAPIPath("networking/firewalls/templates/%s", slug)
16+
return doGETRequest[FirewallTemplate](ctx, c, e)
17+
}
18+
19+
// NOTE: This feature may not currently be available to all users.
20+
// ListFirewallTemplates gets all available firewall templates for the account.
21+
func (c *Client) ListFirewallTemplates(ctx context.Context, opts *ListOptions) ([]FirewallTemplate, error) {
22+
return getPaginatedResults[FirewallTemplate](ctx, c, "networking/firewalls/templates", opts)
23+
}

firewalls.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type Firewall struct {
3333
type DevicesCreationOptions struct {
3434
Linodes []int `json:"linodes,omitempty"`
3535
NodeBalancers []int `json:"nodebalancers,omitempty"`
36+
Interfaces []int `json:"interfaces,omitempty"`
3637
}
3738

3839
// FirewallCreateOptions fields are those accepted by CreateFirewall
@@ -50,6 +51,31 @@ type FirewallUpdateOptions struct {
5051
Tags *[]string `json:"tags,omitempty"`
5152
}
5253

54+
// FirewallSettings represents the default firewalls for Linodes,
55+
// Linode VPC and public interfaces, and NodeBalancers.
56+
type FirewallSettings struct {
57+
DefaultFirewallIDs DefaultFirewallIDs `json:"default_firewall_ids"`
58+
}
59+
60+
type DefaultFirewallIDs struct {
61+
Linode *int `json:"linode"`
62+
NodeBalancer *int `json:"nodebalancer"`
63+
PublicInterface *int `json:"public_interface"`
64+
VPCInterface *int `json:"vpc_interface"`
65+
}
66+
67+
// FirewallSettingsUpdateOptions is an options struct used when Updating FirewallSettings
68+
type FirewallSettingsUpdateOptions struct {
69+
DefaultFirewallIDs *DefaultFirewallIDsOptions `json:"default_firewall_ids,omitempty"`
70+
}
71+
72+
type DefaultFirewallIDsOptions struct {
73+
Linode **int `json:"linode,omitempty"`
74+
NodeBalancer **int `json:"nodebalancer,omitempty"`
75+
PublicInterface **int `json:"public_interface,omitempty"`
76+
VPCInterface **int `json:"vpc_interface,omitempty"`
77+
}
78+
5379
// GetUpdateOptions converts a Firewall to FirewallUpdateOptions for use in Client.UpdateFirewall.
5480
func (f *Firewall) GetUpdateOptions() FirewallUpdateOptions {
5581
return FirewallUpdateOptions{
@@ -109,3 +135,13 @@ func (c *Client) DeleteFirewall(ctx context.Context, firewallID int) error {
109135
e := formatAPIPath("networking/firewalls/%d", firewallID)
110136
return doDELETERequest(ctx, c, e)
111137
}
138+
139+
// GetFirewallSettings returns default firewalls for Linodes, Linode VPC and public interfaces, and NodeBalancers.
140+
func (c *Client) GetFirewallSettings(ctx context.Context) (*FirewallSettings, error) {
141+
return doGETRequest[FirewallSettings](ctx, c, "networking/firewalls/settings")
142+
}
143+
144+
// UpdateFirewallSettings updates the default firewalls for Linodes, Linode VPC and public interfaces, and NodeBalancers.
145+
func (c *Client) UpdateFirewallSettings(ctx context.Context, opts FirewallSettingsUpdateOptions) (*FirewallSettings, error) {
146+
return doPUTRequest[FirewallSettings](ctx, c, "networking/firewalls/settings", opts)
147+
}

instance_ips.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,18 @@ type InstanceIPv4Response struct {
2121

2222
// InstanceIP represents an Instance IP with additional DNS and networking details
2323
type InstanceIP struct {
24-
Address string `json:"address"`
25-
Gateway string `json:"gateway"`
26-
SubnetMask string `json:"subnet_mask"`
27-
Prefix int `json:"prefix"`
28-
Type InstanceIPType `json:"type"`
29-
Public bool `json:"public"`
30-
RDNS string `json:"rdns"`
31-
LinodeID int `json:"linode_id"`
32-
Region string `json:"region"`
33-
VPCNAT1To1 *InstanceIPNAT1To1 `json:"vpc_nat_1_1"`
34-
Reserved bool `json:"reserved"`
24+
Address string `json:"address"`
25+
Gateway string `json:"gateway"`
26+
SubnetMask string `json:"subnet_mask"`
27+
Prefix int `json:"prefix"`
28+
Type InstanceIPType `json:"type"`
29+
Public bool `json:"public"`
30+
RDNS string `json:"rdns"`
31+
LinodeID int `json:"linode_id"`
32+
InterfaceID *int `json:"interface_id"`
33+
Region string `json:"region"`
34+
VPCNAT1To1 *InstanceIPNAT1To1 `json:"vpc_nat_1_1"`
35+
Reserved bool `json:"reserved"`
3536
}
3637

3738
// VPCIP represents a private IP address in a VPC subnet with additional networking details
@@ -47,8 +48,10 @@ type VPCIP struct {
4748
NAT1To1 *string `json:"nat_1_1"`
4849
VPCID int `json:"vpc_id"`
4950
SubnetID int `json:"subnet_id"`
50-
ConfigID int `json:"config_id"`
5151
InterfaceID int `json:"interface_id"`
52+
53+
// The type of this field will be made a pointer in the next major release of linodego.
54+
ConfigID int `json:"config_id"`
5255
}
5356

5457
// InstanceIPv6Response contains the IPv6 addresses and ranges for an Instance

instances.go

Lines changed: 104 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package linodego
33
import (
44
"context"
55
"encoding/json"
6+
"fmt"
67
"net"
78
"time"
89

@@ -180,23 +181,32 @@ type InstancePasswordResetOptions struct {
180181

181182
// InstanceCreateOptions require only Region and Type
182183
type InstanceCreateOptions struct {
183-
Region string `json:"region"`
184-
Type string `json:"type"`
185-
Label string `json:"label,omitempty"`
186-
RootPass string `json:"root_pass,omitempty"`
187-
AuthorizedKeys []string `json:"authorized_keys,omitempty"`
188-
AuthorizedUsers []string `json:"authorized_users,omitempty"`
189-
StackScriptID int `json:"stackscript_id,omitempty"`
190-
StackScriptData map[string]string `json:"stackscript_data,omitempty"`
191-
BackupID int `json:"backup_id,omitempty"`
192-
Image string `json:"image,omitempty"`
193-
Interfaces []InstanceConfigInterfaceCreateOptions `json:"interfaces,omitempty"`
194-
BackupsEnabled bool `json:"backups_enabled,omitempty"`
195-
PrivateIP bool `json:"private_ip,omitempty"`
196-
Tags []string `json:"tags,omitempty"`
197-
Metadata *InstanceMetadataOptions `json:"metadata,omitempty"`
198-
FirewallID int `json:"firewall_id,omitempty"`
199-
InterfaceGeneration InterfaceGeneration `json:"interface_generation,omitempty"`
184+
Region string `json:"region"`
185+
Type string `json:"type"`
186+
Label string `json:"label,omitempty"`
187+
RootPass string `json:"root_pass,omitempty"`
188+
AuthorizedKeys []string `json:"authorized_keys,omitempty"`
189+
AuthorizedUsers []string `json:"authorized_users,omitempty"`
190+
StackScriptID int `json:"stackscript_id,omitempty"`
191+
StackScriptData map[string]string `json:"stackscript_data,omitempty"`
192+
BackupID int `json:"backup_id,omitempty"`
193+
Image string `json:"image,omitempty"`
194+
BackupsEnabled bool `json:"backups_enabled,omitempty"`
195+
PrivateIP bool `json:"private_ip,omitempty"`
196+
NetworkHelper *bool `json:"network_helper,omitempty"`
197+
Tags []string `json:"tags,omitempty"`
198+
Metadata *InstanceMetadataOptions `json:"metadata,omitempty"`
199+
FirewallID int `json:"firewall_id,omitempty"`
200+
InterfaceGeneration InterfaceGeneration `json:"interface_generation,omitempty"`
201+
202+
// Linode Interfaces to create the new instance with.
203+
// Conflicts with Interfaces.
204+
// NOTE: Linode Interfaces may not currently be available to all users.
205+
LinodeInterfaces []LinodeInterfaceCreateOptions `json:"-"`
206+
207+
// Legacy (config) Interfaces to create the new instance with.
208+
// Conflicts with LinodeInterfaces.
209+
Interfaces []InstanceConfigInterfaceCreateOptions `json:"-"`
200210

201211
// NOTE: Disk encryption may not currently be available to all users.
202212
DiskEncryption InstanceDiskEncryption `json:"disk_encryption,omitempty"`
@@ -238,6 +248,83 @@ type InstanceUpdateOptions struct {
238248
MaintenancePolicy *string `json:"maintenance_policy,omitempty"`
239249
}
240250

251+
// MarshalJSON contains logic necessary to populate the `interfaces` field of
252+
// InstanceCreateOptions depending on whether Interfaces or LinodeInterfaces
253+
// is specified.
254+
func (i InstanceCreateOptions) MarshalJSON() ([]byte, error) {
255+
type Mask InstanceCreateOptions
256+
257+
resultData := struct {
258+
*Mask
259+
260+
Interfaces any `json:"interfaces,omitempty"`
261+
}{
262+
Mask: (*Mask)(&i),
263+
Interfaces: nil,
264+
}
265+
266+
if i.Interfaces != nil && i.LinodeInterfaces != nil {
267+
return nil, fmt.Errorf("fields Interfaces and LinodeInterfaces cannot be specified together")
268+
}
269+
270+
if i.Interfaces != nil {
271+
resultData.Interfaces = i.Interfaces
272+
}
273+
274+
if i.LinodeInterfaces != nil {
275+
resultData.Interfaces = i.LinodeInterfaces
276+
}
277+
278+
return json.Marshal(resultData)
279+
}
280+
281+
// UnmarshalJSON contains logic necessary to populate the Interfaces field
282+
// depending on the value of interface_generation.
283+
func (i *InstanceCreateOptions) UnmarshalJSON(b []byte) error {
284+
type Mask InstanceCreateOptions
285+
286+
p := struct {
287+
*Mask
288+
289+
GenericInterfaces any `json:"interfaces,omitempty"`
290+
}{
291+
Mask: (*Mask)(i),
292+
}
293+
294+
if err := json.Unmarshal(b, &p); err != nil {
295+
return err
296+
}
297+
298+
if p.GenericInterfaces == nil {
299+
// No interfaces were given - nothing to do here.
300+
return nil
301+
}
302+
303+
if i.InterfaceGeneration == GenerationLinode {
304+
data := struct {
305+
Interfaces []LinodeInterfaceCreateOptions `json:"interfaces"`
306+
}{}
307+
308+
err := json.Unmarshal(b, &data)
309+
i.LinodeInterfaces = data.Interfaces
310+
311+
return err
312+
}
313+
314+
if i.InterfaceGeneration == GenerationLegacyConfig {
315+
data := struct {
316+
Interfaces []InstanceConfigInterfaceCreateOptions `json:"interfaces"`
317+
}{}
318+
319+
err := json.Unmarshal(b, &data)
320+
i.Interfaces = data.Interfaces
321+
322+
return err
323+
}
324+
325+
return fmt.Errorf("cannot unmarshal interfaces without valid value for interface_generation")
326+
}
327+
241328
// UnmarshalJSON implements the json.Unmarshaler interface
242329
func (i *Instance) UnmarshalJSON(b []byte) error {
243330
type Mask Instance

0 commit comments

Comments
 (0)