This repository has been archived by the owner on Jan 8, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 327
Feature: waypoint job
CLI
#3067
Merged
Merged
Changes from 8 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
ee2ac89
CLI: Add `waypoint job` command for job management
briancain 792bb02
Generate CLI website docs
briancain a79f605
internal: Show job id that's being waited on
briancain f0333c9
Add Changelog
briancain 0bdfce4
cli: Allow for limits, descending by job id, and show completion time
briancain d7223e9
Website autogen
briancain 43708c9
website: Add CLI to nav data json for website
briancain 4545d5a
Remove extra route typo
briancain ebd3cc1
Add more fields to job inspect
briancain 8e871c4
Fix docstring in job inspect
briancain File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
```release-note:feature | ||
**cli:** Introduce a new CLI command for job management and inspection | ||
`waypoint job`. | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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] <job-id> | ||
|
||
Cancel a running job by id from Waypoint server. | ||
|
||
` + c.Flags().Help()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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] <job-id> | ||
|
||
Connects the local CLI to an active job stream. | ||
|
||
` + c.Flags().Help()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
package cli | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/golang/protobuf/jsonpb" | ||
"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 | ||
} | ||
|
||
c.ui.Output("Job Configuration", terminal.WithHeaderStyle()) | ||
c.ui.NamedValues([]terminal.NamedValue{ | ||
{ | ||
Name: "ID", Value: resp.Id, | ||
}, | ||
{ | ||
Name: "Operation", Value: op, | ||
}, | ||
{ | ||
Name: "State", Value: jobState, | ||
}, | ||
{ | ||
briancain marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 list [options] | ||
|
||
Inspect the details of a job by id in Waypoint server. | ||
|
||
` + c.Flags().Help()) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll open a new issue once this PR is wrapped up to finish implementing this.