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

Add Vultr VPC support #210

Merged
merged 6 commits into from
Apr 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 13 additions & 10 deletions govultr.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,18 @@ type Client struct {
ISO ISOService
Kubernetes KubernetesService
LoadBalancer LoadBalancerService
Network NetworkService
ObjectStorage ObjectStorageService
OS OSService
Plan PlanService
Region RegionService
ReservedIP ReservedIPService
Snapshot SnapshotService
SSHKey SSHKeyService
StartupScript StartupScriptService
User UserService
// Deprecated: Network should no longer be used. Instead, use VPC.
Network NetworkService
ObjectStorage ObjectStorageService
OS OSService
Plan PlanService
Region RegionService
ReservedIP ReservedIPService
Snapshot SnapshotService
SSHKey SSHKeyService
StartupScript StartupScriptService
User UserService
VPC VPCService

// Optional function called after every successful request made to the Vultr API
onRequestCompleted RequestCompletionCallback
Expand Down Expand Up @@ -121,6 +123,7 @@ func NewClient(httpClient *http.Client) *Client {
client.SSHKey = &SSHKeyServiceHandler{client}
client.StartupScript = &StartupScriptServiceHandler{client}
client.User = &UserServiceHandler{client}
client.VPC = &VPCServiceHandler{client}

return client
}
Expand Down
128 changes: 105 additions & 23 deletions instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,17 @@ type InstanceService interface {
GetBandwidth(ctx context.Context, instanceID string) (*Bandwidth, error)
GetNeighbors(ctx context.Context, instanceID string) (*Neighbors, error)

// Deprecated: ListPrivateNetworks should no longer be used. Instead, use ListVPCInfo.
ListPrivateNetworks(ctx context.Context, instanceID string, options *ListOptions) ([]PrivateNetwork, *Meta, error)
// Deprecated: AttachPrivateNetwork should no longer be used. Instead, use AttachVPC.
AttachPrivateNetwork(ctx context.Context, instanceID, networkID string) error
// Deprecated: DetachPrivateNetwork should no longer be used. Instead, use DetachVPC.
DetachPrivateNetwork(ctx context.Context, instanceID, networkID string) error

ListVPCInfo(ctx context.Context, instanceID string, options *ListOptions) ([]VPCInfo, *Meta, error)
AttachVPC(ctx context.Context, instanceID, vpcID string) error
DetachVPC(ctx context.Context, instanceID, vpcID string) error

ISOStatus(ctx context.Context, instanceID string) (*Iso, error)
AttachISO(ctx context.Context, instanceID, isoID string) error
DetachISO(ctx context.Context, instanceID string) error
Expand Down Expand Up @@ -131,12 +138,25 @@ type privateNetworksBase struct {
}

// PrivateNetwork information for a given instance.
// Deprecated: PrivateNetwork should no longer be used. Instead, use VPCInfo.
type PrivateNetwork struct {
NetworkID string `json:"network_id"`
MacAddress string `json:"mac_address"`
IPAddress string `json:"ip_address"`
}

type vpcInfoBase struct {
VPCs []VPCInfo `json:"vpcs"`
Meta *Meta `json:"meta"`
}

// VPCInfo information for a given instance.
type VPCInfo struct {
ID string `json:"id"`
MacAddress string `json:"mac_address"`
IPAddress string `json:"ip_address"`
}

type isoStatusBase struct {
IsoStatus *Iso `json:"iso_status"`
}
Expand Down Expand Up @@ -209,22 +229,26 @@ type Upgrades struct {

// InstanceCreateReq struct used to create an instance.
type InstanceCreateReq struct {
Region string `json:"region,omitempty"`
Plan string `json:"plan,omitempty"`
Label string `json:"label,omitempty"`
Tag string `json:"tag,omitempty"`
OsID int `json:"os_id,omitempty"`
ISOID string `json:"iso_id,omitempty"`
AppID int `json:"app_id,omitempty"`
ImageID string `json:"image_id,omitempty"`
FirewallGroupID string `json:"firewall_group_id,omitempty"`
Hostname string `json:"hostname,omitempty"`
IPXEChainURL string `json:"ipxe_chain_url,omitempty"`
ScriptID string `json:"script_id,omitempty"`
SnapshotID string `json:"snapshot_id,omitempty"`
EnableIPv6 *bool `json:"enable_ipv6,omitempty"`
EnablePrivateNetwork *bool `json:"enable_private_network,omitempty"`
Region string `json:"region,omitempty"`
Plan string `json:"plan,omitempty"`
Label string `json:"label,omitempty"`
Tag string `json:"tag,omitempty"`
OsID int `json:"os_id,omitempty"`
ISOID string `json:"iso_id,omitempty"`
AppID int `json:"app_id,omitempty"`
ImageID string `json:"image_id,omitempty"`
FirewallGroupID string `json:"firewall_group_id,omitempty"`
Hostname string `json:"hostname,omitempty"`
IPXEChainURL string `json:"ipxe_chain_url,omitempty"`
ScriptID string `json:"script_id,omitempty"`
SnapshotID string `json:"snapshot_id,omitempty"`
EnableIPv6 *bool `json:"enable_ipv6,omitempty"`
// Deprecated: EnablePrivateNetwork should no longer be used. Instead, use EnableVPC.
EnablePrivateNetwork *bool `json:"enable_private_network,omitempty"`
// Deprecated: AttachPrivateNetwork should no longer be used. Instead, use AttachVPC.
AttachPrivateNetwork []string `json:"attach_private_network,omitempty"`
EnableVPC *bool `json:"enable_vpc,omitempty"`
AttachVPC []string `json:"attach_vpc,omitempty"`
SSHKeys []string `json:"sshkey_id,omitempty"`
Backups string `json:"backups,omitempty"`
DDOSProtection *bool `json:"ddos_protection,omitempty"`
Expand All @@ -235,16 +259,22 @@ type InstanceCreateReq struct {

// InstanceUpdateReq struct used to update an instance.
type InstanceUpdateReq struct {
Plan string `json:"plan,omitempty"`
Label string `json:"label,omitempty"`
Tag string `json:"tag,omitempty"`
OsID int `json:"os_id,omitempty"`
AppID int `json:"app_id,omitempty"`
ImageID string `json:"image_id,omitempty"`
EnableIPv6 *bool `json:"enable_ipv6,omitempty"`
EnablePrivateNetwork *bool `json:"enable_private_network,omitempty"`
Plan string `json:"plan,omitempty"`
Label string `json:"label,omitempty"`
Tag string `json:"tag,omitempty"`
OsID int `json:"os_id,omitempty"`
AppID int `json:"app_id,omitempty"`
ImageID string `json:"image_id,omitempty"`
EnableIPv6 *bool `json:"enable_ipv6,omitempty"`
// Deprecated: EnablePrivateNetwork should no longer be used. Instead, use EnableVPC.
EnablePrivateNetwork *bool `json:"enable_private_network,omitempty"`
// Deprecated: AttachPrivateNetwork should no longer be used. Instead, use AttachVPC.
AttachPrivateNetwork []string `json:"attach_private_network,omitempty"`
// Deprecated: DetachPrivateNetwork should no longer be used. Instead, use DetachVPC.
DetachPrivateNetwork []string `json:"detach_private_network,omitempty"`
EnableVPC *bool `json:"enable_vpc,omitempty"`
AttachVPC []string `json:"attach_vpc,omitempty"`
DetachVPC []string `json:"detach_vpc,omitempty"`
Backups string `json:"backups,omitempty"`
DDOSProtection *bool `json:"ddos_protection"`
UserData string `json:"user_data,omitempty"`
Expand Down Expand Up @@ -477,6 +507,7 @@ func (i *InstanceServiceHandler) GetNeighbors(ctx context.Context, instanceID st
}

// ListPrivateNetworks currently attached to an instance.
// Deprecated: ListPrivateNetworks should no longer be used. Instead, use ListVPCInfo
func (i *InstanceServiceHandler) ListPrivateNetworks(ctx context.Context, instanceID string, options *ListOptions) ([]PrivateNetwork, *Meta, error) {
uri := fmt.Sprintf("%s/%s/private-networks", instancePath, instanceID)
req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
Expand All @@ -500,6 +531,7 @@ func (i *InstanceServiceHandler) ListPrivateNetworks(ctx context.Context, instan
}

// AttachPrivateNetwork to an instance
// Deprecated: AttachPrivateNetwork should no longer be used. Instead, use AttachVPC
func (i *InstanceServiceHandler) AttachPrivateNetwork(ctx context.Context, instanceID, networkID string) error {
uri := fmt.Sprintf("%s/%s/private-networks/attach", instancePath, instanceID)
body := RequestBody{"network_id": networkID}
Expand All @@ -513,6 +545,7 @@ func (i *InstanceServiceHandler) AttachPrivateNetwork(ctx context.Context, insta
}

// DetachPrivateNetwork from an instance.
// Deprecated: DetachPrivateNetwork should no longer be used. Instead, use DetachVPC
func (i *InstanceServiceHandler) DetachPrivateNetwork(ctx context.Context, instanceID, networkID string) error {
uri := fmt.Sprintf("%s/%s/private-networks/detach", instancePath, instanceID)
body := RequestBody{"network_id": networkID}
Expand All @@ -525,6 +558,55 @@ func (i *InstanceServiceHandler) DetachPrivateNetwork(ctx context.Context, insta
return i.client.DoWithContext(ctx, req, nil)
}

// ListVPCInfo currently attached to an instance.
func (i *InstanceServiceHandler) ListVPCInfo(ctx context.Context, instanceID string, options *ListOptions) ([]VPCInfo, *Meta, error) {
uri := fmt.Sprintf("%s/%s/vpcs", instancePath, instanceID)
req, err := i.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, nil, err
}

newValues, err := query.Values(options)
if err != nil {
return nil, nil, err
}

req.URL.RawQuery = newValues.Encode()

vpcs := new(vpcInfoBase)
if err = i.client.DoWithContext(ctx, req, vpcs); err != nil {
return nil, nil, err
}

return vpcs.VPCs, vpcs.Meta, nil
}

// AttachVPC to an instance
func (i *InstanceServiceHandler) AttachVPC(ctx context.Context, instanceID, vpcID string) error {
uri := fmt.Sprintf("%s/%s/vpcs/attach", instancePath, instanceID)
body := RequestBody{"vpc_id": vpcID}

req, err := i.client.NewRequest(ctx, http.MethodPost, uri, body)
if err != nil {
return err
}

return i.client.DoWithContext(ctx, req, nil)
}

// DetachVPC from an instance.
func (i *InstanceServiceHandler) DetachVPC(ctx context.Context, instanceID, vpcID string) error {
uri := fmt.Sprintf("%s/%s/vpcs/detach", instancePath, instanceID)
body := RequestBody{"vpc_id": vpcID}

req, err := i.client.NewRequest(ctx, http.MethodPost, uri, body)
if err != nil {
return err
}

return i.client.DoWithContext(ctx, req, nil)
}

// ISOStatus retrieves the current ISO state for a given VPS.
// The returned state may be one of: ready | isomounting | isomounted.
func (i *InstanceServiceHandler) ISOStatus(ctx context.Context, instanceID string) (*Iso, error) {
Expand Down
69 changes: 69 additions & 0 deletions instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,49 @@ func TestServerServiceHandler_ListPrivateNetworks(t *testing.T) {
}
}

func TestServerServiceHandler_ListVPCInfo(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/v2/instances/14b3e7d6-ffb5-4994-8502-57fcd9db3b33/vpcs", func(writer http.ResponseWriter, request *http.Request) {
response := `{"vpcs": [{"id": "v1-net539626f0798d7","mac_address": "5a:02:00:00:24:e9","ip_address": "10.99.0.3"}],"meta":{"total":1,"links":{"next":"thisismycusror","prev":""}}}`
fmt.Fprint(writer, response)
})

options := &ListOptions{
PerPage: 1,
Cursor: "",
}
vpc, meta, err := client.Instance.ListVPCInfo(ctx, "14b3e7d6-ffb5-4994-8502-57fcd9db3b33", options)
if err != nil {
t.Errorf("Instance.ListVPCInfo returned %+v, ", err)
}

expected := []VPCInfo{
{
ID: "v1-net539626f0798d7",
MacAddress: "5a:02:00:00:24:e9",
IPAddress: "10.99.0.3",
},
}

if !reflect.DeepEqual(vpc, expected) {
t.Errorf("Instance.ListVPCInfo returned %+v, expected %+v", vpc, expected)
}

expectedMeta := &Meta{
Total: 1,
Links: &Links{
Next: "thisismycusror",
Prev: "",
},
}

if !reflect.DeepEqual(meta, expectedMeta) {
t.Errorf("Instance.ListVPCInfo meta returned %+v, expected %+v", meta, expectedMeta)
}
}

func TestServerServiceHandler_GetUserData(t *testing.T) {
setup()
defer teardown()
Expand Down Expand Up @@ -987,6 +1030,32 @@ func TestServerServiceHandler_DetachPrivateNetwork(t *testing.T) {
}
}

func TestServerServiceHandler_AttachVPC(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/v2/instances/14b3e7d6-ffb5-4994-8502-57fcd9db3b33/vpcs/attach", func(writer http.ResponseWriter, request *http.Request) {
fmt.Fprint(writer)
})

if err := client.Instance.AttachVPC(ctx, "14b3e7d6-ffb5-4994-8502-57fcd9db3b33", "14b3e7d6-ffb5-4994-8502-57fcd9db3b33"); err != nil {
t.Errorf("Instance.AttachVPC returned %+v", err)
}
}

func TestServerServiceHandler_DetachVPC(t *testing.T) {
setup()
defer teardown()

mux.HandleFunc("/v2/instances/14b3e7d6-ffb5-4994-8502-57fcd9db3b33/vpcs/detach", func(writer http.ResponseWriter, request *http.Request) {
fmt.Fprint(writer)
})

if err := client.Instance.DetachVPC(ctx, "14b3e7d6-ffb5-4994-8502-57fcd9db3b33", "14b3e7d6-ffb5-4994-8502-57fcd9db3b33"); err != nil {
t.Errorf("Instance.DetachVPC returned %+v", err)
}
}

func TestServerServiceHandler_ISOAttach(t *testing.T) {
setup()
defer teardown()
Expand Down
8 changes: 6 additions & 2 deletions load_balancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ type LoadBalancerReq struct {
ProxyProtocol *bool `json:"proxy_protocol,omitempty"`
BalancingAlgorithm string `json:"balancing_algorithm,omitempty"`
FirewallRules []LBFirewallRule `json:"firewall_rules"`
PrivateNetwork *string `json:"private_network,omitempty"`
// Deprecated: PrivateNetwork should no longer be used. Instead, use VPC.
PrivateNetwork *string `json:"private_network,omitempty"`
VPC *string `json:"vpc,omitempty"`
}

// InstanceList represents instances that are attached to your load balancer
Expand All @@ -86,7 +88,9 @@ type GenericInfo struct {
SSLRedirect *bool `json:"ssl_redirect,omitempty"`
StickySessions *StickySessions `json:"sticky_sessions,omitempty"`
ProxyProtocol *bool `json:"proxy_protocol,omitempty"`
PrivateNetwork string `json:"private_network,omitempty"`
// Deprecated: PrivateNetwork should no longer be used. Instead, use VPC.
PrivateNetwork string `json:"private_network,omitempty"`
VPC string `json:"vpc,omitempty"`
}

// StickySessions represents cookie for your load balancer
Expand Down
Loading