cli: support wildcard namespace in alloc subcommands (#18095)

The alloc exec and filesystem/logs commands allow passing the `-job` flag to
select a random allocation. If the namespace for the command is set to `*`, the
RPC handler doesn't handle this correctly as it's expecting to query for a
specific job. Most commands handle this ambiguity by first verifying that only a
single object of the type in question exists (ex. a single node or job).

Update these commands so that when the `-job` flag is set we first verify
there's a single job that matches. This also allows us to extend the
functionality to allow for the `-job` flag to support prefix matching.

Fixes: #12097
This commit is contained in:
Tim Gross 2023-07-31 13:15:15 -04:00
parent f2c70e9d51
commit 9fe88ebefe
8 changed files with 43 additions and 18 deletions

3
.changelog/18095.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
cli: support wildcard namespaces in alloc subcommands when the `-job` flag is used
```

View File

@ -51,7 +51,7 @@ Exec Specific Options:
Sets the task to exec command in Sets the task to exec command in
-job -job
Use a random allocation from the specified job ID. Use a random allocation from the specified job ID or prefix.
-i -i
Pass stdin to the container, defaults to true. Pass -i=false to disable. Pass stdin to the container, defaults to true. Pass -i=false to disable.
@ -162,8 +162,13 @@ func (l *AllocExecCommand) Run(args []string) int {
var allocStub *api.AllocationListStub var allocStub *api.AllocationListStub
if job { if job {
jobID := args[0] jobID, ns, err := l.JobIDByPrefix(client, args[0], nil)
allocStub, err = getRandomJobAlloc(client, jobID) if err != nil {
l.Ui.Error(err.Error())
return 1
}
allocStub, err = getRandomJobAlloc(client, jobID, ns)
if err != nil { if err != nil {
l.Ui.Error(fmt.Sprintf("Error fetching allocations: %v", err)) l.Ui.Error(fmt.Sprintf("Error fetching allocations: %v", err))
return 1 return 1

View File

@ -60,7 +60,7 @@ func TestAllocExecCommand_Fails(t *testing.T) {
{ {
"job not found", "job not found",
[]string{"-address=" + url, "-job", "example", "/bin/bash"}, []string{"-address=" + url, "-job", "example", "/bin/bash"},
`job "example" doesn't exist`, `No job(s) with prefix or ID "example" found`,
}, },
{ {
"command missing", "command missing",

View File

@ -59,7 +59,7 @@ FS Specific Options:
Show full information. Show full information.
-job <job-id> -job <job-id>
Use a random allocation from the specified job ID. Use a random allocation from the specified job ID or prefix.
-stat -stat
Show file stat information instead of displaying the file, or listing the directory. Show file stat information instead of displaying the file, or listing the directory.
@ -167,7 +167,13 @@ func (f *AllocFSCommand) Run(args []string) int {
// If -job is specified, use random allocation, otherwise use provided allocation // If -job is specified, use random allocation, otherwise use provided allocation
allocID := args[0] allocID := args[0]
if job { if job {
allocID, err = getRandomJobAllocID(client, args[0]) jobID, ns, err := f.JobIDByPrefix(client, args[0], nil)
if err != nil {
f.Ui.Error(err.Error())
return 1
}
allocID, err = getRandomJobAllocID(client, jobID, ns)
if err != nil { if err != nil {
f.Ui.Error(fmt.Sprintf("Error fetching allocations: %v", err)) f.Ui.Error(fmt.Sprintf("Error fetching allocations: %v", err))
return 1 return 1
@ -381,9 +387,13 @@ func (f *AllocFSCommand) followFile(client *api.Client, alloc *api.Allocation,
// Get Random Allocation from a known jobID. Prefer to use a running allocation, // Get Random Allocation from a known jobID. Prefer to use a running allocation,
// but use a dead allocation if no running allocations are found // but use a dead allocation if no running allocations are found
func getRandomJobAlloc(client *api.Client, jobID string) (*api.AllocationListStub, error) { func getRandomJobAlloc(client *api.Client, jobID, namespace string) (*api.AllocationListStub, error) {
var runningAllocs []*api.AllocationListStub var runningAllocs []*api.AllocationListStub
allocs, _, err := client.Jobs().Allocations(jobID, false, nil) q := &api.QueryOptions{
Namespace: namespace,
}
allocs, _, err := client.Jobs().Allocations(jobID, false, q)
if err != nil { if err != nil {
return nil, fmt.Errorf("error querying job %q: %w", jobID, err) return nil, fmt.Errorf("error querying job %q: %w", jobID, err)
} }
@ -409,8 +419,8 @@ func getRandomJobAlloc(client *api.Client, jobID string) (*api.AllocationListStu
return alloc, err return alloc, err
} }
func getRandomJobAllocID(client *api.Client, jobID string) (string, error) { func getRandomJobAllocID(client *api.Client, jobID, namespace string) (string, error) {
alloc, err := getRandomJobAlloc(client, jobID) alloc, err := getRandomJobAlloc(client, jobID, namespace)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -61,7 +61,7 @@ Logs Specific Options:
and the '-task' option, preference is given to the '-task' option. and the '-task' option, preference is given to the '-task' option.
-job <job-id> -job <job-id>
Use a random allocation from the specified job ID. Use a random allocation from the specified job ID or prefix.
-f -f
Causes the output to not stop when the end of the logs are reached, but Causes the output to not stop when the end of the logs are reached, but
@ -167,7 +167,13 @@ func (l *AllocLogsCommand) Run(args []string) int {
// If -job is specified, use random allocation, otherwise use provided allocation // If -job is specified, use random allocation, otherwise use provided allocation
allocID := args[0] allocID := args[0]
if l.job { if l.job {
allocID, err = getRandomJobAllocID(client, args[0]) jobID, ns, err := l.JobIDByPrefix(client, args[0], nil)
if err != nil {
l.Ui.Error(err.Error())
return 1
}
allocID, err = getRandomJobAllocID(client, jobID, ns)
if err != nil { if err != nil {
l.Ui.Error(fmt.Sprintf("Error fetching allocations: %v", err)) l.Ui.Error(fmt.Sprintf("Error fetching allocations: %v", err))
return 1 return 1

View File

@ -41,7 +41,8 @@ capabilities for the allocation's namespace.
- `-task`: Sets the task to exec command in. - `-task`: Sets the task to exec command in.
- `-job`: Use a random allocation from the specified job ID. - `-job`: Use a random allocation from the specified job or job ID prefix,
preferring a running allocation.
- `-i`: Pass stdin to the container, defaults to true. Pass `-i=false` to - `-i`: Pass stdin to the container, defaults to true. Pass `-i=false` to
disable explicitly. disable explicitly.

View File

@ -48,8 +48,8 @@ When ACLs are enabled, this command requires a token with the `read-fs`,
- `-verbose`: Display verbose output. - `-verbose`: Display verbose output.
- `-job`: Use a random allocation from the specified job, preferring a running - `-job`: Use a random allocation from the specified job or job ID prefix,
allocation. preferring a running allocation.
- `-stat`: Show stat information instead of displaying the file, or listing the - `-stat`: Show stat information instead of displaying the file, or listing the
directory. directory.

View File

@ -43,8 +43,8 @@ When ACLs are enabled, this command requires a token with the `read-logs`,
- `-verbose`: Display verbose output. - `-verbose`: Display verbose output.
- `-job`: Use a random allocation from the specified job, preferring a running - `-job`: Use a random allocation from the specified job or job ID prefix,
allocation. preferring a running allocation.
- `-task`: Specify the task to view the logs. - `-task`: Specify the task to view the logs.