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:
@@ -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
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user