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 VPC 2.0 #261

Merged
merged 5 commits into from
Aug 10, 2023
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
58 changes: 56 additions & 2 deletions bare_metal_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ type BareMetalServerService interface {
MassReboot(ctx context.Context, serverList []string) error

GetUpgrades(ctx context.Context, serverID string) (*Upgrades, *http.Response, error)

ListVPC2Info(ctx context.Context, serverID string) ([]VPC2Info, *http.Response, error)
AttachVPC2(ctx context.Context, serverID string, vpc2Req *AttachVPC2Req) error
DetachVPC2(ctx context.Context, serverID, vpcID string) error
}

// BareMetalServerServiceHandler handles interaction with the Bare Metal methods for the Vultr API
Expand Down Expand Up @@ -92,6 +96,9 @@ type BareMetalCreate struct {
ReservedIPv4 string `json:"reserved_ipv4,omitempty"`
PersistentPxe *bool `json:"persistent_pxe,omitempty"`
Tags []string `json:"tags"`
AttachVPC2 []string `json:"attach_vpc2,omitempty"`
DetachVPC2 []string `json:"detach_vpc2,omitempty"`
EnableVPC2 *bool `json:"enable_vpc2,omitempty"`
}

// BareMetalUpdate represents the optional parameters that can be set when updating a Bare Metal server
Expand All @@ -103,8 +110,11 @@ type BareMetalUpdate struct {
ImageID string `json:"image_id,omitempty"`
UserData string `json:"user_data,omitempty"`
// Deprecated: Tag should no longer be used. Instead, use Tags.
Tag *string `json:"tag,omitempty"`
Tags []string `json:"tags"`
Tag *string `json:"tag,omitempty"`
Tags []string `json:"tags"`
AttachVPC2 []string `json:"attach_vpc2,omitempty"`
DetachVPC2 []string `json:"detach_vpc2,omitempty"`
EnableVPC2 *bool `json:"enable_vpc2,omitempty"`
}

// BareMetalServerBandwidth represents bandwidth information for a Bare Metal server
Expand Down Expand Up @@ -434,3 +444,47 @@ func (b *BareMetalServerServiceHandler) GetUpgrades(ctx context.Context, serverI

return upgrades.Upgrades, resp, nil
}

// ListVPC2Info currently attached to a Bare Metal server.
func (b *BareMetalServerServiceHandler) ListVPC2Info(ctx context.Context, serverID string) ([]VPC2Info, *http.Response, error) {
uri := fmt.Sprintf("%s/%s/vpc2", bmPath, serverID)
req, err := b.client.NewRequest(ctx, http.MethodGet, uri, nil)
if err != nil {
return nil, nil, err
}

vpcs := new(vpc2InfoBase)
resp, err := b.client.DoWithContext(ctx, req, vpcs)
if err != nil {
return nil, resp, err
}

return vpcs.VPCs, resp, nil
}

// AttachVPC2 to a Bare Metal server.
func (b *BareMetalServerServiceHandler) AttachVPC2(ctx context.Context, serverID string, vpc2Req *AttachVPC2Req) error {
uri := fmt.Sprintf("%s/%s/vpc2/attach", bmPath, serverID)

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

_, err = b.client.DoWithContext(ctx, req, nil)
return err
}

// DetachVPC2 from a Bare Metal server.
func (b *BareMetalServerServiceHandler) DetachVPC2(ctx context.Context, serverID, vpcID string) error {
uri := fmt.Sprintf("%s/%s/vpc2/detach", bmPath, serverID)
body := RequestBody{"vpc_id": vpcID}

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

_, err = b.client.DoWithContext(ctx, req, nil)
return err
}
53 changes: 53 additions & 0 deletions bare_metal_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -799,3 +799,56 @@ func TestBareMetalServerServiceHandler_CreateMarketplaceImage(t *testing.T) {
t.Errorf("BareMetalServer.Create returned %+v, expected %+v", bm, expected)
}
}

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

mux.HandleFunc("/v2/bare-metals/14b3e7d6-ffb5-4994-8502-57fcd9db3b33/vpc2", 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"}]}`
fmt.Fprint(writer, response)
})

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

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

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

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

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

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

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

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

if err := client.BareMetalServer.DetachVPC2(ctx, "14b3e7d6-ffb5-4994-8502-57fcd9db3b33", "14b3e7d6-ffb5-4994-8502-57fcd9db3b33"); err != nil {
t.Errorf("BareMetalServer.DetachVPC2 returned %+v", err)
}
}
2 changes: 2 additions & 0 deletions govultr.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type Client struct {
StartupScript StartupScriptService
User UserService
VPC VPCService
VPC2 VPC2Service

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

return client
}
Expand Down
77 changes: 77 additions & 0 deletions instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ type InstanceService interface {
AttachVPC(ctx context.Context, instanceID, vpcID string) error
DetachVPC(ctx context.Context, instanceID, vpcID string) error

ListVPC2Info(ctx context.Context, instanceID string, options *ListOptions) ([]VPC2Info, *Meta, *http.Response, error)
AttachVPC2(ctx context.Context, instanceID string, vpc2Req *AttachVPC2Req) error
DetachVPC2(ctx context.Context, instanceID, vpcID string) error

ISOStatus(ctx context.Context, instanceID string) (*Iso, *http.Response, error)
AttachISO(ctx context.Context, instanceID, isoID string) (*http.Response, error)
DetachISO(ctx context.Context, instanceID string) (*http.Response, error)
Expand Down Expand Up @@ -159,6 +163,23 @@ type VPCInfo struct {
IPAddress string `json:"ip_address"`
}

type vpc2InfoBase struct {
VPCs []VPC2Info `json:"vpcs"`
Meta *Meta `json:"meta"`
}

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

type AttachVPC2Req struct {
VPCID string `json:"vpc_id,omitempty"`
IPAddress *string `json:"ip_address,omitempty"`
}

type isoStatusBase struct {
IsoStatus *Iso `json:"iso_status"`
}
Expand Down Expand Up @@ -253,6 +274,8 @@ type InstanceCreateReq struct {
AttachPrivateNetwork []string `json:"attach_private_network,omitempty"`
EnableVPC *bool `json:"enable_vpc,omitempty"`
AttachVPC []string `json:"attach_vpc,omitempty"`
EnableVPC2 *bool `json:"enable_vpc2,omitempty"`
AttachVPC2 []string `json:"attach_vpc2,omitempty"`
SSHKeys []string `json:"sshkey_id,omitempty"`
Backups string `json:"backups,omitempty"`
DDOSProtection *bool `json:"ddos_protection,omitempty"`
Expand Down Expand Up @@ -281,6 +304,9 @@ type InstanceUpdateReq struct {
EnableVPC *bool `json:"enable_vpc,omitempty"`
AttachVPC []string `json:"attach_vpc,omitempty"`
DetachVPC []string `json:"detach_vpc,omitempty"`
EnableVPC2 *bool `json:"enable_vpc2,omitempty"`
AttachVPC2 []string `json:"attach_vpc2,omitempty"`
DetachVPC2 []string `json:"detach_vpc2,omitempty"`
Backups string `json:"backups,omitempty"`
DDOSProtection *bool `json:"ddos_protection"`
UserData string `json:"user_data,omitempty"`
Expand Down Expand Up @@ -624,6 +650,57 @@ func (i *InstanceServiceHandler) DetachVPC(ctx context.Context, instanceID, vpcI
return err
}

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

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

req.URL.RawQuery = newValues.Encode()

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

return vpcs.VPCs, vpcs.Meta, resp, nil
}

// AttachVPC2 to an instance
func (i *InstanceServiceHandler) AttachVPC2(ctx context.Context, instanceID string, vpc2Req *AttachVPC2Req) error {
uri := fmt.Sprintf("%s/%s/vpc2/attach", instancePath, instanceID)

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

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

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

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

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

// 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, *http.Response, error) {
Expand Down
69 changes: 69 additions & 0 deletions instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,49 @@ func TestServerServiceHandler_ListVPCInfo(t *testing.T) {
}
}

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

mux.HandleFunc("/v2/instances/14b3e7d6-ffb5-4994-8502-57fcd9db3b33/vpc2", 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.ListVPC2Info(ctx, "14b3e7d6-ffb5-4994-8502-57fcd9db3b33", options)
if err != nil {
t.Errorf("Instance.ListVPC2Info returned %+v, ", err)
}

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

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

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

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

func TestServerServiceHandler_GetUserData(t *testing.T) {
setup()
defer teardown()
Expand Down Expand Up @@ -989,6 +1032,32 @@ func TestServerServiceHandler_DetachVPC(t *testing.T) {
}
}

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

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

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

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

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

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

func TestServerServiceHandler_ISOAttach(t *testing.T) {
setup()
defer teardown()
Expand Down
2 changes: 1 addition & 1 deletion network.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const netPath = "/v2/private-networks"
// NetworkService is the interface to interact with the network endpoints on the Vultr API
// Link : https://www.vultr.com/api/#tag/private-Networks
// Deprecated: NetworkService should no longer be used. Instead, use VPCService.
type NetworkService interface {
type NetworkService interface { //nolint:dupl
// Deprecated: NetworkService Create should no longer be used. Instead, use VPCService Create.
Create(ctx context.Context, createReq *NetworkReq) (*Network, *http.Response, error)
// Deprecated: NetworkService Get should no longer be used. Instead, use VPCService Get.
Expand Down
2 changes: 1 addition & 1 deletion vpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const vpcPath = "/v2/vpcs"

// VPCService is the interface to interact with the VPC endpoints on the Vultr API
// Link : https://www.vultr.com/api/#tag/vpcs
type VPCService interface {
type VPCService interface { //nolint:dupl
Create(ctx context.Context, createReq *VPCReq) (*VPC, *http.Response, error)
Get(ctx context.Context, vpcID string) (*VPC, *http.Response, error)
Update(ctx context.Context, vpcID string, description string) error
Expand Down
Loading
Loading