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

@ -57,11 +57,11 @@ Logs Specific Options:
Show full information. Show full information.
-task <task-name> -task <task-name>
Sets the task to view the logs. If task name is given with both an argument Sets the task to view the logs. If task name is given with both an argument
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.