@@ -1,9 +1,321 @@
1 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ // scuttlectl is the CLI for observing and managing a scuttlebot instance.
2 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ //
3 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ // Usage:
4 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ //
5 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ // scuttlectl [--url URL] [--token TOKEN] [--json] <command> [args]
6 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ //
7 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ // Environment variables:
8 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ //
9 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ // SCUTTLEBOT_URL API base URL (default: http://localhost:8080)
10 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ // SCUTTLEBOT_TOKEN API bearer token
1 11 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
package main
2 12 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
3 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- import "fmt"
13 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ import (
14 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "encoding/json"
15 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "flag"
16 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "fmt"
17 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "os"
18 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "strings"
19 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "text/tabwriter"
20 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
21 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "github.com/conflicthq/scuttlebot/cmd/scuttlectl/internal/apiclient"
22 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ )
4 23 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
5 24 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
var version = "dev"
6 25 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
7 26 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
func main() {
8 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- fmt.Printf("scuttlectl %s\n", version)
27 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ // Global flags.
28 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ urlFlag := flag.String("url", envOr("SCUTTLEBOT_URL", "http://localhost:8080"), "scuttlebot API base URL")
29 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tokenFlag := flag.String("token", os.Getenv("SCUTTLEBOT_TOKEN"), "API bearer token")
30 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ jsonFlag := flag.Bool("json", false, "output raw JSON")
31 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ versionFlag := flag.Bool("version", false, "print version and exit")
32 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ flag.Usage = usage
33 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ flag.Parse()
34 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
35 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if *versionFlag {
36 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Println(version)
37 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
38 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
39 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
40 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ args := flag.Args()
41 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if len(args) == 0 {
42 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ usage()
43 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
44 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
45 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
46 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if *tokenFlag == "" {
47 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintln(os.Stderr, "error: API token required (set SCUTTLEBOT_TOKEN or use --token)")
48 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
49 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
50 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
51 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ api := apiclient.New(*urlFlag, *tokenFlag)
52 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
53 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ switch args[0] {
54 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case "status":
55 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cmdStatus(api, *jsonFlag)
56 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case "agents", "agent":
57 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if len(args) < 2 {
58 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(os.Stderr, "usage: scuttlectl %s <subcommand>\n", args[0])
59 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
60 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
61 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ switch args[1] {
62 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case "list":
63 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cmdAgentList(api, *jsonFlag)
64 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case "get":
65 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ requireArgs(args, 3, "scuttlectl agent get <nick>")
66 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cmdAgentGet(api, args[2], *jsonFlag)
67 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case "register":
68 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ requireArgs(args, 3, "scuttlectl agent register <nick> [--type worker] [--channels #a,#b]")
69 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cmdAgentRegister(api, args[2:], *jsonFlag)
70 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case "revoke":
71 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ requireArgs(args, 3, "scuttlectl agent revoke <nick>")
72 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cmdAgentRevoke(api, args[2])
73 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case "rotate":
74 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ requireArgs(args, 3, "scuttlectl agent rotate <nick>")
75 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ cmdAgentRotate(api, args[2], *jsonFlag)
76 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default:
77 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(os.Stderr, "unknown subcommand: %s\n", args[1])
78 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
79 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
80 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case "channels":
81 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if len(args) < 2 || args[1] == "list" {
82 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintln(os.Stderr, "channels list: not yet implemented (requires #12 discovery)")
83 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
84 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
85 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(os.Stderr, "unknown subcommand: channels %s\n", args[1])
86 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
87 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case "logs":
88 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintln(os.Stderr, "logs tail: not yet implemented (requires scribe HTTP endpoint)")
89 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
90 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default:
91 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(os.Stderr, "unknown command: %s\n", args[0])
92 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ usage()
93 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
94 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
95 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
96 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
97 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func cmdStatus(api *apiclient.Client, asJSON bool) {
98 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ raw, err := api.Status()
99 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ die(err)
100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if asJSON {
101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ printJSON(raw)
102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ var s struct {
106 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Status string `json:"status"`
107 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Uptime string `json:"uptime"`
108 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Agents int `json:"agents"`
109 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Started string `json:"started"`
110 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
111 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ must(json.Unmarshal(raw, &s))
112 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
113 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
114 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "status\t%s\n", s.Status)
115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "uptime\t%s\n", s.Uptime)
116 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "agents\t%d\n", s.Agents)
117 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "started\t%s\n", s.Started)
118 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tw.Flush()
119 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
120 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
121 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func cmdAgentList(api *apiclient.Client, asJSON bool) {
122 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ raw, err := api.ListAgents()
123 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ die(err)
124 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if asJSON {
125 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ printJSON(raw)
126 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
127 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
128 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
129 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ var body struct {
130 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Agents []struct {
131 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Nick string `json:"nick"`
132 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Type string `json:"type"`
133 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Channels []string `json:"channels"`
134 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Revoked bool `json:"revoked"`
135 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ } `json:"agents"`
136 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
137 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ must(json.Unmarshal(raw, &body))
138 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
139 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if len(body.Agents) == 0 {
140 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Println("no agents registered")
141 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
142 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
143 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
144 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
145 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintln(tw, "NICK\tTYPE\tCHANNELS\tSTATUS")
146 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for _, a := range body.Agents {
147 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ status := "active"
148 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if a.Revoked {
149 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ status = "revoked"
150 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
151 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", a.Nick, a.Type, strings.Join(a.Channels, ","), status)
152 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
153 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tw.Flush()
154 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
155 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
156 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func cmdAgentGet(api *apiclient.Client, nick string, asJSON bool) {
157 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ raw, err := api.GetAgent(nick)
158 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ die(err)
159 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if asJSON {
160 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ printJSON(raw)
161 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
162 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
163 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
164 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ var a struct {
165 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Nick string `json:"nick"`
166 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Type string `json:"type"`
167 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Channels []string `json:"channels"`
168 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Revoked bool `json:"revoked"`
169 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
170 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ must(json.Unmarshal(raw, &a))
171 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
172 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
173 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ status := "active"
174 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if a.Revoked {
175 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ status = "revoked"
176 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
177 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "nick\t%s\n", a.Nick)
178 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "type\t%s\n", a.Type)
179 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "channels\t%s\n", strings.Join(a.Channels, ", "))
180 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "status\t%s\n", status)
181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tw.Flush()
182 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func cmdAgentRegister(api *apiclient.Client, args []string, asJSON bool) {
185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ nick := args[0]
186 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ agentType := "worker"
187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ var channels []string
188 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
189 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ // Parse optional --type and --channels from remaining args.
190 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fs := flag.NewFlagSet("agent register", flag.ExitOnError)
191 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ typeFlag := fs.String("type", "worker", "agent type (worker, orchestrator, observer)")
192 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ channelsFlag := fs.String("channels", "", "comma-separated list of channels to join")
193 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ _ = fs.Parse(args[1:])
194 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ agentType = *typeFlag
195 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if *channelsFlag != "" {
196 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for _, ch := range strings.Split(*channelsFlag, ",") {
197 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if ch = strings.TrimSpace(ch); ch != "" {
198 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ channels = append(channels, ch)
199 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
200 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
201 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
202 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
203 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ raw, err := api.RegisterAgent(nick, agentType, channels)
204 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ die(err)
205 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if asJSON {
206 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ printJSON(raw)
207 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
208 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
209 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
210 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ var body struct {
211 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Credentials struct {
212 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Nick string `json:"nick"`
213 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Password string `json:"password"`
214 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Server string `json:"server"`
215 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ } `json:"credentials"`
216 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Payload struct {
217 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Token string `json:"token"`
218 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Signature string `json:"signature"`
219 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ } `json:"payload"`
220 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
221 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ must(json.Unmarshal(raw, &body))
222 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
223 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Printf("Agent registered: %s\n\n", nick)
224 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
225 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintln(tw, "CREDENTIAL\tVALUE")
226 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "nick\t%s\n", body.Credentials.Nick)
227 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "password\t%s\n", body.Credentials.Password)
228 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "server\t%s\n", body.Credentials.Server)
229 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tw.Flush()
230 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Println("\nStore these credentials — the password will not be shown again.")
231 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
232 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
233 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func cmdAgentRevoke(api *apiclient.Client, nick string) {
234 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ die(api.RevokeAgent(nick))
235 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Printf("Agent revoked: %s\n", nick)
236 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
237 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
238 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func cmdAgentRotate(api *apiclient.Client, nick string, asJSON bool) {
239 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ raw, err := api.RotateAgent(nick)
240 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ die(err)
241 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if asJSON {
242 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ printJSON(raw)
243 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return
244 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
245 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
246 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ var creds struct {
247 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Nick string `json:"nick"`
248 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Password string `json:"password"`
249 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Server string `json:"server"`
250 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
251 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ must(json.Unmarshal(raw, &creds))
252 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
253 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Printf("Credentials rotated for: %s\n\n", nick)
254 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
255 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintln(tw, "CREDENTIAL\tVALUE")
256 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "nick\t%s\n", creds.Nick)
257 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "password\t%s\n", creds.Password)
258 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(tw, "server\t%s\n", creds.Server)
259 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ tw.Flush()
260 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Println("\nStore this password — it will not be shown again.")
261 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
262 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
263 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func usage() {
264 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(os.Stderr, `scuttlectl %s — scuttlebot management CLI
265 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
266 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Usage:
267 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ scuttlectl [flags] <command> [subcommand] [args]
268 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
269 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Global flags:
270 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ --url API base URL (default: $SCUTTLEBOT_URL or http://localhost:8080)
271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ --token API bearer token (default: $SCUTTLEBOT_TOKEN)
272 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ --json output raw JSON
273 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ --version print version and exit
274 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
275 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Commands:
276 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ status daemon + ergo health
277 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ agents list list all registered agents
278 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ agent get <nick> get a single agent
279 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ agent register <nick> register a new agent, print credentials
280 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ [--type worker|orchestrator|observer]
281 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ [--channels #a,#b,#c]
282 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ agent revoke <nick> revoke agent credentials
283 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ agent rotate <nick> rotate agent password
284 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ channels list list provisioned channels (requires #12)
285 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ logs tail tail scribe log (coming soon)
286 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ `, version)
287 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
288 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
289 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func printJSON(raw json.RawMessage) {
290 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ var buf []byte
291 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ buf, _ = json.MarshalIndent(raw, "", " ")
292 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Println(string(buf))
293 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func requireArgs(args []string, n int, usage string) {
296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if len(args) < n {
297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintf(os.Stderr, "usage: %s\n", usage)
298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
299 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func die(err error) {
303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if err != nil {
304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintln(os.Stderr, "error:", err)
305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
306 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
307 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func must(err error) {
310 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if err != nil {
311 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fmt.Fprintln(os.Stderr, "internal error:", err)
312 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ os.Exit(1)
313 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
314 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
315 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
316 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ func envOr(key, def string) string {
317 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if v := os.Getenv(key); v != "" {
318 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return v
319 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
320 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return def
9 321 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
10 322 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
11 323 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
A DDED sdk/npm/scuttlectl/bin/scuttlectl.js
12 324 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
A DDED sdk/npm/scuttlectl/package.json