222 lines
5.5 KiB
Go
222 lines
5.5 KiB
Go
package cli
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"text/tabwriter"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func NewBucketCmd() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "bucket",
|
|
Short: "Manage storage buckets",
|
|
Long: "Create, list, and manage your storage buckets",
|
|
}
|
|
|
|
cmd.AddCommand(newBucketCreateCmd())
|
|
cmd.AddCommand(newBucketListCmd())
|
|
cmd.AddCommand(newBucketDeleteCmd())
|
|
cmd.AddCommand(newBucketInfoCmd())
|
|
|
|
return cmd
|
|
}
|
|
|
|
func newBucketCreateCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "create <bucket-name>",
|
|
Short: "Create a new bucket",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
config, err := LoadConfig()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load config: %w", err)
|
|
}
|
|
|
|
if !config.IsAuthenticated() {
|
|
return fmt.Errorf("not logged in. Use 'tcman account login' or 'tcman account create'")
|
|
}
|
|
|
|
bucketName := args[0]
|
|
client := NewClient(config.ServerURL, config.AccessToken)
|
|
ctx := context.Background()
|
|
|
|
bucket, err := client.CreateBucket(ctx, bucketName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create bucket: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Bucket '%s' created successfully!\n", bucket.Name)
|
|
fmt.Printf("ID: %d\n", bucket.ID)
|
|
fmt.Printf("Storage Used: %d bytes\n", bucket.StorageUsedBytes)
|
|
fmt.Printf("Created: %s\n", bucket.CreatedAt.Format("2006-01-02 15:04:05"))
|
|
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func newBucketListCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "list",
|
|
Short: "List all buckets",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
config, err := LoadConfig()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load config: %w", err)
|
|
}
|
|
|
|
if !config.IsAuthenticated() {
|
|
return fmt.Errorf("not logged in. Use 'tcman account login' or 'tcman account create'")
|
|
}
|
|
|
|
client := NewClient(config.ServerURL, config.AccessToken)
|
|
ctx := context.Background()
|
|
|
|
buckets, err := client.ListBuckets(ctx)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to list buckets: %w", err)
|
|
}
|
|
|
|
if len(buckets) == 0 {
|
|
fmt.Printf("No buckets found.\n")
|
|
return nil
|
|
}
|
|
|
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
|
fmt.Fprintln(w, "Name\tStorage Used\tCreated")
|
|
fmt.Fprintln(w, "----\t------------\t-------")
|
|
|
|
for _, bucket := range buckets {
|
|
storageStr := formatBytes(bucket.StorageUsedBytes)
|
|
fmt.Fprintf(w, "%s\t%s\t%s\n",
|
|
bucket.Name,
|
|
storageStr,
|
|
bucket.CreatedAt.Format("2006-01-02 15:04"),
|
|
)
|
|
}
|
|
w.Flush()
|
|
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func newBucketInfoCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "info <bucket-name>",
|
|
Short: "Show bucket information",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
config, err := LoadConfig()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load config: %w", err)
|
|
}
|
|
|
|
if !config.IsAuthenticated() {
|
|
return fmt.Errorf("not logged in. Use 'tcman account login' or 'tcman account create'")
|
|
}
|
|
|
|
bucketName := args[0]
|
|
client := NewClient(config.ServerURL, config.AccessToken)
|
|
ctx := context.Background()
|
|
|
|
bucket, err := client.GetBucket(ctx, bucketName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get bucket info: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Bucket Information:\n")
|
|
fmt.Printf(" Name: %s\n", bucket.Name)
|
|
fmt.Printf(" ID: %d\n", bucket.ID)
|
|
fmt.Printf(" Storage Used: %s\n", formatBytes(bucket.StorageUsedBytes))
|
|
fmt.Printf(" Created: %s\n", bucket.CreatedAt.Format("2006-01-02 15:04:05"))
|
|
|
|
objects, err := client.ListObjects(ctx, bucketName)
|
|
if err != nil {
|
|
fmt.Printf(" Objects: Error loading (%v)\n", err)
|
|
} else {
|
|
fmt.Printf(" Objects: %d\n", len(objects))
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func newBucketDeleteCmd() *cobra.Command {
|
|
var force bool
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "delete <bucket-name>",
|
|
Short: "Delete a bucket",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
config, err := LoadConfig()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load config: %w", err)
|
|
}
|
|
|
|
if !config.IsAuthenticated() {
|
|
return fmt.Errorf("not logged in. Use 'tcman account login' or 'tcman account create'")
|
|
}
|
|
|
|
bucketName := args[0]
|
|
client := NewClient(config.ServerURL, config.AccessToken)
|
|
ctx := context.Background()
|
|
|
|
if !force {
|
|
objects, err := client.ListObjects(ctx, bucketName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to check bucket contents: %w", err)
|
|
}
|
|
|
|
if len(objects) > 0 {
|
|
return fmt.Errorf("bucket '%s' contains %d objects. Use --force to delete anyway", bucketName, len(objects))
|
|
}
|
|
|
|
fmt.Printf("Are you sure you want to delete bucket '%s'? (y/N): ", bucketName)
|
|
var response string
|
|
fmt.Scanln(&response)
|
|
if response != "y" && response != "yes" && response != "Y" && response != "YES" {
|
|
fmt.Printf("Cancelled.\n")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
err = client.DeleteBucket(ctx, bucketName)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete bucket: %w", err)
|
|
}
|
|
|
|
fmt.Printf("Bucket '%s' deleted successfully.\n", bucketName)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
cmd.Flags().BoolVar(&force, "force", false, "Force deletion without confirmation")
|
|
return cmd
|
|
}
|
|
|
|
func formatBytes(bytes int64) string {
|
|
if bytes == 0 {
|
|
return "0 B"
|
|
}
|
|
|
|
const unit = 1024
|
|
if bytes < unit {
|
|
return fmt.Sprintf("%d B", bytes)
|
|
}
|
|
|
|
div, exp := int64(unit), 0
|
|
for n := bytes / unit; n >= unit; n /= unit {
|
|
div *= unit
|
|
exp++
|
|
}
|
|
|
|
units := []string{"KB", "MB", "GB", "TB"}
|
|
return fmt.Sprintf("%.1f %s", float64(bytes)/float64(div), units[exp])
|
|
}
|