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
60 changes: 60 additions & 0 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io"
"net/http"
"sort"
"time"
)

Expand Down Expand Up @@ -105,6 +106,11 @@ func (c *Client) ListInstancesWithIPUpdateCtx(ctx context.Context) ([]Instance,
instances = append(instances, instance)
}

// Sort instances by ID for consistent ordering
sort.Slice(instances, func(i, j int) bool {
return instances[i].ID < instances[j].ID
})

return instances, nil
}

Expand Down Expand Up @@ -275,6 +281,11 @@ func (c *Client) ListInstances() ([]Instance, error) {
instances = append(instances, instance)
}

// Sort instances by ID for consistent ordering
sort.Slice(instances, func(i, j int) bool {
return instances[i].ID < instances[j].ID
})

return instances, nil
}

Expand Down Expand Up @@ -395,6 +406,55 @@ func (c *Client) DeleteInstance(instanceID string) (*DeleteInstanceResponse, err
}, nil
}

// ModifyInstance modifies an existing instance configuration
func (c *Client) ModifyInstance(instanceID string, req InstanceModifyRequest) (*InstanceModifyResponse, error) {
jsonData, err := json.Marshal(req)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}

url := fmt.Sprintf("%s/v1/instances/%s/modify", c.baseURL, instanceID)
httpReq, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}

c.setHeaders(httpReq)

resp, err := c.httpClient.Do(httpReq)
if err != nil {
return nil, fmt.Errorf("failed to make request: %w", err)
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response: %w", err)
}

switch resp.StatusCode {
case 401:
return nil, fmt.Errorf("authentication failed: invalid token")
case 404:
return nil, fmt.Errorf("instance not found")
case 400:
return nil, fmt.Errorf("invalid request: %s", string(body))
case 409:
return nil, fmt.Errorf("instance cannot be modified (may not be in RUNNING state)")
case 200, 201, 202:
// Success - continue to parse
default:
return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body))
}

var modifyResp InstanceModifyResponse
if err := json.Unmarshal(body, &modifyResp); err != nil {
return nil, fmt.Errorf("failed to parse response: %w", err)
}

return &modifyResp, nil
}

// AddSSHKey generates and adds SSH keypair to instance
func (c *Client) AddSSHKey(instanceID string) (*AddSSHKeyResponse, error) {
return c.AddSSHKeyCtx(context.Background(), instanceID)
Expand Down
17 changes: 17 additions & 0 deletions api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ type DeleteInstanceResponse struct {
Success bool `json:"success"`
}

type InstanceModifyRequest struct {
CpuCores *int `json:"cpu_cores,omitempty"`
GpuType *string `json:"gpu_type,omitempty"`
NumGpus *int `json:"num_gpus,omitempty"`
DiskSizeGb *int `json:"disk_size_gb,omitempty"`
Mode *string `json:"mode,omitempty"`
}

type InstanceModifyResponse struct {
Identifier string `json:"identifier"`
InstanceName string `json:"instance_name"`
Mode *string `json:"mode,omitempty"`
GpuType *string `json:"gpu_type,omitempty"`
NumGpus *int `json:"num_gpus,omitempty"`
Message string `json:"message,omitempty"`
}

type AddSSHKeyResponse struct {
UUID string `json:"uuid"`
Key string `json:"key"`
Expand Down
Loading
Loading