Skip to content
Open
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
8 changes: 8 additions & 0 deletions cloudscale.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type Client struct {
VolumeSnapshots VolumeSnapshotService
Networks NetworkService
Subnets SubnetService
Routers RouterService
FloatingIPs FloatingIPsService
ServerGroups ServerGroupService
ObjectsUsers ObjectsUsersService
Expand Down Expand Up @@ -86,6 +87,13 @@ func NewClient(httpClient *http.Client) *Client {
client: c,
path: subnetBasePath,
}
c.Routers = RouterServiceOperations{
GenericServiceOperations: GenericServiceOperations[Router, RouterCreateRequest, RouterUpdateRequest]{
client: c,
path: routerBasePath,
},
client: c,
}
c.FloatingIPs = GenericServiceOperations[FloatingIP, FloatingIPCreateRequest, FloatingIPUpdateRequest]{
client: c,
path: floatingIPsBasePath,
Expand Down
110 changes: 110 additions & 0 deletions router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package cloudscale

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

const routerBasePath = "v1/routers"

type Router struct {
ZonalResource
TaggedResource
HREF string `json:"href"`
UUID string `json:"uuid"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
Status string `json:"status"`
InternetGateway bool `json:"internet_gateway"`
InternetGatewayAddresses []IPAddress `json:"internet_gateway_addresses,omitempty"`
Interfaces []RouterInterface `json:"interfaces,omitempty"`
}

type IPAddress struct {
Address string `json:"address"`
Subnet SubnetStub `json:"subnet"`
Version int `json:"version"`
ReversePTR *string `json:"reverse_ptr"`
}
type RouterInterface struct {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there will be a interface API at some point in the not so far future, is going for RouterInterface the right direction? I assumed we would use a generic Interface Type.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially wanted to use interface but we have already an interface type (and, accordingly, an Address type):

type Interface struct {
Type string `json:"type,omitempty"`
Network NetworkStub `json:"network,omitempty"`
Addresses []Address `json:"addresses,omitempty"`
}
type Address struct {
Version int `json:"version"`
Address string `json:"address"`
PrefixLength int `json:"prefix_length"`
Gateway string `json:"gateway"`
ReversePtr string `json:"reverse_ptr"`
Subnet SubnetStub `json:"subnet"`
}

The question I guess is, what do we do. We can e.g. rename the existing Interface to ServerInterface or LegacyInterface because we plan to unify them, and we'll need a new major version anyway due to #91, or we find another name.
Your opinon?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, keep RouterInterface as submitted. On the server, rename the Interface to ServerInterface. This will be a breaking change, but it keeps the naming consistent.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

UUID string `json:"uuid"`
Network NetworkStub `json:"network"`
Addresses []IPAddress `json:"addresses"`
Type string `json:"type"`
MACAddress string `json:"mac_address"`
}

type RouterCreateRequest struct {
ZonalResourceRequest
TaggedResourceRequest
Name string `json:"name"`
InternetGateway bool `json:"internet_gateway"`
}

// RouterUpdateRequest is not implemented yet because the API is not implemented yet
type RouterUpdateRequest struct{}

type RouterService interface {
GenericCreateService[Router, RouterCreateRequest]
GenericGetService[Router]
GenericListService[Router]
// GenericUpdateService[Router, RouterUpdateRequest]
GenericDeleteService[Router]
GenericWaitForService[Router]
// CreateInterface creates a new interface attached to this router
CreateInterface(ctx context.Context, routerUUID string, createReq CreateInterfaceRequest) (*RouterInterface, error)
// DeleteInterface removes an interface attached to this router
DeleteInterface(ctx context.Context, routerUUID, interfaceUUID string) error
}

type CreateInterfaceRequest struct {
Network string `json:"network"`
Addresses []CreateAddressRequest `json:"addresses"`
}
type CreateAddressRequest struct {
Subnet string `json:"subnet"`
Address string `json:"address"`
}

type RouterServiceOperations struct {
GenericServiceOperations[Router, RouterCreateRequest, RouterUpdateRequest]
client *Client
}

func (r RouterServiceOperations) CreateInterface(ctx context.Context, routerUUID string, createReq CreateInterfaceRequest) (*RouterInterface, error) {
path := fmt.Sprintf("%s/%s/interfaces", routerBasePath, routerUUID)
ctx = WithOperationPath(ctx, routerBasePath+"/:id/interfaces")
req, err := r.client.NewRequest(ctx, http.MethodPost, path, createReq)
if err != nil {
return nil, err
}
res := &RouterInterface{}
if err := r.client.Do(ctx, req, res); err != nil {
return nil, err
}
return res, nil
}

func (r RouterServiceOperations) DeleteInterface(ctx context.Context, routerUUID, interfaceUUID string) error {
path := fmt.Sprintf("%s/%s/interfaces/%s", routerBasePath, routerUUID, interfaceUUID)
ctx = WithOperationPath(ctx, routerBasePath+"/:id/interfaces/:interface_id")

req, err := r.client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return err
}
return r.client.Do(ctx, req, nil)
}

const (
RouterActive = "active"
)

var RouterIsActive = func(router *Router) (bool, error) {
if router.Status == RouterActive {
return true, nil
}
return false, fmt.Errorf("waiting for status: %s, current status: %s", RouterActive, router.Status)
}
Loading
Loading