Add hidden ferry pause and resume commands (#4771)

* Add hidden ferry pause and resume functions

* add check for 200 status

* include pause/resume status in ferry status, fix output

* put error string back to previous state
lab-week/event-streaming
Michael Milton 2 years ago committed by GitHub
parent 43c336ff75
commit f7e59d5d04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,136 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package ferry
import (
"context"
"strings"
"time"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/go-retryablehttp"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
var (
_ cli.Command = (*PauseCommand)(nil)
_ cli.CommandAutocomplete = (*PauseCommand)(nil)
)
type PauseCommand struct {
*base.Command
}
func (c *PauseCommand) Synopsis() string {
return "Pauses the running boundary ferry daemon"
}
func (c *PauseCommand) Help() string {
helpText := `
Usage: boundary ferry pause
Pause the boundary ferry daemon:
$ boundary ferry pause
For a full list of examples, please see the documentation.
` + c.Flags().Help()
return strings.TrimSpace(helpText)
}
func (c *PauseCommand) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetOutputFormat)
f := set.NewFlagSet("Client Options")
f.BoolVar(&base.BoolVar{
Name: "output-curl-string",
Target: &c.FlagOutputCurlString,
Usage: "Instead of executing the request, print an equivalent cURL command string and exit.",
})
f.UintVar(&base.UintVar{
Name: "ferry-port",
Target: &c.FlagFerryDaemonPort,
Default: 9300,
EnvVar: base.EnvFerryDaemonPort,
Usage: "The port on which the ferry daemon is listening.",
})
return set
}
func (c *PauseCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}
func (c *PauseCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}
func (c *PauseCommand) Run(args []string) int {
ctx := c.Context
f := c.Flags()
if err := f.Parse(args); err != nil {
c.PrintCliError(err)
return base.CommandUserError
}
resp, apiErr, err := c.Pause(ctx)
if err != nil {
c.PrintCliError(err)
return base.CommandCliError
}
if apiErr != nil {
c.PrintApiError(apiErr, "Error from ferry daemon when attempting to pause")
return base.CommandApiError
}
switch base.Format(c.UI) {
case "json":
if ok := c.PrintJsonItem(resp); !ok {
return base.CommandCliError
}
default:
c.UI.Output("Ferry has been successfully paused.")
}
return base.CommandSuccess
}
func (c *PauseCommand) Pause(ctx context.Context) (*api.Response, *api.Error, error) {
const op = "ferry.(PauseCommand).Pause"
client := retryablehttp.NewClient()
client.Logger = nil
client.RetryWaitMin = 100 * time.Millisecond
client.RetryWaitMax = 1000 * time.Millisecond
req, err := retryablehttp.NewRequestWithContext(ctx, "POST", ferryUrl(c.FlagFerryDaemonPort, "v1/pause"), nil)
if err != nil {
return nil, nil, err
}
if c.FlagOutputCurlString {
api.LastOutputStringError = &api.OutputStringError{Request: req}
return nil, nil, api.LastOutputStringError
}
resp, err := client.Do(req)
if err != nil {
return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("client do failed"))
}
apiResp := api.NewResponse(resp)
apiErr, err := apiResp.Decode(nil)
if err != nil {
return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("error decoding Resume response"))
}
if apiErr != nil {
return nil, apiErr, nil
}
return apiResp, nil, nil
}

@ -0,0 +1,136 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package ferry
import (
"context"
"strings"
"time"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/go-retryablehttp"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
var (
_ cli.Command = (*ResumeCommand)(nil)
_ cli.CommandAutocomplete = (*ResumeCommand)(nil)
)
type ResumeCommand struct {
*base.Command
}
func (c *ResumeCommand) Synopsis() string {
return "Resumes the paused boundary ferry daemon"
}
func (c *ResumeCommand) Help() string {
helpText := `
Usage: boundary ferry resume
Resume the boundary ferry daemon:
$ boundary ferry resume
For a full list of examples, please see the documentation.
` + c.Flags().Help()
return strings.TrimSpace(helpText)
}
func (c *ResumeCommand) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetOutputFormat)
f := set.NewFlagSet("Client Options")
f.BoolVar(&base.BoolVar{
Name: "output-curl-string",
Target: &c.FlagOutputCurlString,
Usage: "Instead of executing the request, print an equivalent cURL command string and exit.",
})
f.UintVar(&base.UintVar{
Name: "ferry-port",
Target: &c.FlagFerryDaemonPort,
Default: 9300,
EnvVar: base.EnvFerryDaemonPort,
Usage: "The port on which the ferry daemon is listening.",
})
return set
}
func (c *ResumeCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}
func (c *ResumeCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}
func (c *ResumeCommand) Run(args []string) int {
ctx := c.Context
f := c.Flags()
if err := f.Parse(args); err != nil {
c.PrintCliError(err)
return base.CommandUserError
}
resp, apiErr, err := c.Resume(ctx)
if err != nil {
c.PrintCliError(err)
return base.CommandCliError
}
if apiErr != nil {
c.PrintApiError(apiErr, "Error from ferry daemon when attempting to resume")
return base.CommandApiError
}
switch base.Format(c.UI) {
case "json":
if ok := c.PrintJsonItem(resp); !ok {
return base.CommandCliError
}
default:
c.UI.Output("Ferry has been successfully resumed.")
}
return base.CommandSuccess
}
func (c *ResumeCommand) Resume(ctx context.Context) (*api.Response, *api.Error, error) {
const op = "ferry.(ResumeCommand).Resume"
client := retryablehttp.NewClient()
client.Logger = nil
client.RetryWaitMin = 100 * time.Millisecond
client.RetryWaitMax = 1000 * time.Millisecond
req, err := retryablehttp.NewRequestWithContext(ctx, "POST", ferryUrl(c.FlagFerryDaemonPort, "v1/resume"), nil)
if err != nil {
return nil, nil, err
}
if c.FlagOutputCurlString {
api.LastOutputStringError = &api.OutputStringError{Request: req}
return nil, nil, api.LastOutputStringError
}
resp, err := client.Do(req)
if err != nil {
return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("client do failed"))
}
apiResp := api.NewResponse(resp)
apiErr, err := apiResp.Decode(nil)
if err != nil {
return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("error decoding Resume response"))
}
if apiErr != nil {
return nil, apiErr, nil
}
return apiResp, nil, nil
}

@ -107,6 +107,7 @@ type GetStatusResponse struct {
AuthTokenId string `json:"auth_token_id"`
AuthTokenExpiry time.Time `json:"auth_token_expiry"`
Version string `json:"version"`
Status string `json:"status"`
Errors []string `json:"errors"`
Warnings []string `json:"warnings"`
}
@ -152,6 +153,7 @@ func printStatusTable(status *GetStatusResponse) string {
"Auth Token Id": status.AuthTokenId,
"Auth Token Expiration": time.Until(status.AuthTokenExpiry).Round(time.Second).String(),
"Version": status.Version,
"Status": status.Status,
}
maxLength := base.MaxAttributesLength(nonAttributeMap, nil, nil)

@ -21,5 +21,15 @@ func init() {
Command: base.NewCommand(ui),
}, nil
}
Commands["ferry pause"] = func() (cli.Command, error) {
return &ferry.PauseCommand{
Command: base.NewCommand(ui),
}, nil
}
Commands["ferry resume"] = func() (cli.Command, error) {
return &ferry.ResumeCommand{
Command: base.NewCommand(ui),
}, nil
}
})
}

@ -23,5 +23,15 @@ func init() {
Command: base.NewCommand(ui),
}, nil
}
Commands["ferry pause"] = func() (cli.Command, error) {
return &ferry.PauseCommand{
Command: base.NewCommand(ui),
}, nil
}
Commands["ferry resume"] = func() (cli.Command, error) {
return &ferry.ResumeCommand{
Command: base.NewCommand(ui),
}, nil
}
})
}

@ -241,7 +241,7 @@ func RunCustom(args []string, runOpts *RunOptions) (exitCode int) {
initCommands(ui, serverCmdUi, runOpts)
hiddenCommands := []string{"version", "ferry", "ferry status"}
hiddenCommands := []string{"version", "ferry", "ferry status", "ferry pause", "ferry resume"}
cli := &cli.CLI{
Name: "boundary",

Loading…
Cancel
Save