Update scopes CLI command in the model of the roles command (#262)

* Update scopes CLI command in the model of the roles command

* Pull help functions to helper methods
This commit is contained in:
Jeff Mitchell authored and GitHub committed 2020-08-13 11:20:22 -04:00
1 parent f1d69ea1ee
commit b75a6fc5e5
12 files changed
+442 -353

No files matched your search

+5
View File
@@ -61,6 +61,11 @@ type Command struct {
FlagTokenName string
flagOutputCurlString bool
FlagId string
FlagName string
FlagDescription string
FlagVersion int
client *api.Client
}
+22 -2
View File
@@ -59,13 +59,33 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
}, nil
},
"scopes create": func() (cli.Command, error) {
return &scopes.CreateScopeCommand{
return &scopes.Command{
Command: base.NewCommand(ui),
Func: "create",
}, nil
},
"scopes read": func() (cli.Command, error) {
return &scopes.ReadScopeCommand{
return &scopes.Command{
Command: base.NewCommand(ui),
Func: "read",
}, nil
},
"scopes update": func() (cli.Command, error) {
return &scopes.Command{
Command: base.NewCommand(ui),
Func: "update",
}, nil
},
"scopes delete": func() (cli.Command, error) {
return &scopes.Command{
Command: base.NewCommand(ui),
Func: "delete",
}, nil
},
"scopes list": func() (cli.Command, error) {
return &scopes.Command{
Command: base.NewCommand(ui),
Func: "list",
}, nil
},
"config": func() (cli.Command, error) {
@@ -372,7 +372,7 @@ func (c *Command) ParseFlagsAndConfig(args []string) int {
c.UI.Error(fmt.Sprintf("Invalid dev auth method ID, must start with %q", prefix))
return 1
}
if len(c.flagDevAuthMethodId) != 13 {
if len(c.flagDevAuthMethodId) != 15 {
c.UI.Error(fmt.Sprintf("Invalid dev auth method ID, must be 10 base62 characters after %q", prefix))
return 1
}
+1 -1
View File
@@ -180,7 +180,7 @@ func (c *Command) Run(args []string) int {
c.UI.Error(fmt.Sprintf("Invalid dev auth method ID, must start with %q", prefix))
return 1
}
if len(c.flagDevAuthMethodId) != 13 {
if len(c.flagDevAuthMethodId) != 15 {
c.UI.Error(fmt.Sprintf("Invalid dev auth method ID, must be 10 base62 characters after %q", prefix))
return 1
}
+4 -102
View File
@@ -2,22 +2,16 @@ package roles
import (
"fmt"
"net/textproto"
"strings"
"time"
"github.com/hashicorp/boundary/api/roles"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/cmd/common"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/mitchellh/go-wordwrap"
)
func synopsisFunc(inFunc string) string {
if inFunc == "" {
return wordwrap.WrapString("Manage Boundary roles", base.TermWidth)
}
return wordwrap.WrapString(fmt.Sprintf("%s a role within Boundary", textproto.CanonicalMIMEHeaderKey(inFunc)), base.TermWidth)
}
func principalsGrantsSynopsisFunc(inFunc string, principals bool) string {
var in string
switchStr := "principals (users, groups)"
@@ -35,76 +29,6 @@ func principalsGrantsSynopsisFunc(inFunc string, principals bool) string {
return wordwrap.WrapString(fmt.Sprintf("%s a role within Boundary", in), base.TermWidth)
}
func baseHelp() string {
return base.WrapForHelpText([]string{
"Usage: boundary roles [sub command] [options] [args]",
"",
" This command allows operations on Boundary roles. Examples:",
"",
" Create a role:",
"",
` $ boundary roles create -name foo -description "For ProdOps usage"`,
"",
" Add a grant to a role:",
"",
` $ boundary roles add-grants -id r_1234567890 -grant "type=host-catalog;actions=create,delete"`,
"",
" Please see the role subcommand help for detailed usage information.",
})
}
func createHelp() string {
return base.WrapForHelpText([]string{
"Usage: boundary roles create [options] [args]",
"",
" Create a role. Example:",
"",
` $ boundary roles create -name ops -description "Role for ops grants"`,
"",
"",
})
}
func updateHelp() string {
return base.WrapForHelpText([]string{
"Usage: boundary roles update [options] [args]",
"",
" Update a role given its ID. Example:",
"",
` $ boundary roles update -id r_1234567890 -description "Development host grants"`,
})
}
func readHelp() string {
return base.WrapForHelpText([]string{
"Usage: boundary roles read [options] [args]",
"",
" Read a role given its ID. Example:",
"",
` $ boundary roles read -id r_1234567890`,
})
}
func deleteHelp() string {
return base.WrapForHelpText([]string{
"Usage: boundary roles delete [options] [args]",
"",
" Delete a role given its ID. Example:",
"",
` $ boundary roles delete -id r_1234567890`,
})
}
func listHelp() string {
return base.WrapForHelpText([]string{
"Usage: boundary roles list [options] [args]",
"",
" List roles within a scope. Example:",
"",
` $ boundary roles list -org o_1234567890`,
})
}
func addPrincipalsHelp() string {
return base.WrapForHelpText([]string{
"Usage: boundary roles add-principals [options] [args]",
@@ -136,26 +60,10 @@ func removePrincipalsHelp() string {
}
func populateFlags(c *Command, f *base.FlagSet, flagNames []string) {
common.PopulateCommonFlags(c.Command, f, resource.Role, flagNames)
for _, name := range flagNames {
switch name {
case "id":
f.StringVar(&base.StringVar{
Name: "id",
Target: &c.flagId,
Usage: "ID of the role to operate on",
})
case "name":
f.StringVar(&base.StringVar{
Name: "name",
Target: &c.flagName,
Usage: "Name to set on the role",
})
case "description":
f.StringVar(&base.StringVar{
Name: "description",
Target: &c.flagDescription,
Usage: "Description to set on the role",
})
case "grantscopeid":
f.StringVar(&base.StringVar{
Name: "grant-scope-id",
@@ -174,12 +82,6 @@ func populateFlags(c *Command, f *base.FlagSet, flagNames []string) {
Target: &c.flagGrants,
Usage: "The grants to add, remove, or set. May be specified multiple times. Can be in compact string format or JSON (be sure to escape JSON properly).",
})
case "version":
f.IntVar(&base.IntVar{
Name: "version",
Target: &c.flagVersion,
Usage: "The version of the resource against which to perform an update operation. If not specified, the command will perform a check-and-set automatically.",
})
}
}
}
+33 -37
View File
@@ -6,7 +6,9 @@ import (
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/roles"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/cmd/common"
"github.com/hashicorp/boundary/internal/perms"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/kr/pretty"
"github.com/mitchellh/cli"
@@ -21,39 +23,32 @@ type Command struct {
Func string
flagId string
flagName string
flagDescription string
flagGrantScopeId string
flagPrincipals []string
flagGrants []string
flagVersion int
}
func (c *Command) Synopsis() string {
switch c.Func {
case "create", "update", "read", "delete", "list":
return synopsisFunc(c.Func)
case "", "create", "update", "read", "delete", "list":
return common.SynopsisFunc(c.Func, "role")
case "add-principals", "set-principals", "remove-principals":
return principalsGrantsSynopsisFunc(c.Func, true)
case "add-grants", "set-grants", "remove-grants":
return principalsGrantsSynopsisFunc(c.Func, false)
}
return "Manage Boundary roles"
return ""
}
var helpMap = map[string]func() string{
"create": createHelp,
"update": updateHelp,
"read": readHelp,
"delete": deleteHelp,
"list": listHelp,
"add-principals": addPrincipalsHelp,
"set-principals": setPrincipalsHelp,
"remove-principals": removePrincipalsHelp,
"add-grants": addPrincipalsHelp,
"set-grants": setPrincipalsHelp,
"remove-grants": removePrincipalsHelp,
var helpMap = func() map[string]func() string {
ret := common.HelpMap(resource.Role)
ret["add-principals"] = addPrincipalsHelp
ret["set-principals"] = setPrincipalsHelp
ret["remove-principals"] = removePrincipalsHelp
ret["add-grants"] = addPrincipalsHelp
ret["set-grants"] = setPrincipalsHelp
ret["remove-grants"] = removePrincipalsHelp
return ret
}
var flagsMap = map[string][]string{
@@ -70,10 +65,11 @@ var flagsMap = map[string][]string{
}
func (c *Command) Help() string {
hm := helpMap()
if c.Func == "" {
return baseHelp()
return hm["base"]()
}
return helpMap[c.Func]() + "\n\n" + c.Flags().Help()
return hm[c.Func]() + "\n\n" + c.Flags().Help()
}
func (c *Command) Flags() *base.FlagSets {
@@ -105,7 +101,7 @@ func (c *Command) Run(args []string) int {
return 1
}
if strutil.StrListContains(flagsMap[c.Func], "id") && c.flagId == "" {
if strutil.StrListContains(flagsMap[c.Func], "id") && c.FlagId == "" {
c.UI.Error("ID is required but not passed in via -id")
return 1
}
@@ -118,19 +114,19 @@ func (c *Command) Run(args []string) int {
var opts []roles.Option
switch c.flagName {
switch c.FlagName {
case "":
case "null":
opts = append(opts, roles.DefaultName())
default:
opts = append(opts, roles.WithName(c.flagName))
opts = append(opts, roles.WithName(c.FlagName))
}
switch c.flagDescription {
switch c.FlagDescription {
case "":
case "null":
opts = append(opts, roles.DefaultDescription())
default:
opts = append(opts, roles.WithDescription(c.flagDescription))
opts = append(opts, roles.WithDescription(c.FlagDescription))
}
switch c.flagGrantScopeId {
case "":
@@ -200,11 +196,11 @@ func (c *Command) Run(args []string) int {
case "create", "read", "delete", "list":
// These don't udpate so don't need the existing version
default:
switch c.flagVersion {
switch c.FlagVersion {
case 0:
opts = append(opts, roles.WithAutomaticVersioning())
default:
version = uint32(c.flagVersion)
version = uint32(c.FlagVersion)
}
}
@@ -217,25 +213,25 @@ func (c *Command) Run(args []string) int {
case "create":
role, apiErr, err = roleClient.Create(c.Context, opts...)
case "update":
role, apiErr, err = roleClient.Update(c.Context, c.flagId, version, opts...)
role, apiErr, err = roleClient.Update(c.Context, c.FlagId, version, opts...)
case "read":
role, apiErr, err = roleClient.Read(c.Context, c.flagId, opts...)
role, apiErr, err = roleClient.Read(c.Context, c.FlagId, opts...)
case "delete":
existed, apiErr, err = roleClient.Delete(c.Context, c.flagId, opts...)
existed, apiErr, err = roleClient.Delete(c.Context, c.FlagId, opts...)
case "list":
listedRoles, apiErr, err = roleClient.List(c.Context, opts...)
case "add-principals":
role, apiErr, err = roleClient.AddPrincipals(c.Context, c.flagId, version, principals, opts...)
role, apiErr, err = roleClient.AddPrincipals(c.Context, c.FlagId, version, principals, opts...)
case "set-principals":
role, apiErr, err = roleClient.SetPrincipals(c.Context, c.flagId, version, principals, opts...)
role, apiErr, err = roleClient.SetPrincipals(c.Context, c.FlagId, version, principals, opts...)
case "remove-principals":
role, apiErr, err = roleClient.RemovePrincipals(c.Context, c.flagId, version, principals, opts...)
role, apiErr, err = roleClient.RemovePrincipals(c.Context, c.FlagId, version, principals, opts...)
case "add-grants":
role, apiErr, err = roleClient.AddGrants(c.Context, c.flagId, version, grants, opts...)
role, apiErr, err = roleClient.AddGrants(c.Context, c.FlagId, version, grants, opts...)
case "set-grants":
role, apiErr, err = roleClient.SetGrants(c.Context, c.flagId, version, grants, opts...)
role, apiErr, err = roleClient.SetGrants(c.Context, c.FlagId, version, grants, opts...)
case "remove-grants":
role, apiErr, err = roleClient.RemoveGrants(c.Context, c.flagId, version, grants, opts...)
role, apiErr, err = roleClient.RemoveGrants(c.Context, c.FlagId, version, grants, opts...)
}
plural := "role"
-108
View File
@@ -1,108 +0,0 @@
package scopes
import (
"fmt"
"strings"
"github.com/hashicorp/boundary/api/scopes"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/kr/pretty"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
var _ cli.Command = (*CreateScopeCommand)(nil)
var _ cli.CommandAutocomplete = (*CreateScopeCommand)(nil)
type CreateScopeCommand struct {
*base.Command
flagName string
flagDescription string
}
func (c *CreateScopeCommand) Synopsis() string {
return "Creates a scope within a parent scope"
}
func (c *CreateScopeCommand) Help() string {
helpText := `
Usage: boundary scopes create
Creates a new scope within the scope specified by the ID from the
"scope" parameter or the associated environment variable.
Example:
$ boundary scopes create -scope=<scope_id> -name=<name>
` + c.Flags().Help()
return strings.TrimSpace(helpText)
}
func (c *CreateScopeCommand) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
f := set.NewFlagSet("Command Options")
f.StringVar(&base.StringVar{
Name: "name",
Target: &c.flagName,
Completion: complete.PredictAnything,
Usage: "An optional name assigned to the project for display purposes",
})
f.StringVar(&base.StringVar{
Name: "description",
Target: &c.flagDescription,
Completion: complete.PredictNothing,
Usage: "An optional description assigned to the project for display purposes",
})
return set
}
func (c *CreateScopeCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictAnything
}
func (c *CreateScopeCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}
func (c *CreateScopeCommand) Run(args []string) int {
f := c.Flags()
if err := f.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
client, err := c.Client()
if err != nil {
c.UI.Error(err.Error())
return 2
}
scp, apiErr, err := scopes.NewScopesClient(client).Create(c.Context,
client.ScopeId(),
scopes.WithName(c.flagName),
scopes.WithDescription(c.flagDescription))
switch {
case err != nil:
c.UI.Error(fmt.Errorf("error creating project: %w", err).Error())
return 2
case apiErr != nil:
c.UI.Error(pretty.Sprint(apiErr))
return 2
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(printScope(scp))
}
return 0
}
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"github.com/hashicorp/boundary/internal/cmd/base"
)
func printScope(in *scopes.Scope) string {
func generateScopeTableOutput(in *scopes.Scope) string {
var ret []string
// This if true is here to line up columns for easy editing
if true {
-101
View File
@@ -1,101 +0,0 @@
package scopes
import (
"fmt"
"strings"
"github.com/hashicorp/boundary/api/scopes"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/kr/pretty"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
var _ cli.Command = (*ReadScopeCommand)(nil)
var _ cli.CommandAutocomplete = (*ReadScopeCommand)(nil)
type ReadScopeCommand struct {
*base.Command
flagId string
}
func (c *ReadScopeCommand) Synopsis() string {
return "Reads a scope's data"
}
func (c *ReadScopeCommand) Help() string {
helpText := `
Usage: boundary scopes read
Returns information about a scope specified by the ID. The request will take place within the scope of the caller's authentication token.
Example:
$ boundary scopes read -id=<scope_id>
` + c.Flags().Help()
return strings.TrimSpace(helpText)
}
func (c *ReadScopeCommand) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
f := set.NewFlagSet("Command Options")
f.StringVar(&base.StringVar{
Name: "id",
Target: &c.flagId,
Completion: complete.PredictNothing,
Usage: "The ID of the scope to read",
})
return set
}
func (c *ReadScopeCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictAnything
}
func (c *ReadScopeCommand) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}
func (c *ReadScopeCommand) Run(args []string) int {
f := c.Flags()
if err := f.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
client, err := c.Client()
if err != nil {
c.UI.Error(err.Error())
return 2
}
if len(c.flagId) == 0 {
c.UI.Error("No scope ID supplied via -id")
return 1
}
scp, apiErr, err := scopes.NewScopesClient(client).Read(c.Context, c.flagId)
switch {
case err != nil:
c.UI.Error(fmt.Errorf("error reading project: %w", err).Error())
return 2
case apiErr != nil:
c.UI.Error(pretty.Sprint(apiErr))
return 2
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(printScope(scp))
}
return 0
}
+229
View File
@@ -0,0 +1,229 @@
package scopes
import (
"fmt"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/scopes"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/cmd/common"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/kr/pretty"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
var _ cli.Command = (*Command)(nil)
var _ cli.CommandAutocomplete = (*Command)(nil)
type Command struct {
*base.Command
Func string
}
func (c *Command) Synopsis() string {
return common.SynopsisFunc(c.Func, "scope")
}
var flagsMap = map[string][]string{
"create": {"name", "description"},
"update": {"id", "name", "description", "version"},
"read": {"id"},
"delete": {"id"},
}
func (c *Command) Help() string {
helpMap := common.HelpMap(resource.Scope)
if c.Func == "" {
return helpMap["base"]()
}
return helpMap[c.Func]() + "\n\n" + c.Flags().Help()
}
func (c *Command) Flags() *base.FlagSets {
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
f := set.NewFlagSet("Command Options")
common.PopulateCommonFlags(c.Command, f, resource.Scope, flagsMap[c.Func])
return set
}
func (c *Command) AutocompleteArgs() complete.Predictor {
return complete.PredictAnything
}
func (c *Command) AutocompleteFlags() complete.Flags {
return c.Flags().Completions()
}
func (c *Command) Run(args []string) int {
if c.Func == "" {
return cli.RunResultHelp
}
f := c.Flags()
if err := f.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
if strutil.StrListContains(flagsMap[c.Func], "id") && c.FlagId == "" {
c.UI.Error("ID is required but not passed in via -id")
return 1
}
client, err := c.Client()
if err != nil {
c.UI.Error(fmt.Sprintf("Error creating API client: %s", err.Error()))
return 2
}
var opts []scopes.Option
switch c.FlagName {
case "":
case "null":
opts = append(opts, scopes.DefaultName())
default:
opts = append(opts, scopes.WithName(c.FlagName))
}
switch c.FlagDescription {
case "":
case "null":
opts = append(opts, scopes.DefaultDescription())
default:
opts = append(opts, scopes.WithDescription(c.FlagDescription))
}
scopeClient := scopes.NewScopesClient(client)
// Perform check-and-set when needed
var version uint32
switch c.Func {
case "create", "read", "delete", "list":
// These don't udpate so don't need the existing version
default:
switch c.FlagVersion {
case 0:
opts = append(opts, scopes.WithAutomaticVersioning())
default:
version = uint32(c.FlagVersion)
}
}
var existed bool
var scope *scopes.Scope
var listedScopes []*scopes.Scope
var apiErr *api.Error
switch c.Func {
case "create":
scope, apiErr, err = scopeClient.Create(c.Context, client.ScopeId(), opts...)
case "update":
scope, apiErr, err = scopeClient.Update(c.Context, c.FlagId, version, opts...)
case "read":
scope, apiErr, err = scopeClient.Read(c.Context, c.FlagId, opts...)
case "delete":
existed, apiErr, err = scopeClient.Delete(c.Context, c.FlagId, opts...)
case "list":
listedScopes, apiErr, err = scopeClient.List(c.Context, client.ScopeId(), opts...)
}
plural := "scope"
if c.Func == "list" {
plural = "scopes"
}
if err != nil {
c.UI.Error(fmt.Sprintf("Error trying to %s %s: %s", c.Func, plural, err.Error()))
return 2
}
if apiErr != nil {
c.UI.Error(fmt.Sprintf("Error from controller when performing %s on %s: %s", c.Func, plural, pretty.Sprint(apiErr)))
return 1
}
switch c.Func {
case "delete":
switch base.Format(c.UI) {
case "json":
c.UI.Output("null")
case "table":
output := "The delete operation completed successfully"
switch existed {
case true:
output += "."
default:
output += ", however the resource did not exist at the time."
}
c.UI.Output(output)
}
return 0
case "list":
switch base.Format(c.UI) {
case "json":
if len(listedScopes) == 0 {
c.UI.Output("null")
return 0
}
b, err := base.JsonFormatter{}.Format(listedScopes)
if err != nil {
c.UI.Error(fmt.Errorf("Error formatting to JSON: %w", err).Error())
return 1
}
c.UI.Output(string(b))
case "table":
if len(listedScopes) == 0 {
c.UI.Output("No scopes found")
return 0
}
var output []string
output = []string{
"",
"Scope information:",
}
for i, s := range listedScopes {
if i > 0 {
output = append(output, "")
}
if true {
output = append(output,
fmt.Sprintf(" ID: %s", s.Id),
)
}
if s.Name != "" {
output = append(output,
fmt.Sprintf(" Name: %s", s.Name),
)
}
if s.Description != "" {
output = append(output,
fmt.Sprintf(" Description: %s", s.Description),
)
}
}
c.UI.Output(base.WrapForHelpText(output))
}
return 0
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(generateScopeTableOutput(scope))
case "json":
b, err := base.JsonFormatter{}.Format(scope)
if err != nil {
c.UI.Error(fmt.Errorf("Error formatting to JSON: %w", err).Error())
return 1
}
c.UI.Output(string(b))
}
return 0
}
+39
View File
@@ -0,0 +1,39 @@
package common
import (
"fmt"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/types/resource"
)
func PopulateCommonFlags(c *base.Command, f *base.FlagSet, resourceType resource.Type, flagNames []string) {
for _, name := range flagNames {
switch name {
case "id":
f.StringVar(&base.StringVar{
Name: "id",
Target: &c.FlagId,
Usage: fmt.Sprintf("ID of the %s on which to operate", resourceType.String()),
})
case "name":
f.StringVar(&base.StringVar{
Name: "name",
Target: &c.FlagName,
Usage: fmt.Sprintf("Name to set on the %s", resourceType.String()),
})
case "description":
f.StringVar(&base.StringVar{
Name: "description",
Target: &c.FlagDescription,
Usage: fmt.Sprintf("Description to set on the %s", resourceType.String()),
})
case "version":
f.IntVar(&base.IntVar{
Name: "version",
Target: &c.FlagVersion,
Usage: fmt.Sprintf("The version of the %s against which to perform an update operation. If not specified, the command will perform a check-and-set automatically.", resourceType.String()),
})
}
}
}
+107
View File
@@ -0,0 +1,107 @@
package common
import (
"fmt"
"net/textproto"
"strings"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/mitchellh/go-wordwrap"
)
func SynopsisFunc(inFunc, resourceType string) string {
if inFunc == "" {
return wordwrap.WrapString(fmt.Sprintf("Manage Boundary %ss", resourceType), base.TermWidth)
}
return wordwrap.WrapString(fmt.Sprintf("%s a %s within Boundary", textproto.CanonicalMIMEHeaderKey(inFunc), resourceType), base.TermWidth)
}
func HelpMap(resourceType resource.Type) map[string]func() string {
prefixMap := map[string]string{
resource.Scope.String(): "o",
resource.Role.String(): "r",
resource.Group.String(): "g",
resource.User.String(): "u",
}
return map[string]func() string{
"base": func() string {
return base.WrapForHelpText(subType([]string{
"Usage: boundary {{type}}s [sub command] [options] [args]",
"",
" This command allows operations on Boundary {{type}}s. Examples",
"",
" Create a {{type}}:",
"",
` $ boundary {{type}}s create -name prodops -description "For ProdOps usage"`,
"",
" Please see the {{type}}s subcommand help for detailed usage information.",
}, resourceType, prefixMap))
},
"create": func() string {
return base.WrapForHelpText(subType([]string{
"Usage: boundary {{type}}s create [options] [args]",
"",
" Create a {{type}}. Example:",
"",
` $ boundary {{type}}s create -name prodops -description "{{uppertype}} for ProdOps"`,
"",
"",
}, resourceType, prefixMap))
},
"update": func() string {
return base.WrapForHelpText(subType([]string{
"Usage: boundary {{type}}s update [options] [args]",
"",
" Update a {{type}} given its ID. Example:",
"",
` $ boundary {{type}}s update -id {{prefix}}_1234567890 -name "devops" -description "{{uppertype}} for DevOps"`,
}, resourceType, prefixMap))
},
"read": func() string {
return base.WrapForHelpText(subType([]string{
"Usage: boundary {{type}}s read [options] [args]",
"",
" Read a {{type}} given its ID. Example:",
"",
` $ boundary {{type}}s read -id {{prefix}}_1234567890`,
}, resourceType, prefixMap))
},
"delete": func() string {
return base.WrapForHelpText(subType([]string{
"Usage: boundary {{type}}s delete [options] [args]",
"",
" Delete a {{type}} given its ID. Example:",
"",
` $ boundary {{type}}s delete -id {{prefix}}_1234567890`,
}, resourceType, prefixMap))
},
"list": func() string {
return base.WrapForHelpText(subType([]string{
"Usage: boundary {{type}}s list [options] [args]",
"",
" List {{type}}s within an enclosing scope or resource. Example:",
"",
` $ boundary {{type}}s list`,
}, resourceType, prefixMap))
},
}
}
func subType(in []string, resType resource.Type, prefixMap map[string]string) []string {
for i, v := range in {
in[i] =
strings.Replace(
strings.Replace(
strings.Replace(
v, "{{type}}", resType.String(), -1),
"{{uppertype}}", textproto.CanonicalMIMEHeaderKey(resType.String()), -1),
"{{prefix}}", prefixMap[resType.String()], -1)
}
return in
}