feat: add list-hosts command to CLI

Adds a list-hosts command that mirrors the MCP list_hosts functionality,
allowing discovery of available deployment targets from the command line.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 07:30:57 +01:00
parent 95b795dcfd
commit 56365835c7

View File

@@ -16,7 +16,7 @@ import (
"github.com/urfave/cli/v3" "github.com/urfave/cli/v3"
) )
const version = "0.1.6" const version = "0.1.7"
func main() { func main() {
app := &cli.Command{ app := &cli.Command{
@@ -27,6 +27,7 @@ func main() {
listenerCommand(), listenerCommand(),
mcpCommand(), mcpCommand(),
deployCommand(), deployCommand(),
listHostsCommand(),
}, },
} }
@@ -270,3 +271,88 @@ func deployCommand() *cli.Command {
}, },
} }
} }
func listHostsCommand() *cli.Command {
return &cli.Command{
Name: "list-hosts",
Usage: "List available deployment targets",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "nats-url",
Usage: "NATS server URL",
Sources: cli.EnvVars("HOMELAB_DEPLOY_NATS_URL"),
Required: true,
},
&cli.StringFlag{
Name: "nkey-file",
Usage: "Path to NKey seed file for NATS authentication",
Sources: cli.EnvVars("HOMELAB_DEPLOY_NKEY_FILE"),
Required: true,
},
&cli.StringFlag{
Name: "tier",
Usage: "Filter by tier (test or prod)",
Sources: cli.EnvVars("HOMELAB_DEPLOY_TIER"),
},
&cli.StringFlag{
Name: "discover-subject",
Usage: "NATS subject for host discovery",
Sources: cli.EnvVars("HOMELAB_DEPLOY_DISCOVER_SUBJECT"),
Value: "deploy.discover",
},
&cli.IntFlag{
Name: "timeout",
Usage: "Timeout in seconds for discovery",
Sources: cli.EnvVars("HOMELAB_DEPLOY_DISCOVER_TIMEOUT"),
Value: 5,
},
},
Action: func(ctx context.Context, c *cli.Command) error {
tierFilter := c.String("tier")
if tierFilter != "" && tierFilter != "test" && tierFilter != "prod" {
return fmt.Errorf("tier must be 'test' or 'prod', got %q", tierFilter)
}
// Handle shutdown signals
ctx, cancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer cancel()
responses, err := deploycli.Discover(
ctx,
c.String("nats-url"),
c.String("nkey-file"),
c.String("discover-subject"),
time.Duration(c.Int("timeout"))*time.Second,
)
if err != nil {
return fmt.Errorf("discovery failed: %w", err)
}
if len(responses) == 0 {
fmt.Println("No hosts responded to discovery request")
return nil
}
fmt.Println("Available deployment targets:")
fmt.Println()
for _, resp := range responses {
if tierFilter != "" && resp.Tier != tierFilter {
continue
}
role := resp.Role
if role == "" {
role = "(none)"
}
fmt.Printf("- %s (tier=%s, role=%s)\n", resp.Hostname, resp.Tier, role)
for _, subj := range resp.DeploySubjects {
fmt.Printf(" %s\n", subj)
}
}
return nil
},
}
}