Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project: Virtual Private Cloud #381

Merged
merged 21 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9e2ab66
Support Linode VPC (#362)
zliang-akamai Aug 29, 2023
4d3bb35
Fix instance create opts (#373)
zliang-akamai Sep 1, 2023
b587732
Merge branch 'main' into proj/vpc
zliang-akamai Sep 13, 2023
be510b5
Merge branch 'main' into proj/vpc
zliang-akamai Sep 26, 2023
9eee757
Change vpc to vpc_id in InstanceConfigInterface (#388)
zliang-akamai Sep 26, 2023
efeae87
Merge pull request #404 from linode/main
zliang-akamai Oct 11, 2023
7e34133
test: add test coverage for vpc (#405)
ykim-1 Oct 16, 2023
8d36154
Merge pull request #409 from linode/main
zliang-akamai Oct 17, 2023
c889822
Add omitempty tag to `VPCIPv4` struct (#408)
zliang-akamai Oct 21, 2023
0a02d1f
Merge branch 'main' into proj/vpc
zliang-akamai Oct 21, 2023
a362978
Fix and improve VPC test (#412)
zliang-akamai Oct 24, 2023
9b51629
Update VPCSubnet linodes field (#414)
lgarber-akamai Nov 2, 2023
045b3cd
new: Add VPCNAT1To1 configuration to IPAddress struct (#415)
lgarber-akamai Nov 3, 2023
afa0dd8
Merge branch 'main' into proj/vpc
zliang-akamai Nov 6, 2023
c287fea
Fix test workflow
zliang-akamai Nov 6, 2023
b38fbd6
Add config interfaces fixtures
zliang-akamai Nov 6, 2023
7baa4f1
Fix test
zliang-akamai Nov 6, 2023
a9ac19b
Explicitly store fixture in `setupVPCWithSubnetWithInstance` (#421)
zliang-akamai Nov 6, 2023
8b4b603
Rename `ListVPC` to be `ListVPCs` (#420)
lgarber-akamai Nov 7, 2023
b97658d
Rename `ListVPCSubnet` to be `ListVPCSubnets` (#422)
zliang-akamai Nov 7, 2023
d0fbe0f
Merge branch 'main' into proj/vpc
zliang-akamai Nov 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions account_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ const (
ActionVolumeUpdate EventAction = "volume_update"
ActionVolumeDetach EventAction = "volume_detach"
ActionVolumeResize EventAction = "volume_resize"
ActionVPCCreate EventAction = "vpc_create"
ActionVPCDelete EventAction = "vpc_delete"
ActionVPCUpdate EventAction = "vpc_update"
ActionVPCSubnetCreate EventAction = "subnet_create"
ActionVPCSubnetDelete EventAction = "subnet_delete"
ActionVPCSubnetUpdate EventAction = "subnet_update"

// deprecated due to incorrect spelling,
// to be removed in the next major version release.
Expand All @@ -200,6 +206,8 @@ const (
EntityDomain EntityType = "domain"
EntityFirewall EntityType = "firewall"
EntityNodebalancer EntityType = "nodebalancer"
EntityVPC EntityType = "vpc"
EntityVPCSubnet EntityType = "subnet"
)

// EventStatus constants start with Event and include Linode API Event Status values
Expand Down
2 changes: 2 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM=
github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
Expand Down Expand Up @@ -183,6 +184,7 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
228 changes: 228 additions & 0 deletions instance_config_interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package linodego

import (
"context"
"encoding/json"
"fmt"
)

// InstanceConfigInterface contains information about a configuration's network interface
type InstanceConfigInterface struct {
ID int `json:"id"`
IPAMAddress string `json:"ipam_address"`
Label string `json:"label"`
Purpose ConfigInterfacePurpose `json:"purpose"`
Primary bool `json:"primary"`
Active bool `json:"active"`
VPCID *int `json:"vpc_id"`
SubnetID *int `json:"subnet_id"`
IPv4 VPCIPv4 `json:"ipv4"`
IPRanges []string `json:"ip_ranges"`
}

type VPCIPv4 struct {
VPC string `json:"vpc,omitempty"`
NAT1To1 string `json:"nat_1_1,omitempty"`
}

type InstanceConfigInterfaceCreateOptions struct {
IPAMAddress string `json:"ipam_address,omitempty"`
Label string `json:"label,omitempty"`
Purpose ConfigInterfacePurpose `json:"purpose,omitempty"`
Primary bool `json:"primary,omitempty"`
SubnetID *int `json:"subnet_id,omitempty"`
IPv4 *VPCIPv4 `json:"ipv4,omitempty"`
IPRanges []string `json:"ip_ranges,omitempty"`
}

type InstanceConfigInterfaceUpdateOptions struct {
Primary bool `json:"primary,omitempty"`
IPv4 *VPCIPv4 `json:"ipv4,omitempty"`
IPRanges []string `json:"ip_ranges,omitempty"`
}

type InstanceConfigInterfacesReorderOptions struct {
IDs []int `json:"ids"`
}

func getInstanceConfigInterfacesCreateOptionsList(
interfaces []InstanceConfigInterface,
) []InstanceConfigInterfaceCreateOptions {
interfaceOptsList := make([]InstanceConfigInterfaceCreateOptions, len(interfaces))
for index, configInterface := range interfaces {
interfaceOptsList[index] = configInterface.GetCreateOptions()
}
return interfaceOptsList
}

func (i InstanceConfigInterface) GetCreateOptions() InstanceConfigInterfaceCreateOptions {
opts := InstanceConfigInterfaceCreateOptions{
Label: i.Label,
Purpose: i.Purpose,
Primary: i.Primary,
SubnetID: i.SubnetID,
}

if len(i.IPRanges) > 0 {
opts.IPRanges = i.IPRanges
}

if i.Purpose == InterfacePurposeVPC &&
i.IPv4.NAT1To1 != "" && i.IPv4.VPC != "" {
opts.IPv4 = &VPCIPv4{
VPC: i.IPv4.VPC,
NAT1To1: i.IPv4.NAT1To1,
}
}

// workaround for API issue
if i.IPAMAddress == "222" {
opts.IPAMAddress = ""
} else {
opts.IPAMAddress = i.IPAMAddress
}

return opts
}

func (i InstanceConfigInterface) GetUpdateOptions() InstanceConfigInterfaceUpdateOptions {
opts := InstanceConfigInterfaceUpdateOptions{
Primary: i.Primary,
}

if i.Purpose == InterfacePurposeVPC {
opts.IPv4 = &VPCIPv4{
VPC: i.IPv4.VPC,
NAT1To1: i.IPv4.NAT1To1,
}
}

if len(i.IPRanges) > 0 {
opts.IPRanges = i.IPRanges
}

return opts
}

func (c *Client) AppendInstanceConfigInterface(
ctx context.Context,
linodeID int,
configID int,
opts InstanceConfigInterfaceCreateOptions,
) (*InstanceConfigInterface, error) {
body, err := json.Marshal(opts)
if err != nil {
return nil, err
}

req := c.R(ctx).SetResult(&InstanceConfigInterface{}).SetBody(string(body))
e := fmt.Sprintf("/linode/instances/%d/configs/%d/interfaces", linodeID, configID)
r, err := coupleAPIErrors(req.Post(e))
if err != nil {
return nil, err
}

return r.Result().(*InstanceConfigInterface), nil
}

func (c *Client) GetInstanceConfigInterface(
ctx context.Context,
linodeID int,
configID int,
interfaceID int,
) (*InstanceConfigInterface, error) {
e := fmt.Sprintf(
"linode/instances/%d/configs/%d/interfaces/%d",
linodeID,
configID,
interfaceID,
)
req := c.R(ctx).SetResult(&InstanceConfigInterface{})
r, err := coupleAPIErrors(req.Get(e))
if err != nil {
return nil, err
}
return r.Result().(*InstanceConfigInterface), nil
}

func (c *Client) ListInstanceConfigInterfaces(
ctx context.Context,
linodeID int,
configID int,
) ([]InstanceConfigInterface, error) {
e := fmt.Sprintf(
"linode/instances/%d/configs/%d/interfaces",
linodeID,
configID,
)
req := c.R(ctx).SetResult([]InstanceConfigInterface{})
r, err := coupleAPIErrors(req.Get(e))
if err != nil {
return nil, err
}
return *r.Result().(*[]InstanceConfigInterface), nil
}

func (c *Client) UpdateInstanceConfigInterface(
ctx context.Context,
linodeID int,
configID int,
interfaceID int,
opts InstanceConfigInterfaceUpdateOptions,
) (*InstanceConfigInterface, error) {
body, err := json.Marshal(opts)
if err != nil {
return nil, err
}

e := fmt.Sprintf(
"linode/instances/%d/configs/%d/interfaces/%d",
linodeID,
configID,
interfaceID,
)
req := c.R(ctx).SetResult(&InstanceConfigInterface{}).SetBody(string(body))
r, err := coupleAPIErrors(req.Put(e))
if err != nil {
return nil, err
}
return r.Result().(*InstanceConfigInterface), nil
}

func (c *Client) DeleteInstanceConfigInterface(
ctx context.Context,
linodeID int,
configID int,
interfaceID int,
) error {
e := fmt.Sprintf(
"linode/instances/%d/configs/%d/interfaces/%d",
linodeID,
configID,
interfaceID,
)
_, err := coupleAPIErrors(c.R(ctx).Delete(e))
return err
}

func (c *Client) ReorderInstanceConfigInterfaces(
ctx context.Context,
linodeID int,
configID int,
opts InstanceConfigInterfacesReorderOptions,
) error {
body, err := json.Marshal(opts)
if err != nil {
return err
}
e := fmt.Sprintf(
"linode/instances/%d/configs/%d/interfaces/order",
linodeID,
configID,
)

req := c.R(ctx).SetBody(string(body))
_, err = coupleAPIErrors(req.Post(e))

return err
}
44 changes: 19 additions & 25 deletions instance_configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,9 @@ type ConfigInterfacePurpose string
const (
InterfacePurposePublic ConfigInterfacePurpose = "public"
InterfacePurposeVLAN ConfigInterfacePurpose = "vlan"
InterfacePurposeVPC ConfigInterfacePurpose = "vpc"
)

// InstanceConfigInterface contains information about a configuration's network interface
type InstanceConfigInterface struct {
IPAMAddress string `json:"ipam_address"`
Label string `json:"label"`
Purpose ConfigInterfacePurpose `json:"purpose"`
}

// InstanceConfigsPagedResponse represents a paginated InstanceConfig API response
type InstanceConfigsPagedResponse struct {
*PageOptions
Expand All @@ -78,26 +72,26 @@ type InstanceConfigsPagedResponse struct {

// InstanceConfigCreateOptions are InstanceConfig settings that can be used at creation
type InstanceConfigCreateOptions struct {
Label string `json:"label,omitempty"`
Comments string `json:"comments,omitempty"`
Devices InstanceConfigDeviceMap `json:"devices"`
Helpers *InstanceConfigHelpers `json:"helpers,omitempty"`
Interfaces []InstanceConfigInterface `json:"interfaces"`
MemoryLimit int `json:"memory_limit,omitempty"`
Kernel string `json:"kernel,omitempty"`
InitRD int `json:"init_rd,omitempty"`
RootDevice *string `json:"root_device,omitempty"`
RunLevel string `json:"run_level,omitempty"`
VirtMode string `json:"virt_mode,omitempty"`
Label string `json:"label,omitempty"`
Comments string `json:"comments,omitempty"`
Devices InstanceConfigDeviceMap `json:"devices"`
Helpers *InstanceConfigHelpers `json:"helpers,omitempty"`
Interfaces []InstanceConfigInterfaceCreateOptions `json:"interfaces"`
MemoryLimit int `json:"memory_limit,omitempty"`
Kernel string `json:"kernel,omitempty"`
InitRD int `json:"init_rd,omitempty"`
RootDevice *string `json:"root_device,omitempty"`
RunLevel string `json:"run_level,omitempty"`
VirtMode string `json:"virt_mode,omitempty"`
}

// InstanceConfigUpdateOptions are InstanceConfig settings that can be used in updates
type InstanceConfigUpdateOptions struct {
Label string `json:"label,omitempty"`
Comments string `json:"comments"`
Devices *InstanceConfigDeviceMap `json:"devices,omitempty"`
Helpers *InstanceConfigHelpers `json:"helpers,omitempty"`
Interfaces []InstanceConfigInterface `json:"interfaces"`
Label string `json:"label,omitempty"`
Comments string `json:"comments"`
Devices *InstanceConfigDeviceMap `json:"devices,omitempty"`
Helpers *InstanceConfigHelpers `json:"helpers,omitempty"`
Interfaces []InstanceConfigInterfaceCreateOptions `json:"interfaces"`
// MemoryLimit 0 means unlimitted, this is not omitted
MemoryLimit int `json:"memory_limit"`
Kernel string `json:"kernel,omitempty"`
Expand Down Expand Up @@ -141,7 +135,7 @@ func (i InstanceConfig) GetCreateOptions() InstanceConfigCreateOptions {
Comments: i.Comments,
Devices: *i.Devices,
Helpers: i.Helpers,
Interfaces: i.Interfaces,
Interfaces: getInstanceConfigInterfacesCreateOptionsList(i.Interfaces),
MemoryLimit: i.MemoryLimit,
Kernel: i.Kernel,
InitRD: initrd,
Expand All @@ -158,7 +152,7 @@ func (i InstanceConfig) GetUpdateOptions() InstanceConfigUpdateOptions {
Comments: i.Comments,
Devices: i.Devices,
Helpers: i.Helpers,
Interfaces: i.Interfaces,
Interfaces: getInstanceConfigInterfacesCreateOptionsList(i.Interfaces),
MemoryLimit: i.MemoryLimit,
Kernel: i.Kernel,
InitRD: copyInt(i.InitRD),
Expand Down
27 changes: 18 additions & 9 deletions instance_ips.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ type InstanceIPv4Response struct {

// InstanceIP represents an Instance IP with additional DNS and networking details
type InstanceIP struct {
Address string `json:"address"`
Gateway string `json:"gateway"`
SubnetMask string `json:"subnet_mask"`
Prefix int `json:"prefix"`
Type InstanceIPType `json:"type"`
Public bool `json:"public"`
RDNS string `json:"rdns"`
LinodeID int `json:"linode_id"`
Region string `json:"region"`
Address string `json:"address"`
Gateway string `json:"gateway"`
SubnetMask string `json:"subnet_mask"`
Prefix int `json:"prefix"`
Type InstanceIPType `json:"type"`
Public bool `json:"public"`
RDNS string `json:"rdns"`
LinodeID int `json:"linode_id"`
Region string `json:"region"`
VPCNAT1To1 *InstanceIPNAT1To1 `json:"vpc_nat_1_1"`
}

// InstanceIPv6Response contains the IPv6 addresses and ranges for an Instance
Expand All @@ -41,6 +42,14 @@ type InstanceIPv6Response struct {
Global []IPv6Range `json:"global"`
}

// InstanceIPNAT1To1 contains information about the NAT 1:1 mapping
// of a public IP address to a VPC subnet.
type InstanceIPNAT1To1 struct {
Address string `json:"address"`
SubnetID int `json:"subnet_id"`
VPCID int `json:"vpc_id"`
}

// IPv6Range represents a range of IPv6 addresses routed to a single Linode in a given Region
type IPv6Range struct {
Range string `json:"range"`
Expand Down
Loading