From 7e1b91c3725419cdd67aa66586a566af48259066 Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Tue, 21 Apr 2026 11:43:04 +0200 Subject: [PATCH] feat: ucind: implement cluster list command (#316) * ucind: implement cluster list I keep forgetting my ucind clusters, that add the missing list command: ``` % ./ucind cluster list NAME MACHINES miek1 machine-1 ``` Just the name would have been enough, but to actually make use of the tui table a machines list is handy as well. (There isn't much bubbletea in ucind, but I thought lets start now). Signed-off-by: Miek Gieben * Filter directly when listing Filter on ucind managed while listing clusters Signed-off-by: Miek Gieben --------- Signed-off-by: Miek Gieben --- cmd/ucind/cluster/ls.go | 40 +++++++++++++++++++++++++++++++++++++++ cmd/ucind/cluster/root.go | 2 +- internal/ucind/cluster.go | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 cmd/ucind/cluster/ls.go diff --git a/cmd/ucind/cluster/ls.go b/cmd/ucind/cluster/ls.go new file mode 100644 index 00000000..07746415 --- /dev/null +++ b/cmd/ucind/cluster/ls.go @@ -0,0 +1,40 @@ +package cluster + +import ( + "fmt" + "strings" + + "github.com/psviderski/uncloud/internal/cli/tui" + "github.com/psviderski/uncloud/internal/ucind" + "github.com/spf13/cobra" +) + +func NewListCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "ls", + Aliases: []string{"list"}, + Short: "List clusters.", + RunE: func(cmd *cobra.Command, args []string) error { + p := cmd.Context().Value("provisioner").(*ucind.Provisioner) + clusters, err := p.ListClusters(cmd.Context()) + if err != nil { + return fmt.Errorf("list clusters: %w", err) + } + t := tui.NewTable() + t.Headers("NAME", "MACHINES") + for _, cluster := range clusters { + machines := []string{} + for _, m := range cluster.Machines { + machines = append(machines, m.Name) + } + t.Row( + cluster.Name, + strings.Join(machines, tui.Faint.Render(", ")), + ) + } + fmt.Println(t) + return nil + }, + } + return cmd +} diff --git a/cmd/ucind/cluster/root.go b/cmd/ucind/cluster/root.go index 68dd208c..2bef7694 100644 --- a/cmd/ucind/cluster/root.go +++ b/cmd/ucind/cluster/root.go @@ -13,7 +13,7 @@ func NewRootCommand() *cobra.Command { } cmd.AddCommand( NewCreateCommand(), - // NewListCommand(), + NewListCommand(), NewRemoveCommand(), ) return cmd diff --git a/internal/ucind/cluster.go b/internal/ucind/cluster.go index 8e1cbd15..c4b9d224 100644 --- a/internal/ucind/cluster.go +++ b/internal/ucind/cluster.go @@ -322,6 +322,26 @@ func (p *Provisioner) WaitClusterReady(ctx context.Context, c Cluster, timeout t return nil } +func (p *Provisioner) ListClusters(ctx context.Context) ([]Cluster, error) { + nets, err := p.dockerCli.NetworkList(ctx, network.ListOptions{ + Filters: filters.NewArgs( + filters.Arg("label", ManagedLabel), + ), + }) + if err != nil { + return nil, err + } + + clusters := []Cluster{} + for _, net := range nets { + cluster, err := p.InspectCluster(ctx, net.Name) + if err == nil { + clusters = append(clusters, cluster) + } + } + return clusters, nil +} + func (p *Provisioner) RemoveCluster(ctx context.Context, name string) error { if _, err := p.InspectCluster(ctx, name); err != nil { if errors.Is(err, ErrNotFound) {