Add more host-catalog and host-set CLI support (#1567)
Add more host-catalog and host-set CLI support Co-authored-by: Todd <T.Alan.Knight@gmail.com>
This commit is contained in:
1 parent
a834a14785
commit
7d71618df0
37 files changed
+803
-406
No files matched your search
@@ -1,6 +1,7 @@
|
||||
package hostcatalogs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -123,8 +124,26 @@ func DefaultName() Option {
|
||||
}
|
||||
}
|
||||
|
||||
func WithPluginId(inPluginId string) Option {
|
||||
return func(o *options) {
|
||||
o.postMap["plugin_id"] = inPluginId
|
||||
}
|
||||
}
|
||||
|
||||
func WithPluginName(inPluginName string) Option {
|
||||
return func(o *options) {
|
||||
o.queryMap["plugin_name"] = fmt.Sprintf("%v", inPluginName)
|
||||
}
|
||||
}
|
||||
|
||||
func WithSecrets(inSecrets map[string]interface{}) Option {
|
||||
return func(o *options) {
|
||||
o.postMap["secrets"] = inSecrets
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultSecrets() Option {
|
||||
return func(o *options) {
|
||||
o.postMap["secrets"] = nil
|
||||
}
|
||||
}
|
||||
@@ -61,4 +61,5 @@ const (
|
||||
PreferredEndpointsField = "preferred_endpoints"
|
||||
PluginIdField = "plugin_id"
|
||||
PluginField = "plugin"
|
||||
PluginNameField = "plugin_name"
|
||||
)
|
||||
@@ -95,13 +95,13 @@ type structInfo struct {
|
||||
// listing
|
||||
recursiveListing bool
|
||||
|
||||
// extraOptions allows specifying extra options that will be created for a
|
||||
// extraFields allows specifying extra options that will be created for a
|
||||
// given type, e.g. arguments only valid for one call or purpose and not
|
||||
// conveyed within the item itself
|
||||
extraOptions []fieldInfo
|
||||
extraFields []fieldInfo
|
||||
|
||||
// fieldOverrides allows overriding some field behavior without making them
|
||||
// "new" fields like with extraOptions
|
||||
// "new" fields like with extraFields
|
||||
fieldOverrides []fieldInfo
|
||||
|
||||
// createResponseTypes controls for which structs response types are created
|
||||
@@ -156,7 +156,7 @@ var inputStructs = []*structInfo{
|
||||
listTemplate,
|
||||
},
|
||||
pluralResourceName: "scopes",
|
||||
extraOptions: []fieldInfo{
|
||||
extraFields: []fieldInfo{
|
||||
{
|
||||
Name: "SkipAdminRoleCreation",
|
||||
ProtoName: "skip_admin_role_creation",
|
||||
@@ -508,9 +508,18 @@ var inputStructs = []*structInfo{
|
||||
deleteTemplate,
|
||||
listTemplate,
|
||||
},
|
||||
extraFields: []fieldInfo{
|
||||
{
|
||||
Name: "PluginName",
|
||||
ProtoName: "plugin_name",
|
||||
FieldType: "string",
|
||||
SkipDefault: true,
|
||||
Query: true,
|
||||
},
|
||||
},
|
||||
fieldOverrides: []fieldInfo{
|
||||
{
|
||||
Name: "Secrets",
|
||||
Name: "PluginId",
|
||||
SkipDefault: true,
|
||||
},
|
||||
},
|
||||
@@ -632,7 +641,7 @@ var inputStructs = []*structInfo{
|
||||
"CredentialLibraries": {},
|
||||
"CredentialSources": {},
|
||||
},
|
||||
extraOptions: []fieldInfo{
|
||||
extraFields: []fieldInfo{
|
||||
{
|
||||
Name: "HostId",
|
||||
ProtoName: "host_id",
|
||||
|
||||
@@ -44,7 +44,7 @@ type templateInput struct {
|
||||
ResourcePath string
|
||||
ParentTypeName string
|
||||
SliceSubtypes map[string]sliceSubtypeInfo
|
||||
ExtraOptions []fieldInfo
|
||||
ExtraFields []fieldInfo
|
||||
VersionEnabled bool
|
||||
TypeOnCreate bool
|
||||
CreateResponseTypes bool
|
||||
@@ -63,7 +63,7 @@ func fillTemplates() {
|
||||
Fields: in.generatedStructure.fields,
|
||||
PluralResourceName: in.pluralResourceName,
|
||||
ParentTypeName: in.parentTypeName,
|
||||
ExtraOptions: in.extraOptions,
|
||||
ExtraFields: in.extraFields,
|
||||
VersionEnabled: in.versionEnabled,
|
||||
TypeOnCreate: in.typeOnCreate,
|
||||
CreateResponseTypes: in.createResponseTypes,
|
||||
@@ -129,13 +129,13 @@ func fillTemplates() {
|
||||
}
|
||||
optionsMap[input.Package] = optionMap
|
||||
}
|
||||
// Add in extra defined options
|
||||
if len(in.extraOptions) > 0 {
|
||||
// Add in extra defined fields
|
||||
if len(in.extraFields) > 0 {
|
||||
optionMap := optionsMap[input.Package]
|
||||
if optionMap == nil {
|
||||
optionMap = map[string]fieldInfo{}
|
||||
}
|
||||
for _, val := range in.extraOptions {
|
||||
for _, val := range in.extraFields {
|
||||
optionMap[val.Name] = val
|
||||
}
|
||||
optionsMap[input.Package] = optionMap
|
||||
|
||||
@@ -73,6 +73,8 @@ type Command struct {
|
||||
|
||||
FlagScopeId string
|
||||
FlagScopeName string
|
||||
FlagPluginId string
|
||||
FlagPluginName string
|
||||
FlagId string
|
||||
FlagName string
|
||||
FlagDescription string
|
||||
@@ -87,6 +89,10 @@ type Command struct {
|
||||
FlagAttributes string
|
||||
FlagAttrs []CombinedSliceFlagValue
|
||||
|
||||
// Secret values
|
||||
FlagSecrets string
|
||||
FlagScrts []CombinedSliceFlagValue
|
||||
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/observability/event"
|
||||
hostplugin "github.com/hashicorp/boundary/internal/plugin/host"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"github.com/hashicorp/boundary/testing/dbtest"
|
||||
capoidc "github.com/hashicorp/cap/oidc"
|
||||
@@ -100,8 +101,6 @@ func (b *Server) CreateDevDatabase(ctx context.Context, opt ...Option) error {
|
||||
return err
|
||||
}
|
||||
|
||||
b.Database.LogMode(true)
|
||||
|
||||
if err := b.CreateGlobalKmsKeys(ctx); err != nil {
|
||||
if c != nil {
|
||||
err = multierror.Append(err, c())
|
||||
@@ -144,6 +143,19 @@ func (b *Server) CreateDevDatabase(ctx context.Context, opt ...Option) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if opts.withHostPlugin != nil {
|
||||
pluginId, plg := opts.withHostPlugin()
|
||||
b.DevLoopbackHostPluginId = pluginId
|
||||
opts := []hostplugin.Option{
|
||||
hostplugin.WithName("loopback"),
|
||||
hostplugin.WithDescription("Provides an initial loopback host plugin in Boundary"),
|
||||
hostplugin.WithPublicId(b.DevLoopbackHostPluginId),
|
||||
}
|
||||
if _, err = b.CreateHostPlugin(ctx, plg, opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if opts.withSkipHostResourcesCreation {
|
||||
// now that we have passed all the error cases, reset c to be a noop so the
|
||||
// defer doesn't do anything.
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/plugins"
|
||||
"github.com/hashicorp/boundary/api/scopes"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/mitchellh/go-wordwrap"
|
||||
@@ -34,6 +35,17 @@ func ScopeInfoForOutput(scp *scopes.ScopeInfo, maxLength int) string {
|
||||
return WrapMap(4, maxLength, vals)
|
||||
}
|
||||
|
||||
func PluginInfoForOutput(plg *plugins.PluginInfo, maxLength int) string {
|
||||
if plg == nil {
|
||||
return " <not included in response>"
|
||||
}
|
||||
vals := map[string]interface{}{
|
||||
"ID": plg.Id,
|
||||
"Name": plg.Name,
|
||||
}
|
||||
return WrapMap(4, maxLength, vals)
|
||||
}
|
||||
|
||||
func MaxAttributesLength(nonAttributesMap, attributesMap map[string]interface{}, keySubstMap map[string]string) int {
|
||||
// We always print a scope ID and in some cases this particular key ends up
|
||||
// being the longest key, so start with it as a baseline. It's always
|
||||
|
||||
@@ -10,9 +10,11 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/host/static"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
hostplugin "github.com/hashicorp/boundary/internal/plugin/host"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller/auth"
|
||||
"github.com/hashicorp/boundary/internal/target"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/hashicorp/go-secure-stdlib/base62"
|
||||
)
|
||||
|
||||
@@ -584,3 +586,49 @@ func (b *Server) CreateInitialTarget(ctx context.Context) (target.Target, error)
|
||||
|
||||
return tt, nil
|
||||
}
|
||||
|
||||
func (b *Server) CreateHostPlugin(ctx context.Context, plg plgpb.HostPluginServiceServer, opt ...hostplugin.Option) (*hostplugin.Plugin, error) {
|
||||
rw := db.New(b.Database)
|
||||
|
||||
kmsRepo, err := kms.NewRepository(rw, rw)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating kms repository: %w", err)
|
||||
}
|
||||
kmsCache, err := kms.NewKms(kmsRepo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating kms cache: %w", err)
|
||||
}
|
||||
if err := kmsCache.AddExternalWrappers(
|
||||
kms.WithRootWrapper(b.RootKms),
|
||||
); err != nil {
|
||||
return nil, fmt.Errorf("error adding config keys to kms: %w", err)
|
||||
}
|
||||
|
||||
cancelCtx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
go func() {
|
||||
select {
|
||||
case <-b.ShutdownCh:
|
||||
cancel()
|
||||
case <-cancelCtx.Done():
|
||||
}
|
||||
}()
|
||||
|
||||
hpRepo, err := hostplugin.NewRepository(rw, rw, kmsCache)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating host plugin repository: %w", err)
|
||||
}
|
||||
|
||||
plugin := hostplugin.NewPlugin(opt...)
|
||||
plugin, err = hpRepo.CreatePlugin(cancelCtx, plugin, opt...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating host plugin: %w", err)
|
||||
}
|
||||
|
||||
if b.HostPlugins == nil {
|
||||
b.HostPlugins = make(map[string]plgpb.HostPluginServiceServer)
|
||||
}
|
||||
b.HostPlugins[plugin.GetPublicId()] = plg
|
||||
|
||||
return plugin, nil
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package base
|
||||
|
||||
import "github.com/hashicorp/boundary/internal/observability/event"
|
||||
import (
|
||||
"github.com/hashicorp/boundary/internal/observability/event"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
)
|
||||
|
||||
// getOpts - iterate the inbound Options and return a struct.
|
||||
func getOpts(opt ...Option) Options {
|
||||
@@ -33,6 +36,7 @@ type Options struct {
|
||||
withEventFlags *EventFlags
|
||||
withAttributeFieldPrefix string
|
||||
withStatusCode int
|
||||
withHostPlugin func() (string, plugin.HostPluginServiceServer)
|
||||
}
|
||||
|
||||
func getDefaultOptions() Options {
|
||||
@@ -158,3 +162,13 @@ func WithDatabaseTemplate(template string) Option {
|
||||
o.withDatabaseTemplate = template
|
||||
}
|
||||
}
|
||||
|
||||
// WithHostPlugin allows specifying a plugin ID and implementation to create at
|
||||
// startup
|
||||
func WithHostPlugin(pluginId string, plg plugin.HostPluginServiceServer) Option {
|
||||
return func(o *Options) {
|
||||
o.withHostPlugin = func() (string, plugin.HostPluginServiceServer) {
|
||||
return pluginId, plg
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/observability/event"
|
||||
"github.com/hashicorp/boundary/internal/servers"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/hashicorp/boundary/version"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping"
|
||||
@@ -112,6 +113,9 @@ type Server struct {
|
||||
DevTargetDefaultPort int
|
||||
DevTargetSessionMaxSeconds int
|
||||
DevTargetSessionConnectionLimit int
|
||||
DevLoopbackHostPluginId string
|
||||
|
||||
HostPlugins map[string]plgpb.HostPluginServiceServer
|
||||
|
||||
DevOidcSetup oidcSetup
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/auth/password"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/config"
|
||||
"github.com/hashicorp/boundary/internal/host/plugin"
|
||||
"github.com/hashicorp/boundary/internal/host/static"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/intglobals"
|
||||
@@ -47,36 +48,37 @@ type Command struct {
|
||||
controller *controller.Controller
|
||||
worker *worker.Worker
|
||||
|
||||
flagLogLevel string
|
||||
flagLogFormat string
|
||||
flagCombineLogs bool
|
||||
flagLoginName string
|
||||
flagPassword string
|
||||
flagUnprivilegedLoginName string
|
||||
flagUnprivilegedPassword string
|
||||
flagIdSuffix string
|
||||
flagHostAddress string
|
||||
flagTargetDefaultPort int
|
||||
flagTargetSessionMaxSeconds int
|
||||
flagTargetSessionConnectionLimit int
|
||||
flagControllerAPIListenAddr string
|
||||
flagControllerClusterListenAddr string
|
||||
flagControllerPublicClusterAddr string
|
||||
flagControllerOnly bool
|
||||
flagWorkerAuthKey string
|
||||
flagWorkerProxyListenAddr string
|
||||
flagWorkerPublicAddr string
|
||||
flagPassthroughDirectory string
|
||||
flagRecoveryKey string
|
||||
flagDatabaseUrl string
|
||||
flagContainerImage string
|
||||
flagDisableDatabaseDestruction bool
|
||||
flagEventFormat string
|
||||
flagAudit string
|
||||
flagObservations string
|
||||
flagSysEvents string
|
||||
flagEveryEventAllowFilters []string
|
||||
flagEveryEventDenyFilters []string
|
||||
flagLogLevel string
|
||||
flagLogFormat string
|
||||
flagCombineLogs bool
|
||||
flagLoginName string
|
||||
flagPassword string
|
||||
flagUnprivilegedLoginName string
|
||||
flagUnprivilegedPassword string
|
||||
flagIdSuffix string
|
||||
flagHostAddress string
|
||||
flagTargetDefaultPort int
|
||||
flagTargetSessionMaxSeconds int
|
||||
flagTargetSessionConnectionLimit int
|
||||
flagControllerAPIListenAddr string
|
||||
flagControllerClusterListenAddr string
|
||||
flagControllerPublicClusterAddr string
|
||||
flagControllerOnly bool
|
||||
flagWorkerAuthKey string
|
||||
flagWorkerProxyListenAddr string
|
||||
flagWorkerPublicAddr string
|
||||
flagPassthroughDirectory string
|
||||
flagRecoveryKey string
|
||||
flagDatabaseUrl string
|
||||
flagContainerImage string
|
||||
flagDisableDatabaseDestruction bool
|
||||
flagEventFormat string
|
||||
flagAudit string
|
||||
flagObservations string
|
||||
flagSysEvents string
|
||||
flagEveryEventAllowFilters []string
|
||||
flagEveryEventDenyFilters []string
|
||||
flagCreateLoopbackHostCatalogPlugin bool
|
||||
}
|
||||
|
||||
func (c *Command) Synopsis() string {
|
||||
@@ -308,6 +310,12 @@ func (c *Command) Flags() *base.FlagSets {
|
||||
Usage: `The optional every event deny filter. May be specified multiple times.`,
|
||||
})
|
||||
|
||||
f.BoolVar(&base.BoolVar{
|
||||
Name: "create-loopback-hostcatalog-plugin",
|
||||
Target: &c.flagCreateLoopbackHostCatalogPlugin,
|
||||
Hidden: true,
|
||||
})
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
@@ -542,6 +550,9 @@ func (c *Command) Run(args []string) int {
|
||||
}()
|
||||
|
||||
var opts []base.Option
|
||||
if c.flagCreateLoopbackHostCatalogPlugin {
|
||||
opts = append(opts, base.WithHostPlugin("pl_1234567890", plugin.NewLoopbackPlugin()))
|
||||
}
|
||||
switch c.flagDatabaseUrl {
|
||||
case "":
|
||||
if c.flagDisableDatabaseDestruction {
|
||||
|
||||
@@ -83,6 +83,11 @@ func (c *Command) printListTable(items []*hostcatalogs.HostCatalog) string {
|
||||
fmt.Sprintf(" Scope ID: %s", m.ScopeId),
|
||||
)
|
||||
}
|
||||
if m.PluginId != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Plugin ID: %s", m.PluginId),
|
||||
)
|
||||
}
|
||||
if m.Version > 0 {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Version: %d", m.Version),
|
||||
@@ -135,6 +140,9 @@ func printItemTable(result api.GenericResult) string {
|
||||
if item.Description != "" {
|
||||
nonAttributeMap["Description"] = item.Description
|
||||
}
|
||||
if item.PluginId != "" {
|
||||
nonAttributeMap["Plugin ID"] = item.PluginId
|
||||
}
|
||||
if item.Type != "" {
|
||||
nonAttributeMap["Type"] = item.Type
|
||||
}
|
||||
@@ -155,6 +163,22 @@ func printItemTable(result api.GenericResult) string {
|
||||
)
|
||||
}
|
||||
|
||||
if item.Plugin != nil {
|
||||
ret = append(ret,
|
||||
"",
|
||||
" Plugin:",
|
||||
base.PluginInfoForOutput(item.Plugin, maxLength),
|
||||
)
|
||||
}
|
||||
|
||||
if len(item.Attributes) > 0 {
|
||||
ret = append(ret,
|
||||
"",
|
||||
" Attributes:",
|
||||
base.WrapMap(4, maxLength, item.Attributes),
|
||||
)
|
||||
}
|
||||
|
||||
if len(item.AuthorizedActions) > 0 {
|
||||
ret = append(ret,
|
||||
"",
|
||||
@@ -180,14 +204,6 @@ func printItemTable(result api.GenericResult) string {
|
||||
}
|
||||
}
|
||||
|
||||
if len(item.Attributes) > 0 {
|
||||
ret = append(ret,
|
||||
"",
|
||||
" Attributes:",
|
||||
base.WrapMap(4, maxLength, item.Attributes),
|
||||
)
|
||||
}
|
||||
|
||||
return base.WrapForHelpText(ret)
|
||||
}
|
||||
|
||||
|
||||
@@ -77,9 +77,9 @@ func (c *PluginCommand) Help() string {
|
||||
|
||||
var flagsPluginMap = map[string][]string{
|
||||
|
||||
"create": {"scope-id", "name", "description", "attributes", "attr", "string-attr", "bool-attr", "num-attr"},
|
||||
"create": {"scope-id", "name", "description", "plugin-id", "plugin-name", "attributes", "attr", "string-attr", "bool-attr", "num-attr", "secrets", "secret", "string-secret", "bool-secret", "num-secret"},
|
||||
|
||||
"update": {"id", "name", "description", "version", "attributes", "attr", "string-attr", "bool-attr", "num-attr"},
|
||||
"update": {"id", "name", "description", "version", "attributes", "attr", "string-attr", "bool-attr", "num-attr", "secrets", "secret", "string-secret", "bool-secret", "num-secret"},
|
||||
}
|
||||
|
||||
func (c *PluginCommand) Flags() *base.FlagSets {
|
||||
@@ -94,6 +94,9 @@ func (c *PluginCommand) Flags() *base.FlagSets {
|
||||
f = set.NewFlagSet("Attribute Options")
|
||||
common.PopulateAttributeFlags(c.Command, f, flagsPluginMap, c.Func)
|
||||
|
||||
f = set.NewFlagSet("Secrets Options")
|
||||
common.PopulateSecretFlags(c.Command, f, flagsPluginMap, c.Func)
|
||||
|
||||
extraPluginFlagsFunc(c, set, f)
|
||||
|
||||
return set
|
||||
@@ -169,6 +172,17 @@ func (c *PluginCommand) Run(args []string) int {
|
||||
opts = append(opts, hostcatalogs.WithFilter(c.FlagFilter))
|
||||
}
|
||||
|
||||
switch c.FlagPluginId {
|
||||
case "":
|
||||
default:
|
||||
opts = append(opts, hostcatalogs.WithPluginId(c.FlagPluginId))
|
||||
}
|
||||
switch c.FlagPluginName {
|
||||
case "":
|
||||
default:
|
||||
opts = append(opts, hostcatalogs.WithPluginName(c.FlagPluginName))
|
||||
}
|
||||
|
||||
var version uint32
|
||||
|
||||
switch c.Func {
|
||||
@@ -184,16 +198,33 @@ func (c *PluginCommand) Run(args []string) int {
|
||||
if err := common.HandleAttributeFlags(
|
||||
c.Command,
|
||||
"attr",
|
||||
c.FlagAttributes,
|
||||
c.FlagAttrs,
|
||||
func() {
|
||||
hostcatalogs.DefaultAttributes()
|
||||
opts = append(opts, hostcatalogs.DefaultAttributes())
|
||||
},
|
||||
func(in map[string]interface{}) {
|
||||
hostcatalogs.WithAttributes(in)
|
||||
opts = append(opts, hostcatalogs.WithAttributes(in))
|
||||
}); err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error evaluating attribute flags to: %s", err.Error()))
|
||||
return base.CommandCliError
|
||||
}
|
||||
|
||||
if err := common.HandleAttributeFlags(
|
||||
c.Command,
|
||||
"secret",
|
||||
c.FlagSecrets,
|
||||
c.FlagScrts,
|
||||
func() {
|
||||
opts = append(opts, hostcatalogs.DefaultSecrets())
|
||||
},
|
||||
func(in map[string]interface{}) {
|
||||
opts = append(opts, hostcatalogs.WithSecrets(in))
|
||||
}); err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error evaluating secret flags to: %s", err.Error()))
|
||||
return base.CommandCliError
|
||||
}
|
||||
|
||||
if ok := extraPluginFlagsHandlingFunc(c, f, &opts); !ok {
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
@@ -273,6 +273,22 @@ func printItemTable(result api.GenericResult) string {
|
||||
)
|
||||
}
|
||||
|
||||
if item.Plugin != nil {
|
||||
ret = append(ret,
|
||||
"",
|
||||
" Plugin:",
|
||||
base.PluginInfoForOutput(item.Plugin, maxLength),
|
||||
)
|
||||
}
|
||||
|
||||
if len(item.Attributes) > 0 {
|
||||
ret = append(ret,
|
||||
"",
|
||||
" Attributes:",
|
||||
base.WrapMap(4, maxLength, item.Attributes),
|
||||
)
|
||||
}
|
||||
|
||||
if len(item.AuthorizedActions) > 0 {
|
||||
ret = append(ret,
|
||||
"",
|
||||
@@ -289,14 +305,6 @@ func printItemTable(result api.GenericResult) string {
|
||||
)
|
||||
}
|
||||
|
||||
if len(item.Attributes) > 0 {
|
||||
ret = append(ret,
|
||||
"",
|
||||
" Attributes:",
|
||||
base.WrapMap(4, maxLength, item.Attributes),
|
||||
)
|
||||
}
|
||||
|
||||
return base.WrapForHelpText(ret)
|
||||
}
|
||||
|
||||
|
||||
@@ -79,9 +79,9 @@ func (c *PluginCommand) Help() string {
|
||||
|
||||
var flagsPluginMap = map[string][]string{
|
||||
|
||||
"create": {"host-catalog-id", "name", "description"},
|
||||
"create": {"host-catalog-id", "name", "description", "attributes", "attr", "string-attr", "bool-attr", "num-attr"},
|
||||
|
||||
"update": {"id", "name", "description", "version"},
|
||||
"update": {"id", "name", "description", "version", "attributes", "attr", "string-attr", "bool-attr", "num-attr"},
|
||||
}
|
||||
|
||||
func (c *PluginCommand) Flags() *base.FlagSets {
|
||||
@@ -93,6 +93,9 @@ func (c *PluginCommand) Flags() *base.FlagSets {
|
||||
f := set.NewFlagSet("Command Options")
|
||||
common.PopulateCommonFlags(c.Command, f, "plugin-type host set", flagsPluginMap, c.Func)
|
||||
|
||||
f = set.NewFlagSet("Attribute Options")
|
||||
common.PopulateAttributeFlags(c.Command, f, flagsPluginMap, c.Func)
|
||||
|
||||
extraPluginFlagsFunc(c, set, f)
|
||||
|
||||
return set
|
||||
@@ -175,6 +178,21 @@ func (c *PluginCommand) Run(args []string) int {
|
||||
}
|
||||
}
|
||||
|
||||
if err := common.HandleAttributeFlags(
|
||||
c.Command,
|
||||
"attr",
|
||||
c.FlagAttributes,
|
||||
c.FlagAttrs,
|
||||
func() {
|
||||
opts = append(opts, hostsets.DefaultAttributes())
|
||||
},
|
||||
func(in map[string]interface{}) {
|
||||
opts = append(opts, hostsets.WithAttributes(in))
|
||||
}); err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error evaluating attribute flags to: %s", err.Error()))
|
||||
return base.CommandCliError
|
||||
}
|
||||
|
||||
if ok := extraPluginFlagsHandlingFunc(c, f, &opts); !ok {
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
+109
-45
@@ -34,6 +34,20 @@ func PopulateCommonFlags(c *base.Command, f *base.FlagSet, resourceType string,
|
||||
Completion: complete.PredictAnything,
|
||||
Usage: `Scope in which to make the request, identified by name.`,
|
||||
})
|
||||
case "plugin-id":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "plugin-id",
|
||||
Target: &c.FlagPluginId,
|
||||
Completion: complete.PredictAnything,
|
||||
Usage: `ID of a plugin being referenced in the request.`,
|
||||
})
|
||||
case "plugin-name":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "plugin-name",
|
||||
Target: &c.FlagPluginName,
|
||||
Completion: complete.PredictAnything,
|
||||
Usage: `Name of a plugin being referenced in the request.`,
|
||||
})
|
||||
case "id":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "id",
|
||||
@@ -109,7 +123,7 @@ func PopulateAttributeFlags(c *base.Command, f *base.FlagSet, flagNames map[stri
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "attributes",
|
||||
Target: &c.FlagAttributes,
|
||||
Usage: `A JSON map value to use as the entirety of the request's attribute map. Usually this will be soured from a file via "file://" syntax.`,
|
||||
Usage: `A JSON map value to use as the entirety of the request's attributes map. Usually this will be sourced from a file via "file://" syntax.`,
|
||||
})
|
||||
case "attr":
|
||||
f.CombinationSliceVar(&base.CombinationSliceVar{
|
||||
@@ -118,7 +132,7 @@ func PopulateAttributeFlags(c *base.Command, f *base.FlagSet, flagNames map[stri
|
||||
KvSplit: true,
|
||||
KeyDelimiter: &keyDelimiter,
|
||||
ProtoCompatKey: true,
|
||||
Usage: `A key=value attribute to add to the request's attribute map. The type is automatically inferred. Use -string-attr, -bool-attr, or -num-attr if the type needs to be overridden. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
Usage: `A key=value attribute to add to the request's attributes map. The type is automatically inferred. Use -string-attr, -bool-attr, or -num-attr if the type needs to be overridden. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
})
|
||||
case "string-attr":
|
||||
f.CombinationSliceVar(&base.CombinationSliceVar{
|
||||
@@ -127,7 +141,7 @@ func PopulateAttributeFlags(c *base.Command, f *base.FlagSet, flagNames map[stri
|
||||
KvSplit: true,
|
||||
KeyDelimiter: &keyDelimiter,
|
||||
ProtoCompatKey: true,
|
||||
Usage: `A key=value string attribute to add to the request's attribute map. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
Usage: `A key=value string attribute to add to the request's attributes map. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
})
|
||||
case "bool-attr":
|
||||
f.CombinationSliceVar(&base.CombinationSliceVar{
|
||||
@@ -136,7 +150,7 @@ func PopulateAttributeFlags(c *base.Command, f *base.FlagSet, flagNames map[stri
|
||||
KvSplit: true,
|
||||
KeyDelimiter: &keyDelimiter,
|
||||
ProtoCompatKey: true,
|
||||
Usage: `A key=value bool attribute to add to the request's attribute map. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
Usage: `A key=value bool attribute to add to the request's attributes map. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
})
|
||||
case "num-attr":
|
||||
f.CombinationSliceVar(&base.CombinationSliceVar{
|
||||
@@ -145,7 +159,57 @@ func PopulateAttributeFlags(c *base.Command, f *base.FlagSet, flagNames map[stri
|
||||
KvSplit: true,
|
||||
KeyDelimiter: &keyDelimiter,
|
||||
ProtoCompatKey: true,
|
||||
Usage: `A key=value numeric attribute to add to the request's attribute map. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
Usage: `A key=value numeric attribute to add to the request's attributes map. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func PopulateSecretFlags(c *base.Command, f *base.FlagSet, flagNames map[string][]string, command string) {
|
||||
keyDelimiter := "."
|
||||
for _, name := range flagNames[command] {
|
||||
switch name {
|
||||
case "secrets":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "secrets",
|
||||
Target: &c.FlagSecrets,
|
||||
Usage: `A JSON map value to use as the entirety of the request's secrets map. Usually this will be sourced from a file via "file://" syntax.`,
|
||||
})
|
||||
case "secret":
|
||||
f.CombinationSliceVar(&base.CombinationSliceVar{
|
||||
Name: "secret",
|
||||
Target: &c.FlagScrts,
|
||||
KvSplit: true,
|
||||
KeyDelimiter: &keyDelimiter,
|
||||
ProtoCompatKey: true,
|
||||
Usage: `A key=value secret to add to the request's secrets map. The type is automatically inferred. Use -string-secret, -bool-secret, or -num-secret if the type needs to be overridden. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
})
|
||||
case "string-secret":
|
||||
f.CombinationSliceVar(&base.CombinationSliceVar{
|
||||
Name: "string-secret",
|
||||
Target: &c.FlagScrts,
|
||||
KvSplit: true,
|
||||
KeyDelimiter: &keyDelimiter,
|
||||
ProtoCompatKey: true,
|
||||
Usage: `A key=value string secret to add to the request's secrets map. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
})
|
||||
case "bool-secret":
|
||||
f.CombinationSliceVar(&base.CombinationSliceVar{
|
||||
Name: "bool-secret",
|
||||
Target: &c.FlagScrts,
|
||||
KvSplit: true,
|
||||
KeyDelimiter: &keyDelimiter,
|
||||
ProtoCompatKey: true,
|
||||
Usage: `A key=value bool secret to add to the request's secrets map. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
})
|
||||
case "num-secret":
|
||||
f.CombinationSliceVar(&base.CombinationSliceVar{
|
||||
Name: "num-secret",
|
||||
Target: &c.FlagScrts,
|
||||
KvSplit: true,
|
||||
KeyDelimiter: &keyDelimiter,
|
||||
ProtoCompatKey: true,
|
||||
Usage: `A key=value numeric secret to add to the request's secrets map. Can be specified multiple times. Supports sourcing values from files via "file://" and env vars via "env://"`,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -157,23 +221,23 @@ var jsonNumberRegex = regexp.MustCompile(`^-?(?:0|[1-9]\d*)(?:\.\d+)?$`)
|
||||
// HandleAttributeFlags takes in a command and a func to call for default (that
|
||||
// is, set to nil) and non-default values. Suffix can be used to allow this
|
||||
// logic to be used for various needs, e.g. -attr vs -secret.
|
||||
func HandleAttributeFlags(c *base.Command, suffix string, defaultFunc func(), setFunc func(map[string]interface{})) error {
|
||||
// If we were given -attributes, use that as-is
|
||||
switch c.FlagAttributes {
|
||||
func HandleAttributeFlags(c *base.Command, suffix, fullField string, sepFields []base.CombinedSliceFlagValue, defaultFunc func(), setFunc func(map[string]interface{})) error {
|
||||
// If we were given a fullly defined field, use that as-is
|
||||
switch fullField {
|
||||
case "":
|
||||
// Nothing, continue on
|
||||
case "null":
|
||||
defaultFunc()
|
||||
return nil
|
||||
default:
|
||||
parsedString, err := parseutil.ParsePath(c.FlagAttributes)
|
||||
parsedString, err := parseutil.ParsePath(fullField)
|
||||
if err != nil && !errors.Is(err, parseutil.ErrNotAUrl) {
|
||||
return fmt.Errorf("error parsing attributes flag as a URL: %w", err)
|
||||
return fmt.Errorf("error parsing %s flag as a URL: %w", suffix, err)
|
||||
}
|
||||
// We should be able to parse the string as a JSON object
|
||||
var setMap map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(parsedString), &setMap); err != nil {
|
||||
return fmt.Errorf("error parsing attributes flag as JSON: %w", err)
|
||||
return fmt.Errorf("error parsing %s flag as JSON: %w", suffix, err)
|
||||
}
|
||||
setFunc(setMap)
|
||||
return nil
|
||||
@@ -181,8 +245,8 @@ func HandleAttributeFlags(c *base.Command, suffix string, defaultFunc func(), se
|
||||
|
||||
setMap := map[string]interface{}{}
|
||||
|
||||
for _, attr := range c.FlagAttrs {
|
||||
if len(attr.Keys) == 0 {
|
||||
for _, field := range sepFields {
|
||||
if len(field.Keys) == 0 {
|
||||
// No idea why this would happen, but skip it
|
||||
continue
|
||||
}
|
||||
@@ -191,101 +255,101 @@ func HandleAttributeFlags(c *base.Command, suffix string, defaultFunc func(), se
|
||||
var err error
|
||||
|
||||
// First, perform any needed parsing if we are given the type
|
||||
switch attr.Name {
|
||||
switch field.Name {
|
||||
case "num-" + suffix:
|
||||
// JSON treats all numbers equally, however, we will try to be a
|
||||
// little better so that we don't include decimals if we don't need
|
||||
// to (and don't have to worry about precision if not necessary)
|
||||
if strings.Contains(attr.Value, ".") {
|
||||
val, err = strconv.ParseFloat(attr.Value, 64)
|
||||
if strings.Contains(field.Value, ".") {
|
||||
val, err = strconv.ParseFloat(field.Value, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing attribute %q as a float: %w", attr.Value, err)
|
||||
return fmt.Errorf("error parsing value %q as a float: %w", field.Value, err)
|
||||
}
|
||||
} else {
|
||||
val, err = strconv.ParseInt(attr.Value, 10, 64)
|
||||
val, err = strconv.ParseInt(field.Value, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing attribute %q as an integer: %w", attr.Value, err)
|
||||
return fmt.Errorf("error parsing value %q as an integer: %w", field.Value, err)
|
||||
}
|
||||
}
|
||||
|
||||
case "string-" + suffix:
|
||||
val = strings.Trim(attr.Value, `"`)
|
||||
val = strings.Trim(field.Value, `"`)
|
||||
|
||||
case "bool-" + suffix:
|
||||
switch attr.Value {
|
||||
switch field.Value {
|
||||
case "true":
|
||||
val = true
|
||||
case "false":
|
||||
val = false
|
||||
default:
|
||||
return fmt.Errorf("error parsing attribute %q as a bool", attr.Value)
|
||||
return fmt.Errorf("error parsing value %q as a bool", field.Value)
|
||||
}
|
||||
|
||||
case suffix:
|
||||
// In this case, use heuristics to just do the right thing the vast
|
||||
// majority of the time
|
||||
switch {
|
||||
case attr.Value == "null": // Explicit null, we want to set to a null value to clear it
|
||||
case field.Value == "null": // Explicit null, we want to set to a null value to clear it
|
||||
val = nil
|
||||
|
||||
case attr.Value == "true": // bool true
|
||||
case field.Value == "true": // bool true
|
||||
val = true
|
||||
|
||||
case attr.Value == "false": // bool false
|
||||
case field.Value == "false": // bool false
|
||||
val = false
|
||||
|
||||
case strings.HasPrefix(attr.Value, `"`): // explicitly quoted string
|
||||
val = strings.Trim(attr.Value, `"`)
|
||||
case strings.HasPrefix(field.Value, `"`): // explicitly quoted string
|
||||
val = strings.Trim(field.Value, `"`)
|
||||
|
||||
case jsonNumberRegex.Match([]byte(strings.Trim(attr.Value, `"`))): // number
|
||||
case jsonNumberRegex.Match([]byte(strings.Trim(field.Value, `"`))): // number
|
||||
// Same logic as above
|
||||
if strings.Contains(attr.Value, ".") {
|
||||
val, err = strconv.ParseFloat(attr.Value, 64)
|
||||
if strings.Contains(field.Value, ".") {
|
||||
val, err = strconv.ParseFloat(field.Value, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing attribute %q as a float: %w", attr.Value, err)
|
||||
return fmt.Errorf("error parsing value %q as a float: %w", field.Value, err)
|
||||
}
|
||||
} else {
|
||||
val, err = strconv.ParseInt(attr.Value, 10, 64)
|
||||
val, err = strconv.ParseInt(field.Value, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing attribute %q as an integer: %w", attr.Value, err)
|
||||
return fmt.Errorf("error parsing value %q as an integer: %w", field.Value, err)
|
||||
}
|
||||
}
|
||||
|
||||
case strings.HasPrefix(attr.Value, "["): // serialized JSON array
|
||||
case strings.HasPrefix(field.Value, "["): // serialized JSON array
|
||||
var s []interface{}
|
||||
u := json.NewDecoder(bytes.NewBufferString(attr.Value))
|
||||
u := json.NewDecoder(bytes.NewBufferString(field.Value))
|
||||
u.UseNumber()
|
||||
if err := u.Decode(&s); err != nil {
|
||||
return fmt.Errorf("error parsing attribute %q as a json array: %w", attr.Value, err)
|
||||
return fmt.Errorf("error parsing value %q as a json array: %w", field.Value, err)
|
||||
}
|
||||
val = s
|
||||
|
||||
case strings.HasPrefix(attr.Value, "{"): // serialized JSON map
|
||||
case strings.HasPrefix(field.Value, "{"): // serialized JSON map
|
||||
var m map[string]interface{}
|
||||
u := json.NewDecoder(bytes.NewBufferString(attr.Value))
|
||||
u := json.NewDecoder(bytes.NewBufferString(field.Value))
|
||||
u.UseNumber()
|
||||
if err := u.Decode(&m); err != nil {
|
||||
return fmt.Errorf("error parsing attribute %q as a json map: %w", attr.Value, err)
|
||||
return fmt.Errorf("error parsing value %q as a json map: %w", field.Value, err)
|
||||
}
|
||||
val = m
|
||||
|
||||
default:
|
||||
// Default is to treat as a string value
|
||||
val = attr.Value
|
||||
val = field.Value
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown attribute flag %q", attr.Name)
|
||||
return fmt.Errorf("unknown flag %q", field.Name)
|
||||
}
|
||||
|
||||
// Now we have to insert it in the right position in the attribute map
|
||||
// Now we have to insert it in the right position in the final map
|
||||
currMap := setMap
|
||||
for i, segment := range attr.Keys {
|
||||
for i, segment := range field.Keys {
|
||||
if segment == "" {
|
||||
return fmt.Errorf("key segment %q for value %q is empty", segment, attr.Value)
|
||||
return fmt.Errorf("key segment %q for value %q is empty", segment, field.Value)
|
||||
}
|
||||
|
||||
switch {
|
||||
case i == len(attr.Keys)-1:
|
||||
case i == len(field.Keys)-1:
|
||||
// If we get an explicit "null" override whatever is currently
|
||||
// there
|
||||
if val == nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
@@ -170,12 +171,12 @@ func TestHandleAttributeFlags(t *testing.T) {
|
||||
name: "strings-only",
|
||||
args: []base.CombinedSliceFlagValue{
|
||||
{
|
||||
Name: "string-attr",
|
||||
Name: "string-%s",
|
||||
Keys: []string{"foo"},
|
||||
Value: "bar",
|
||||
},
|
||||
{
|
||||
Name: "string-attr",
|
||||
Name: "string-%s",
|
||||
Keys: []string{"bar"},
|
||||
Value: `"baz"`,
|
||||
},
|
||||
@@ -189,12 +190,12 @@ func TestHandleAttributeFlags(t *testing.T) {
|
||||
name: "nums-only",
|
||||
args: []base.CombinedSliceFlagValue{
|
||||
{
|
||||
Name: "num-attr",
|
||||
Name: "num-%s",
|
||||
Keys: []string{"foo"},
|
||||
Value: "-1.2",
|
||||
},
|
||||
{
|
||||
Name: "num-attr",
|
||||
Name: "num-%s",
|
||||
Keys: []string{"bar"},
|
||||
Value: "5",
|
||||
},
|
||||
@@ -208,7 +209,7 @@ func TestHandleAttributeFlags(t *testing.T) {
|
||||
name: "bad-float-num",
|
||||
args: []base.CombinedSliceFlagValue{
|
||||
{
|
||||
Name: "num-attr",
|
||||
Name: "num-%s",
|
||||
Keys: []string{"foo"},
|
||||
Value: "-15d.2",
|
||||
},
|
||||
@@ -219,7 +220,7 @@ func TestHandleAttributeFlags(t *testing.T) {
|
||||
name: "bad-int-num",
|
||||
args: []base.CombinedSliceFlagValue{
|
||||
{
|
||||
Name: "num-attr",
|
||||
Name: "num-%s",
|
||||
Keys: []string{"foo"},
|
||||
Value: "-15d3",
|
||||
},
|
||||
@@ -230,12 +231,12 @@ func TestHandleAttributeFlags(t *testing.T) {
|
||||
name: "bools-only",
|
||||
args: []base.CombinedSliceFlagValue{
|
||||
{
|
||||
Name: "bool-attr",
|
||||
Name: "bool-%s",
|
||||
Keys: []string{"foo"},
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Name: "bool-attr",
|
||||
Name: "bool-%s",
|
||||
Keys: []string{"bar"},
|
||||
Value: "false",
|
||||
},
|
||||
@@ -249,7 +250,7 @@ func TestHandleAttributeFlags(t *testing.T) {
|
||||
name: "bad-bool",
|
||||
args: []base.CombinedSliceFlagValue{
|
||||
{
|
||||
Name: "bool-attr",
|
||||
Name: "bool-%s",
|
||||
Keys: []string{"foo"},
|
||||
Value: "t",
|
||||
},
|
||||
@@ -260,47 +261,47 @@ func TestHandleAttributeFlags(t *testing.T) {
|
||||
name: "attr-only",
|
||||
args: []base.CombinedSliceFlagValue{
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"b1"},
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"b2"},
|
||||
Value: "false",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"s1"},
|
||||
Value: "scoopde",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"s2"},
|
||||
Value: `"woop"`,
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"n1"},
|
||||
Value: "-1.2",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"n2"},
|
||||
Value: "5",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"a"},
|
||||
Value: `["foo", 1.5, true, ["bar"], {"hip": "hop"}]`,
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"nil"},
|
||||
Value: "null",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"m"},
|
||||
Value: `{"b": true, "n": 6, "s": "scoopde", "a": ["bar"], "m": {"hip": "hop"}}`,
|
||||
},
|
||||
@@ -333,37 +334,37 @@ func TestHandleAttributeFlags(t *testing.T) {
|
||||
name: "map-array-structure",
|
||||
args: []base.CombinedSliceFlagValue{
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"bools"},
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"bools"},
|
||||
Value: "false",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"strings", "s1"},
|
||||
Value: "scoopde",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"strings", "s2"},
|
||||
Value: `"woop"`,
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"numbers", "reps"},
|
||||
Value: "-1.2",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"numbers", "reps"},
|
||||
Value: "5",
|
||||
},
|
||||
{
|
||||
Name: "attr",
|
||||
Name: "%s",
|
||||
Keys: []string{"strings", "s2"}, // This will overwrite above!
|
||||
Value: "null",
|
||||
},
|
||||
@@ -381,25 +382,32 @@ func TestHandleAttributeFlags(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
for _, typ := range []string{"attr", "secret"} {
|
||||
t.Run(fmt.Sprintf("%s-%s", tt.name, typ), func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
|
||||
// Note: we do the setup on each run to make sure we aren't carrying
|
||||
// state over; just like in the real CLI where each run would have
|
||||
// pristine state.
|
||||
c := new(base.Command)
|
||||
c.FlagAttrs = tt.args
|
||||
var outMap map[string]interface{}
|
||||
// Note: we do the setup on each run to make sure we aren't carrying
|
||||
// state over; just like in the real CLI where each run would have
|
||||
// pristine state.
|
||||
c := new(base.Command)
|
||||
var outMap map[string]interface{}
|
||||
|
||||
err := HandleAttributeFlags(c, "attr", func() {}, func(in map[string]interface{}) { outMap = in })
|
||||
if tt.expectedErr != "" {
|
||||
require.Error(err)
|
||||
assert.Contains(err.Error(), tt.expectedErr)
|
||||
return
|
||||
}
|
||||
args := make([]base.CombinedSliceFlagValue, 0, len(tt.args))
|
||||
for _, arg := range tt.args {
|
||||
arg.Name = fmt.Sprintf(arg.Name, typ)
|
||||
args = append(args, arg)
|
||||
}
|
||||
|
||||
require.NoError(err)
|
||||
assert.Equal(tt.expectedMap, outMap)
|
||||
})
|
||||
err := HandleAttributeFlags(c, typ, "", args, func() {}, func(in map[string]interface{}) { outMap = in })
|
||||
if tt.expectedErr != "" {
|
||||
require.Error(err)
|
||||
assert.Contains(err.Error(), tt.expectedErr)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(err)
|
||||
assert.Equal(tt.expectedMap, outMap)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,13 @@ type cmdInfo struct {
|
||||
// HasGenericAttributes controls whether to generate flags for -attributes,
|
||||
// -attr, -string-attr, etc.
|
||||
HasGenericAttributes bool
|
||||
|
||||
// HasGenericSecrets controls whether to generate flags for -secrets,
|
||||
// -secret, -string-secret, etc.
|
||||
HasGenericSecrets bool
|
||||
|
||||
// IsPluginType controls whether standard plugin flags are generated
|
||||
IsPluginType bool
|
||||
}
|
||||
|
||||
var inputStructs = map[string][]*cmdInfo{
|
||||
@@ -269,9 +276,11 @@ var inputStructs = map[string][]*cmdInfo{
|
||||
HasName: true,
|
||||
HasDescription: true,
|
||||
Container: "Scope",
|
||||
IsPluginType: true,
|
||||
VersionedActions: []string{"update"},
|
||||
NeedsSubtypeInCreate: true,
|
||||
HasGenericAttributes: true,
|
||||
HasGenericSecrets: true,
|
||||
},
|
||||
},
|
||||
"hostsets": {
|
||||
@@ -302,18 +311,19 @@ var inputStructs = map[string][]*cmdInfo{
|
||||
VersionedActions: []string{"update"},
|
||||
},
|
||||
{
|
||||
ResourceType: resource.HostSet.String(),
|
||||
Pkg: "hostsets",
|
||||
StdActions: []string{"create", "update"},
|
||||
SubActionPrefix: "plugin",
|
||||
HasExtraCommandVars: true,
|
||||
SkipNormalHelp: true,
|
||||
HasExtraHelpFunc: true,
|
||||
HasId: true,
|
||||
HasName: true,
|
||||
Container: "HostCatalog",
|
||||
HasDescription: true,
|
||||
VersionedActions: []string{"update"},
|
||||
ResourceType: resource.HostSet.String(),
|
||||
Pkg: "hostsets",
|
||||
StdActions: []string{"create", "update"},
|
||||
SubActionPrefix: "plugin",
|
||||
HasExtraCommandVars: true,
|
||||
SkipNormalHelp: true,
|
||||
HasExtraHelpFunc: true,
|
||||
HasId: true,
|
||||
HasName: true,
|
||||
Container: "HostCatalog",
|
||||
HasDescription: true,
|
||||
HasGenericAttributes: true,
|
||||
VersionedActions: []string{"update"},
|
||||
},
|
||||
},
|
||||
"hosts": {
|
||||
|
||||
@@ -170,15 +170,16 @@ func (c *{{ camelCase .SubActionPrefix }}Command) Help() string {
|
||||
|
||||
var flags{{ camelCase .SubActionPrefix }}Map = map[string][]string{
|
||||
{{ with $attrFlags := ", \"attributes\", \"attr\", \"string-attr\", \"bool-attr\", \"num-attr\"" }}
|
||||
{{ with $secretFlags := ", \"secrets\", \"secret\", \"string-secret\", \"bool-secret\", \"num-secret\"" }}
|
||||
{{ range $i, $action := $input.StdActions }}
|
||||
{{ if eq $action "create" }}
|
||||
"create": { "{{ kebabCase $input.Container }}-id", "name", "description" {{ if $input.HasGenericAttributes }} {{ $attrFlags }} {{ end }} },
|
||||
"create": { "{{ kebabCase $input.Container }}-id", "name", "description" {{ if $input.IsPluginType }} , "plugin-id", "plugin-name" {{ end }} {{ if $input.HasGenericAttributes }} {{ $attrFlags }} {{ end }} {{ if $input.HasGenericSecrets }} {{ $secretFlags }} {{ end }} },
|
||||
{{ end }}
|
||||
{{ if eq $action "read" }}
|
||||
"read": {"id"},
|
||||
{{ end }}
|
||||
{{ if eq $action "update" }}
|
||||
"update": {"id", "name", "description" {{ if hasAction $input.VersionedActions "update" }}, "version" {{ end }} {{ if $input.HasGenericAttributes }} {{ $attrFlags }} {{ end }} },
|
||||
"update": {"id", "name", "description" {{ if hasAction $input.VersionedActions "update" }}, "version" {{ end }} {{ if $input.HasGenericAttributes }} {{ $attrFlags }} {{ end }} {{ if $input.HasGenericSecrets }} {{ $secretFlags }} {{ end }} },
|
||||
{{ end }}
|
||||
{{ if eq $action "delete" }}
|
||||
"delete": {"id"},
|
||||
@@ -188,6 +189,7 @@ var flags{{ camelCase .SubActionPrefix }}Map = map[string][]string{
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
func (c *{{ camelCase .SubActionPrefix }}Command) Flags() *base.FlagSets {
|
||||
@@ -204,6 +206,11 @@ func (c *{{ camelCase .SubActionPrefix }}Command) Flags() *base.FlagSets {
|
||||
common.PopulateAttributeFlags(c.Command, f, flags{{ camelCase .SubActionPrefix }}Map, c.Func)
|
||||
{{ end }}
|
||||
|
||||
{{ if .HasGenericSecrets }}
|
||||
f = set.NewFlagSet("Secrets Options")
|
||||
common.PopulateSecretFlags(c.Command, f, flags{{ camelCase .SubActionPrefix }}Map, c.Func)
|
||||
{{ end }}
|
||||
|
||||
extra{{ camelCase .SubActionPrefix }}FlagsFunc(c, set, f)
|
||||
|
||||
return set
|
||||
@@ -314,6 +321,19 @@ func (c *{{ camelCase .SubActionPrefix }}Command) Run(args []string) int {
|
||||
opts = append(opts, {{ .Pkg }}.WithScopeName(c.FlagScopeName))
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ if .IsPluginType }}
|
||||
switch c.FlagPluginId {
|
||||
case "":
|
||||
default:
|
||||
opts = append(opts, {{ .Pkg }}.WithPluginId(c.FlagPluginId))
|
||||
}
|
||||
switch c.FlagPluginName {
|
||||
case "":
|
||||
default:
|
||||
opts = append(opts, {{ .Pkg }}.WithPluginName(c.FlagPluginName))
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
var version uint32
|
||||
{{ if .VersionedActions }}
|
||||
@@ -334,17 +354,36 @@ func (c *{{ camelCase .SubActionPrefix }}Command) Run(args []string) int {
|
||||
if err := common.HandleAttributeFlags(
|
||||
c.Command,
|
||||
"attr",
|
||||
c.FlagAttributes,
|
||||
c.FlagAttrs,
|
||||
func() {
|
||||
{{ .Pkg }}.DefaultAttributes()
|
||||
opts = append(opts, {{ .Pkg }}.DefaultAttributes())
|
||||
},
|
||||
func(in map[string]interface{}) {
|
||||
{{ .Pkg }}.WithAttributes(in)
|
||||
opts = append(opts, {{ .Pkg }}.WithAttributes(in))
|
||||
}); err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error evaluating attribute flags to: %s", err.Error()))
|
||||
return base.CommandCliError
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ if .HasGenericSecrets }}
|
||||
if err := common.HandleAttributeFlags(
|
||||
c.Command,
|
||||
"secret",
|
||||
c.FlagSecrets,
|
||||
c.FlagScrts,
|
||||
func() {
|
||||
opts = append(opts, {{ .Pkg }}.DefaultSecrets())
|
||||
},
|
||||
func(in map[string]interface{}) {
|
||||
opts = append(opts, {{ .Pkg }}.WithSecrets(in))
|
||||
}); err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error evaluating secret flags to: %s", err.Error()))
|
||||
return base.CommandCliError
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
if ok := extra{{ camelCase .SubActionPrefix }}FlagsHandlingFunc(c, f, &opts, ); !ok {
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
@@ -1247,7 +1247,7 @@
|
||||
},
|
||||
{
|
||||
"name": "plugin_name",
|
||||
"description": "As an alternative to providing the plugin id in the provided HostCatalog,\nthis field can be used to lookup the plugin using it's name.",
|
||||
"description": "As an alternative to providing the plugin id in the provided HostCatalog,\nthis field can be used to lookup the plugin using its name.",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string"
|
||||
|
||||
@@ -235,8 +235,8 @@ type CreateHostCatalogRequest struct {
|
||||
|
||||
Item *hostcatalogs.HostCatalog `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
|
||||
// As an alternative to providing the plugin id in the provided HostCatalog,
|
||||
// this field can be used to lookup the plugin using it's name.
|
||||
PluginName string `protobuf:"bytes,2,opt,name=plugin_name,json=pluginName,proto3" json:"plugin_name,omitempty"`
|
||||
// this field can be used to lookup the plugin using its name.
|
||||
PluginName string `protobuf:"bytes,2,opt,name=plugin_name,proto3" json:"plugin_name,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CreateHostCatalogRequest) Reset() {
|
||||
@@ -576,113 +576,113 @@ var file_controller_api_services_v1_host_catalog_service_proto_rawDesc = []byte{
|
||||
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x73, 0x2e, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x05, 0x69,
|
||||
0x74, 0x65, 0x6d, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48,
|
||||
0x74, 0x65, 0x6d, 0x73, 0x22, 0x87, 0x01, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48,
|
||||
0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x49, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x35, 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, 0x68, 0x6f, 0x73, 0x74, 0x63,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x20, 0x0a, 0x0b,
|
||||
0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x0a, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x78, 0x0a,
|
||||
0x19, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c,
|
||||
0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72,
|
||||
0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x49, 0x0a, 0x04,
|
||||
0x69, 0x74, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 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, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f,
|
||||
0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f,
|
||||
0x67, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xb2, 0x01, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x02, 0x69, 0x64, 0x12, 0x49, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x35, 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, 0x68, 0x6f,
|
||||
0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f,
|
||||
0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12,
|
||||
0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b,
|
||||
0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x66, 0x0a, 0x19,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f,
|
||||
0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x04, 0x69, 0x74, 0x65,
|
||||
0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 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, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x04,
|
||||
0x69, 0x74, 0x65, 0x6d, 0x22, 0x2a, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f,
|
||||
0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
|
||||
0x22, 0x1b, 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61,
|
||||
0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xde, 0x07,
|
||||
0x0a, 0x12, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x12, 0xbd, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74,
|
||||
0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61,
|
||||
0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x09, 0x52, 0x0b, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x78,
|
||||
0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61,
|
||||
0x6c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75,
|
||||
0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x49, 0x0a,
|
||||
0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 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, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c,
|
||||
0x6f, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c,
|
||||
0x6f, 0x67, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xb2, 0x01, 0x0a, 0x18, 0x55, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x49, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x35, 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, 0x68,
|
||||
0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48,
|
||||
0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73,
|
||||
0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x66, 0x0a,
|
||||
0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c,
|
||||
0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x04, 0x69, 0x74,
|
||||
0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 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, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52,
|
||||
0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x2a, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48,
|
||||
0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
|
||||
0x64, 0x22, 0x1b, 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xde,
|
||||
0x07, 0x0a, 0x12, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xbd, 0x01, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73,
|
||||
0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74,
|
||||
0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74,
|
||||
0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x44, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x6f, 0x73,
|
||||
0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62,
|
||||
0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x1d, 0x12, 0x1b, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61,
|
||||
0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x43, 0x61, 0x74,
|
||||
0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x12, 0xba, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x6f,
|
||||
0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x43,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44,
|
||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74,
|
||||
0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04,
|
||||
0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x1d, 0x12, 0x1b, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20,
|
||||
0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x43, 0x61, 0x74, 0x61,
|
||||
0x6c, 0x6f, 0x67, 0x2e, 0x12, 0xba, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x6f, 0x73,
|
||||
0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x43,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34,
|
||||
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x6f, 0x73, 0x74,
|
||||
0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f,
|
||||
0x76, 0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73,
|
||||
0x92, 0x41, 0x1f, 0x12, 0x1d, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x73, 0x74,
|
||||
0x20, 0x6f, 0x66, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67,
|
||||
0x73, 0x2e, 0x12, 0xc2, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73,
|
||||
0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74,
|
||||
0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74,
|
||||
0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76,
|
||||
0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x92,
|
||||
0x41, 0x1f, 0x12, 0x1d, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20,
|
||||
0x6f, 0x66, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73,
|
||||
0x2e, 0x12, 0xc2, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x22, 0x11, 0x2f,
|
||||
0x76, 0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73,
|
||||
0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x18, 0x12,
|
||||
0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20,
|
||||
0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0xc7, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x34, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
|
||||
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c,
|
||||
0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x45, 0x82, 0xd3, 0xe4, 0x93,
|
||||
0x02, 0x24, 0x32, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74,
|
||||
0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x18, 0x12, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x73, 0x20, 0x61, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f,
|
||||
0x67, 0x12, 0xbb, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74,
|
||||
0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43,
|
||||
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74,
|
||||
0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x40, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x22, 0x11, 0x2f, 0x76,
|
||||
0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x3a,
|
||||
0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x18, 0x12, 0x16,
|
||||
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x43,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0xc7, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x34, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
|
||||
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f,
|
||||
0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x45, 0x82, 0xd3, 0xe4, 0x93, 0x02,
|
||||
0x24, 0x32, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61,
|
||||
0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62,
|
||||
0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x18, 0x12, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x73, 0x20, 0x61, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67,
|
||||
0x12, 0xbb, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61,
|
||||
0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
|
||||
0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x76, 0x31,
|
||||
0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f, 0x7b,
|
||||
0x69, 0x64, 0x7d, 0x92, 0x41, 0x18, 0x12, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20,
|
||||
0x61, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x42, 0x4d,
|
||||
0x5a, 0x4b, 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,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x39, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x2a, 0x16, 0x2f, 0x76,
|
||||
0x31, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2f,
|
||||
0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x18, 0x12, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73,
|
||||
0x20, 0x61, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x42,
|
||||
0x4d, 0x5a, 0x4b, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -19,7 +19,7 @@ type HostCatalog struct {
|
||||
*store.HostCatalog
|
||||
tableName string `gorm:"-"`
|
||||
|
||||
secrets *structpb.Struct `gorm:"-"`
|
||||
Secrets *structpb.Struct `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewHostCatalog creates a new in memory HostCatalog assigned to a scopeId
|
||||
@@ -42,7 +42,7 @@ func NewHostCatalog(ctx context.Context, scopeId, pluginId string, opt ...Option
|
||||
Description: opts.withDescription,
|
||||
Attributes: attrs,
|
||||
},
|
||||
secrets: opts.withSecrets,
|
||||
Secrets: opts.withSecrets,
|
||||
}
|
||||
return hc, nil
|
||||
}
|
||||
@@ -57,11 +57,11 @@ func allocHostCatalog() *HostCatalog {
|
||||
// secret. The secret shallow copied.
|
||||
func (c *HostCatalog) clone() *HostCatalog {
|
||||
cp := proto.Clone(c.HostCatalog)
|
||||
newSecret := proto.Clone(c.secrets)
|
||||
newSecret := proto.Clone(c.Secrets)
|
||||
|
||||
hc := &HostCatalog{
|
||||
HostCatalog: cp.(*store.HostCatalog),
|
||||
secrets: newSecret.(*structpb.Struct),
|
||||
Secrets: newSecret.(*structpb.Struct),
|
||||
}
|
||||
// proto.Clone will convert slices with length and capacity of 0 to nil.
|
||||
// Fix this since gorm treats empty slices differently than nil.
|
||||
|
||||
@@ -19,8 +19,9 @@ type Repository struct {
|
||||
kms *kms.Kms
|
||||
|
||||
// plugins is a map from plugin resource id to host plugin client.
|
||||
// TODO: When we are using go-plugin change from using a plgpb.HostPluginServiceServer
|
||||
// to the client.
|
||||
//
|
||||
// TODO: When we are using go-plugin change from using a
|
||||
// plgpb.HostPluginServiceServer to the client.
|
||||
plugins map[string]plgpb.HostPluginServiceServer
|
||||
// defaultLimit provides a default for limiting the number of results
|
||||
// returned from the repo
|
||||
|
||||
@@ -274,8 +274,8 @@ func toPluginCatalog(ctx context.Context, in *HostCatalog) (*pb.HostCatalog, err
|
||||
}
|
||||
hc.Attributes = attrs
|
||||
}
|
||||
if in.secrets != nil {
|
||||
hc.Secrets = in.secrets
|
||||
if in.Secrets != nil {
|
||||
hc.Secrets = in.Secrets
|
||||
}
|
||||
return hc, nil
|
||||
}
|
||||
@@ -212,7 +212,7 @@ func TestRepository_CreateCatalog(t *testing.T) {
|
||||
PluginId: plg.GetPublicId(),
|
||||
Attributes: []byte{},
|
||||
},
|
||||
secrets: func() *structpb.Struct {
|
||||
Secrets: func() *structpb.Struct {
|
||||
st, err := structpb.NewStruct(map[string]interface{}{
|
||||
"k1": "v1",
|
||||
"k2": 2,
|
||||
@@ -276,7 +276,7 @@ func TestRepository_CreateCatalog(t *testing.T) {
|
||||
cSecret := allocHostCatalogSecret()
|
||||
err = rw.LookupWhere(ctx, &cSecret, "catalog_id=?", got.GetPublicId())
|
||||
if tt.wantSecret == nil {
|
||||
assert.Nil(got.secrets)
|
||||
assert.Nil(got.Secrets)
|
||||
require.Error(t, err)
|
||||
require.True(t, errors.IsNotFoundError(err))
|
||||
return
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package host
|
||||
|
||||
// getOpts - iterate the inbound Options and return a struct
|
||||
func getOpts(opt ...Option) options {
|
||||
// GetOpts - iterate the inbound Options and return a struct
|
||||
func GetOpts(opt ...Option) options {
|
||||
opts := getDefaultOptions()
|
||||
for _, o := range opt {
|
||||
o(&opts)
|
||||
@@ -16,6 +16,7 @@ type Option func(*options)
|
||||
type options struct {
|
||||
withName string
|
||||
withDescription string
|
||||
withPublicId string
|
||||
withLimit int
|
||||
}
|
||||
|
||||
@@ -40,6 +41,13 @@ func WithName(name string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithPublicId provides an optional specific public ID
|
||||
func WithPublicId(with string) Option {
|
||||
return func(o *options) {
|
||||
o.withPublicId = with
|
||||
}
|
||||
}
|
||||
|
||||
// WithLimit provides an option to provide a limit. Intentionally allowing
|
||||
// negative integers. If WithLimit < 0, then unlimited results are
|
||||
// returned. If WithLimit == 0, then default limits are used for results.
|
||||
|
||||
@@ -9,19 +9,25 @@ import (
|
||||
func Test_GetOpts(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("WithName", func(t *testing.T) {
|
||||
opts := getOpts(WithName("test"))
|
||||
opts := GetOpts(WithName("test"))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withName = "test"
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithDescription", func(t *testing.T) {
|
||||
opts := getOpts(WithDescription("test desc"))
|
||||
opts := GetOpts(WithDescription("test desc"))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withDescription = "test desc"
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithPublicId", func(t *testing.T) {
|
||||
opts := GetOpts(WithPublicId("pl_1234567890"))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withPublicId = "pl_1234567890"
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithLimit", func(t *testing.T) {
|
||||
opts := getOpts(WithLimit(5))
|
||||
opts := GetOpts(WithLimit(5))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withLimit = 5
|
||||
assert.Equal(t, opts, testOpts)
|
||||
|
||||
@@ -17,7 +17,7 @@ type Plugin struct {
|
||||
// NewPlugin creates a new in memory Plugin assigned to the global scope.
|
||||
// Name, Description are the only allowed option. All other options are ignored.
|
||||
func NewPlugin(opt ...Option) *Plugin {
|
||||
opts := getOpts(opt...)
|
||||
opts := GetOpts(opt...)
|
||||
p := &Plugin{
|
||||
Plugin: &store.Plugin{
|
||||
ScopeId: scope.Global.String(),
|
||||
|
||||
@@ -15,8 +15,6 @@ import (
|
||||
func TestPlugin_Create(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
|
||||
type args struct{}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
opts []Option
|
||||
|
||||
@@ -32,7 +32,7 @@ func NewRepository(r db.Reader, w db.Writer, kms *kms.Kms, opt ...Option) (*Repo
|
||||
return nil, errors.NewDeprecated(errors.InvalidParameter, op, "kms")
|
||||
}
|
||||
|
||||
opts := getOpts(opt...)
|
||||
opts := GetOpts(opt...)
|
||||
if opts.withLimit == 0 {
|
||||
// zero signals the boundary defaults should be used.
|
||||
opts.withLimit = db.DefaultLimit
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
// unique within p.ScopeID.
|
||||
//
|
||||
// Both p.CreateTime and c.UpdateTime are ignored.
|
||||
func (r *Repository) CreatePlugin(ctx context.Context, p *Plugin, _ ...Option) (*Plugin, error) {
|
||||
func (r *Repository) CreatePlugin(ctx context.Context, p *Plugin, opt ...Option) (*Plugin, error) {
|
||||
const op = "host.(Repository).CreatePlugin"
|
||||
if p == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "nil Plugin")
|
||||
@@ -39,11 +39,16 @@ func (r *Repository) CreatePlugin(ctx context.Context, p *Plugin, _ ...Option) (
|
||||
}
|
||||
p = p.clone()
|
||||
|
||||
id, err := newPluginId()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
opts := GetOpts(opt...)
|
||||
|
||||
p.PublicId = opts.withPublicId
|
||||
if p.PublicId == "" {
|
||||
var err error
|
||||
p.PublicId, err = newPluginId()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
}
|
||||
p.PublicId = id
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, p.ScopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
@@ -122,7 +127,7 @@ func (r *Repository) ListPlugins(ctx context.Context, scopeIds []string, opt ...
|
||||
if len(scopeIds) == 0 {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no scope id")
|
||||
}
|
||||
opts := getOpts(opt...)
|
||||
opts := GetOpts(opt...)
|
||||
limit := r.defaultLimit
|
||||
if opts.withLimit != 0 {
|
||||
// non-zero signals an override of the default limit for the repo.
|
||||
|
||||
@@ -23,7 +23,7 @@ message HostCatalog {
|
||||
resources.scopes.v1.ScopeInfo scope = 30;
|
||||
|
||||
// The ID of the plugin of which this catalog is created.
|
||||
string plugin_id = 34 [json_name="plugin_id"];
|
||||
string plugin_id = 34 [json_name="plugin_id", (custom_options.v1.generate_sdk_option) = true];
|
||||
|
||||
// Output only. Plugin information for this resource.
|
||||
resources.plugins.v1.PluginInfo plugin = 35;
|
||||
|
||||
@@ -104,8 +104,8 @@ message ListHostCatalogsResponse {
|
||||
message CreateHostCatalogRequest {
|
||||
api.resources.hostcatalogs.v1.HostCatalog item = 1;
|
||||
// As an alternative to providing the plugin id in the provided HostCatalog,
|
||||
// this field can be used to lookup the plugin using it's name.
|
||||
string plugin_name = 2;
|
||||
// this field can be used to lookup the plugin using its name.
|
||||
string plugin_name = 2 [json_name="plugin_name"];
|
||||
}
|
||||
|
||||
message CreateHostCatalogResponse {
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/servers/controller/common"
|
||||
"github.com/hashicorp/boundary/internal/session"
|
||||
"github.com/hashicorp/boundary/internal/target"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-secure-stdlib/mlock"
|
||||
"github.com/patrickmn/go-cache"
|
||||
@@ -104,6 +104,10 @@ func New(ctx context.Context, conf *Config) (*Controller, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if conf.HostPlugins == nil {
|
||||
conf.HostPlugins = make(map[string]plugin.HostPluginServiceServer)
|
||||
}
|
||||
|
||||
// Set up repo stuff
|
||||
dbase := db.New(c.conf.Database)
|
||||
kmsRepo, err := kms.NewRepository(dbase, dbase)
|
||||
@@ -137,7 +141,7 @@ func New(ctx context.Context, conf *Config) (*Controller, error) {
|
||||
return static.NewRepository(dbase, dbase, c.kms)
|
||||
}
|
||||
c.PluginHostRepoFn = func() (*hostplugin.Repository, error) {
|
||||
return hostplugin.NewRepository(dbase, dbase, c.kms, map[string]plgpb.HostPluginServiceServer{})
|
||||
return hostplugin.NewRepository(dbase, dbase, c.kms, c.conf.HostPlugins)
|
||||
}
|
||||
c.HostPluginRepoFn = func() (*host.Repository, error) {
|
||||
return host.NewRepository(dbase, dbase, c.kms)
|
||||
|
||||
@@ -50,9 +50,14 @@ var (
|
||||
action.List,
|
||||
}
|
||||
|
||||
collectionTypeMap = map[resource.Type]action.ActionSet{
|
||||
resource.HostSet: host_sets.CollectionActions,
|
||||
resource.Host: hosts.CollectionActions,
|
||||
collectionTypeMap = map[string]map[resource.Type]action.ActionSet{
|
||||
"static": {
|
||||
resource.HostSet: host_sets.CollectionActions,
|
||||
resource.Host: hosts.CollectionActions,
|
||||
},
|
||||
"plugin": {
|
||||
resource.HostSet: host_sets.CollectionActions,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -121,11 +126,11 @@ func (s Service) ListHostCatalogs(ctx context.Context, req *pbs.ListHostCatalogs
|
||||
return &pbs.ListHostCatalogsResponse{}, nil
|
||||
}
|
||||
|
||||
ul, pluginInfoMap, err := s.listFromRepo(ctx, scopeIds)
|
||||
items, pluginInfoMap, err := s.listFromRepo(ctx, scopeIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ul) == 0 {
|
||||
if len(items) == 0 {
|
||||
return &pbs.ListHostCatalogsResponse{}, nil
|
||||
}
|
||||
|
||||
@@ -133,11 +138,11 @@ func (s Service) ListHostCatalogs(ctx context.Context, req *pbs.ListHostCatalogs
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
finalItems := make([]*pb.HostCatalog, 0, len(ul))
|
||||
finalItems := make([]*pb.HostCatalog, 0, len(items))
|
||||
res := perms.Resource{
|
||||
Type: resource.HostCatalog,
|
||||
}
|
||||
for _, item := range ul {
|
||||
for _, item := range items {
|
||||
res.Id = item.GetPublicId()
|
||||
res.ScopeId = item.GetScopeId()
|
||||
authorizedActions := authResults.FetchActionSetForId(ctx, item.GetPublicId(), IdActions, auth.WithResource(&res)).Strings()
|
||||
@@ -155,11 +160,20 @@ func (s Service) ListHostCatalogs(ctx context.Context, req *pbs.ListHostCatalogs
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authorizedActions))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedCollectionActionsField) {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, item.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var collType string
|
||||
switch item.(type) {
|
||||
case *static.HostCatalog:
|
||||
collType = "static"
|
||||
case *plugin.HostCatalog:
|
||||
collType = "plugin"
|
||||
}
|
||||
if collType != "" {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap[collType], authResults.Scope.Id, item.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedCollectionActions(collectionActions))
|
||||
}
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedCollectionActions(collectionActions))
|
||||
}
|
||||
switch hc := item.(type) {
|
||||
case *plugin.HostCatalog:
|
||||
@@ -210,11 +224,20 @@ func (s Service) GetHostCatalog(ctx context.Context, req *pbs.GetHostCatalogRequ
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, hc.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedCollectionActionsField) {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, hc.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var collType string
|
||||
switch hc.(type) {
|
||||
case *static.HostCatalog:
|
||||
collType = "static"
|
||||
case *plugin.HostCatalog:
|
||||
collType = "plugin"
|
||||
}
|
||||
if collType != "" {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap[collType], authResults.Scope.Id, hc.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedCollectionActions(collectionActions))
|
||||
}
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedCollectionActions(collectionActions))
|
||||
}
|
||||
if plg != nil {
|
||||
outputOpts = append(outputOpts, handlers.WithPlugin(plg))
|
||||
@@ -258,11 +281,20 @@ func (s Service) CreateHostCatalog(ctx context.Context, req *pbs.CreateHostCatal
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, hc.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedCollectionActionsField) {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, hc.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var collType string
|
||||
switch hc.(type) {
|
||||
case *static.HostCatalog:
|
||||
collType = "static"
|
||||
case *plugin.HostCatalog:
|
||||
collType = "plugin"
|
||||
}
|
||||
if collType != "" {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap[collType], authResults.Scope.Id, hc.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedCollectionActions(collectionActions))
|
||||
}
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedCollectionActions(collectionActions))
|
||||
}
|
||||
if plg != nil {
|
||||
outputOpts = append(outputOpts, handlers.WithPlugin(plg))
|
||||
@@ -309,7 +341,7 @@ func (s Service) UpdateHostCatalog(ctx context.Context, req *pbs.UpdateHostCatal
|
||||
outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, hc.GetPublicId(), IdActions).Strings()))
|
||||
}
|
||||
if outputFields.Has(globals.AuthorizedCollectionActionsField) {
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, hc.GetPublicId())
|
||||
collectionActions, err := auth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap["static"], authResults.Scope.Id, hc.GetPublicId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -408,7 +440,7 @@ func (s Service) listFromRepo(ctx context.Context, scopeIds []string) ([]host.Ca
|
||||
}
|
||||
|
||||
func (s Service) createStaticInRepo(ctx context.Context, projId string, item *pb.HostCatalog) (*static.HostCatalog, error) {
|
||||
const op = "host_catalogs.(Service).createInRepo"
|
||||
const op = "host_catalogs.(Service).createStaticInRepo"
|
||||
h, err := toStorageStaticCatalog(ctx, projId, item)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to build catalog for creation"))
|
||||
@@ -428,7 +460,7 @@ func (s Service) createStaticInRepo(ctx context.Context, projId string, item *pb
|
||||
}
|
||||
|
||||
func (s Service) createPluginInRepo(ctx context.Context, projId string, req *pbs.CreateHostCatalogRequest) (*plugin.HostCatalog, *plugins.PluginInfo, error) {
|
||||
const op = "host_catalogs.(Service).createInRepo"
|
||||
const op = "host_catalogs.(Service).createPluginInRepo"
|
||||
item := req.GetItem()
|
||||
pluginId := item.GetPluginId()
|
||||
if pluginId == "" {
|
||||
@@ -716,13 +748,15 @@ func validateCreateRequest(req *pbs.CreateHostCatalogRequest) error {
|
||||
case static.Subtype:
|
||||
case plugin.Subtype:
|
||||
if req.GetItem().GetPlugin() != nil {
|
||||
badFields[globals.PluginField] = fmt.Sprintf("This is a read only field.")
|
||||
badFields[globals.PluginField] = "This is a read only field."
|
||||
}
|
||||
if req.GetItem().GetPluginId() == "" && req.GetPluginName() == "" {
|
||||
badFields[globals.PluginIdField] = fmt.Sprintf("This is a required field.")
|
||||
badFields[globals.PluginIdField] = "This or plugin name is a required field."
|
||||
badFields[globals.PluginNameField] = "This or plugin id is a required field."
|
||||
}
|
||||
if req.GetItem().GetPluginId() != "" && req.GetPluginName() != "" {
|
||||
badFields[globals.PluginIdField] = fmt.Sprintf("Can't set the plugin name field along with this field.")
|
||||
badFields[globals.PluginIdField] = "Can't set the plugin name field along with this field."
|
||||
badFields[globals.PluginNameField] = "Can't set the plugin id field along with this field."
|
||||
}
|
||||
default:
|
||||
badFields[globals.TypeField] = fmt.Sprintf("This is a required field and must be either %q or %q.", static.Subtype.String(), plugin.Subtype.String())
|
||||
|
||||
@@ -36,17 +36,27 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var authorizedCollectionActions = map[string]*structpb.ListValue{
|
||||
"host-sets": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
var authorizedCollectionActions = map[string]map[string]*structpb.ListValue{
|
||||
"static": {
|
||||
"host-sets": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
"hosts": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
},
|
||||
"hosts": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
"plugin": {
|
||||
"host-sets": {
|
||||
Values: []*structpb.Value{
|
||||
structpb.NewStringValue("create"),
|
||||
structpb.NewStringValue("list"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -86,7 +96,7 @@ func TestGet_Static(t *testing.T) {
|
||||
UpdatedTime: hc.UpdateTime.GetTimestamp(),
|
||||
Type: "static",
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["static"],
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
@@ -187,7 +197,7 @@ func TestGet_Plugin(t *testing.T) {
|
||||
UpdatedTime: hc.UpdateTime.GetTimestamp(),
|
||||
Type: plugin.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["plugin"],
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
@@ -277,7 +287,7 @@ func TestList(t *testing.T) {
|
||||
Version: 1,
|
||||
Type: "static",
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["static"],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -301,7 +311,7 @@ func TestList(t *testing.T) {
|
||||
Version: 1,
|
||||
Type: plugin.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["plugin"],
|
||||
}
|
||||
wantSomeCatalogs = append(wantSomeCatalogs, cat)
|
||||
testPluginCatalogs = append(testPluginCatalogs, cat)
|
||||
@@ -318,7 +328,7 @@ func TestList(t *testing.T) {
|
||||
Version: 1,
|
||||
Type: "static",
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["static"],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -341,7 +351,7 @@ func TestList(t *testing.T) {
|
||||
Version: 1,
|
||||
Type: plugin.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["plugin"],
|
||||
})
|
||||
}
|
||||
|
||||
@@ -597,7 +607,7 @@ func TestCreate_Static(t *testing.T) {
|
||||
Description: &wrappers.StringValue{Value: "desc"},
|
||||
Type: "static",
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["static"],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -764,7 +774,7 @@ func TestCreate_Plugin(t *testing.T) {
|
||||
Description: &wrappers.StringValue{Value: "desc"},
|
||||
Type: plugin.Subtype.String(),
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["plugin"],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -951,7 +961,7 @@ func TestUpdate(t *testing.T) {
|
||||
CreatedTime: hc.GetCreateTime().GetTimestamp(),
|
||||
Type: "static",
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["static"],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -977,7 +987,7 @@ func TestUpdate(t *testing.T) {
|
||||
CreatedTime: hc.GetCreateTime().GetTimestamp(),
|
||||
Type: "static",
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["static"],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1032,7 +1042,7 @@ func TestUpdate(t *testing.T) {
|
||||
CreatedTime: hc.GetCreateTime().GetTimestamp(),
|
||||
Type: "static",
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["static"],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1055,7 +1065,7 @@ func TestUpdate(t *testing.T) {
|
||||
CreatedTime: hc.GetCreateTime().GetTimestamp(),
|
||||
Type: "static",
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["static"],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1080,7 +1090,7 @@ func TestUpdate(t *testing.T) {
|
||||
CreatedTime: hc.GetCreateTime().GetTimestamp(),
|
||||
Type: "static",
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["static"],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -1105,7 +1115,7 @@ func TestUpdate(t *testing.T) {
|
||||
CreatedTime: hc.GetCreateTime().GetTimestamp(),
|
||||
Type: "static",
|
||||
AuthorizedActions: testAuthorizedActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions,
|
||||
AuthorizedCollectionActions: authorizedCollectionActions["static"],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -226,7 +226,7 @@ var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_rawDesc = [
|
||||
0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf4, 0x07, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x22, 0xfa, 0x07, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74,
|
||||
0x61, 0x6c, 0x6f, 0x67, 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,
|
||||
@@ -234,68 +234,69 @@ var file_controller_api_resources_hostcatalogs_v1_host_catalog_proto_rawDesc = [
|
||||
0x2d, 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, 0x73, 0x63, 0x6f, 0x70, 0x65,
|
||||
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05,
|
||||
0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x22, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
|
||||
0x5f, 0x69, 0x64, 0x12, 0x47, 0x0a, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x18, 0x23, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x2f, 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, 0x70,
|
||||
0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e,
|
||||
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x46, 0x0a, 0x04,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72,
|
||||
0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x14, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd,
|
||||
0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x04,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x22, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29,
|
||||
0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b,
|
||||
0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73,
|
||||
0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,
|
||||
0x75, 0x74, 0x65, 0x73, 0x18, 0x64, 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, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69,
|
||||
0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 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,
|
||||
0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 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, 0x12,
|
||||
0x9d, 0x01, 0x0a, 0x1d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63,
|
||||
0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x18, 0xb6, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x56, 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, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e,
|
||||
0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
||||
0x52, 0x1d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c,
|
||||
0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a,
|
||||
0x6a, 0x0a, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c,
|
||||
0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e,
|
||||
0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
|
||||
0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x22, 0x0a, 0x09, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x22, 0x20, 0x01, 0x28, 0x09, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x09,
|
||||
0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x12, 0x47, 0x0a, 0x06, 0x70, 0x6c, 0x75,
|
||||
0x67, 0x69, 0x6e, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 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, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x70, 0x6c, 0x75, 0x67,
|
||||
0x69, 0x6e, 0x12, 0x46, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||
0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x14,
|
||||
0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x64, 0x65,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||
0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x22, 0xa0,
|
||||
0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e,
|
||||
0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x5a, 0x5a, 0x58, 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, 0x68, 0x6f,
|
||||
0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x3b, 0x68, 0x6f, 0x73, 0x74, 0x63,
|
||||
0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||
0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e,
|
||||
0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x46,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||
0x52, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18,
|
||||
0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x52,
|
||||
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||
0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3d, 0x0a, 0x0a,
|
||||
0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x64, 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, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52,
|
||||
0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x73,
|
||||
0x65, 0x63, 0x72, 0x65, 0x74, 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, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x07, 0x73, 0x65, 0x63,
|
||||
0x72, 0x65, 0x74, 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, 0x12, 0x9d, 0x01, 0x0a, 0x1d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72,
|
||||
0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
|
||||
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb6, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x56,
|
||||
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, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61,
|
||||
0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61,
|
||||
0x74, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64,
|
||||
0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
|
||||
0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6a, 0x0a, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
|
||||
0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||
0x01, 0x42, 0x5a, 0x5a, 0x58, 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, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73,
|
||||
0x3b, 0x68, 0x6f, 0x73, 0x74, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x73, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
Reference in new issue
Block a user