diff --git a/.changelog/3067.txt b/.changelog/3067.txt new file mode 100644 index 00000000000..ec1c61b1805 --- /dev/null +++ b/.changelog/3067.txt @@ -0,0 +1,4 @@ +```release-note:feature +**cli:** Introduce a new CLI command for job management and inspection +`waypoint job`. +``` diff --git a/internal/cli/job_cancel.go b/internal/cli/job_cancel.go new file mode 100644 index 00000000000..ae866eef342 --- /dev/null +++ b/internal/cli/job_cancel.go @@ -0,0 +1,84 @@ +package cli + +import ( + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/hashicorp/waypoint-plugin-sdk/terminal" + "github.com/hashicorp/waypoint/internal/clierrors" + "github.com/hashicorp/waypoint/internal/pkg/flag" + pb "github.com/hashicorp/waypoint/pkg/server/gen" +) + +type JobCancelCommand struct { + *baseCommand + + flagJson bool +} + +func (c *JobCancelCommand) Run(args []string) int { + // Initialize. If we fail, we just exit since Init handles the UI. + if err := c.Init( + WithArgs(args), + WithFlags(c.Flags()), + ); err != nil { + return 1 + } + + ctx := c.Ctx + + var jobId string + if len(c.args) == 0 { + c.ui.Output("Job ID required.\n\n%s", c.Help(), terminal.WithErrorStyle()) + return 1 + } else { + jobId = c.args[0] + } + + sg := c.ui.StepGroup() + defer sg.Wait() + + s := sg.Add("Cancelling job %q", jobId) + defer func() { s.Abort() }() + + _, err := c.project.Client().CancelJob(ctx, &pb.CancelJobRequest{ + JobId: jobId, + }) + if err != nil { + s.Update("Failed to marked job %q for cancellation", jobId) + s.Status(terminal.StatusError) + s.Done() + + if status.Code(err) == codes.NotFound { + c.ui.Output("Job id not found: %s", clierrors.Humanize(err), + terminal.WithErrorStyle()) + return 1 + } + + c.ui.Output(clierrors.Humanize(err), terminal.WithErrorStyle()) + return 1 + } + + s.Update("Marked job %q for cancellation", jobId) + s.Done() + + return 0 +} + +func (c *JobCancelCommand) Flags() *flag.Sets { + return c.flagSet(flagSetOperation, func(set *flag.Sets) { + }) +} + +func (c *JobCancelCommand) Synopsis() string { + return "Cancel a running a job by id" +} + +func (c *JobCancelCommand) Help() string { + return formatHelp(` +Usage: waypoint job cancel [options] + + Cancel a running job by id from Waypoint server. + +` + c.Flags().Help()) +} diff --git a/internal/cli/job_get_stream.go b/internal/cli/job_get_stream.go new file mode 100644 index 00000000000..bd699069815 --- /dev/null +++ b/internal/cli/job_get_stream.go @@ -0,0 +1,74 @@ +package cli + +import ( + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/hashicorp/waypoint-plugin-sdk/terminal" + "github.com/hashicorp/waypoint/internal/clierrors" + "github.com/hashicorp/waypoint/internal/pkg/flag" + pb "github.com/hashicorp/waypoint/pkg/server/gen" +) + +type JobGetStreamCommand struct { + *baseCommand + + flagJson bool +} + +func (c *JobGetStreamCommand) Run(args []string) int { + // Initialize. If we fail, we just exit since Init handles the UI. + if err := c.Init( + WithArgs(args), + WithFlags(c.Flags()), + ); err != nil { + return 1 + } + ctx := c.Ctx + + var jobId string + if len(c.args) == 0 { + c.ui.Output("Job ID required.\n\n%s", c.Help(), terminal.WithErrorStyle()) + return 1 + } else { + jobId = c.args[0] + } + + _, err := c.project.Client().GetJobStream(ctx, &pb.GetJobStreamRequest{ + JobId: jobId, + }) + if err != nil { + if status.Code(err) == codes.NotFound { + c.ui.Output("Job id not found: %s", clierrors.Humanize(err), + terminal.WithErrorStyle()) + return 1 + } + + c.ui.Output(clierrors.Humanize(err), terminal.WithErrorStyle()) + return 1 + } + + // TODO(briancain): process and print terminal events like `internal/client/job.go` + c.ui.Output("Job stream is not implemented yet!", terminal.WithWarningStyle()) + + return 0 +} + +func (c *JobGetStreamCommand) Flags() *flag.Sets { + return c.flagSet(flagSetOperation, func(set *flag.Sets) { + //f := set.NewSet("Command Options") + }) +} + +func (c *JobGetStreamCommand) Synopsis() string { + return "Attach a local CLI to a job stream by id" +} + +func (c *JobGetStreamCommand) Help() string { + return formatHelp(` +Usage: waypoint job get-stream [options] + + Connects the local CLI to an active job stream. + +` + c.Flags().Help()) +} diff --git a/internal/cli/job_inspect.go b/internal/cli/job_inspect.go new file mode 100644 index 00000000000..f1599521966 --- /dev/null +++ b/internal/cli/job_inspect.go @@ -0,0 +1,211 @@ +package cli + +import ( + "fmt" + + "github.com/dustin/go-humanize" + "github.com/golang/protobuf/jsonpb" + "github.com/golang/protobuf/ptypes" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/hashicorp/waypoint-plugin-sdk/terminal" + "github.com/hashicorp/waypoint/internal/clierrors" + "github.com/hashicorp/waypoint/internal/pkg/flag" + pb "github.com/hashicorp/waypoint/pkg/server/gen" +) + +type JobInspectCommand struct { + *baseCommand + + flagJson bool +} + +func (c *JobInspectCommand) Run(args []string) int { + // Initialize. If we fail, we just exit since Init handles the UI. + if err := c.Init( + WithArgs(args), + WithFlags(c.Flags()), + ); err != nil { + return 1 + } + ctx := c.Ctx + + var jobId string + if len(c.args) == 0 { + c.ui.Output("Job ID required.\n\n%s", c.Help(), terminal.WithErrorStyle()) + return 1 + } else { + jobId = c.args[0] + } + + resp, err := c.project.Client().GetJob(ctx, &pb.GetJobRequest{ + JobId: jobId, + }) + if err != nil { + if status.Code(err) == codes.NotFound { + c.ui.Output("Job id not found: %s", clierrors.Humanize(err), + terminal.WithErrorStyle()) + return 1 + } + + c.ui.Output(clierrors.Humanize(err), terminal.WithErrorStyle()) + return 1 + } + if resp == nil { + c.ui.Output("The requested job id %q was empty", jobId, terminal.WithWarningStyle()) + return 0 + } + + if c.flagJson { + var m jsonpb.Marshaler + m.Indent = "\t" + str, err := m.MarshalToString(resp) + if err != nil { + c.ui.Output(clierrors.Humanize(err), terminal.WithErrorStyle()) + return 1 + } + + fmt.Println(str) + return 0 + } + + var op string + // Job_Noop seems to be missing the isJob_operation method + switch resp.Operation.(type) { + case *pb.Job_Build: + op = "Build" + case *pb.Job_Push: + op = "Push" + case *pb.Job_Deploy: + op = "Deploy" + case *pb.Job_Destroy: + op = "Destroy" + case *pb.Job_Release: + op = "Release" + case *pb.Job_Validate: + op = "Validate" + case *pb.Job_Auth: + op = "Auth" + case *pb.Job_Docs: + op = "Docs" + case *pb.Job_ConfigSync: + op = "ConfigSync" + case *pb.Job_Exec: + op = "Exec" + case *pb.Job_Up: + op = "Up" + case *pb.Job_Logs: + op = "Logs" + case *pb.Job_QueueProject: + op = "QueueProject" + case *pb.Job_Poll: + op = "Poll" + case *pb.Job_StatusReport: + op = "StatusReport" + case *pb.Job_StartTask: + op = "StartTask" + case *pb.Job_StopTask: + op = "StopTask" + case *pb.Job_Init: + op = "Init" + default: + op = "Unknown" + } + + var jobState string + switch resp.State { + case pb.Job_UNKNOWN: + jobState = "Unknown" + case pb.Job_QUEUED: + jobState = "Queued" + case pb.Job_WAITING: + jobState = "Waiting" + case pb.Job_RUNNING: + jobState = "Running" + case pb.Job_ERROR: + jobState = "Error" + case pb.Job_SUCCESS: + jobState = "Sucecss" + default: + jobState = "Unknown" + } + + var targetRunner string + switch target := resp.TargetRunner.Target.(type) { + case *pb.Ref_Runner_Any: + targetRunner = "*" + case *pb.Ref_Runner_Id: + targetRunner = target.Id.Id + } + + var completeTime string + if time, err := ptypes.Timestamp(resp.CompleteTime); err == nil { + completeTime = humanize.Time(time) + } + var cancelTime string + if time, err := ptypes.Timestamp(resp.CancelTime); err == nil { + cancelTime = humanize.Time(time) + } + + c.ui.Output("Job Configuration", terminal.WithHeaderStyle()) + c.ui.NamedValues([]terminal.NamedValue{ + { + Name: "ID", Value: resp.Id, + }, + { + Name: "Singleton ID", Value: resp.SingletonId, + }, + { + Name: "Operation", Value: op, + }, + { + Name: "State", Value: jobState, + }, + { + Name: "Complete Time", Value: completeTime, + }, + { + Name: "Cancel Time", Value: cancelTime, + }, + { + Name: "Target Runner", Value: targetRunner, + }, + { + Name: "Workspace", Value: resp.Workspace.Workspace, + }, + { + Name: "Project", Value: resp.Application.Project, + }, + { + Name: "Application", Value: resp.Application.Application, + }, + }, terminal.WithInfoStyle()) + + return 0 +} + +func (c *JobInspectCommand) Flags() *flag.Sets { + return c.flagSet(flagSetOperation, func(set *flag.Sets) { + f := set.NewSet("Command Options") + f.BoolVar(&flag.BoolVar{ + Name: "json", + Target: &c.flagJson, + Default: false, + Usage: "Output the list of jobs as json.", + }) + }) +} + +func (c *JobInspectCommand) Synopsis() string { + return "Inspect the details of a job by id in Waypoint" +} + +func (c *JobInspectCommand) Help() string { + return formatHelp(` +Usage: waypoint job inspect [options] + + Inspect the details of a job by id in Waypoint server. + +` + c.Flags().Help()) +} diff --git a/internal/cli/job_list.go b/internal/cli/job_list.go new file mode 100644 index 00000000000..3c299b763ef --- /dev/null +++ b/internal/cli/job_list.go @@ -0,0 +1,208 @@ +package cli + +import ( + "fmt" + + "github.com/dustin/go-humanize" + "github.com/golang/protobuf/jsonpb" + "github.com/golang/protobuf/ptypes" + + "github.com/hashicorp/waypoint-plugin-sdk/terminal" + "github.com/hashicorp/waypoint/internal/clierrors" + "github.com/hashicorp/waypoint/internal/pkg/flag" + pb "github.com/hashicorp/waypoint/pkg/server/gen" +) + +type JobListCommand struct { + *baseCommand + + flagJson bool + flagLimit int + flagDesc bool +} + +func (c *JobListCommand) Run(args []string) int { + // Initialize. If we fail, we just exit since Init handles the UI. + if err := c.Init( + WithArgs(args), + WithFlags(c.Flags()), + ); err != nil { + return 1 + } + ctx := c.Ctx + + req := &pb.ListJobsRequest{} + + // NOTE(briancain): This is technically not a "public API" function + resp, err := c.project.Client().XListJobs(ctx, req) + if err != nil { + c.ui.Output(clierrors.Humanize(err), terminal.WithErrorStyle()) + return 1 + } + + jobs := resp.Jobs + + if c.flagDesc { + var reverse []*pb.Job + for i := len(jobs) - 1; i >= 0; i-- { + reverse = append(reverse, jobs[i]) + } + jobs = reverse + } + + if c.flagLimit > 0 && c.flagLimit <= len(jobs) { + jobs = jobs[len(jobs)-c.flagLimit:] + } + + if c.flagJson { + var m jsonpb.Marshaler + m.Indent = "\t" + for _, t := range jobs { + str, err := m.MarshalToString(t) + if err != nil { + c.ui.Output(clierrors.Humanize(err), terminal.WithErrorStyle()) + return 1 + } + + fmt.Println(str) + } + return 0 + } + + c.ui.Output("Waypoint Jobs", terminal.WithHeaderStyle()) + + tblHeaders := []string{"ID", "Operation", "State", "Time Completed", "Target Runner", "Workspace", "Project", "Application"} + tbl := terminal.NewTable(tblHeaders...) + + for _, j := range jobs { + var op string + // Job_Noop seems to be missing the isJob_operation method + switch j.Operation.(type) { + case *pb.Job_Build: + op = "Build" + case *pb.Job_Push: + op = "Push" + case *pb.Job_Deploy: + op = "Deploy" + case *pb.Job_Destroy: + op = "Destroy" + case *pb.Job_Release: + op = "Release" + case *pb.Job_Validate: + op = "Validate" + case *pb.Job_Auth: + op = "Auth" + case *pb.Job_Docs: + op = "Docs" + case *pb.Job_ConfigSync: + op = "ConfigSync" + case *pb.Job_Exec: + op = "Exec" + case *pb.Job_Up: + op = "Up" + case *pb.Job_Logs: + op = "Logs" + case *pb.Job_QueueProject: + op = "QueueProject" + case *pb.Job_Poll: + op = "Poll" + case *pb.Job_StatusReport: + op = "StatusReport" + case *pb.Job_StartTask: + op = "StartTask" + case *pb.Job_StopTask: + op = "StopTask" + case *pb.Job_Init: + op = "Init" + default: + op = "Unknown" + } + + var jobState string + switch j.State { + case pb.Job_UNKNOWN: + jobState = "Unknown" + case pb.Job_QUEUED: + jobState = "Queued" + case pb.Job_WAITING: + jobState = "Waiting" + case pb.Job_RUNNING: + jobState = "Running" + case pb.Job_ERROR: + jobState = "Error" + case pb.Job_SUCCESS: + jobState = "Sucecss" + default: + jobState = "Unknown" + } + + var targetRunner string + switch target := j.TargetRunner.Target.(type) { + case *pb.Ref_Runner_Any: + targetRunner = "*" + case *pb.Ref_Runner_Id: + targetRunner = target.Id.Id + } + + var completeTime string + if time, err := ptypes.Timestamp(j.CompleteTime); err == nil { + completeTime = humanize.Time(time) + } + + tblColumn := []string{ + j.Id, + op, + jobState, + completeTime, + targetRunner, + j.Workspace.Workspace, + j.Application.Project, + j.Application.Application, + } + + tbl.Rich(tblColumn, nil) + } + + c.ui.Table(tbl) + + return 0 +} + +func (c *JobListCommand) Flags() *flag.Sets { + return c.flagSet(flagSetOperation, func(set *flag.Sets) { + f := set.NewSet("Command Options") + f.BoolVar(&flag.BoolVar{ + Name: "desc", + Target: &c.flagDesc, + Default: false, + Usage: "Output the list of jobs from newest to oldest.", + }) + + f.BoolVar(&flag.BoolVar{ + Name: "json", + Target: &c.flagJson, + Default: false, + Usage: "Output the list of jobs as json.", + }) + + f.IntVar(&flag.IntVar{ + Name: "limit", + Target: &c.flagLimit, + Default: 0, + Usage: "If set, will limit the number of jobs to list.", + }) + }) +} + +func (c *JobListCommand) Synopsis() string { + return "List all jobs in Waypoint" +} + +func (c *JobListCommand) Help() string { + return formatHelp(` +Usage: waypoint job list [options] + + List all known jobs from Waypoint server. + +` + c.Flags().Help()) +} diff --git a/internal/cli/main.go b/internal/cli/main.go index ff6cf6c9b7f..4a7db73b6e2 100644 --- a/internal/cli/main.go +++ b/internal/cli/main.go @@ -390,6 +390,33 @@ func Commands( }, nil }, + "job": func() (cli.Command, error) { + return &helpCommand{ + SynopsisText: helpText["job"][0], + HelpText: helpText["job"][1], + }, nil + }, + "job list": func() (cli.Command, error) { + return &JobListCommand{ + baseCommand: baseCommand, + }, nil + }, + "job inspect": func() (cli.Command, error) { + return &JobInspectCommand{ + baseCommand: baseCommand, + }, nil + }, + "job cancel": func() (cli.Command, error) { + return &JobCancelCommand{ + baseCommand: baseCommand, + }, nil + }, + "job get-stream": func() (cli.Command, error) { + return &JobGetStreamCommand{ + baseCommand: baseCommand, + }, nil + }, + "token": func() (cli.Command, error) { return &helpCommand{ SynopsisText: helpText["token"][0], @@ -977,6 +1004,13 @@ For more information see: https://waypointproject.io/docs/url `, }, + "job": { + "Job introspection and management", + ` +Manage and check the status of jobs in Waypoint. +`, + }, + "project": { "Project management", ` diff --git a/internal/client/job.go b/internal/client/job.go index 42829b91e8b..0682474c8d0 100644 --- a/internal/client/job.go +++ b/internal/client/job.go @@ -540,7 +540,8 @@ func (c *Project) queueAndStreamJob( switch event.State.Current { case pb.Job_QUEUED: stateEventTimer = time.AfterFunc(stateEventPause, func() { - ui.Output("Operation is queued. Waiting for runner assignment...", + ui.Output("Operation is queued waiting for job %q. Waiting for runner assignment...", + queueResp.JobId, terminal.WithHeaderStyle()) ui.Output("If you interrupt this command, the job will still run in the background.", terminal.WithInfoStyle()) diff --git a/website/content/commands/job-cancel.mdx b/website/content/commands/job-cancel.mdx new file mode 100644 index 00000000000..f40d6356140 --- /dev/null +++ b/website/content/commands/job-cancel.mdx @@ -0,0 +1,39 @@ +--- +layout: commands +page_title: 'Commands: Job cancel' +sidebar_title: 'job cancel' +description: 'Cancel a running a job by id' +--- + +# Waypoint Job cancel + +Command: `waypoint job cancel` + +Cancel a running a job by id + +@include "commands/job-cancel_desc.mdx" + +## Usage + +Usage: `waypoint job cancel [options] ` + +Cancel a running job by id from Waypoint server. + +#### Global Options + +- `-plain` - Plain output: no colors, no animation. +- `-app=` (`-a`) - App to target. Certain commands require a single app target for Waypoint configurations with multiple apps. If you have a single app, then this can be ignored. +- `-project=` (`-p`) - Project to target. +- `-workspace=` (`-w`) - Workspace to operate in. + +#### Operation Options + +- `-label=` - Labels to set for this operation. Can be specified multiple times. +- `-local` - True to use a local runner to execute the operation, false to use a remote runner. + If unset, Waypoint will automatically determine where the operation will occur, + defaulting to remote if possible. +- `-remote-source=` - Override configurations for how remote runners source data. This is specified to the data source type being used in your configuration. This is used for example to set a specific Git ref to run against. +- `-var=` - Variable value to set for this operation. Can be specified multiple times. +- `-var-file=` - HCL or JSON file containing variable values to set for this operation. If any "_.auto.wpvars" or "_.auto.wpvars.json" files are present, they will be automatically loaded. + +@include "commands/job-cancel_more.mdx" diff --git a/website/content/commands/job-get-stream.mdx b/website/content/commands/job-get-stream.mdx new file mode 100644 index 00000000000..d63f77c71e5 --- /dev/null +++ b/website/content/commands/job-get-stream.mdx @@ -0,0 +1,39 @@ +--- +layout: commands +page_title: 'Commands: Job get-stream' +sidebar_title: 'job get-stream' +description: 'Attach a local CLI to a job stream by id' +--- + +# Waypoint Job get-stream + +Command: `waypoint job get-stream` + +Attach a local CLI to a job stream by id + +@include "commands/job-get-stream_desc.mdx" + +## Usage + +Usage: `waypoint job get-stream [options] ` + +Connects the local CLI to an active job stream. + +#### Global Options + +- `-plain` - Plain output: no colors, no animation. +- `-app=` (`-a`) - App to target. Certain commands require a single app target for Waypoint configurations with multiple apps. If you have a single app, then this can be ignored. +- `-project=` (`-p`) - Project to target. +- `-workspace=` (`-w`) - Workspace to operate in. + +#### Operation Options + +- `-label=` - Labels to set for this operation. Can be specified multiple times. +- `-local` - True to use a local runner to execute the operation, false to use a remote runner. + If unset, Waypoint will automatically determine where the operation will occur, + defaulting to remote if possible. +- `-remote-source=` - Override configurations for how remote runners source data. This is specified to the data source type being used in your configuration. This is used for example to set a specific Git ref to run against. +- `-var=` - Variable value to set for this operation. Can be specified multiple times. +- `-var-file=` - HCL or JSON file containing variable values to set for this operation. If any "_.auto.wpvars" or "_.auto.wpvars.json" files are present, they will be automatically loaded. + +@include "commands/job-get-stream_more.mdx" diff --git a/website/content/commands/job-inspect.mdx b/website/content/commands/job-inspect.mdx new file mode 100644 index 00000000000..adee2e3e8f3 --- /dev/null +++ b/website/content/commands/job-inspect.mdx @@ -0,0 +1,43 @@ +--- +layout: commands +page_title: 'Commands: Job inspect' +sidebar_title: 'job inspect' +description: 'Inspect the details of a job by id in Waypoint' +--- + +# Waypoint Job inspect + +Command: `waypoint job inspect` + +Inspect the details of a job by id in Waypoint + +@include "commands/job-inspect_desc.mdx" + +## Usage + +Usage: `waypoint job inspect [options] ` + +Inspect the details of a job by id in Waypoint server. + +#### Global Options + +- `-plain` - Plain output: no colors, no animation. +- `-app=` (`-a`) - App to target. Certain commands require a single app target for Waypoint configurations with multiple apps. If you have a single app, then this can be ignored. +- `-project=` (`-p`) - Project to target. +- `-workspace=` (`-w`) - Workspace to operate in. + +#### Operation Options + +- `-label=` - Labels to set for this operation. Can be specified multiple times. +- `-local` - True to use a local runner to execute the operation, false to use a remote runner. + If unset, Waypoint will automatically determine where the operation will occur, + defaulting to remote if possible. +- `-remote-source=` - Override configurations for how remote runners source data. This is specified to the data source type being used in your configuration. This is used for example to set a specific Git ref to run against. +- `-var=` - Variable value to set for this operation. Can be specified multiple times. +- `-var-file=` - HCL or JSON file containing variable values to set for this operation. If any "_.auto.wpvars" or "_.auto.wpvars.json" files are present, they will be automatically loaded. + +#### Command Options + +- `-json` - Output the list of jobs as json. + +@include "commands/job-inspect_more.mdx" diff --git a/website/content/commands/job-list.mdx b/website/content/commands/job-list.mdx new file mode 100644 index 00000000000..d1ae5433746 --- /dev/null +++ b/website/content/commands/job-list.mdx @@ -0,0 +1,45 @@ +--- +layout: commands +page_title: 'Commands: Job list' +sidebar_title: 'job list' +description: 'List all jobs in Waypoint' +--- + +# Waypoint Job list + +Command: `waypoint job list` + +List all jobs in Waypoint + +@include "commands/job-list_desc.mdx" + +## Usage + +Usage: `waypoint job list [options]` + +List all known jobs from Waypoint server. + +#### Global Options + +- `-plain` - Plain output: no colors, no animation. +- `-app=` (`-a`) - App to target. Certain commands require a single app target for Waypoint configurations with multiple apps. If you have a single app, then this can be ignored. +- `-project=` (`-p`) - Project to target. +- `-workspace=` (`-w`) - Workspace to operate in. + +#### Operation Options + +- `-label=` - Labels to set for this operation. Can be specified multiple times. +- `-local` - True to use a local runner to execute the operation, false to use a remote runner. + If unset, Waypoint will automatically determine where the operation will occur, + defaulting to remote if possible. +- `-remote-source=` - Override configurations for how remote runners source data. This is specified to the data source type being used in your configuration. This is used for example to set a specific Git ref to run against. +- `-var=` - Variable value to set for this operation. Can be specified multiple times. +- `-var-file=` - HCL or JSON file containing variable values to set for this operation. If any "_.auto.wpvars" or "_.auto.wpvars.json" files are present, they will be automatically loaded. + +#### Command Options + +- `-desc` - Output the list of jobs from newest to oldest. +- `-json` - Output the list of jobs as json. +- `-limit=` - If set, will limit the number of jobs to list. + +@include "commands/job-list_more.mdx" diff --git a/website/content/partials/commands/job-cancel_desc.mdx b/website/content/partials/commands/job-cancel_desc.mdx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/website/content/partials/commands/job-cancel_more.mdx b/website/content/partials/commands/job-cancel_more.mdx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/website/content/partials/commands/job-get-stream_desc.mdx b/website/content/partials/commands/job-get-stream_desc.mdx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/website/content/partials/commands/job-get-stream_more.mdx b/website/content/partials/commands/job-get-stream_more.mdx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/website/content/partials/commands/job-inspect_desc.mdx b/website/content/partials/commands/job-inspect_desc.mdx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/website/content/partials/commands/job-inspect_more.mdx b/website/content/partials/commands/job-inspect_more.mdx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/website/content/partials/commands/job-list_desc.mdx b/website/content/partials/commands/job-list_desc.mdx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/website/content/partials/commands/job-list_more.mdx b/website/content/partials/commands/job-list_more.mdx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/website/data/commands-nav-data.json b/website/data/commands-nav-data.json index 07289bff462..d5a147c1142 100644 --- a/website/data/commands-nav-data.json +++ b/website/data/commands-nav-data.json @@ -170,6 +170,22 @@ "title": "hostname register", "path": "hostname-register" }, + { + "title": "job list", + "path": "job-list" + }, + { + "title": "job inspect", + "path": "job-inspect" + }, + { + "title": "job cancel", + "path": "job-cancel" + }, + { + "title": "job get-stream", + "path": "job-get-stream" + }, { "title": "plugin", "path": "plugin"