Skip to content

Commit

Permalink
added reserved ipv6 actions
Browse files Browse the repository at this point in the history
  • Loading branch information
imaskm committed Nov 22, 2024
1 parent 0039e24 commit 08e9fbc
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 38 deletions.
78 changes: 40 additions & 38 deletions godo.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,44 +54,45 @@ type Client struct {
ratemtx sync.Mutex

// Services used for communicating with the API
Account AccountService
Actions ActionsService
Apps AppsService
Balance BalanceService
BillingHistory BillingHistoryService
CDNs CDNService
Certificates CertificatesService
Databases DatabasesService
Domains DomainsService
Droplets DropletsService
DropletActions DropletActionsService
DropletAutoscale DropletAutoscaleService
Firewalls FirewallsService
FloatingIPs FloatingIPsService
FloatingIPActions FloatingIPActionsService
Functions FunctionsService
Images ImagesService
ImageActions ImageActionsService
Invoices InvoicesService
Keys KeysService
Kubernetes KubernetesService
LoadBalancers LoadBalancersService
Monitoring MonitoringService
OneClick OneClickService
Projects ProjectsService
Regions RegionsService
Registry RegistryService
Registries RegistriesService
ReservedIPs ReservedIPsService
ReservedIPV6s ReservedIPV6sService
ReservedIPActions ReservedIPActionsService
Sizes SizesService
Snapshots SnapshotsService
Storage StorageService
StorageActions StorageActionsService
Tags TagsService
UptimeChecks UptimeChecksService
VPCs VPCsService
Account AccountService
Actions ActionsService
Apps AppsService
Balance BalanceService
BillingHistory BillingHistoryService
CDNs CDNService
Certificates CertificatesService
Databases DatabasesService
Domains DomainsService
Droplets DropletsService
DropletActions DropletActionsService
DropletAutoscale DropletAutoscaleService
Firewalls FirewallsService
FloatingIPs FloatingIPsService
FloatingIPActions FloatingIPActionsService
Functions FunctionsService
Images ImagesService
ImageActions ImageActionsService
Invoices InvoicesService
Keys KeysService
Kubernetes KubernetesService
LoadBalancers LoadBalancersService
Monitoring MonitoringService
OneClick OneClickService
Projects ProjectsService
Regions RegionsService
Registry RegistryService
Registries RegistriesService
ReservedIPs ReservedIPsService
ReservedIPV6s ReservedIPV6sService
ReservedIPActions ReservedIPActionsService
ReservedIPV6Actions ReservedIPV6ActionsService
Sizes SizesService
Snapshots SnapshotsService
Storage StorageService
StorageActions StorageActionsService
Tags TagsService
UptimeChecks UptimeChecksService
VPCs VPCsService

// Optional function called after every successful request made to the DO APIs
onRequestCompleted RequestCompletionCallback
Expand Down Expand Up @@ -298,6 +299,7 @@ func NewClient(httpClient *http.Client) *Client {
c.ReservedIPs = &ReservedIPsServiceOp{client: c}
c.ReservedIPV6s = &ReservedIPV6sServiceOp{client: c}
c.ReservedIPActions = &ReservedIPActionsServiceOp{client: c}
c.ReservedIPV6Actions = &ReservedIPV6ActionsServiceOp{client: c}
c.Sizes = &SizesServiceOp{client: c}
c.Snapshots = &SnapshotsServiceOp{client: c}
c.Storage = &StorageServiceOp{client: c}
Expand Down
57 changes: 57 additions & 0 deletions reserved_ipv6_actions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package godo

import (
"context"
"fmt"
"net/http"
)

// ReservedIPActionsService is an interface for interfacing with the
// reserved IPs actions endpoints of the Digital Ocean API.
// See: https://docs.digitalocean.com/reference/api/api-reference/#tag/Reserved-IP-Actions
type ReservedIPV6ActionsService interface {
Assign(ctx context.Context, ip string, dropletID int) (*Action, *Response, error)
Unassign(ctx context.Context, ip string) (*Action, *Response, error)
}

// ReservedIPActionsServiceOp handles communication with the reserved IPs
// action related methods of the DigitalOcean API.
type ReservedIPV6ActionsServiceOp struct {
client *Client
}

// Assign a reserved IP to a droplet.
func (s *ReservedIPV6ActionsServiceOp) Assign(ctx context.Context, ip string, dropletID int) (*Action, *Response, error) {
request := &ActionRequest{
"type": "assign",
"droplet_id": dropletID,
}
return s.doV6Action(ctx, ip, request)
}

// Unassign a rerserved IP from the droplet it is currently assigned to.
func (s *ReservedIPV6ActionsServiceOp) Unassign(ctx context.Context, ip string) (*Action, *Response, error) {
request := &ActionRequest{"type": "unassign"}
return s.doV6Action(ctx, ip, request)
}

func (s *ReservedIPV6ActionsServiceOp) doV6Action(ctx context.Context, ip string, request *ActionRequest) (*Action, *Response, error) {
path := reservedIPV6ActionPath(ip)

req, err := s.client.NewRequest(ctx, http.MethodPost, path, request)
if err != nil {
return nil, nil, err
}

root := new(actionRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}

return root.Event, resp, err
}

func reservedIPV6ActionPath(ip string) string {
return fmt.Sprintf("%s/%s/actions", reservedIPV6sBasePath, ip)
}
79 changes: 79 additions & 0 deletions reserved_ipv6_actions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package godo

import (
"encoding/json"
"fmt"
"net/http"
"reflect"
"testing"
)

func TestReservedIPV6sActions_Assign(t *testing.T) {
setup()
defer teardown()
dropletID := 12345
assignRequest := &ActionRequest{
"droplet_id": float64(dropletID),
"type": "assign",
}

mux.HandleFunc("/v2/reserved_ipv6/2604:a880:800:14::42c3:d000/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}

testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, assignRequest) {
t.Errorf("Request body = %#v, expected %#v", v, assignRequest)
}

fmt.Fprintf(w, `{"action":{"status":"in-progress","id":1,"type":"assign_ip","resource_type":"reserved_ipv6"}}`)

})

assign, _, err := client.ReservedIPV6Actions.Assign(ctx, "2604:a880:800:14::42c3:d000", 12345)
if err != nil {
t.Errorf("ReservedIPV6sActions.Assign returned error: %v", err)
}

expected := &Action{Status: "in-progress", ID: 1, Type: "assign_ip", ResourceType: "reserved_ipv6"}
if !reflect.DeepEqual(assign, expected) {
t.Errorf("ReservedIPV6sActions.Assign returned %+v, expected %+v", assign, expected)
}
}

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

unassignRequest := &ActionRequest{
"type": "unassign",
}

mux.HandleFunc("/v2/reserved_ipv6/2604:a880:800:14::42c3:d000/actions", func(w http.ResponseWriter, r *http.Request) {
v := new(ActionRequest)
err := json.NewDecoder(r.Body).Decode(v)
if err != nil {
t.Fatalf("decode json: %v", err)
}

testMethod(t, r, http.MethodPost)
if !reflect.DeepEqual(v, unassignRequest) {
t.Errorf("Request body = %+v, expected %+v", v, unassignRequest)
}

fmt.Fprintf(w, `{"action":{"status":"in-progress","id":1,"type":"unassign_ip","resource_type":"reserved_ipv6"}}`)
})

action, _, err := client.ReservedIPV6Actions.Unassign(ctx, "2604:a880:800:14::42c3:d000")
if err != nil {
t.Errorf("ReservedIPV6sActions.Unassign returned error: %v", err)
}

expected := &Action{Status: "in-progress", ID: 1, Type: "unassign_ip", ResourceType: "reserved_ipv6"}
if !reflect.DeepEqual(action, expected) {
t.Errorf("ReservedIPV6sActions.Unassign returned %+v, expected %+v", action, expected)
}
}

0 comments on commit 08e9fbc

Please sign in to comment.