cli/cmd/prod/cmd_lb.go

114 lines
2.5 KiB
Go
Raw Permalink Normal View History

package prod
import (
"context"
"fmt"
"os"
"time"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-devops/infra"
"github.com/spf13/cobra"
)
var lbCmd = &cobra.Command{
Use: "lb",
Short: "Manage Hetzner load balancer",
Long: `View and manage the Hetzner Cloud managed load balancer.
Requires: HCLOUD_TOKEN`,
}
var lbStatusCmd = &cobra.Command{
Use: "status",
Short: "Show load balancer status and target health",
RunE: runLBStatus,
}
var lbCreateCmd = &cobra.Command{
Use: "create",
Short: "Create load balancer from infra.yaml",
RunE: runLBCreate,
}
func init() {
lbCmd.AddCommand(lbStatusCmd)
lbCmd.AddCommand(lbCreateCmd)
}
func getHCloudClient() (*infra.HCloudClient, error) {
token := os.Getenv("HCLOUD_TOKEN")
if token == "" {
return nil, fmt.Errorf("HCLOUD_TOKEN environment variable required")
}
return infra.NewHCloudClient(token), nil
}
func runLBStatus(cmd *cobra.Command, args []string) error {
hc, err := getHCloudClient()
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
lbs, err := hc.ListLoadBalancers(ctx)
if err != nil {
return fmt.Errorf("list load balancers: %w", err)
}
if len(lbs) == 0 {
cli.Print("No load balancers found\n")
return nil
}
for _, lb := range lbs {
cli.Print("%s %s\n", cli.BoldStyle.Render("▶"), cli.TitleStyle.Render(lb.Name))
cli.Print(" ID: %d\n", lb.ID)
cli.Print(" IP: %s\n", lb.PublicNet.IPv4.IP)
cli.Print(" Algorithm: %s\n", lb.Algorithm.Type)
cli.Print(" Location: %s\n", lb.Location.Name)
if len(lb.Services) > 0 {
cli.Print("\n Services:\n")
for _, s := range lb.Services {
cli.Print(" %s :%d -> :%d proxy_protocol=%v\n",
s.Protocol, s.ListenPort, s.DestinationPort, s.Proxyprotocol)
}
}
if len(lb.Targets) > 0 {
cli.Print("\n Targets:\n")
for _, t := range lb.Targets {
ip := ""
if t.IP != nil {
ip = t.IP.IP
}
for _, hs := range t.HealthStatus {
icon := cli.SuccessStyle.Render("●")
if hs.Status != "healthy" {
icon = cli.ErrorStyle.Render("○")
}
cli.Print(" %s %s :%d %s\n", icon, ip, hs.ListenPort, hs.Status)
}
}
}
fmt.Println()
}
return nil
}
func runLBCreate(cmd *cobra.Command, args []string) error {
cfg, _, err := loadConfig()
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
return stepLoadBalancer(ctx, cfg)
}