Skip to content

Commit 7d751fd

Browse files
CLI: Update hypeman SDK to 508a8c69feb30aa3e3ce115b4037b564ad9a3cda and add new commands/flags
Bump the CLI to the latest hypeman-go revision and expand command/flag coverage for newly exposed SDK methods, including snapshots, instance stats/update, memory reclaim, and tag/compression options. Made-with: Cursor
1 parent 2e77f11 commit 7d751fd

20 files changed

Lines changed: 1134 additions & 99 deletions

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
github.com/google/go-containerregistry v0.20.7
1111
github.com/gorilla/websocket v1.5.3
1212
github.com/itchyny/json2yaml v0.1.4
13-
github.com/kernel/hypeman-go v0.15.0
13+
github.com/kernel/hypeman-go v0.16.1-0.20260323172303-508a8c69feb3
1414
github.com/knadh/koanf/parsers/yaml v1.1.0
1515
github.com/knadh/koanf/providers/env v1.1.0
1616
github.com/knadh/koanf/providers/file v1.2.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnV
7676
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
7777
github.com/itchyny/json2yaml v0.1.4 h1:/pErVOXGG5iTyXHi/QKR4y3uzhLjGTEmmJIy97YT+k8=
7878
github.com/itchyny/json2yaml v0.1.4/go.mod h1:6iudhBZdarpjLFRNj+clWLAkGft+9uCcjAZYXUH9eGI=
79-
github.com/kernel/hypeman-go v0.15.0 h1:igcd8tArES1FMbuzEGjQ9HqPF3Zwi6yAvHoE4dkKx4Y=
80-
github.com/kernel/hypeman-go v0.15.0/go.mod h1:guRrhyP9QW/ebUS1UcZ0uZLLJeGAAhDNzSi68U4M9hI=
79+
github.com/kernel/hypeman-go v0.16.1-0.20260323172303-508a8c69feb3 h1:g6qT9G/Qrxqqdl9gjqTnhDAHlePxV68OyQjlqXA6WX4=
80+
github.com/kernel/hypeman-go v0.16.1-0.20260323172303-508a8c69feb3/go.mod h1:guRrhyP9QW/ebUS1UcZ0uZLLJeGAAhDNzSi68U4M9hI=
8181
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
8282
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
8383
github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo=

pkg/cmd/build.go

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ Examples:
8585
Name: "memory",
8686
Usage: "Memory limit for builder VM in MB (default 2048)",
8787
},
88+
&cli.StringSliceFlag{
89+
Name: "tag",
90+
Usage: "Set build tag key-value pair (KEY=VALUE, can be repeated)",
91+
},
8892
},
8993
Commands: []*cli.Command{
9094
&buildListCmd,
@@ -186,6 +190,17 @@ func handleBuild(ctx context.Context, cmd *cli.Command) error {
186190
if cmd.IsSet("memory") {
187191
params.MemoryMB = hypeman.Opt(int64(cmd.Int("memory")))
188192
}
193+
tags, malformedTags := parseKeyValueSpecs(cmd.StringSlice("tag"))
194+
for _, malformed := range malformedTags {
195+
fmt.Fprintf(os.Stderr, "Warning: ignoring malformed tag: %s\n", malformed)
196+
}
197+
if len(tags) > 0 {
198+
tagsJSON, err := marshalStringMap(tags)
199+
if err != nil {
200+
return fmt.Errorf("failed to encode tags: %w", err)
201+
}
202+
params.Tags = hypeman.Opt(tagsJSON)
203+
}
189204

190205
// Start build
191206
build, err := client.Builds.New(ctx, params, opts...)
@@ -359,24 +374,28 @@ var buildListCmd = cli.Command{
359374
Aliases: []string{"q"},
360375
Usage: "Only display build IDs",
361376
},
377+
&cli.StringSliceFlag{
378+
Name: "tag",
379+
Usage: "Filter by tag key-value pair (KEY=VALUE, can be repeated)",
380+
},
362381
},
363382
Action: handleBuildList,
364383
HideHelpCommand: true,
365384
}
366385

367386
var buildGetCmd = cli.Command{
368-
Name: "get",
369-
Usage: "Get build details",
370-
ArgsUsage: "<id>",
371-
Action: handleBuildGet,
387+
Name: "get",
388+
Usage: "Get build details",
389+
ArgsUsage: "<id>",
390+
Action: handleBuildGet,
372391
HideHelpCommand: true,
373392
}
374393

375394
var buildCancelCmd = cli.Command{
376-
Name: "cancel",
377-
Usage: "Cancel a build",
378-
ArgsUsage: "<id>",
379-
Action: handleBuildCancel,
395+
Name: "cancel",
396+
Usage: "Cancel a build",
397+
ArgsUsage: "<id>",
398+
Action: handleBuildCancel,
380399
HideHelpCommand: true,
381400
}
382401

@@ -390,19 +409,27 @@ func handleBuildList(ctx context.Context, cmd *cli.Command) error {
390409

391410
format := cmd.Root().String("format")
392411
transform := cmd.Root().String("transform")
412+
params := hypeman.BuildListParams{}
413+
tags, malformedTags := parseKeyValueSpecs(cmd.StringSlice("tag"))
414+
for _, malformed := range malformedTags {
415+
fmt.Fprintf(os.Stderr, "Warning: ignoring malformed tag filter: %s\n", malformed)
416+
}
417+
if len(tags) > 0 {
418+
params.Tags = tags
419+
}
393420

394421
if format != "auto" {
395422
var res []byte
396423
opts = append(opts, option.WithResponseBodyInto(&res))
397-
_, err := client.Builds.List(ctx, opts...)
424+
_, err := client.Builds.List(ctx, params, opts...)
398425
if err != nil {
399426
return err
400427
}
401428
obj := gjson.ParseBytes(res)
402429
return ShowJSON(os.Stdout, "build list", obj, format, transform)
403430
}
404431

405-
builds, err := client.Builds.List(ctx, opts...)
432+
builds, err := client.Builds.List(ctx, params, opts...)
406433
if err != nil {
407434
return err
408435
}

pkg/cmd/cmd.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ func init() {
7575
&pushCmd,
7676
&runCmd,
7777
&psCmd,
78+
&statsCmd,
79+
&updateCmd,
7880
&inspectCmd,
7981
&logsCmd,
8082
&rmCmd,
@@ -85,6 +87,7 @@ func init() {
8587
&forkCmd,
8688
&imageCmd,
8789
&ingressCmd,
90+
&snapshotCmd,
8891
&volumeCmd,
8992
&resourcesCmd,
9093
&deviceCmd,

pkg/cmd/cmdutil.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"io"
67
"log"
@@ -38,6 +39,30 @@ func getDefaultRequestOptions(cmd *cli.Command) []option.RequestOption {
3839
return opts
3940
}
4041

42+
func parseKeyValueSpecs(specs []string) (map[string]string, []string) {
43+
values := make(map[string]string)
44+
var malformed []string
45+
46+
for _, spec := range specs {
47+
parts := strings.SplitN(spec, "=", 2)
48+
if len(parts) != 2 || parts[0] == "" {
49+
malformed = append(malformed, spec)
50+
continue
51+
}
52+
values[parts[0]] = parts[1]
53+
}
54+
55+
return values, malformed
56+
}
57+
58+
func marshalStringMap(input map[string]string) (string, error) {
59+
payload, err := json.Marshal(input)
60+
if err != nil {
61+
return "", err
62+
}
63+
return string(payload), nil
64+
}
65+
4166
var debugMiddlewareOption = option.WithMiddleware(
4267
func(r *http.Request, mn option.MiddlewareNext) (*http.Response, error) {
4368
logger := log.Default()

pkg/cmd/cp.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,6 @@ func copyDirContentsToInstance(ctx context.Context, baseURL, apiKey, instanceID,
535535
return nil
536536
}
537537

538-
539538
// createDirOnInstanceWithUidGid creates a directory on the instance with explicit uid/gid
540539
func createDirOnInstanceWithUidGid(ctx context.Context, baseURL, apiKey, instanceID, dstPath string, mode fs.FileMode, uid, gid uint32) error {
541540
wsURL, err := buildCpWsURL(baseURL, instanceID)
@@ -980,5 +979,3 @@ func copyFromInstanceToStdout(ctx context.Context, baseURL, apiKey, instanceID,
980979
}
981980
return nil
982981
}
983-
984-

pkg/cmd/devicecmd.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,24 @@ Examples:
7777
Name: "name",
7878
Usage: "Optional name for the device (auto-generated if not provided)",
7979
},
80+
&cli.StringSliceFlag{
81+
Name: "tag",
82+
Usage: "Set device tag key-value pair (KEY=VALUE, can be repeated)",
83+
},
8084
},
8185
Action: handleDeviceRegister,
8286
HideHelpCommand: true,
8387
}
8488

8589
var deviceListCmd = cli.Command{
86-
Name: "list",
87-
Usage: "List registered devices",
90+
Name: "list",
91+
Usage: "List registered devices",
92+
Flags: []cli.Flag{
93+
&cli.StringSliceFlag{
94+
Name: "tag",
95+
Usage: "Filter by tag key-value pair (KEY=VALUE, can be repeated)",
96+
},
97+
},
8898
Action: handleDeviceList,
8999
HideHelpCommand: true,
90100
}
@@ -208,6 +218,13 @@ func handleDeviceRegister(ctx context.Context, cmd *cli.Command) error {
208218
if name := cmd.String("name"); name != "" {
209219
params.Name = hypeman.Opt(name)
210220
}
221+
tags, malformedTags := parseKeyValueSpecs(cmd.StringSlice("tag"))
222+
for _, malformed := range malformedTags {
223+
fmt.Fprintf(os.Stderr, "Warning: ignoring malformed tag: %s\n", malformed)
224+
}
225+
if len(tags) > 0 {
226+
params.Tags = tags
227+
}
211228

212229
var opts []option.RequestOption
213230
if cmd.Root().Bool("debug") {
@@ -244,7 +261,15 @@ func handleDeviceList(ctx context.Context, cmd *cli.Command) error {
244261

245262
var res []byte
246263
opts = append(opts, option.WithResponseBodyInto(&res))
247-
_, err := client.Devices.List(ctx, opts...)
264+
params := hypeman.DeviceListParams{}
265+
tags, malformedTags := parseKeyValueSpecs(cmd.StringSlice("tag"))
266+
for _, malformed := range malformedTags {
267+
fmt.Fprintf(os.Stderr, "Warning: ignoring malformed tag filter: %s\n", malformed)
268+
}
269+
if len(tags) > 0 {
270+
params.Tags = tags
271+
}
272+
_, err := client.Devices.List(ctx, params, opts...)
248273
if err != nil {
249274
return err
250275
}

pkg/cmd/format.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
type TableWriter struct {
1919
w io.Writer
2020
headers []string
21-
widths []int // natural widths (max of header and cell values)
21+
widths []int // natural widths (max of header and cell values)
2222
rows [][]string
2323

2424
// TruncOrder specifies column indices in truncation priority order.
@@ -297,4 +297,3 @@ func ResolveInstance(ctx context.Context, client *hypeman.Client, identifier str
297297
return "", fmt.Errorf("ambiguous instance identifier %q matches: %s", identifier, strings.Join(ids, ", "))
298298
}
299299
}
300-

0 commit comments

Comments
 (0)