Add alias CLI CRUDL commands (#4353)

* Add alias CLI CRUDL commands
This commit is contained in:
Todd committed 2024-02-29 15:51:24 -08:00
1 parent eceb1fd40e
commit 78e10864c4
18 files changed
+1218 -58

No files matched your search

+12 -1
View File
@@ -28,6 +28,7 @@ type Alias struct {
Version uint32 `json:"version,omitempty"`
Value string `json:"value,omitempty"`
DestinationId string `json:"destination_id,omitempty"`
Type string `json:"type,omitempty"`
Attributes map[string]interface{} `json:"attributes,omitempty"`
AuthorizedActions []string `json:"authorized_actions,omitempty"`
@@ -114,7 +115,7 @@ func (c *Client) ApiClient() *api.Client {
return c.client
}
func (c *Client) Create(ctx context.Context, scopeId string, opt ...Option) (*AliasCreateResult, error) {
func (c *Client) Create(ctx context.Context, resourceType string, alias string, scopeId string, opt ...Option) (*AliasCreateResult, error) {
if scopeId == "" {
return nil, fmt.Errorf("empty scopeId value passed into Create request")
}
@@ -124,6 +125,16 @@ func (c *Client) Create(ctx context.Context, scopeId string, opt ...Option) (*Al
if c.client == nil {
return nil, fmt.Errorf("nil client")
}
if resourceType == "" {
return nil, fmt.Errorf("empty resourceType value passed into Create request")
} else {
opts.postMap["type"] = resourceType
}
if alias == "" {
return nil, fmt.Errorf("empty alias value passed into Create request")
} else {
opts.postMap["value"] = alias
}
opts.postMap["scope_id"] = scopeId
@@ -0,0 +1,9 @@
// Code generated by "make api"; DO NOT EDIT.
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package aliases
type AuthorizeSessionArguments struct {
HostId string `json:"host_id,omitempty"`
}
@@ -0,0 +1,40 @@
// Code generated by "make api"; DO NOT EDIT.
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package aliases
import (
"fmt"
"github.com/mitchellh/mapstructure"
)
type TargetAliasAttributes struct {
AuthorizeSessionArguments *AuthorizeSessionArguments `json:"authorize_session_arguments,omitempty"`
}
func AttributesMapToTargetAliasAttributes(in map[string]interface{}) (*TargetAliasAttributes, error) {
if in == nil {
return nil, fmt.Errorf("nil input map")
}
var out TargetAliasAttributes
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Result: &out,
TagName: "json",
})
if err != nil {
return nil, fmt.Errorf("error creating mapstructure decoder: %w", err)
}
if err := dec.Decode(in); err != nil {
return nil, fmt.Errorf("error decoding: %w", err)
}
return &out, nil
}
func (pt *Alias) GetTargetAliasAttributes() (*TargetAliasAttributes, error) {
if pt.Type != "target" {
return nil, fmt.Errorf("asked to fetch %s-type attributes but alias is of type %s", "target", pt.Type)
}
return AttributesMapToTargetAliasAttributes(pt.Attributes)
}
+39 -1
View File
@@ -764,12 +764,50 @@ var inputStructs = []*structInfo{
},
// Alias related resources
{
inProto: &aliases.TargetAliasAttributes{},
outFile: "aliases/target_alias_attributes.gen.go",
subtypeName: "target",
parentTypeName: "Alias",
templates: []*template.Template{
mapstructureConversionTemplate,
},
},
{
inProto: &aliases.AuthorizeSessionArguments{},
outFile: "aliases/authorize_session_arguments.gen.go",
skipOptions: true,
},
{
inProto: &aliases.Alias{},
outFile: "aliases/alias.gen.go",
templates: []*template.Template{
clientTemplate,
commonCreateTemplate,
template.Must(template.New("").Funcs(
template.FuncMap{
"snakeCase": snakeCase,
"funcName": func() string {
return "Create"
},
"apiAction": func() string {
return ""
},
"extraRequiredParams": func() []requiredParam {
return []requiredParam{
{
Name: "resourceType",
Typ: "string",
PostType: "type",
},
{
Name: "alias",
Typ: "string",
PostType: "value",
},
}
},
},
).Parse(createTemplateStr)),
readTemplate,
updateTemplate,
deleteTemplate,
+2 -2
View File
@@ -470,8 +470,8 @@ func (c *Client) {{ funcName }} (ctx context.Context, {{ range extraRequiredPara
if c.client == nil {
return nil, fmt.Errorf("nil client")
}
{{ range extraRequiredParams }} if {{ .Name }} == "" {
}{{ range extraRequiredParams }}
if {{ .Name }} == "" {
return nil, fmt.Errorf("empty {{ .Name }} value passed into {{ funcName }} request")
} else {
opts.postMap["{{ .PostType }}"] = {{ .Name }}
+42
View File
@@ -6,6 +6,7 @@ package cmd
import (
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/cmd/commands/accountscmd"
"github.com/hashicorp/boundary/internal/cmd/commands/aliasescmd"
"github.com/hashicorp/boundary/internal/cmd/commands/authenticate"
"github.com/hashicorp/boundary/internal/cmd/commands/authmethodscmd"
"github.com/hashicorp/boundary/internal/cmd/commands/authtokenscmd"
@@ -157,6 +158,47 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
Func: "update",
}),
"aliases": func() (cli.Command, error) {
return &aliasescmd.Command{
Command: base.NewCommand(ui, opts...),
}, nil
},
"aliases read": clientCacheWrapper(
&aliasescmd.Command{
Command: base.NewCommand(ui, opts...),
Func: "read",
}),
"aliases delete": clientCacheWrapper(
&aliasescmd.Command{
Command: base.NewCommand(ui, opts...),
Func: "delete",
}),
"aliases list": clientCacheWrapper(
&aliasescmd.Command{
Command: base.NewCommand(ui, opts...),
Func: "list",
}),
"aliases create": clientCacheWrapper(
&aliasescmd.Command{
Command: base.NewCommand(ui, opts...),
Func: "create",
}),
"aliases update": clientCacheWrapper(
&aliasescmd.Command{
Command: base.NewCommand(ui, opts...),
Func: "update",
}),
"aliases create target": clientCacheWrapper(
&aliasescmd.TargetCommand{
Command: base.NewCommand(ui, opts...),
Func: "create",
}),
"aliases update target": clientCacheWrapper(
&aliasescmd.TargetCommand{
Command: base.NewCommand(ui, opts...),
Func: "update",
}),
"auth-methods": func() (cli.Command, error) {
return &authmethodscmd.Command{
Command: base.NewCommand(ui, opts...),
@@ -0,0 +1,308 @@
// Code generated by "make cli"; DO NOT EDIT.
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package aliasescmd
import (
"errors"
"fmt"
"sync"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/aliases"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/cmd/common"
"github.com/hashicorp/go-secure-stdlib/strutil"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
func initFlags() {
flagsOnce.Do(func() {
extraFlags := extraActionsFlagsMapFunc()
for k, v := range extraFlags {
flagsMap[k] = append(flagsMap[k], v...)
}
})
}
var (
_ cli.Command = (*Command)(nil)
_ cli.CommandAutocomplete = (*Command)(nil)
)
type Command struct {
*base.Command
Func string
plural string
}
func (c *Command) AutocompleteArgs() complete.Predictor {
initFlags()
return complete.PredictAnything
}
func (c *Command) AutocompleteFlags() complete.Flags {
initFlags()
return c.Flags().Completions()
}
func (c *Command) Synopsis() string {
if extra := extraSynopsisFunc(c); extra != "" {
return extra
}
synopsisStr := "alias"
return common.SynopsisFunc(c.Func, synopsisStr)
}
func (c *Command) Help() string {
initFlags()
var helpStr string
helpMap := common.HelpMap("alias")
switch c.Func {
case "read":
helpStr = helpMap[c.Func]() + c.Flags().Help()
case "delete":
helpStr = helpMap[c.Func]() + c.Flags().Help()
case "list":
helpStr = helpMap[c.Func]() + c.Flags().Help()
default:
helpStr = c.extraHelpFunc(helpMap)
}
// Keep linter from complaining if we don't actually generate code using it
_ = helpMap
return helpStr
}
var flagsMap = map[string][]string{
"read": {"id"},
"delete": {"id"},
"list": {"scope-id", "filter", "recursive"},
}
func (c *Command) Flags() *base.FlagSets {
if len(flagsMap[c.Func]) == 0 {
return c.FlagSet(base.FlagSetNone)
}
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
f := set.NewFlagSet("Command Options")
common.PopulateCommonFlags(c.Command, f, "alias", flagsMap, c.Func)
extraFlagsFunc(c, set, f)
return set
}
func (c *Command) Run(args []string) int {
initFlags()
switch c.Func {
case "":
return cli.RunResultHelp
case "create":
return cli.RunResultHelp
case "update":
return cli.RunResultHelp
}
c.plural = "alias"
switch c.Func {
case "list":
c.plural = "aliases"
}
f := c.Flags()
if err := f.Parse(args); err != nil {
c.PrintCliError(err)
return base.CommandUserError
}
if strutil.StrListContains(flagsMap[c.Func], "id") && c.FlagId == "" {
c.PrintCliError(errors.New("ID is required but not passed in via -id"))
return base.CommandUserError
}
var opts []aliases.Option
if strutil.StrListContains(flagsMap[c.Func], "scope-id") {
switch c.Func {
case "list":
if c.FlagScopeId == "" {
c.PrintCliError(errors.New("Scope ID must be passed in via -scope-id or BOUNDARY_SCOPE_ID"))
return base.CommandUserError
}
}
}
client, err := c.Client()
if c.WrapperCleanupFunc != nil {
defer func() {
if err := c.WrapperCleanupFunc(); err != nil {
c.PrintCliError(fmt.Errorf("Error cleaning kms wrapper: %w", err))
}
}()
}
if err != nil {
c.PrintCliError(fmt.Errorf("Error creating API client: %w", err))
return base.CommandCliError
}
aliasesClient := aliases.NewClient(client)
switch c.FlagRecursive {
case true:
opts = append(opts, aliases.WithRecursive(true))
}
if c.FlagFilter != "" {
opts = append(opts, aliases.WithFilter(c.FlagFilter))
}
var version uint32
if ok := extraFlagsHandlingFunc(c, f, &opts); !ok {
return base.CommandUserError
}
var resp *api.Response
var item *aliases.Alias
var items []*aliases.Alias
var readResult *aliases.AliasReadResult
var deleteResult *aliases.AliasDeleteResult
var listResult *aliases.AliasListResult
switch c.Func {
case "read":
readResult, err = aliasesClient.Read(c.Context, c.FlagId, opts...)
if exitCode := c.checkFuncError(err); exitCode > 0 {
return exitCode
}
resp = readResult.GetResponse()
item = readResult.GetItem()
case "delete":
deleteResult, err = aliasesClient.Delete(c.Context, c.FlagId, opts...)
if exitCode := c.checkFuncError(err); exitCode > 0 {
return exitCode
}
resp = deleteResult.GetResponse()
case "list":
listResult, err = aliasesClient.List(c.Context, c.FlagScopeId, opts...)
if exitCode := c.checkFuncError(err); exitCode > 0 {
return exitCode
}
resp = listResult.GetResponse()
items = listResult.GetItems()
}
resp, item, items, err = executeExtraActions(c, resp, item, items, err, aliasesClient, version, opts)
if exitCode := c.checkFuncError(err); exitCode > 0 {
return exitCode
}
output, err := printCustomActionOutput(c)
if err != nil {
c.PrintCliError(err)
return base.CommandUserError
}
if output {
return base.CommandSuccess
}
switch c.Func {
case "delete":
switch base.Format(c.UI) {
case "json":
if ok := c.PrintJsonItem(resp); !ok {
return base.CommandCliError
}
case "table":
c.UI.Output("The delete operation completed successfully.")
}
return base.CommandSuccess
case "list":
switch base.Format(c.UI) {
case "json":
if ok := c.PrintJsonItems(resp); !ok {
return base.CommandCliError
}
case "table":
c.UI.Output(c.printListTable(items))
}
return base.CommandSuccess
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(printItemTable(item, resp))
case "json":
if ok := c.PrintJsonItem(resp); !ok {
return base.CommandCliError
}
}
return base.CommandSuccess
}
func (c *Command) checkFuncError(err error) int {
if err == nil {
return 0
}
if apiErr := api.AsServerError(err); apiErr != nil {
c.PrintApiError(apiErr, fmt.Sprintf("Error from controller when performing %s on %s", c.Func, c.plural))
return base.CommandApiError
}
c.PrintCliError(fmt.Errorf("Error trying to %s %s: %s", c.Func, c.plural, err.Error()))
return base.CommandCliError
}
var (
flagsOnce = new(sync.Once)
extraActionsFlagsMapFunc = func() map[string][]string { return nil }
extraSynopsisFunc = func(*Command) string { return "" }
extraFlagsFunc = func(*Command, *base.FlagSets, *base.FlagSet) {}
extraFlagsHandlingFunc = func(*Command, *base.FlagSets, *[]aliases.Option) bool { return true }
executeExtraActions = func(_ *Command, inResp *api.Response, inItem *aliases.Alias, inItems []*aliases.Alias, inErr error, _ *aliases.Client, _ uint32, _ []aliases.Option) (*api.Response, *aliases.Alias, []*aliases.Alias, error) {
return inResp, inItem, inItems, inErr
}
printCustomActionOutput = func(*Command) (bool, error) { return false, nil }
)
+194
View File
@@ -0,0 +1,194 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package aliasescmd
import (
"fmt"
"time"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/aliases"
"github.com/hashicorp/boundary/internal/cmd/base"
)
type extraCmdVars struct {
flagMembers []string
}
func (c *Command) extraHelpFunc(helpMap map[string]func() string) string {
var helpStr string
switch c.Func {
case "":
return base.WrapForHelpText([]string{
"Usage: boundary aliases [sub command] [options] [args]",
"",
" This command allows operations on Boundary alias resources. Example:",
"",
" Read an alias:",
"",
` $ boundary aliases read -id alt_1234567890`,
"",
" Please see the aliases subcommand help for detailed usage information.",
})
case "create":
helpStr = base.WrapForHelpText([]string{
"Usage: boundary aliases create target [options] [args]",
"",
" Create an alias. Example:",
"",
` $ boundary aliases create target -value prod-ops.example -name prodops -description "Target alias for ProdOps"`,
"",
" Please see the typed subcommand help for detailed usage information.",
})
case "update":
helpStr = base.WrapForHelpText([]string{
"Usage: boundary aliases update target [options] [args]",
"",
" Update an alias. Example:",
"",
` $ boundary aliases update target -id alt_1234567890 -name devops`,
"",
" Please see the typed subcommand help for detailed usage information.",
})
default:
helpStr = ""
}
return helpStr + c.Flags().Help()
}
func (c *Command) printListTable(items []*aliases.Alias) string {
if len(items) == 0 {
return "No aliases found"
}
var output []string
output = []string{
"",
"Alias information:",
}
for i, item := range items {
if i > 0 {
output = append(output, "")
}
if item.Id != "" {
output = append(output,
fmt.Sprintf(" ID: %s", item.Id),
)
} else {
output = append(output,
fmt.Sprintf(" ID: %s", "(not available)"),
)
}
if c.FlagRecursive && item.ScopeId != "" {
output = append(output,
fmt.Sprintf(" Scope ID: %s", item.ScopeId),
)
}
if item.Version > 0 {
output = append(output,
fmt.Sprintf(" Version: %d", item.Version),
)
}
if item.Type != "" {
output = append(output,
fmt.Sprintf(" Type: %s", item.Type),
)
}
if item.Name != "" {
output = append(output,
fmt.Sprintf(" Name: %s", item.Name),
)
}
if item.Description != "" {
output = append(output,
fmt.Sprintf(" Description: %s", item.Description),
)
}
if item.Value != "" {
output = append(output,
fmt.Sprintf(" Value: %s", item.Value),
)
}
if item.DestinationId != "" {
output = append(output,
fmt.Sprintf(" Destination ID: %s", item.DestinationId),
)
}
if len(item.AuthorizedActions) > 0 {
output = append(output,
" Authorized Actions:",
base.WrapSlice(6, item.AuthorizedActions),
)
}
}
return base.WrapForHelpText(output)
}
func printItemTable(item *aliases.Alias, resp *api.Response) string {
nonAttributeMap := map[string]any{}
if item.Id != "" {
nonAttributeMap["ID"] = item.Id
}
if item.Version != 0 {
nonAttributeMap["Version"] = item.Version
}
if item.Type != "" {
nonAttributeMap["Type"] = item.Type
}
if !item.CreatedTime.IsZero() {
nonAttributeMap["Created Time"] = item.CreatedTime.Local().Format(time.RFC1123)
}
if !item.UpdatedTime.IsZero() {
nonAttributeMap["Updated Time"] = item.UpdatedTime.Local().Format(time.RFC1123)
}
if item.Name != "" {
nonAttributeMap["Name"] = item.Name
}
if item.Description != "" {
nonAttributeMap["Description"] = item.Description
}
if item.Value != "" {
nonAttributeMap["Value"] = item.Value
}
if item.DestinationId != "" {
nonAttributeMap["Destination ID"] = item.DestinationId
}
maxLength := base.MaxAttributesLength(nonAttributeMap, nil, nil)
ret := []string{
"",
"Alias information:",
base.WrapMap(2, maxLength+2, nonAttributeMap),
}
if item.Scope != nil {
ret = append(ret,
"",
" Scope:",
base.ScopeInfoForOutput(item.Scope, maxLength),
)
}
if len(item.AuthorizedActions) > 0 {
ret = append(ret,
"",
" Authorized Actions:",
base.WrapSlice(4, item.AuthorizedActions),
)
}
if len(item.Attributes) > 0 {
ret = append(ret,
"",
" Attributes:",
// TODO: This looks kind of ugly but it is used across boundary.
// Revisit the formatting of attributes that have nested maps.
base.WrapMap(4, maxLength+2, item.Attributes),
)
}
return base.WrapForHelpText(ret)
}
@@ -0,0 +1,273 @@
// Code generated by "make cli"; DO NOT EDIT.
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package aliasescmd
import (
"errors"
"fmt"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/aliases"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/cmd/common"
"github.com/hashicorp/go-secure-stdlib/strutil"
"github.com/mitchellh/cli"
"github.com/posener/complete"
)
func initTargetFlags() {
flagsOnce.Do(func() {
extraFlags := extraTargetActionsFlagsMapFunc()
for k, v := range extraFlags {
flagsTargetMap[k] = append(flagsTargetMap[k], v...)
}
})
}
var (
_ cli.Command = (*TargetCommand)(nil)
_ cli.CommandAutocomplete = (*TargetCommand)(nil)
)
type TargetCommand struct {
*base.Command
Func string
plural string
extraTargetCmdVars
}
func (c *TargetCommand) AutocompleteArgs() complete.Predictor {
initTargetFlags()
return complete.PredictAnything
}
func (c *TargetCommand) AutocompleteFlags() complete.Flags {
initTargetFlags()
return c.Flags().Completions()
}
func (c *TargetCommand) Synopsis() string {
if extra := extraTargetSynopsisFunc(c); extra != "" {
return extra
}
synopsisStr := "alias"
synopsisStr = fmt.Sprintf("%s %s", "target-type", synopsisStr)
return common.SynopsisFunc(c.Func, synopsisStr)
}
func (c *TargetCommand) Help() string {
initTargetFlags()
var helpStr string
helpMap := common.HelpMap("alias")
switch c.Func {
default:
helpStr = c.extraTargetHelpFunc(helpMap)
}
// Keep linter from complaining if we don't actually generate code using it
_ = helpMap
return helpStr
}
var flagsTargetMap = map[string][]string{
"create": {"scope-id", "name", "description"},
"update": {"id", "name", "description", "version"},
}
func (c *TargetCommand) Flags() *base.FlagSets {
if len(flagsTargetMap[c.Func]) == 0 {
return c.FlagSet(base.FlagSetNone)
}
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
f := set.NewFlagSet("Command Options")
common.PopulateCommonFlags(c.Command, f, "target-type alias", flagsTargetMap, c.Func)
extraTargetFlagsFunc(c, set, f)
return set
}
func (c *TargetCommand) Run(args []string) int {
initTargetFlags()
switch c.Func {
case "":
return cli.RunResultHelp
}
c.plural = "target-type alias"
switch c.Func {
case "list":
c.plural = "target-type aliases"
}
f := c.Flags()
if err := f.Parse(args); err != nil {
c.PrintCliError(err)
return base.CommandUserError
}
if strutil.StrListContains(flagsTargetMap[c.Func], "id") && c.FlagId == "" {
c.PrintCliError(errors.New("ID is required but not passed in via -id"))
return base.CommandUserError
}
var opts []aliases.Option
if strutil.StrListContains(flagsTargetMap[c.Func], "scope-id") {
switch c.Func {
case "create":
if c.FlagScopeId == "" {
c.PrintCliError(errors.New("Scope ID must be passed in via -scope-id or BOUNDARY_SCOPE_ID"))
return base.CommandUserError
}
}
}
client, err := c.Client()
if c.WrapperCleanupFunc != nil {
defer func() {
if err := c.WrapperCleanupFunc(); err != nil {
c.PrintCliError(fmt.Errorf("Error cleaning kms wrapper: %w", err))
}
}()
}
if err != nil {
c.PrintCliError(fmt.Errorf("Error creating API client: %w", err))
return base.CommandCliError
}
aliasesClient := aliases.NewClient(client)
switch c.FlagName {
case "":
case "null":
opts = append(opts, aliases.DefaultName())
default:
opts = append(opts, aliases.WithName(c.FlagName))
}
switch c.FlagDescription {
case "":
case "null":
opts = append(opts, aliases.DefaultDescription())
default:
opts = append(opts, aliases.WithDescription(c.FlagDescription))
}
switch c.FlagRecursive {
case true:
opts = append(opts, aliases.WithRecursive(true))
}
if c.FlagFilter != "" {
opts = append(opts, aliases.WithFilter(c.FlagFilter))
}
var version uint32
switch c.Func {
case "update":
switch c.FlagVersion {
case 0:
opts = append(opts, aliases.WithAutomaticVersioning(true))
default:
version = uint32(c.FlagVersion)
}
}
if ok := extraTargetFlagsHandlingFunc(c, f, &opts); !ok {
return base.CommandUserError
}
var resp *api.Response
var item *aliases.Alias
var updateResult *aliases.AliasUpdateResult
switch c.Func {
case "update":
updateResult, err = aliasesClient.Update(c.Context, c.FlagId, version, opts...)
if exitCode := c.checkFuncError(err); exitCode > 0 {
return exitCode
}
resp = updateResult.GetResponse()
item = updateResult.GetItem()
}
resp, item, err = executeExtraTargetActions(c, resp, item, err, aliasesClient, version, opts)
if exitCode := c.checkFuncError(err); exitCode > 0 {
return exitCode
}
output, err := printCustomTargetActionOutput(c)
if err != nil {
c.PrintCliError(err)
return base.CommandUserError
}
if output {
return base.CommandSuccess
}
switch c.Func {
}
switch base.Format(c.UI) {
case "table":
c.UI.Output(printItemTable(item, resp))
case "json":
if ok := c.PrintJsonItem(resp); !ok {
return base.CommandCliError
}
}
return base.CommandSuccess
}
func (c *TargetCommand) checkFuncError(err error) int {
if err == nil {
return 0
}
if apiErr := api.AsServerError(err); apiErr != nil {
c.PrintApiError(apiErr, fmt.Sprintf("Error from controller when performing %s on %s", c.Func, c.plural))
return base.CommandApiError
}
c.PrintCliError(fmt.Errorf("Error trying to %s %s: %s", c.Func, c.plural, err.Error()))
return base.CommandCliError
}
var (
extraTargetActionsFlagsMapFunc = func() map[string][]string { return nil }
extraTargetSynopsisFunc = func(*TargetCommand) string { return "" }
extraTargetFlagsFunc = func(*TargetCommand, *base.FlagSets, *base.FlagSet) {}
extraTargetFlagsHandlingFunc = func(*TargetCommand, *base.FlagSets, *[]aliases.Option) bool { return true }
executeExtraTargetActions = func(_ *TargetCommand, inResp *api.Response, inItem *aliases.Alias, inErr error, _ *aliases.Client, _ uint32, _ []aliases.Option) (*api.Response, *aliases.Alias, error) {
return inResp, inItem, inErr
}
printCustomTargetActionOutput = func(*TargetCommand) (bool, error) { return false, nil }
)
@@ -0,0 +1,148 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package aliasescmd
import (
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/aliases"
"github.com/hashicorp/boundary/internal/cmd/base"
)
func init() {
extraTargetActionsFlagsMapFunc = extraTargetActionsFlagsMapFuncImpl
extraTargetFlagsFunc = extraTargetFlagsFuncImpl
extraTargetFlagsHandlingFunc = extraTargetFlagHandlingFuncImpl
executeExtraTargetActions = executeExtraTargetActionsImpl
}
type extraTargetCmdVars struct {
flagValue string
flagDestinationId string
flagAuthorizeSessionHostId string
}
func extraTargetActionsFlagsMapFuncImpl() map[string][]string {
return map[string][]string{
"create": {"value", "destination-id", "authorize-session-host-id"},
"update": {"value", "destination-id", "authorize-session-host-id"},
}
}
func (c *TargetCommand) extraTargetHelpFunc(helpMap map[string]func() string) string {
var helpStr string
switch c.Func {
case "":
return base.WrapForHelpText([]string{
"Usage: boundary aliases [sub command] [options] [args]",
"",
" This command allows operations on Boundary alias resources. Example:",
"",
" Read an alias:",
"",
` $ boundary aliases read -id alt_1234567890`,
"",
" Please see the aliases subcommand help for detailed usage information.",
})
case "create":
helpStr = base.WrapForHelpText([]string{
"Usage: boundary aliases create target [options] [args]",
"",
" Create a target-type alias. Example:",
"",
` $ boundary aliases create target -value prod-ops.example -name prodops -description "Target alias for ProdOps"`,
"",
"",
})
case "update":
helpStr = base.WrapForHelpText([]string{
"Usage: boundary aliases update target [options] [args]",
"",
" Update an alias. Example:",
"",
` $ boundary aliases update target -id alt_1234567890 -name devops`,
"",
"",
})
}
return helpStr + c.Flags().Help()
}
func extraTargetFlagsFuncImpl(c *TargetCommand, set *base.FlagSets, f *base.FlagSet) {
for _, name := range flagsTargetMap[c.Func] {
switch name {
case "value":
f.StringVar(&base.StringVar{
Name: "value",
Target: &c.flagValue,
Usage: "The value of the alias",
})
case "destination-id":
f.StringVar(&base.StringVar{
Name: "destination-id",
Target: &c.flagDestinationId,
Usage: "The target id that the alias points to.",
})
}
}
f = set.NewFlagSet("Target Alias Options")
for _, name := range flagsTargetMap[c.Func] {
switch name {
case "authorize-session-host-id":
f.StringVar(&base.StringVar{
Name: "authorize-session-host-id",
Target: &c.flagAuthorizeSessionHostId,
Usage: "The host id to pass in when authorizing a session with this alias.",
})
}
}
}
func extraTargetFlagHandlingFuncImpl(c *TargetCommand, _ *base.FlagSets, opts *[]aliases.Option) bool {
var attributes map[string]any
addAttribute := func(name string, value any) {
if attributes == nil {
attributes = make(map[string]any)
}
attributes[name] = value
}
switch c.flagDestinationId {
case "":
case "null":
*opts = append(*opts, aliases.DefaultDestinationId())
default:
*opts = append(*opts, aliases.WithDestinationId(c.flagDestinationId))
}
switch c.flagAuthorizeSessionHostId {
case "":
case "null":
addAttribute("authorize_session_arguments", nil)
default:
asa := aliases.AuthorizeSessionArguments{HostId: c.flagAuthorizeSessionHostId}
addAttribute("authorize_session_arguments", asa)
}
if attributes != nil {
*opts = append(*opts, aliases.WithAttributes(attributes))
}
return true
}
func executeExtraTargetActionsImpl(c *TargetCommand, inResp *api.Response, inItem *aliases.Alias, inErr error, aliasesClient *aliases.Client, version uint32, opts []aliases.Option) (*api.Response, *aliases.Alias, error) {
switch c.Func {
case "create":
// we specify our own create action here because we have more required
// fields in the sdk than is specified in the templates for all the other
// resources.
createResult, err := aliasesClient.Create(c.Context, "target", c.flagValue, c.FlagScopeId, opts...)
if err != nil {
return nil, nil, err
}
return createResult.GetResponse(), createResult.GetItem(), nil
}
return inResp, inItem, inErr
}
+1
View File
@@ -47,6 +47,7 @@ func HelpMap(resType string) map[string]func() string {
resource.SessionRecording.String(): "sr",
resource.StorageBucket.String(): "sb",
resource.Policy.String(): "p",
resource.Alias.String(): "alt",
}
return map[string]func() string{
"base": func() string {
+26
View File
@@ -150,6 +150,32 @@ var inputStructs = map[string][]*cmdInfo{
VersionedActions: []string{"update"},
},
},
"aliases": {
{
ResourceType: resource.Alias.String(),
Pkg: "aliases",
StdActions: []string{"read", "delete", "list"},
HasExtraHelpFunc: true,
Container: "Scope",
HasId: true,
},
{
ResourceType: resource.Alias.String(),
Pkg: "aliases",
StdActions: []string{"create", "update"},
SubActionPrefix: "target",
HasExtraCommandVars: true,
SkipNormalHelp: true,
HasExtraHelpFunc: true,
HasId: true,
HasName: true,
HasDescription: true,
Container: "Scope",
VersionedActions: []string{"update"},
NeedsSubtypeInCreate: true,
SkipClientCallActions: []string{"create"},
},
},
"authmethods": {
{
ResourceType: resource.AuthMethod.String(),
@@ -6,6 +6,7 @@ package aliases
import (
"context"
"fmt"
"strings"
"github.com/hashicorp/boundary/globals"
"github.com/hashicorp/boundary/internal/alias/target"
@@ -49,6 +50,8 @@ var (
)
)
const aliasTypeTarget = "target"
func init() {
var err error
if maskManager, err = handlers.NewMaskManager(
@@ -522,6 +525,9 @@ func toProto(ctx context.Context, in *target.Alias, opt ...handlers.Option) (*pb
if outputFields.Has(globals.ScopeIdField) {
out.ScopeId = in.GetScopeId()
}
if outputFields.Has(globals.TypeField) {
out.Type = aliasTypeTarget
}
if outputFields.Has(globals.NameField) && in.GetName() != "" {
out.Name = wrapperspb.String(in.GetName())
}
@@ -576,8 +582,14 @@ func validateCreateRequest(req *pbs.CreateAliasRequest) error {
if scope.Global.String() != req.GetItem().GetScopeId() {
badFields["scope_id"] = "This field is missing or improperly formatted."
}
if req.GetItem().GetValue() == "" {
badFields[globals.ValueField] = "This field is required."
}
if !strings.EqualFold(req.GetItem().GetType(), aliasTypeTarget) {
badFields[globals.TypeField] = "This field is required. Current supported values are 'target'."
}
if req.GetItem().GetTargetAliasAttributes().GetAuthorizeSessionArguments().GetHostId() != "" && req.GetItem().GetDestinationId().GetValue() == "" {
badFields["destination_id"] = "This field is required when 'attributes.authorize_sesion_arguments.host_id' is specified."
badFields[globals.DestinationIdField] = "This field is required when 'attributes.authorize_sesion_arguments.host_id' is specified."
}
return badFields
})
@@ -68,6 +68,7 @@ func TestGet(t *testing.T) {
globalScopeInfo := &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String(), Name: "global", Description: "Global Scope"}
wantAlias := &pb.Alias{
Type: "target",
Id: og.GetPublicId(),
ScopeId: "global",
Scope: globalScopeInfo,
@@ -166,6 +167,7 @@ func TestList(t *testing.T) {
for i := 0; i < 10; i++ {
gg := target.TestAlias(t, rw, fmt.Sprintf("test%d.alias", i))
wantGlobalAliass = append(wantGlobalAliass, &pb.Alias{
Type: "target",
Id: gg.GetPublicId(),
ScopeId: gg.GetScopeId(),
Scope: &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String(), Name: "global", Description: "Global Scope"},
@@ -261,6 +263,7 @@ func TestList(t *testing.T) {
func aliasToProto(u *target.Alias, si *scopes.ScopeInfo, authorizedActions []string) *pb.Alias {
pu := &pb.Alias{
Type: "target",
Id: u.GetPublicId(),
Value: u.GetValue(),
ScopeId: u.GetScopeId(),
@@ -737,12 +740,14 @@ func TestCreate(t *testing.T) {
{
name: "Create a valid Alias",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
Value: "valid.alias",
}},
res: &pbs.CreateAliasResponse{
Uri: fmt.Sprintf("aliases/%s_", globals.TargetAliasPrefix),
Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
Scope: globalScopeInfo,
Value: "valid.alias",
@@ -754,6 +759,7 @@ func TestCreate(t *testing.T) {
{
name: "Alias to existing target",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
Value: "target-assigned.valid.alias",
DestinationId: wrapperspb.String(tar.GetPublicId()),
@@ -761,6 +767,7 @@ func TestCreate(t *testing.T) {
res: &pbs.CreateAliasResponse{
Uri: fmt.Sprintf("aliases/%s_", globals.TargetAliasPrefix),
Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
Scope: globalScopeInfo,
Value: "target-assigned.valid.alias",
@@ -770,9 +777,19 @@ func TestCreate(t *testing.T) {
},
},
},
{
name: "Omitting the alias type",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
ScopeId: scope.Global.String(),
Value: "target-assigned.valid.alias",
DestinationId: wrapperspb.String(tar.GetPublicId()),
}},
errContains: `This field is required`,
},
{
name: "host id with no destination target",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
Value: "host-id.no-destination.alias",
Attrs: &pb.Alias_TargetAliasAttributes{
@@ -788,6 +805,7 @@ func TestCreate(t *testing.T) {
{
name: "Alias to non existing target",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
Value: "unknowntarget.alias",
DestinationId: wrapperspb.String("ttcp_1234567890"),
@@ -797,6 +815,7 @@ func TestCreate(t *testing.T) {
{
name: "Duplicate Alias Value",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
Value: al.GetValue(),
}},
@@ -805,6 +824,7 @@ func TestCreate(t *testing.T) {
{
name: "Duplicate Alias Name",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
Value: "duplicate.alias.name",
Name: wrapperspb.String(al.GetName()),
@@ -814,6 +834,7 @@ func TestCreate(t *testing.T) {
{
name: "must be in global scope",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
Type: "target",
ScopeId: p.GetPublicId(),
Value: "must.be.in.global.scope",
}},
@@ -822,6 +843,7 @@ func TestCreate(t *testing.T) {
{
name: "Can't specify Id",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
Id: globals.TargetAliasPrefix + "_notallowed",
}},
@@ -831,6 +853,7 @@ func TestCreate(t *testing.T) {
{
name: "Can't specify Created Time",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
CreatedTime: timestamppb.Now(),
}},
@@ -840,6 +863,7 @@ func TestCreate(t *testing.T) {
{
name: "Can't specify Update Time",
req: &pbs.CreateAliasRequest{Item: &pb.Alias{
Type: "target",
ScopeId: scope.Global.String(),
UpdatedTime: timestamppb.Now(),
}},
@@ -942,6 +966,7 @@ func TestUpdate(t *testing.T) {
},
res: &pbs.UpdateAliasResponse{
Item: &pb.Alias{
Type: "target",
Id: og.GetPublicId(),
ScopeId: og.GetScopeId(),
Scope: globalScopeInfo,
@@ -968,6 +993,7 @@ func TestUpdate(t *testing.T) {
},
res: &pbs.UpdateAliasResponse{
Item: &pb.Alias{
Type: "target",
Id: og.GetPublicId(),
ScopeId: og.GetScopeId(),
Scope: globalScopeInfo,
@@ -1024,6 +1050,7 @@ func TestUpdate(t *testing.T) {
},
res: &pbs.UpdateAliasResponse{
Item: &pb.Alias{
Type: "target",
Id: og.GetPublicId(),
ScopeId: og.GetScopeId(),
Scope: globalScopeInfo,
@@ -1049,6 +1076,7 @@ func TestUpdate(t *testing.T) {
},
res: &pbs.UpdateAliasResponse{
Item: &pb.Alias{
Type: "target",
Id: og.GetPublicId(),
Name: wrapperspb.String("updated"),
ScopeId: og.GetScopeId(),
@@ -1075,6 +1103,7 @@ func TestUpdate(t *testing.T) {
},
res: &pbs.UpdateAliasResponse{
Item: &pb.Alias{
Type: "target",
Id: og.GetPublicId(),
ScopeId: og.GetScopeId(),
Scope: globalScopeInfo,
@@ -1114,6 +1143,7 @@ func TestUpdate(t *testing.T) {
},
res: &pbs.UpdateAliasResponse{
Item: &pb.Alias{
Type: "target",
Id: og.GetPublicId(),
ScopeId: og.GetScopeId(),
Scope: globalScopeInfo,
@@ -1139,6 +1169,7 @@ func TestUpdate(t *testing.T) {
},
res: &pbs.UpdateAliasResponse{
Item: &pb.Alias{
Type: "target",
Id: og.GetPublicId(),
ScopeId: og.GetScopeId(),
Scope: globalScopeInfo,
@@ -1163,6 +1194,7 @@ func TestUpdate(t *testing.T) {
},
res: &pbs.UpdateAliasResponse{
Item: &pb.Alias{
Type: "target",
Id: og.GetPublicId(),
ScopeId: og.GetScopeId(),
Scope: globalScopeInfo,
+4
View File
@@ -4856,6 +4856,10 @@
"type": "string",
"description": "destination_id is the id of the resource that this Alias points to."
},
"type": {
"type": "string",
"description": "type is the type of the alias."
},
"attributes": {
"type": "object",
"description": "The attributes that are applicable for the specific Alias type."
@@ -73,13 +73,16 @@ message Alias {
}
]; // @gotags: `class:"public" eventstream:"observation"`
// type is the type of the alias.
string type = 110; // @gotags: `class:"public" eventstream:"observation"`
oneof attrs {
// The attributes that are applicable for the specific Alias type.
google.protobuf.Struct attributes = 110 [
google.protobuf.Struct attributes = 120 [
(custom_options.v1.generate_sdk_option) = true,
(custom_options.v1.subtype) = "default"
];
TargetAliasAttributes target_alias_attributes = 101 [
TargetAliasAttributes target_alias_attributes = 121 [
(google.api.field_visibility).restriction = "INTERNAL",
(custom_options.v1.generate_sdk_option) = true,
(custom_options.v1.subtype) = "target"
+15 -6
View File
@@ -36,7 +36,7 @@ func TestList(t *testing.T) {
expected := lr.Items
assert.Len(expected, 0)
cr, err := aliasClient.Create(tc.Context(), scopeId, aliases.WithValue("alias0"))
cr, err := aliasClient.Create(tc.Context(), "target", "alias0", scopeId)
require.NoError(err)
require.NotNil(cr)
expected = append(expected, cr.Item)
@@ -46,7 +46,7 @@ func TestList(t *testing.T) {
assert.ElementsMatch(comparableSlice(expected[:1]), comparableSlice(ulResult.Items))
for i := 1; i < 10; i++ {
newAcctResult, err := aliasClient.Create(tc.Context(), scopeId, aliases.WithValue(fmt.Sprintf("alias%d", i)))
newAcctResult, err := aliasClient.Create(tc.Context(), "target", fmt.Sprintf("alias%d", i), scopeId)
require.NoError(err)
expected = append(expected, newAcctResult.Item)
}
@@ -101,7 +101,7 @@ func TestCrud(t *testing.T) {
assert.EqualValues(wantedVersion, u.Version)
}
u, err := aliasClient.Create(tc.Context(), scopeId, aliases.WithValue("alias.value"))
u, err := aliasClient.Create(tc.Context(), "target", "alias.value", scopeId)
checkAlias("create", u.Item, err, "alias.value", 1)
u, err = aliasClient.Read(tc.Context(), u.Item.Id)
@@ -126,14 +126,23 @@ func TestErrors(t *testing.T) {
client.SetToken(token.Token)
aliasClient := aliases.NewClient(client)
u, err := aliasClient.Create(tc.Context(), scopeId, aliases.WithValue("first"))
u, err := aliasClient.Create(tc.Context(), "target", "first", scopeId)
require.NoError(err)
assert.NotNil(u)
// Creating an alias of an unknown type
_, err = aliasClient.Create(tc.Context(), "unknown", "first", scopeId)
require.Error(err)
apiErr := api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Response().StatusCode())
require.Len(apiErr.Details.RequestFields, 1)
assert.Equal(apiErr.Details.RequestFields[0].Name, "type")
// A malformed id is processed as the id and not a different path to the api.
_, err = aliasClient.Read(tc.Context(), fmt.Sprintf("%s/../", u.Item.Id))
require.Error(err)
apiErr := api.AsServerError(err)
apiErr = api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Response().StatusCode())
require.Len(apiErr.Details.RequestFields, 1)
@@ -147,7 +156,7 @@ func TestErrors(t *testing.T) {
assert.EqualValues(http.StatusNotFound, apiErr.Response().StatusCode())
// Create another resource with the same name.
_, err = aliasClient.Create(tc.Context(), scopeId, aliases.WithValue("first"))
_, err = aliasClient.Create(tc.Context(), "target", "first", scopeId)
require.Error(err)
apiErr = api.AsServerError(err)
require.NotNil(apiErr)
@@ -57,6 +57,8 @@ type Alias struct {
Value string `protobuf:"bytes,90,opt,name=value,proto3" json:"value,omitempty" class:"public"` // @gotags: `class:"public"`
// destination_id is the id of the resource that this Alias points to.
DestinationId *wrapperspb.StringValue `protobuf:"bytes,100,opt,name=destination_id,proto3" json:"destination_id,omitempty" class:"public" eventstream:"observation"` // @gotags: `class:"public" eventstream:"observation"`
// type is the type of the alias.
Type string `protobuf:"bytes,110,opt,name=type,proto3" json:"type,omitempty" class:"public" eventstream:"observation"` // @gotags: `class:"public" eventstream:"observation"`
// Types that are assignable to Attrs:
//
// *Alias_Attributes
@@ -168,6 +170,13 @@ func (x *Alias) GetDestinationId() *wrapperspb.StringValue {
return nil
}
func (x *Alias) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (m *Alias) GetAttrs() isAlias_Attrs {
if m != nil {
return m.Attrs
@@ -202,11 +211,11 @@ type isAlias_Attrs interface {
type Alias_Attributes struct {
// The attributes that are applicable for the specific Alias type.
Attributes *structpb.Struct `protobuf:"bytes,110,opt,name=attributes,proto3,oneof"`
Attributes *structpb.Struct `protobuf:"bytes,120,opt,name=attributes,proto3,oneof"`
}
type Alias_TargetAliasAttributes struct {
TargetAliasAttributes *TargetAliasAttributes `protobuf:"bytes,101,opt,name=target_alias_attributes,json=targetAliasAttributes,proto3,oneof"`
TargetAliasAttributes *TargetAliasAttributes `protobuf:"bytes,121,opt,name=target_alias_attributes,json=targetAliasAttributes,proto3,oneof"`
}
func (*Alias_Attributes) isAlias_Attrs() {}
@@ -335,8 +344,8 @@ var file_controller_api_resources_aliases_v1_alias_proto_rawDesc = []byte{
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf8,
0x06, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a,
0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8c,
0x07, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a,
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70,
0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70,
0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x1e, 0x20,
@@ -373,48 +382,49 @@ var file_controller_api_resources_aliases_v1_alias_proto_rawDesc = []byte{
0x6c, 0x75, 0x65, 0x42, 0x27, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x1f, 0x0a, 0x0e, 0x64,
0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x12, 0x0d, 0x44,
0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x0e, 0x64, 0x65,
0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x12, 0x4a, 0x0a, 0x0a,
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x0f, 0xa0, 0xda, 0x29, 0x01, 0x9a,
0xe3, 0x29, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x74,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x94, 0x01, 0x0a, 0x17, 0x74, 0x61, 0x72,
0x67, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,
0x75, 0x74, 0x65, 0x73, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x63, 0x6f, 0x6e,
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f,
0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x2e, 0x76, 0x31,
0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x41, 0x74, 0x74, 0x72,
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x1e, 0xa0, 0xda, 0x29, 0x01, 0x9a, 0xe3, 0x29, 0x06,
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0xfa, 0xd2, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x49, 0x4e,
0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x48, 0x00, 0x52, 0x15, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
0x41, 0x6c, 0x69, 0x61, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12,
0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x42, 0x07, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x22, 0x9a, 0x01, 0x0a, 0x15, 0x54, 0x61,
0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04,
0x74, 0x79, 0x70, 0x65, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
0x12, 0x4a, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x78,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x0f, 0xa0,
0xda, 0x29, 0x01, 0x9a, 0xe3, 0x29, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x00,
0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x94, 0x01, 0x0a,
0x17, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x5f, 0x61, 0x74,
0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x79, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a,
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65,
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73,
0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x1e, 0xa0, 0xda, 0x29, 0x01,
0x9a, 0xe3, 0x29, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0xfa, 0xd2, 0xe4, 0x93, 0x02, 0x0a,
0x12, 0x08, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x48, 0x00, 0x52, 0x15, 0x74, 0x61,
0x72, 0x67, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
0x74, 0x65, 0x73, 0x12, 0x80, 0x01, 0x0a, 0x1b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x2e, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x1b, 0x61, 0x75, 0x74, 0x68, 0x6f,
0x72, 0x69, 0x7a, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x67,
0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7a, 0x0a, 0x19, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65,
0x6e, 0x74, 0x73, 0x12, 0x5d, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x64,
0x20, 0x01, 0x28, 0x09, 0x42, 0x40, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x38, 0x0a, 0x2e,
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x6f,
0x72, 0x69, 0x7a, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x67,
0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x12, 0x06,
0x48, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x52, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61,
0x6d, 0x65, 0x42, 0x50, 0x5a, 0x4e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64,
0x61, 0x72, 0x79, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x62, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75,
0x72, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x3b, 0x61, 0x6c, 0x69,
0x61, 0x73, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x74, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65,
0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09,
0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x22, 0x9a, 0x01,
0x0a, 0x15, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x41, 0x74, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x80, 0x01, 0x0a, 0x1b, 0x61, 0x75, 0x74, 0x68,
0x6f, 0x72, 0x69, 0x7a, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72,
0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73,
0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73,
0x73, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x1b, 0x61,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
0x5f, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7a, 0x0a, 0x19, 0x41, 0x75,
0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x41, 0x72,
0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x5d, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f,
0x69, 0x64, 0x18, 0x64, 0x20, 0x01, 0x28, 0x09, 0x42, 0x40, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd,
0x29, 0x38, 0x0a, 0x2e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x61,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
0x5f, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x5f,
0x69, 0x64, 0x12, 0x06, 0x48, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x52, 0x0a, 0x6c, 0x6f, 0x67, 0x69,
0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x50, 0x5a, 0x4e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62,
0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x62, 0x73, 0x2f,
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72,
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73,
0x3b, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (