homelab: scaffold unified CLI (registry, manifest, claim/release) in infra/cli
Begin evolving the existing infra/cli into the agent-facing "homelab" CLI decided in the design/grilling session: one composable, JSON-capable surface for the operations agents run over and over (mined from 51k commands across 2,225 past sessions; the infra inner-loop is ~29% of them). v0.1 targets that loop — work/tf/claim — and ships here, in place, in infra/cli. This first slice: - command registry + dispatcher (longest-prefix verb matching) and a `manifest`/`manifest --json` progressive-discovery entrypoint; every verb declares a read|write tier so write-gating can be added later (everything is allowed for now). - claim/release verbs wrapping the existing presence script (not reimplemented), with label-taxonomy validation. - main() front-dispatches the homelab verb surface but falls through to the legacy webhook -use-case path verbatim, so the in-cluster infra-cli image is unaffected. - fix a pre-existing vet error (glog.Infof missing format directive) that blocked `go test`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
70e217db24
commit
ed6f22fd53
9 changed files with 426 additions and 3 deletions
56
cli/cmd_claim.go
Normal file
56
cli/cmd_claim.go
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func claimCommands() []Command {
|
||||
return []Command{
|
||||
{Path: []string{"claim"}, Tier: TierWrite,
|
||||
Summary: "claim a shared infra resource on the presence board",
|
||||
Run: runClaim},
|
||||
{Path: []string{"release"}, Tier: TierWrite,
|
||||
Summary: "release a presence claim",
|
||||
Run: runRelease},
|
||||
}
|
||||
}
|
||||
|
||||
// runClaim parses `<kind>:<name> --purpose "..."` in either order (the presence
|
||||
// script takes the label first, so we can't rely on Go's flag package which
|
||||
// stops at the first positional).
|
||||
func runClaim(args []string) error {
|
||||
var label, purpose string
|
||||
for i := 0; i < len(args); i++ {
|
||||
a := args[i]
|
||||
switch {
|
||||
case a == "--purpose" || a == "-purpose":
|
||||
if i+1 < len(args) {
|
||||
purpose = args[i+1]
|
||||
i++
|
||||
}
|
||||
case strings.HasPrefix(a, "--purpose="):
|
||||
purpose = strings.TrimPrefix(a, "--purpose=")
|
||||
case !strings.HasPrefix(a, "-") && label == "":
|
||||
label = a
|
||||
}
|
||||
}
|
||||
if label == "" {
|
||||
return fmt.Errorf(`usage: homelab claim <kind>:<name> --purpose "what + why"`)
|
||||
}
|
||||
return presenceClaim(label, purpose)
|
||||
}
|
||||
|
||||
func runRelease(args []string) error {
|
||||
var label string
|
||||
for _, a := range args {
|
||||
if !strings.HasPrefix(a, "-") {
|
||||
label = a
|
||||
break
|
||||
}
|
||||
}
|
||||
if label == "" {
|
||||
return fmt.Errorf("usage: homelab release <kind>:<name>")
|
||||
}
|
||||
return presenceRelease(label)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue