Skip to content

Commit 29dde0e

Browse files
committed
Partial ID match and name match
1 parent 3a85c7f commit 29dde0e

File tree

4 files changed

+71
-5
lines changed

4 files changed

+71
-5
lines changed

pkg/cmd/exec.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"syscall"
1515

1616
"github.com/gorilla/websocket"
17+
"github.com/onkernel/hypeman-go"
1718
"github.com/urfave/cli/v3"
1819
"golang.org/x/term"
1920
)
@@ -75,7 +76,13 @@ func handleExec(ctx context.Context, cmd *cli.Command) error {
7576
return fmt.Errorf("instance ID required\nUsage: hypeman exec [flags] <instance-id> [-- command...]")
7677
}
7778

78-
instanceID := args[0]
79+
// Resolve instance by ID, partial ID, or name
80+
client := hypeman.NewClient(getDefaultRequestOptions(cmd)...)
81+
instanceID, err := ResolveInstance(ctx, &client, args[0])
82+
if err != nil {
83+
return err
84+
}
85+
7986
var command []string
8087

8188
// Parse command after -- separator or remaining args

pkg/cmd/format.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package cmd
22

33
import (
4+
"context"
45
"fmt"
56
"io"
67
"strings"
78
"time"
9+
10+
"github.com/onkernel/hypeman-go"
811
)
912

1013
// TableWriter provides simple table formatting for CLI output
@@ -145,4 +148,48 @@ func randomSuffix(n int) string {
145148
return string(b)
146149
}
147150

151+
// ResolveInstance resolves an instance identifier to a full instance ID.
152+
// It supports:
153+
// - Full instance ID (exact match)
154+
// - Partial instance ID (prefix match)
155+
// - Instance name (exact match)
156+
// Returns an error if the identifier is ambiguous or not found.
157+
func ResolveInstance(ctx context.Context, client *hypeman.Client, identifier string) (string, error) {
158+
// List all instances
159+
instances, err := client.Instances.List(ctx)
160+
if err != nil {
161+
return "", fmt.Errorf("failed to list instances: %w", err)
162+
}
163+
164+
var matches []hypeman.Instance
165+
166+
for _, inst := range *instances {
167+
// Exact ID match - return immediately
168+
if inst.ID == identifier {
169+
return inst.ID, nil
170+
}
171+
// Exact name match - return immediately
172+
if inst.Name == identifier {
173+
return inst.ID, nil
174+
}
175+
// Partial ID match (prefix)
176+
if strings.HasPrefix(inst.ID, identifier) {
177+
matches = append(matches, inst)
178+
}
179+
}
180+
181+
switch len(matches) {
182+
case 0:
183+
return "", fmt.Errorf("no instance found matching %q", identifier)
184+
case 1:
185+
return matches[0].ID, nil
186+
default:
187+
// Ambiguous - show matching IDs
188+
ids := make([]string, len(matches))
189+
for i, m := range matches {
190+
ids[i] = TruncateID(m.ID)
191+
}
192+
return "", fmt.Errorf("ambiguous instance identifier %q matches: %s", identifier, strings.Join(ids, ", "))
193+
}
194+
}
148195

pkg/cmd/logs.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,14 @@ func handleLogs(ctx context.Context, cmd *cli.Command) error {
3535
return fmt.Errorf("instance ID required\nUsage: hypeman logs [flags] <instance>")
3636
}
3737

38-
instanceID := args[0]
39-
4038
client := hypeman.NewClient(getDefaultRequestOptions(cmd)...)
4139

40+
// Resolve instance by ID, partial ID, or name
41+
instanceID, err := ResolveInstance(ctx, &client, args[0])
42+
if err != nil {
43+
return err
44+
}
45+
4246
params := hypeman.InstanceStreamLogsParams{}
4347
if cmd.IsSet("follow") {
4448
params.Follow = hypeman.Opt(cmd.Bool("follow"))

pkg/cmd/rm.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,15 @@ func handleRm(ctx context.Context, cmd *cli.Command) error {
3434
client := hypeman.NewClient(getDefaultRequestOptions(cmd)...)
3535

3636
var lastErr error
37-
for _, instanceID := range args {
37+
for _, identifier := range args {
38+
// Resolve instance by ID, partial ID, or name
39+
instanceID, err := ResolveInstance(ctx, &client, identifier)
40+
if err != nil {
41+
fmt.Printf("Error: %v\n", err)
42+
lastErr = err
43+
continue
44+
}
45+
3846
// Check instance state if not forcing
3947
if !force {
4048
inst, err := client.Instances.Get(
@@ -56,7 +64,7 @@ func handleRm(ctx context.Context, cmd *cli.Command) error {
5664
}
5765

5866
// Delete the instance
59-
err := client.Instances.Delete(
67+
err = client.Instances.Delete(
6068
ctx,
6169
instanceID,
6270
option.WithMiddleware(debugMiddleware(cmd.Root().Bool("debug"))),

0 commit comments

Comments
 (0)