Skip to content
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
14 changes: 14 additions & 0 deletions tfs/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package tfs

import (
"github.com/thalassa-cloud/client-go/pkg/client"
)

type Client struct {
client.Client
}

func New(c client.Client, opts ...client.Option) (*Client, error) {
c.WithOptions(opts...)
return &Client{c}, nil
}
7 changes: 7 additions & 0 deletions tfs/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package tfs

import "time"

var (
DefaultPollIntervalForWaiting = 1 * time.Second
)
14 changes: 14 additions & 0 deletions tfs/metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package tfs

// Labels are key-value pairs that can be used to label resources.
// Keys and values must be RFC 1123 compliant.
// Label keys and values must be 1-63 characters long, and must conform to the following
// - contain at most 63 characters
// - contain only lowercase alphanumeric characters or '-'
// - start with an alphanumeric character
// - end with an alphanumeric character
type Labels map[string]string

// Annotations are key-value pairs that can be used to annotate resources.
// Keys must be RFC 1123 compliant, but the values may contain any ascii characters.
type Annotations map[string]string
167 changes: 167 additions & 0 deletions tfs/tfs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package tfs

import (
"context"
"errors"
"fmt"
"strings"
"time"

"github.com/thalassa-cloud/client-go/pkg/client"
)

const (
TfsEndpoint = "/v1/tfs"
)

// ListTfsInstances lists all TFS instances for a given organisation.
func (c *Client) ListTfsInstances(ctx context.Context, request *ListTfsInstancesRequest) ([]TfsInstance, error) {
tfsInstances := []TfsInstance{}
req := c.R().SetResult(&tfsInstances)
if request != nil {
for _, filter := range request.Filters {
for k, v := range filter.ToParams() {
req.SetQueryParam(k, v)
}
}
}

resp, err := c.Do(ctx, req, client.GET, TfsEndpoint)
if err != nil {
return nil, err
}

if err := c.Check(resp); err != nil {
return tfsInstances, err
}
return tfsInstances, nil
}

// GetTfsInstance retrieves a specific TFS instance by its identity.
func (c *Client) GetTfsInstance(ctx context.Context, identity string) (*TfsInstance, error) {
var tfsInstance *TfsInstance
req := c.R().SetResult(&tfsInstance)
resp, err := c.Do(ctx, req, client.GET, fmt.Sprintf("%s/%s", TfsEndpoint, identity))
if err != nil {
return nil, err
}
if err := c.Check(resp); err != nil {
return tfsInstance, err
}
return tfsInstance, nil
}

// CreateTfsInstance creates a new TFS instance.
func (c *Client) CreateTfsInstance(ctx context.Context, create CreateTfsInstanceRequest) (*TfsInstance, error) {
var tfsInstance *TfsInstance
req := c.R().
SetBody(create).SetResult(&tfsInstance)

resp, err := c.Do(ctx, req, client.POST, TfsEndpoint)
if err != nil {
return nil, err
}
if err := c.Check(resp); err != nil {
return tfsInstance, err
}
return tfsInstance, nil
}

// UpdateTfsInstance updates an existing TFS instance.
func (c *Client) UpdateTfsInstance(ctx context.Context, identity string, update UpdateTfsInstanceRequest) (*TfsInstance, error) {
var tfsInstance *TfsInstance
req := c.R().
SetBody(update).SetResult(&tfsInstance)

resp, err := c.Do(ctx, req, client.PUT, fmt.Sprintf("%s/%s", TfsEndpoint, identity))
if err != nil {
return nil, err
}
if err := c.Check(resp); err != nil {
return tfsInstance, err
}
return tfsInstance, nil
}

// DeleteTfsInstance deletes a specific TFS instance by its identity.
func (c *Client) DeleteTfsInstance(ctx context.Context, identity string) error {
req := c.R()

resp, err := c.Do(ctx, req, client.DELETE, fmt.Sprintf("%s/%s", TfsEndpoint, identity))
if err != nil {
return err
}
if err := c.Check(resp); err != nil {
return err
}
return nil
}

// WaitUntilTfsInstanceIsAvailable waits until a TFS instance is available.
// The user is expected to provide a timeout context.
func (c *Client) WaitUntilTfsInstanceIsAvailable(ctx context.Context, tfsIdentity string) error {
return c.WaitUntilTfsInstanceIsStatus(ctx, tfsIdentity, TfsStatusAvailable)
}

// WaitUntilTfsInstanceIsStatus waits until a TFS instance is in a specific status.
// The user is expected to provide a timeout context.
func (c *Client) WaitUntilTfsInstanceIsStatus(ctx context.Context, tfsIdentity string, status TfsStatus) error {
tfsInstance, err := c.GetTfsInstance(ctx, tfsIdentity)
if err != nil {
return err
}
if strings.EqualFold(string(tfsInstance.Status), string(status)) {
return nil
}
// wait until the TFS instance is in the desired status
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(DefaultPollIntervalForWaiting):
}

tfsInstance, err = c.GetTfsInstance(ctx, tfsIdentity)
if err != nil {
return err
}
if strings.EqualFold(string(tfsInstance.Status), string(status)) {
return nil
}
}
}

// WaitUntilTfsInstanceIsDeleted waits until a TFS instance is deleted.
// The user is expected to provide a timeout context.
func (c *Client) WaitUntilTfsInstanceIsDeleted(ctx context.Context, tfsIdentity string) error {
tfsInstance, err := c.GetTfsInstance(ctx, tfsIdentity)
if err != nil {
if errors.Is(err, client.ErrNotFound) {
return nil
}
return err
}
if strings.EqualFold(string(tfsInstance.Status), string(TfsStatusDeleted)) {
return nil
}
if !strings.EqualFold(string(tfsInstance.Status), string(TfsStatusDeleting)) {
return fmt.Errorf("TFS instance %s is not being deleted (status: %s)", tfsIdentity, tfsInstance.Status)
}
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(DefaultPollIntervalForWaiting):
tfsInstance, err := c.GetTfsInstance(ctx, tfsIdentity)
if err != nil {
if errors.Is(err, client.ErrNotFound) {
return nil
}
return err
}
if strings.EqualFold(string(tfsInstance.Status), string(TfsStatusDeleted)) {
return nil
}
}
}
}
123 changes: 123 additions & 0 deletions tfs/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package tfs

import (
"time"

"github.com/thalassa-cloud/client-go/filters"
"github.com/thalassa-cloud/client-go/iaas"
"github.com/thalassa-cloud/client-go/pkg/base"
)

// Tfs represents a Thalassa Filesystem Service (TFS) instance
// TFS provides a high-availability, multi-availability zone Network File System (NFS) service
// for shared storage across your infrastructure. TFS supports NFSv4 and NFSv4.1 protocols.
type TfsInstance struct {
Identity string `json:"identity"`
Name string `json:"name"`
Slug string `json:"slug"`
Description *string `json:"description,omitempty"`
Labels Labels `json:"labels,omitempty"`
Annotations Annotations `json:"annotations,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
DeletedAt *time.Time `json:"deletedAt,omitempty"`
ObjectVersion int `json:"objectVersion"`

Region *iaas.Region `json:"region,omitempty"`

Organisation *base.Organisation `json:"organisation,omitempty"`

Vpc *iaas.Vpc `json:"vpc,omitempty"`

// SubnetId is the subnet where the TFS instance is deployed
Subnet *iaas.Subnet `json:"subnet,omitempty"`

// Endpoints is a list of endpoints that are associated with the TFS instance
Endpoints []iaas.Endpoint `json:"endpoints,omitempty"`

// SecurityGroups is a list of security groups attached to the TFS instance
SecurityGroups []iaas.SecurityGroup `json:"securityGroups,omitempty"`

// SizeGB is the size of the TFS instance in GB
SizeGB int `json:"size"`

// DeleteProtection is a flag that prevents the TFS instance from being deleted
DeleteProtection bool `json:"deleteProtection"`

// Status is the status of the TFS instance
Status TfsStatus `json:"status"`

// LastStatusChangedAt is the time the status of the TFS instance was last changed
LastStatusChangedAt *time.Time `json:"lastStatusChangedAt,omitempty"`
}

type TfsStatus string

const (
// TfsStatusCreating is the status of the TFS instance that is being created
TfsStatusCreating TfsStatus = "Creating"
TfsStatusProvisioning TfsStatus = "Provisioning"
TfsStatusAvailable TfsStatus = "Available"
TfsStatusDeleting TfsStatus = "Deleting"
TfsStatusDeleted TfsStatus = "Deleted"
TfsStatusError TfsStatus = "Error"
TfsStatusUnknown TfsStatus = "Unknown"
)

type CreateTfsInstanceRequest struct {
// Name is the name of the TFS instance
Name string `json:"name"`

// Description is a human-readable description of the object
Description string `json:"description,omitempty"`
// Annotations is a map of key-value pairs used for storing additional information
Annotations Annotations `json:"annotations,omitempty"`

// Labels is a map of key-value pairs used for filtering and grouping objects
Labels Labels `json:"labels,omitempty"`

// CloudRegionIdentity is the identity of the cloud region to create the TFS instance in
CloudRegionIdentity string `json:"cloudRegionIdentity"`

// VpcIdentity is the identity of the VPC to create the TFS instance in
VpcIdentity string `json:"vpcIdentity"`

// SubnetIdentity is the identity of the subnet to create the TFS instance in
SubnetIdentity string `json:"subnetIdentity"`

// SizeGB is the size of the TFS instance in GB
SizeGB int `json:"size"`

// SecurityGroupAttachments is a list of security group identities to attach to the TFS instance
SecurityGroupAttachments []string `json:"securityGroupAttachments,omitempty"`

// DeleteProtection is a flag that prevents the TFS instance from being deleted
DeleteProtection bool `json:"deleteProtection"`
}

type UpdateTfsInstanceRequest struct {
// Name is the name of the TFS instance
Name string `json:"name"`

// Description is a human-readable description of the object
Description string `json:"description,omitempty"`
// Annotations is a map of key-value pairs used for storing additional information
Annotations Annotations `json:"annotations,omitempty"`

// Labels is a map of key-value pairs used for filtering and grouping objects
Labels Labels `json:"labels,omitempty"`

// SizeGB is the size of the TFS instance in GB
SizeGB int `json:"size"`

// SecurityGroupAttachments is a list of security group identities to attach to the TFS instance
SecurityGroupAttachments []string `json:"securityGroupAttachments,omitempty"`

// DeleteProtection is a flag that prevents the TFS instance from being deleted
DeleteProtection bool `json:"deleteProtection"`
}

type ListTfsInstancesRequest struct {
// Filters is a list of filters to apply to the list of TFS instances
Filters []filters.Filter
}
17 changes: 13 additions & 4 deletions thalassa/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,19 @@ import (
"github.com/thalassa-cloud/client-go/objectstorage"
"github.com/thalassa-cloud/client-go/pkg/client"
"github.com/thalassa-cloud/client-go/quotas"
"github.com/thalassa-cloud/client-go/tfs"
)

type Client interface {
Audit() *audit.Client
DbaaSAlphaV1() *dbaasalphav1.Client
IaaS() *iaas.Client
IAM() *iam.Client
Kubernetes() *kubernetes.Client
Me() *me.Client
DbaaSAlphaV1() *dbaasalphav1.Client
IAM() *iam.Client
ObjectStorage() *objectstorage.Client
Quotas() *quotas.Client
Audit() *audit.Client

Tfs() *tfs.Client
// SetOrganisation sets the organisation for the client
SetOrganisation(organisation string)
}
Expand Down Expand Up @@ -111,3 +112,11 @@ func (c *thalassaCloudClient) Audit() *audit.Client {
}
return auditClient
}

func (c *thalassaCloudClient) Tfs() *tfs.Client {
tfsClient, err := tfs.New(c.client)
if err != nil {
panic(err)
}
return tfsClient
}