Skip to content

Commit 15d4ef5

Browse files
authored
feat: Allow container matching by ID prefix (#175)
1 parent 2f5f515 commit 15d4ef5

File tree

5 files changed

+26
-16
lines changed

5 files changed

+26
-16
lines changed

cmd/uncloud/service/exec.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func NewExecCommand() *cobra.Command {
2828
Use: "exec [OPTIONS] SERVICE [COMMAND ARGS...]",
2929
Short: "Execute a command in a running service container",
3030
Long: `Execute a command (interactive shell by default) in a running container within a service.
31-
If the service has multiple replicas, the command will be executed in a random container.
31+
If the service has multiple replicas and no container ID is specified, the command will be executed in a random container.
3232
`,
3333
Example: `
3434
# Start an interactive shell ("bash" or "sh" will be tried by default)
@@ -37,8 +37,8 @@ If the service has multiple replicas, the command will be executed in a random c
3737
# Start an interactive shell with explicit command
3838
uc exec web-service /bin/zsh
3939
40-
# List files in the specific container of the service
41-
uc exec --container d792ea7347e5 web-service ls -la
40+
# List files in the specific container of the service; --container accepts full ID or a (unique) prefix
41+
uc exec --container d792e web-service ls -la
4242
4343
# Pipe input to a command inside the service container
4444
cat backup.sql | uc exec -T db-service psql -U postgres mydb

pkg/client/container.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/docker/compose/v2/pkg/progress"
1111
"github.com/docker/docker/api/types/container"
1212
"github.com/docker/docker/pkg/jsonmessage"
13-
"github.com/docker/docker/pkg/stringid"
1413
"github.com/psviderski/uncloud/internal/docker"
1514
machinedocker "github.com/psviderski/uncloud/internal/machine/docker"
1615
"github.com/psviderski/uncloud/internal/secret"
@@ -200,7 +199,7 @@ func toPullProgressEvent(jm jsonmessage.JSONMessage) *progress.Event {
200199
}
201200

202201
// InspectContainer returns the information about the specified container within the service.
203-
// containerNameOrID can be name, ID, or truncated ID of the container.
202+
// containerNameOrID can be name, full ID, or ID prefix of the container.
204203
func (cli *Client) InspectContainer(
205204
ctx context.Context, serviceNameOrID, containerNameOrID string,
206205
) (api.MachineServiceContainer, error) {
@@ -209,13 +208,23 @@ func (cli *Client) InspectContainer(
209208
return api.MachineServiceContainer{}, fmt.Errorf("inspect service: %w", err)
210209
}
211210

212-
// TODO: support matching by any prefix of the container ID
211+
prefixMatchCandidates := []api.MachineServiceContainer{}
213212
for _, c := range svc.Containers {
214213
if c.Container.ID == containerNameOrID ||
215-
c.Container.Name == containerNameOrID ||
216-
stringid.TruncateID(c.Container.ID) == containerNameOrID {
214+
c.Container.Name == containerNameOrID {
217215
return c, nil
218216
}
217+
218+
if strings.HasPrefix(c.Container.ID, containerNameOrID) {
219+
prefixMatchCandidates = append(prefixMatchCandidates, c)
220+
}
221+
}
222+
223+
if len(prefixMatchCandidates) == 1 {
224+
return prefixMatchCandidates[0], nil
225+
} else if len(prefixMatchCandidates) > 1 {
226+
return api.MachineServiceContainer{}, fmt.Errorf(
227+
"multiple containers found with ID prefix '%s'", containerNameOrID)
219228
}
220229

221230
return api.MachineServiceContainer{}, api.ErrNotFound

test/e2e/exec_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ func TestExecBasicCommands(t *testing.T) {
224224

225225
var stdout, stderr bytes.Buffer
226226

227-
containerID := service.Containers[1].Container.ID
227+
// Use container prefix
228+
containerIDPrefix := service.Containers[1].Container.ID[:3]
228229
execOptions := api.ExecOptions{
229230
Command: []string{"hostname"},
230231
AttachStdout: true,
@@ -233,7 +234,7 @@ func TestExecBasicCommands(t *testing.T) {
233234
Stderr: &stderr,
234235
}
235236

236-
exitCode, err := cli.ExecContainer(ctx, multiServiceName, containerID, execOptions)
237+
exitCode, err := cli.ExecContainer(ctx, multiServiceName, containerIDPrefix, execOptions)
237238

238239
require.NoError(t, err)
239240
assert.Equal(t, 0, exitCode)

website/docs/9-cli-reference/uc_exec.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Execute a command in a running service container
55
## Synopsis
66

77
Execute a command (interactive shell by default) in a running container within a service.
8-
If the service has multiple replicas, the command will be executed in a random container.
8+
If the service has multiple replicas and no container ID is specified, the command will be executed in a random container.
99

1010

1111
```
@@ -22,8 +22,8 @@ uc exec [OPTIONS] SERVICE [COMMAND ARGS...] [flags]
2222
# Start an interactive shell with explicit command
2323
uc exec web-service /bin/zsh
2424
25-
# List files in the specific container of the service
26-
uc exec --container d792ea7347e5 web-service ls -la
25+
# List files in the specific container of the service; --container accepts full ID or a (unique) prefix
26+
uc exec --container d792e web-service ls -la
2727
2828
# Pipe input to a command inside the service container
2929
cat backup.sql | uc exec -T db-service psql -U postgres mydb

website/docs/9-cli-reference/uc_service_exec.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Execute a command in a running service container
55
## Synopsis
66

77
Execute a command (interactive shell by default) in a running container within a service.
8-
If the service has multiple replicas, the command will be executed in a random container.
8+
If the service has multiple replicas and no container ID is specified, the command will be executed in a random container.
99

1010

1111
```
@@ -22,8 +22,8 @@ uc service exec [OPTIONS] SERVICE [COMMAND ARGS...] [flags]
2222
# Start an interactive shell with explicit command
2323
uc exec web-service /bin/zsh
2424
25-
# List files in the specific container of the service
26-
uc exec --container d792ea7347e5 web-service ls -la
25+
# List files in the specific container of the service; --container accepts full ID or a (unique) prefix
26+
uc exec --container d792e web-service ls -la
2727
2828
# Pipe input to a command inside the service container
2929
cat backup.sql | uc exec -T db-service psql -U postgres mydb

0 commit comments

Comments
 (0)