From 2152b89551d7df528f02139df690a7442793d379 Mon Sep 17 00:00:00 2001 From: Anna Lushnikova Date: Thu, 9 Jan 2025 17:26:30 -0500 Subject: [PATCH 1/2] [kubernetes]: make kubernetes maintenance_policy day case insensitive (#767) --- kubernetes.go | 2 +- kubernetes_test.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kubernetes.go b/kubernetes.go index 9b3bcfa1..07842c72 100644 --- a/kubernetes.go +++ b/kubernetes.go @@ -315,7 +315,7 @@ var ( // KubernetesMaintenanceToDay returns the appropriate KubernetesMaintenancePolicyDay for the given string. func KubernetesMaintenanceToDay(day string) (KubernetesMaintenancePolicyDay, error) { - d, ok := toDay[day] + d, ok := toDay[strings.ToLower(day)] if !ok { return 0, fmt.Errorf("unknown day: %q", day) } diff --git a/kubernetes_test.go b/kubernetes_test.go index 32b8f4f9..c23ba437 100644 --- a/kubernetes_test.go +++ b/kubernetes_test.go @@ -351,7 +351,7 @@ func TestKubernetesClusters_Get(t *testing.T) { ], "maintenance_policy": { "start_time": "00:00", - "day": "monday" + "day": "Monday" }, "created_at": "2018-06-15T07:10:23Z", "updated_at": "2018-06-15T07:11:26Z" @@ -633,7 +633,7 @@ func TestKubernetesClusters_Create(t *testing.T) { ], "maintenance_policy": { "start_time": "00:00", - "day": "monday" + "day": "Monday" }, "control_plane_firewall": { "enabled": true, @@ -743,7 +743,7 @@ func TestKubernetesClusters_Create_AutoScalePool(t *testing.T) { ], "maintenance_policy": { "start_time": "00:00", - "day": "monday" + "day": "Monday" } } }` @@ -851,7 +851,7 @@ func TestKubernetesClusters_Update(t *testing.T) { ], "maintenance_policy": { "start_time": "00:00", - "day": "monday" + "day": "Monday" }, "control_plane_firewall": { "enabled": true, @@ -944,7 +944,7 @@ func TestKubernetesClusters_Update_FalseAutoUpgrade(t *testing.T) { ], "maintenance_policy": { "start_time": "00:00", - "day": "monday" + "day": "Monday" } } }` From 4307a29d3a264945834f68f861e39e9dab0076f0 Mon Sep 17 00:00:00 2001 From: guptado <141348137+guptado@users.noreply.github.com> Date: Fri, 10 Jan 2025 21:00:50 +0530 Subject: [PATCH 2/2] support partner interconnect attachment operations (#769) --- godo.go | 80 +++--- partner_interconnect_attachments.go | 278 +++++++++++++++++++ partner_interconnect_attachments_test.go | 339 +++++++++++++++++++++++ 3 files changed, 658 insertions(+), 39 deletions(-) create mode 100644 partner_interconnect_attachments.go create mode 100644 partner_interconnect_attachments_test.go diff --git a/godo.go b/godo.go index 2469c14a..2c078848 100644 --- a/godo.go +++ b/godo.go @@ -54,45 +54,46 @@ 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 - ReservedIPV6Actions ReservedIPV6ActionsService - 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 + PartnerInterconnectAttachments PartnerInterconnectAttachmentsService // Optional function called after every successful request made to the DO APIs onRequestCompleted RequestCompletionCallback @@ -307,6 +308,7 @@ func NewClient(httpClient *http.Client) *Client { c.Tags = &TagsServiceOp{client: c} c.UptimeChecks = &UptimeChecksServiceOp{client: c} c.VPCs = &VPCsServiceOp{client: c} + c.PartnerInterconnectAttachments = &PartnerInterconnectAttachmentsServiceOp{client: c} c.headers = make(map[string]string) diff --git a/partner_interconnect_attachments.go b/partner_interconnect_attachments.go new file mode 100644 index 00000000..87a0e9ed --- /dev/null +++ b/partner_interconnect_attachments.go @@ -0,0 +1,278 @@ +package godo + +import ( + "context" + "fmt" + "net/http" + "time" +) + +const partnerInterconnectAttachmentsBasePath = "/v2/partner_interconnect/attachments" + +// PartnerInterconnectAttachmentsService is an interface for managing Partner Interconnect Attachments with the +// DigitalOcean API. +// See: https://docs.digitalocean.com/reference/api/api-reference/#tag/PartnerInterconnectAttachments +type PartnerInterconnectAttachmentsService interface { + List(context.Context, *ListOptions) ([]*PartnerInterconnectAttachment, *Response, error) + Create(context.Context, *PartnerInterconnectAttachmentCreateRequest) (*PartnerInterconnectAttachment, *Response, error) + Get(context.Context, string) (*PartnerInterconnectAttachment, *Response, error) + Update(context.Context, string, *PartnerInterconnectAttachmentUpdateRequest) (*PartnerInterconnectAttachment, *Response, error) + Delete(context.Context, string) (*Response, error) + GetServiceKey(context.Context, string) (*ServiceKey, *Response, error) + SetRoutes(context.Context, string, *PartnerInterconnectAttachmentSetRoutesRequest) (*PartnerInterconnectAttachment, *Response, error) + ListRoutes(context.Context, string, *ListOptions) ([]*RemoteRoute, *Response, error) +} + +var _ PartnerInterconnectAttachmentsService = &PartnerInterconnectAttachmentsServiceOp{} + +// PartnerInterconnectAttachmentsServiceOp interfaces with the Partner Interconnect Attachment endpoints in the DigitalOcean API. +type PartnerInterconnectAttachmentsServiceOp struct { + client *Client +} + +// PartnerInterconnectAttachmentCreateRequest represents a request to create a Partner Interconnect Attachment. +type PartnerInterconnectAttachmentCreateRequest struct { + // Name is the name of the Partner Interconnect Attachment + Name string `json:"name,omitempty"` + // ConnectionBandwidthInMbps is the bandwidth of the connection in Mbps + ConnectionBandwidthInMbps int `json:"connection_bandwidth_in_mbps,omitempty"` + // Region is the region where the Partner Interconnect Attachment is created + Region string `json:"region,omitempty"` + // NaaSProvider is the name of the Network as a Service provider + NaaSProvider string `json:"naas_provider,omitempty"` + // VPCIDs is the IDs of the VPCs to which the Partner Interconnect Attachment is connected + VPCIDs []string `json:"vpc_ids,omitempty"` + // BGP is the BGP configuration of the Partner Interconnect Attachment + BGP BGP `json:"bgp,omitempty"` +} + +// PartnerInterconnectAttachmentUpdateRequest represents a request to update a Partner Interconnect Attachment. +type PartnerInterconnectAttachmentUpdateRequest struct { + // Name is the name of the Partner Interconnect Attachment + Name string `json:"name,omitempty"` + //VPCIDs is the IDs of the VPCs to which the Partner Interconnect Attachment is connected + VPCIDs []string `json:"vpc_ids,omitempty"` +} + +type PartnerInterconnectAttachmentSetRoutesRequest struct { + // Routes is the list of routes to be used for the Partner Interconnect Attachment + Routes []string `json:"routes,omitempty"` +} + +// BGP represents the BGP configuration of a Partner Interconnect Attachment. +type BGP struct { + // LocalASN is the local ASN + LocalASN int `json:"local_asn,omitempty"` + // LocalRouterIP is the local router IP + LocalRouterIP string `json:"local_router_ip,omitempty"` + // PeerASN is the peer ASN + PeerASN int `json:"peer_asn,omitempty"` + // PeerRouterIP is the peer router IP + PeerRouterIP string `json:"peer_router_ip,omitempty"` +} + +// ServiceKey represents the service key of a Partner Interconnect Attachment. +type ServiceKey struct { + ServiceKey string `json:"service_key,omitempty"` +} + +// RemoteRoute represents a route for a Partner Interconnect Attachment. +type RemoteRoute struct { + // ID is the generated ID of the Route + ID string `json:"id,omitempty"` + // Cidr is the CIDR of the route + Cidr string `json:"cidr,omitempty"` +} + +// PartnerInterconnectAttachment represents a DigitalOcean Partner Interconnect Attachment. +type PartnerInterconnectAttachment struct { + // ID is the generated ID of the Partner Interconnect Attachment + ID string `json:"id,omitempty"` + // Name is the name of the Partner Interconnect Attachment + Name string `json:"name,omitempty"` + // State is the state of the Partner Interconnect Attachment + State string `json:"state,omitempty"` + // ConnectionBandwidthInMbps is the bandwidth of the connection in Mbps + ConnectionBandwidthInMbps int `json:"connection_bandwidth_in_mbps,omitempty"` + // Region is the region where the Partner Interconnect Attachment is created + Region string `json:"region,omitempty"` + // NaaSProvider is the name of the Network as a Service provider + NaaSProvider string `json:"naas_provider,omitempty"` + // VPCIDs is the IDs of the VPCs to which the Partner Interconnect Attachment is connected + VPCIDs []string `json:"vpc_ids,omitempty"` + // BGP is the BGP configuration of the Partner Interconnect Attachment + BGP BGP `json:"bgp,omitempty"` + // CreatedAt is time when this Partner Interconnect Attachment was first created + CreatedAt time.Time `json:"created_at,omitempty"` +} + +type partnerInterconnectAttachmentRoot struct { + PartnerInterconnectAttachment *PartnerInterconnectAttachment `json:"partner_interconnect_attachment"` +} + +type partnerInterconnectAttachmentsRoot struct { + PartnerInterconnectAttachments []*PartnerInterconnectAttachment `json:"partner_interconnect_attachments"` + Links *Links `json:"links"` + Meta *Meta `json:"meta"` +} + +type serviceKeyRoot struct { + ServiceKey *ServiceKey `json:"service_key"` +} + +type remoteRoutesRoot struct { + RemoteRoutes []*RemoteRoute `json:"remote_routes"` + Links *Links `json:"links"` + Meta *Meta `json:"meta"` +} + +// List returns a list of all Partner Interconnect Attachments, with optional pagination. +func (s *PartnerInterconnectAttachmentsServiceOp) List(ctx context.Context, opt *ListOptions) ([]*PartnerInterconnectAttachment, *Response, error) { + path, err := addOptions(partnerInterconnectAttachmentsBasePath, opt) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(partnerInterconnectAttachmentsRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + if m := root.Meta; m != nil { + resp.Meta = m + } + return root.PartnerInterconnectAttachments, resp, nil +} + +// Create creates a new Partner Interconnect Attachment. +func (s *PartnerInterconnectAttachmentsServiceOp) Create(ctx context.Context, create *PartnerInterconnectAttachmentCreateRequest) (*PartnerInterconnectAttachment, *Response, error) { + path := partnerInterconnectAttachmentsBasePath + req, err := s.client.NewRequest(ctx, http.MethodPost, path, create) + if err != nil { + return nil, nil, err + } + + root := new(partnerInterconnectAttachmentRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.PartnerInterconnectAttachment, resp, nil +} + +// Get returns the details of a Partner Interconnect Attachment. +func (s *PartnerInterconnectAttachmentsServiceOp) Get(ctx context.Context, id string) (*PartnerInterconnectAttachment, *Response, error) { + path := fmt.Sprintf("%s/%s", partnerInterconnectAttachmentsBasePath, id) + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(partnerInterconnectAttachmentRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.PartnerInterconnectAttachment, resp, nil +} + +// Update updates a Partner Interconnect Attachment properties. +func (s *PartnerInterconnectAttachmentsServiceOp) Update(ctx context.Context, id string, update *PartnerInterconnectAttachmentUpdateRequest) (*PartnerInterconnectAttachment, *Response, error) { + path := fmt.Sprintf("%s/%s", partnerInterconnectAttachmentsBasePath, id) + req, err := s.client.NewRequest(ctx, http.MethodPatch, path, update) + if err != nil { + return nil, nil, err + } + + root := new(partnerInterconnectAttachmentRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.PartnerInterconnectAttachment, resp, nil +} + +// Delete deletes a Partner Interconnect Attachment. +func (s *PartnerInterconnectAttachmentsServiceOp) Delete(ctx context.Context, id string) (*Response, error) { + path := fmt.Sprintf("%s/%s", partnerInterconnectAttachmentsBasePath, id) + req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +func (s *PartnerInterconnectAttachmentsServiceOp) GetServiceKey(ctx context.Context, id string) (*ServiceKey, *Response, error) { + path := fmt.Sprintf("%s/%s/service_key", partnerInterconnectAttachmentsBasePath, id) + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(serviceKeyRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.ServiceKey, resp, nil +} + +// ListRoutes lists all routes for a Partner Interconnect Attachment. +func (s *PartnerInterconnectAttachmentsServiceOp) ListRoutes(ctx context.Context, id string, opt *ListOptions) ([]*RemoteRoute, *Response, error) { + path, err := addOptions(fmt.Sprintf("%s/%s/remote_routes", partnerInterconnectAttachmentsBasePath, id), opt) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(remoteRoutesRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + if l := root.Links; l != nil { + resp.Links = l + } + if m := root.Meta; m != nil { + resp.Meta = m + } + + return root.RemoteRoutes, resp, nil +} + +// SetRoutes updates specific properties of a Partner Interconnect Attachment. +func (s *PartnerInterconnectAttachmentsServiceOp) SetRoutes(ctx context.Context, id string, set *PartnerInterconnectAttachmentSetRoutesRequest) (*PartnerInterconnectAttachment, *Response, error) { + path := fmt.Sprintf("%s/%s/remote_routes", partnerInterconnectAttachmentsBasePath, id) + req, err := s.client.NewRequest(ctx, http.MethodPut, path, set) + if err != nil { + return nil, nil, err + } + + root := new(partnerInterconnectAttachmentRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.PartnerInterconnectAttachment, resp, nil +} diff --git a/partner_interconnect_attachments_test.go b/partner_interconnect_attachments_test.go new file mode 100644 index 00000000..2d74e3cd --- /dev/null +++ b/partner_interconnect_attachments_test.go @@ -0,0 +1,339 @@ +package godo + +import ( + "encoding/json" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var vInterconnectTestObj = &PartnerInterconnectAttachment{ + ID: "880b7f98-f062-404d-b33c-458d545696f6", + Name: "my-new-partner-interconnect", + State: "ACTIVE", + ConnectionBandwidthInMbps: 50, + Region: "NYC", + NaaSProvider: "MEGAPORT", + VPCIDs: []string{"f5a0c5e4-7537-47de-bb8d-46c766f89ffb"}, + BGP: BGP{ + LocalASN: 64532, + LocalRouterIP: "169.250.0.1", + PeerASN: 133937, + PeerRouterIP: "169.250.0.6", + }, + CreatedAt: time.Date(2024, 12, 26, 21, 48, 40, 995304079, time.UTC), +} + +var vInterconnectTestJSON = ` + { + "id":"880b7f98-f062-404d-b33c-458d545696f6", + "name":"my-new-partner-interconnect", + "state":"ACTIVE", + "connection_bandwidth_in_mbps":50, + "region":"NYC", + "naas_provider":"MEGAPORT", + "vpc_ids":["f5a0c5e4-7537-47de-bb8d-46c766f89ffb"], + "bgp":{ + "local_asn":64532, + "local_router_ip":"169.250.0.1", + "peer_asn":133937, + "peer_router_ip":"169.250.0.6" + }, + "created_at":"2024-12-26T21:48:40.995304079Z" + } +` + +func TestPartnerInterconnectAttachments_List(t *testing.T) { + setup() + defer teardown() + + svc := client.PartnerInterconnectAttachments + path := "/v2/partner_interconnect/attachments" + want := []*PartnerInterconnectAttachment{ + vInterconnectTestObj, + } + links := &Links{ + Pages: &Pages{ + Last: "http://localhost/v2/partner_interconnect/attachments?page=3&per_page=1", + Next: "http://localhost/v2/partner_interconnect/attachments?page=2&per_page=1", + }, + } + meta := &Meta{ + Total: 3, + } + jsonBlob := ` +{ + "partner_interconnect_attachments": [ +` + vInterconnectTestJSON + ` + ], + "links": { + "pages": { + "last": "http://localhost/v2/partner_interconnect/attachments?page=3&per_page=1", + "next": "http://localhost/v2/partner_interconnect/attachments?page=2&per_page=1" + } + }, + "meta": {"total": 3} +} +` + mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + w.Write([]byte(jsonBlob)) + }) + + got, resp, err := svc.List(ctx, nil) + require.NoError(t, err) + assert.Equal(t, want, got) + assert.Equal(t, resp.Links, links) + assert.Equal(t, resp.Meta, meta) +} + +func TestPartnerInterconnectAttachments_Create(t *testing.T) { + setup() + defer teardown() + + svc := client.PartnerInterconnectAttachments + path := "/v2/partner_interconnect/attachments" + want := vInterconnectTestObj + req := &PartnerInterconnectAttachmentCreateRequest{ + Name: "my-new-partner-interconnect", + ConnectionBandwidthInMbps: 50, + Region: "NYC", + NaaSProvider: "MEGAPORT", + VPCIDs: []string{"f5a0c5e4-7537-47de-bb8d-46c766f89ffb"}, + BGP: BGP{ + LocalASN: 64532, + LocalRouterIP: "169.250.0.1", + PeerASN: 133937, + PeerRouterIP: "169.250.0.6", + }, + } + jsonBlob := ` +{ + "partner_interconnect_attachment": +` + vInterconnectTestJSON + ` +} +` + + mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { + c := new(PartnerInterconnectAttachmentCreateRequest) + err := json.NewDecoder(r.Body).Decode(c) + if err != nil { + t.Fatal(err) + } + + testMethod(t, r, http.MethodPost) + require.Equal(t, c, req) + w.Write([]byte(jsonBlob)) + }) + + got, _, err := svc.Create(ctx, req) + require.NoError(t, err) + require.Equal(t, want, got) +} + +func TestPartnerInterconnectAttachments_Get(t *testing.T) { + setup() + defer teardown() + + svc := client.PartnerInterconnectAttachments + path := "/v2/partner_interconnect/attachments" + want := vInterconnectTestObj + id := "880b7f98-f062-404d-b33c-458d545696f6" + jsonBlob := ` +{ + "partner_interconnect_attachment": +` + vInterconnectTestJSON + ` +} +` + + mux.HandleFunc(path+"/"+id, func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + w.Write([]byte(jsonBlob)) + }) + + got, _, err := svc.Get(ctx, id) + require.NoError(t, err) + require.Equal(t, want, got) +} + +func TestPartnerInterconnectAttachments_Update(t *testing.T) { + setup() + defer teardown() + + svc := client.PartnerInterconnectAttachments + path := "/v2/partner_interconnect/attachments" + want := vInterconnectTestObj + id := "880b7f98-f062-404d-b33c-458d545696f6" + req := &PartnerInterconnectAttachmentUpdateRequest{ + Name: "my-renamed-partner-interconnect", + VPCIDs: []string{"g5a0c5e4-7537-47de-bb8d-46c766f89ffb"}, + } + jsonBlob := ` +{ + "partner_interconnect_attachment": +` + vInterconnectTestJSON + ` +} +` + + mux.HandleFunc(path+"/"+id, func(w http.ResponseWriter, r *http.Request) { + v := new(PartnerInterconnectAttachmentUpdateRequest) + err := json.NewDecoder(r.Body).Decode(v) + if err != nil { + t.Fatal(err) + } + + testMethod(t, r, http.MethodPatch) + require.Equal(t, v, req) + w.Write([]byte(jsonBlob)) + }) + + got, _, err := svc.Update(ctx, id, req) + require.NoError(t, err) + require.Equal(t, want, got) +} + +func TestPartnerInterconnectAttachment_Delete(t *testing.T) { + setup() + defer teardown() + + svc := client.PartnerInterconnectAttachments + path := "/v2/partner_interconnect/attachments" + id := "880b7f98-f062-404d-b33c-458d545696f6" + + mux.HandleFunc(path+"/"+id, func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodDelete) + }) + + _, err := svc.Delete(ctx, id) + require.NoError(t, err) +} + +func TestPartnerInterconnectAttachment_GetServiceKey(t *testing.T) { + setup() + defer teardown() + + svc := client.PartnerInterconnectAttachments + path := "/v2/partner_interconnect/attachments" + want := &ServiceKey{ + ServiceKey: "my-service-key", + } + id := "880b7f98-f062-404d-b33c-458d545696f6" + jsonBlob := ` +{ + "service_key": { + "service_key": "my-service-key" + } +} +` + + mux.HandleFunc(path+"/"+id+"/service_key", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + w.Write([]byte(jsonBlob)) + }) + + got, _, err := svc.GetServiceKey(ctx, id) + require.NoError(t, err) + require.Equal(t, want, got) +} + +func TestPartnerInterconnectAttachment_ListRoutes(t *testing.T) { + setup() + defer teardown() + + svc := client.PartnerInterconnectAttachments + path := "/v2/partner_interconnect/attachments" + want := []*RemoteRoute{ + { + ID: "a0eb6eb0-fa38-41a8-a5de-1a75524667fe", + Cidr: "169.250.0.0/29", + }, + } + links := &Links{ + Pages: &Pages{ + Last: "http://localhost/v2/partner_interconnect/attachments?page=2&per_page=1", + Next: "http://localhost/v2/partner_interconnect/attachments?page=2&per_page=1", + }, + } + meta := &Meta{ + Total: 1, + } + id := "880b7f98-f062-404d-b33c-458d545696f6" + jsonBlob := ` +{ + "remote_routes": [ + {"id": "a0eb6eb0-fa38-41a8-a5de-1a75524667fe", "cidr": "169.250.0.0/29"} + ], + "links": { + "pages": { + "last": "http://localhost/v2/partner_interconnect/attachments?page=2&per_page=1", + "next": "http://localhost/v2/partner_interconnect/attachments?page=2&per_page=1" + } + }, + "meta": {"total": 1} +} +` + + mux.HandleFunc(path+"/"+id+"/remote_routes", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + w.Write([]byte(jsonBlob)) + }) + + got, resp, err := svc.ListRoutes(ctx, id, nil) + require.NoError(t, err) + require.Equal(t, want, got) + assert.Equal(t, resp.Links, links) + assert.Equal(t, resp.Meta, meta) +} + +func TestPartnerInterconnectAttachment_Set(t *testing.T) { + tests := []struct { + desc string + id string + req *PartnerInterconnectAttachmentSetRoutesRequest + mockResponse string + expectedRequestBody string + expectedUpdatedInterconnect *PartnerInterconnectAttachment + }{ + { + desc: "set remote routes", + id: "880b7f98-f062-404d-b33c-458d545696f6", + req: &PartnerInterconnectAttachmentSetRoutesRequest{ + Routes: []string{"169.250.0.1/29", "169.250.0.6/29"}, + }, + mockResponse: ` +{ + "partner_interconnect_attachment": +` + vInterconnectTestJSON + ` +} + `, + expectedRequestBody: `{"routes":["169.250.0.1/29", "169.250.0.6/29"]}`, + expectedUpdatedInterconnect: vInterconnectTestObj, + }, + } + + for _, tt := range tests { + setup() + + mux.HandleFunc("/v2/partner_interconnect/attachments/"+tt.id+"/remote_routes", func(w http.ResponseWriter, r *http.Request) { + v := new(PartnerInterconnectAttachmentSetRoutesRequest) + err := json.NewDecoder(r.Body).Decode(v) + if err != nil { + t.Fatal(err) + } + + testMethod(t, r, http.MethodPut) + require.Equal(t, v, tt.req) + w.Write([]byte(tt.mockResponse)) + }) + + got, _, err := client.PartnerInterconnectAttachments.SetRoutes(ctx, tt.id, tt.req) + + teardown() + + require.NoError(t, err) + require.Equal(t, tt.expectedUpdatedInterconnect, got) + } +}