cli: jobs allow querying jobs in all namespaces
This commit is contained in:
parent
e784fe331a
commit
7a33a75449
|
@ -28,6 +28,12 @@ var (
|
|||
ClientConnTimeout = 1 * time.Second
|
||||
)
|
||||
|
||||
const (
|
||||
// AllNamespacesNamespace is a sentinel Namespace value to indicate that api should search for
|
||||
// jobs and allocations in all the namespaces the requester can access.
|
||||
AllNamespacesNamespace = "*"
|
||||
)
|
||||
|
||||
// QueryOptions are used to parametrize a query
|
||||
type QueryOptions struct {
|
||||
// Providing a datacenter overwrites the region provided
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/api/contexts"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
@ -119,10 +120,11 @@ func (c *JobDeploymentsCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
if len(jobs) > 1 && strings.TrimSpace(jobID) != jobs[0].ID {
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs)))
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs, c.allNamespaces())))
|
||||
return 1
|
||||
}
|
||||
jobID = jobs[0].ID
|
||||
q := &api.QueryOptions{Namespace: jobs[0].JobSummary.Namespace}
|
||||
|
||||
// Truncate the id unless full length is requested
|
||||
length := shortId
|
||||
|
@ -131,7 +133,7 @@ func (c *JobDeploymentsCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
if latest {
|
||||
deploy, _, err := client.Jobs().LatestDeployment(jobID, nil)
|
||||
deploy, _, err := client.Jobs().LatestDeployment(jobID, q)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error retrieving deployments: %s", err))
|
||||
return 1
|
||||
|
@ -152,7 +154,7 @@ func (c *JobDeploymentsCommand) Run(args []string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
deploys, _, err := client.Jobs().Deployments(jobID, all, nil)
|
||||
deploys, _, err := client.Jobs().Deployments(jobID, all, q)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error retrieving deployments: %s", err))
|
||||
return 1
|
||||
|
|
|
@ -131,12 +131,14 @@ func (c *JobHistoryCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
if len(jobs) > 1 && strings.TrimSpace(jobID) != jobs[0].ID {
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs)))
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs, c.allNamespaces())))
|
||||
return 1
|
||||
}
|
||||
|
||||
q := &api.QueryOptions{Namespace: jobs[0].JobSummary.Namespace}
|
||||
|
||||
// Prefix lookup matched a single job
|
||||
versions, diffs, _, err := client.Jobs().Versions(jobs[0].ID, diff, nil)
|
||||
versions, diffs, _, err := client.Jobs().Versions(jobs[0].ID, diff, q)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error retrieving job versions: %s", err))
|
||||
return 1
|
||||
|
|
|
@ -127,7 +127,7 @@ func (c *JobInspectCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
if len(jobs) > 1 && strings.TrimSpace(jobID) != jobs[0].ID {
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs)))
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs, c.allNamespaces())))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ func (c *JobInspectCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Prefix lookup matched a single job
|
||||
job, err := getJob(client, jobs[0].ID, version)
|
||||
job, err := getJob(client, jobs[0].JobSummary.Namespace, jobs[0].ID, version)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error inspecting job: %s", err))
|
||||
return 1
|
||||
|
@ -183,13 +183,17 @@ func (c *JobInspectCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// getJob retrieves the job optionally at a particular version.
|
||||
func getJob(client *api.Client, jobID string, version *uint64) (*api.Job, error) {
|
||||
func getJob(client *api.Client, namespace, jobID string, version *uint64) (*api.Job, error) {
|
||||
var q *api.QueryOptions
|
||||
if namespace != "" {
|
||||
q = &api.QueryOptions{Namespace: namespace}
|
||||
}
|
||||
if version == nil {
|
||||
job, _, err := client.Jobs().Info(jobID, nil)
|
||||
job, _, err := client.Jobs().Info(jobID, q)
|
||||
return job, err
|
||||
}
|
||||
|
||||
versions, _, _, err := client.Jobs().Versions(jobID, false, nil)
|
||||
versions, _, _, err := client.Jobs().Versions(jobID, false, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -127,13 +127,14 @@ func (c *JobPeriodicForceCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
if len(periodicJobs) > 1 {
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple periodic jobs\n\n%s", createStatusListOutput(periodicJobs)))
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple periodic jobs\n\n%s", createStatusListOutput(periodicJobs, c.allNamespaces())))
|
||||
return 1
|
||||
}
|
||||
jobID = periodicJobs[0].ID
|
||||
q := &api.WriteOptions{Namespace: periodicJobs[0].JobSummary.Namespace}
|
||||
|
||||
// force the evaluation
|
||||
evalID, _, err := client.Jobs().PeriodicForce(jobID, nil)
|
||||
evalID, _, err := client.Jobs().PeriodicForce(jobID, q)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error forcing periodic job %q: %s", jobID, err))
|
||||
return 1
|
||||
|
|
|
@ -125,13 +125,14 @@ func (c *JobPromoteCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
if len(jobs) > 1 && strings.TrimSpace(jobID) != jobs[0].ID {
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs)))
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs, c.allNamespaces())))
|
||||
return 1
|
||||
}
|
||||
jobID = jobs[0].ID
|
||||
q := &api.QueryOptions{Namespace: jobs[0].JobSummary.Namespace}
|
||||
|
||||
// Do a prefix lookup
|
||||
deploy, _, err := client.Jobs().LatestDeployment(jobID, nil)
|
||||
deploy, _, err := client.Jobs().LatestDeployment(jobID, q)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error retrieving deployment: %s", err))
|
||||
return 1
|
||||
|
@ -142,11 +143,12 @@ func (c *JobPromoteCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
wq := &api.WriteOptions{Namespace: jobs[0].JobSummary.Namespace}
|
||||
var u *api.DeploymentUpdateResponse
|
||||
if len(groups) == 0 {
|
||||
u, _, err = client.Deployments().PromoteAll(deploy.ID, nil)
|
||||
u, _, err = client.Deployments().PromoteAll(deploy.ID, wq)
|
||||
} else {
|
||||
u, _, err = client.Deployments().PromoteGroups(deploy.ID, groups, nil)
|
||||
u, _, err = client.Deployments().PromoteGroups(deploy.ID, groups, wq)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/api/contexts"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
@ -144,12 +145,13 @@ func (c *JobRevertCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
if len(jobs) > 1 && strings.TrimSpace(jobID) != jobs[0].ID {
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs)))
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs, c.allNamespaces())))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Prefix lookup matched a single job
|
||||
resp, _, err := client.Jobs().Revert(jobs[0].ID, revertVersion, nil, nil, consulToken, vaultToken)
|
||||
q := &api.WriteOptions{Namespace: jobs[0].JobSummary.Namespace}
|
||||
resp, _, err := client.Jobs().Revert(jobs[0].ID, revertVersion, nil, q, consulToken, vaultToken)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error retrieving job versions: %s", err))
|
||||
return 1
|
||||
|
|
|
@ -122,9 +122,12 @@ func (c *JobStatusCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
allNamespaces := c.allNamespaces()
|
||||
|
||||
// Invoke list mode if no job ID.
|
||||
if len(args) == 0 {
|
||||
jobs, _, err := client.Jobs().List(nil)
|
||||
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying jobs: %s", err))
|
||||
return 1
|
||||
|
@ -134,7 +137,7 @@ func (c *JobStatusCommand) Run(args []string) int {
|
|||
// No output if we have no jobs
|
||||
c.Ui.Output("No running jobs")
|
||||
} else {
|
||||
c.Ui.Output(createStatusListOutput(jobs))
|
||||
c.Ui.Output(createStatusListOutput(jobs, allNamespaces))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
@ -152,11 +155,12 @@ func (c *JobStatusCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
if len(jobs) > 1 && strings.TrimSpace(jobID) != jobs[0].ID {
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs)))
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs, allNamespaces)))
|
||||
return 1
|
||||
}
|
||||
// Prefix lookup matched a single job
|
||||
job, _, err := client.Jobs().Info(jobs[0].ID, nil)
|
||||
q := &api.QueryOptions{Namespace: jobs[0].JobSummary.Namespace}
|
||||
job, _, err := client.Jobs().Info(jobs[0].ID, q)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying job: %s", err))
|
||||
return 1
|
||||
|
@ -313,20 +317,24 @@ func (c *JobStatusCommand) outputParameterizedInfo(client *api.Client, job *api.
|
|||
// outputJobInfo prints information about the passed non-periodic job. If a
|
||||
// request fails, an error is returned.
|
||||
func (c *JobStatusCommand) outputJobInfo(client *api.Client, job *api.Job) error {
|
||||
var q *api.QueryOptions
|
||||
if job.Namespace != nil {
|
||||
q = &api.QueryOptions{Namespace: *job.Namespace}
|
||||
}
|
||||
|
||||
// Query the allocations
|
||||
jobAllocs, _, err := client.Jobs().Allocations(*job.ID, c.allAllocs, nil)
|
||||
jobAllocs, _, err := client.Jobs().Allocations(*job.ID, c.allAllocs, q)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error querying job allocations: %s", err)
|
||||
}
|
||||
|
||||
// Query the evaluations
|
||||
jobEvals, _, err := client.Jobs().Evaluations(*job.ID, nil)
|
||||
jobEvals, _, err := client.Jobs().Evaluations(*job.ID, q)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error querying job evaluations: %s", err)
|
||||
}
|
||||
|
||||
latestDeployment, _, err := client.Jobs().LatestDeployment(*job.ID, nil)
|
||||
latestDeployment, _, err := client.Jobs().LatestDeployment(*job.ID, q)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error querying latest job deployment: %s", err)
|
||||
}
|
||||
|
@ -505,7 +513,8 @@ func formatAllocList(allocations []*api.Allocation, verbose bool, uuidLength int
|
|||
// where appropriate
|
||||
func (c *JobStatusCommand) outputJobSummary(client *api.Client, job *api.Job) error {
|
||||
// Query the summary
|
||||
summary, _, err := client.Jobs().Summary(*job.ID, nil)
|
||||
q := &api.QueryOptions{Namespace: *job.Namespace}
|
||||
summary, _, err := client.Jobs().Summary(*job.ID, q)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error querying job summary: %s", err)
|
||||
}
|
||||
|
@ -650,16 +659,29 @@ func (c *JobStatusCommand) outputFailedPlacements(failedEval *api.Evaluation) {
|
|||
}
|
||||
|
||||
// list general information about a list of jobs
|
||||
func createStatusListOutput(jobs []*api.JobListStub) string {
|
||||
func createStatusListOutput(jobs []*api.JobListStub, displayNS bool) string {
|
||||
out := make([]string, len(jobs)+1)
|
||||
out[0] = "ID|Type|Priority|Status|Submit Date"
|
||||
for i, job := range jobs {
|
||||
out[i+1] = fmt.Sprintf("%s|%s|%d|%s|%s",
|
||||
job.ID,
|
||||
getTypeString(job),
|
||||
job.Priority,
|
||||
getStatusString(job.Status, &job.Stop),
|
||||
formatTime(time.Unix(0, job.SubmitTime)))
|
||||
if displayNS {
|
||||
out[0] = "ID|Namespace|Type|Priority|Status|Submit Date"
|
||||
for i, job := range jobs {
|
||||
out[i+1] = fmt.Sprintf("%s|%s|%s|%d|%s|%s",
|
||||
job.ID,
|
||||
job.JobSummary.Namespace,
|
||||
getTypeString(job),
|
||||
job.Priority,
|
||||
getStatusString(job.Status, &job.Stop),
|
||||
formatTime(time.Unix(0, job.SubmitTime)))
|
||||
}
|
||||
} else {
|
||||
out[0] = "ID|Type|Priority|Status|Submit Date"
|
||||
for i, job := range jobs {
|
||||
out[i+1] = fmt.Sprintf("%s|%s|%d|%s|%s",
|
||||
job.ID,
|
||||
getTypeString(job),
|
||||
job.Priority,
|
||||
getStatusString(job.Status, &job.Stop),
|
||||
formatTime(time.Unix(0, job.SubmitTime)))
|
||||
}
|
||||
}
|
||||
return formatList(out)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/nomad/api"
|
||||
"github.com/hashicorp/nomad/api/contexts"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
@ -126,11 +127,12 @@ func (c *JobStopCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
if len(jobs) > 1 && strings.TrimSpace(jobID) != jobs[0].ID {
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs)))
|
||||
c.Ui.Error(fmt.Sprintf("Prefix matched multiple jobs\n\n%s", createStatusListOutput(jobs, c.allNamespaces())))
|
||||
return 1
|
||||
}
|
||||
// Prefix lookup matched a single job
|
||||
job, _, err := client.Jobs().Info(jobs[0].ID, nil)
|
||||
q := &api.QueryOptions{Namespace: jobs[0].JobSummary.Namespace}
|
||||
job, _, err := client.Jobs().Info(jobs[0].ID, q)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error deregistering job: %s", err))
|
||||
return 1
|
||||
|
@ -160,7 +162,8 @@ func (c *JobStopCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Invoke the stop
|
||||
evalID, _, err := client.Jobs().Deregister(*job.ID, purge, nil)
|
||||
wq := &api.WriteOptions{Namespace: jobs[0].JobSummary.Namespace}
|
||||
evalID, _, err := client.Jobs().Deregister(*job.ID, purge, wq)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error deregistering job: %s", err))
|
||||
return 1
|
||||
|
|
|
@ -113,7 +113,7 @@ type ApiClientFactory func() (*api.Client, error)
|
|||
|
||||
// Client is used to initialize and return a new API client using
|
||||
// the default command line arguments and env vars.
|
||||
func (m *Meta) Client() (*api.Client, error) {
|
||||
func (m *Meta) clientConfig() *api.Config {
|
||||
config := api.DefaultConfig()
|
||||
if m.flagAddress != "" {
|
||||
config.Address = m.flagAddress
|
||||
|
@ -142,7 +142,15 @@ func (m *Meta) Client() (*api.Client, error) {
|
|||
config.SecretID = m.token
|
||||
}
|
||||
|
||||
return api.NewClient(config)
|
||||
return config
|
||||
}
|
||||
|
||||
func (m *Meta) Client() (*api.Client, error) {
|
||||
return api.NewClient(m.clientConfig())
|
||||
}
|
||||
|
||||
func (m *Meta) allNamespaces() bool {
|
||||
return m.clientConfig().Namespace == api.AllNamespacesNamespace
|
||||
}
|
||||
|
||||
func (m *Meta) Colorize() *colorstring.Colorize {
|
||||
|
|
|
@ -28,6 +28,12 @@ var (
|
|||
ClientConnTimeout = 1 * time.Second
|
||||
)
|
||||
|
||||
const (
|
||||
// AllNamespacesNamespace is a sentinel Namespace value to indicate that api should search for
|
||||
// jobs and allocations in all the namespaces the requester can access.
|
||||
AllNamespacesNamespace = "*"
|
||||
)
|
||||
|
||||
// QueryOptions are used to parametrize a query
|
||||
type QueryOptions struct {
|
||||
// Providing a datacenter overwrites the region provided
|
||||
|
|
Loading…
Reference in New Issue