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
12 changes: 12 additions & 0 deletions cmd/api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package api

import (
"github.com/spf13/cobra"
)

// ApiCmd represents the api command
var ApiCmd = &cobra.Command{
Use: "api",
Short: "Direct API access",
Long: "Make raw HTTP requests to the Thalassa Cloud API.",
}
89 changes: 89 additions & 0 deletions cmd/api/raw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package api

import (
"fmt"
"strings"

"github.com/spf13/cobra"

"github.com/thalassa-cloud/cli/internal/thalassaclient"
)

var (
rawMethod string
rawData string
rawShowHeaders bool
)

// rawCmd represents the raw API request command
var rawCmd = &cobra.Command{
Use: "raw PATH",
Short: "Make a raw HTTP request to the API",
Long: `Make a raw HTTP request to the Thalassa Cloud API.

Similar to 'kubectl get --raw', this bypasses the CLI resource layer and sends
the request directly to the API server. Uses the same authentication and
context (organisation, endpoint) as other tcloud commands.

PATH must start with a slash (e.g. /v1/me/organisations).
Requires client-go with RawRequest support.`,
Example: ` tcloud api raw /v1/me/organisations
tcloud api raw -X GET /v1/iaas/regions
tcloud api raw -X POST -d '{"name":"test"}' /v1/some/resource
tcloud api raw --show-headers /v1/me`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
path := args[0]
if !strings.HasPrefix(path, "/") {
return fmt.Errorf("path must start with /")
}

client, err := thalassaclient.GetThalassaClient()
if err != nil {
return fmt.Errorf("failed to create client: %w", err)
}

rq := client.GetClient()
method := strings.ToUpper(rawMethod)
if method == "" {
method = "GET"
}

var body []byte
if rawData != "" {
body = []byte(rawData)
}

resp, err := rq.RawRequest(cmd.Context(), method, path, body)
if err != nil {
return fmt.Errorf("request failed: %w", err)
}
defer resp.RawResponse.Body.Close()

if rawShowHeaders {
for k, v := range resp.RawResponse.Header {
fmt.Printf("%s: %s\n", k, strings.Join(v, ", "))
}
fmt.Println()
}

out := resp.Body()
fmt.Print(string(out))
if len(out) > 0 && out[len(out)-1] != '\n' {
fmt.Println()
}

if resp.StatusCode() < 200 || resp.StatusCode() >= 300 {
return fmt.Errorf("API returned status %d", resp.StatusCode())
}
return nil
},
}

func init() {
ApiCmd.AddCommand(rawCmd)

rawCmd.Flags().StringVarP(&rawMethod, "request", "X", "GET", "HTTP method (GET, POST, PUT, PATCH, DELETE)")
rawCmd.Flags().StringVarP(&rawData, "data", "d", "", "Request body (for POST, PUT, PATCH)")
rawCmd.Flags().BoolVar(&rawShowHeaders, "show-headers", false, "Print response headers")
}
2 changes: 2 additions & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/spf13/cobra"

"github.com/thalassa-cloud/cli/cmd/api"
"github.com/thalassa-cloud/cli/cmd/audit"
"github.com/thalassa-cloud/cli/cmd/context"
"github.com/thalassa-cloud/cli/cmd/dbaas"
Expand Down Expand Up @@ -54,6 +55,7 @@ func init() {
// Register completions
RootCmd.RegisterFlagCompletionFunc("organisation", completion.CompleteOrganisation)

RootCmd.AddCommand(api.ApiCmd)
RootCmd.AddCommand(context.ContextCmd)
RootCmd.AddCommand(version.VersionCmd)

Expand Down
2 changes: 1 addition & 1 deletion cmd/dbaas/backup-schedules/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ var backupScheduleListCmd = &cobra.Command{
// If cluster identity is provided as argument, list schedules for that cluster
if len(args) > 0 {
clusterIdentity := args[0]
schedules, err = client.DBaaS().ListDbBackupSchedules(cmd.Context(), clusterIdentity)
schedules, err = client.DBaaS().ListDbBackupSchedules(cmd.Context(), clusterIdentity, &dbaas.ListDbBackupSchedulesRequest{})
if err != nil {
return fmt.Errorf("failed to list backup schedules for cluster: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/olekukonko/tablewriter v0.0.5
github.com/spf13/cobra v1.10.2
github.com/stretchr/testify v1.11.1
github.com/thalassa-cloud/client-go v0.28.2
github.com/thalassa-cloud/client-go v0.29.3
gopkg.in/yaml.v3 v3.0.1
k8s.io/apimachinery v0.35.0
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/thalassa-cloud/client-go v0.28.2 h1:UHaR0BMYgVjXbdKkiRQlAVwIblC7vXaGXrbQwELtdN8=
github.com/thalassa-cloud/client-go v0.28.2/go.mod h1:CPY800FtJifCr1rJP4giXaXMoq7ierOyMl6KjkAvzm4=
github.com/thalassa-cloud/client-go v0.29.3 h1:nwPiZcxiK/QnEw5X9iwmFLb36IVnSw99UC5zlOZlZ1s=
github.com/thalassa-cloud/client-go v0.29.3/go.mod h1:CPY800FtJifCr1rJP4giXaXMoq7ierOyMl6KjkAvzm4=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
Expand Down
Loading