diff --git a/CHANGELOG.md b/CHANGELOG.md index 365cd034d..353d5b891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,25 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. +## Next + +### Deprecations/Changes + +* Per the note in Boundary 0.12.0, the `vault` credential library subtype has + now been removed in favor of `vault-generic`. For example, instead of + `boundary credential-libraries create vault`, you must use `boundary + credential-libraries create vault-generic`. + +### New and Improved + +* cli: New generic commands `read`, `update`, and `delete` have been added. + These allow operating on resources by directly specifying the ID of the + resource as the next parameter (e.g. `boundary update ttcp_1234567890`). + Subtypes do not need to be specified (e.g. that command is equivalent to + `boundary targets update tcp -id ttcp_1234567890`), and any flags given after + the ID are passed through to the type-specific subcommand. Once the ID has + been entered, autocomplete is also supported. + ## 0.14.2 (2023/11/2) ### New and Improved diff --git a/cmd/boundary/main.go b/cmd/boundary/main.go index b3bc548ff..774a8aedd 100644 --- a/cmd/boundary/main.go +++ b/cmd/boundary/main.go @@ -4,14 +4,11 @@ package main import ( - "math/rand" "os" - "time" "github.com/hashicorp/boundary/internal/cmd" ) func main() { - rand.Seed(time.Now().UnixNano()) os.Exit(cmd.Run(os.Args[1:])) } diff --git a/globals/prefixes.go b/globals/prefixes.go index 6f2ecaa90..93e859194 100644 --- a/globals/prefixes.go +++ b/globals/prefixes.go @@ -4,6 +4,7 @@ package globals import ( + "fmt" "strings" "github.com/hashicorp/boundary/internal/types/resource" @@ -125,57 +126,231 @@ const ( ChannelRecordingPrefix = "chr" ) -var prefixToResourceType = map[string]resource.Type{ - AuthTokenPrefix: resource.AuthToken, - PasswordAuthMethodPrefix: resource.AuthMethod, - PasswordAccountPrefix: resource.Account, - PasswordAccountPreviousPrefix: resource.Account, - OidcAuthMethodPrefix: resource.AuthMethod, - OidcAccountPrefix: resource.Account, - OidcManagedGroupPrefix: resource.ManagedGroup, - GlobalPrefix: resource.Scope, - ProjectPrefix: resource.Scope, - OrgPrefix: resource.Scope, - UserPrefix: resource.User, - GroupPrefix: resource.Group, - RolePrefix: resource.Role, - StaticCredentialStorePrefix: resource.CredentialStore, - StaticCredentialStorePreviousPrefix: resource.CredentialStore, - VaultCredentialStorePrefix: resource.CredentialStore, - VaultCredentialLibraryPrefix: resource.CredentialLibrary, - VaultSshCertificateCredentialLibraryPrefix: resource.CredentialLibrary, - UsernamePasswordCredentialPrefix: resource.Credential, - UsernamePasswordCredentialPreviousPrefix: resource.Credential, - SshPrivateKeyCredentialPrefix: resource.Credential, - JsonCredentialPrefix: resource.Credential, - StaticHostCatalogPrefix: resource.HostCatalog, - StaticHostSetPrefix: resource.HostSet, - StaticHostPrefix: resource.Host, - PluginHostCatalogPrefix: resource.HostCatalog, - PluginHostCatalogPreviousPrefix: resource.HostCatalog, - PluginHostSetPrefix: resource.HostSet, - PluginHostSetPreviousPrefix: resource.HostSet, - PluginHostPrefix: resource.Host, - PluginHostPreviousPrefix: resource.Host, - SessionPrefix: resource.Session, - TcpTargetPrefix: resource.Target, - SshTargetPrefix: resource.Target, - WorkerPrefix: resource.Worker, - PluginStorageBucketPrefix: resource.StorageBucket, - SessionRecordingPrefix: resource.SessionRecording, +type ResourceInfo struct { + Type resource.Type + Domain string + Subtype Subtype +} + +var prefixToResourceType = map[string]ResourceInfo{ + AuthTokenPrefix: { + Type: resource.AuthToken, + Subtype: UnknownSubtype, + }, + + PasswordAuthMethodPrefix: { + Type: resource.AuthMethod, + Subtype: UnknownSubtype, + }, + PasswordAccountPrefix: { + Type: resource.Account, + Subtype: UnknownSubtype, + }, + PasswordAccountPreviousPrefix: { + Type: resource.Account, + Subtype: UnknownSubtype, + }, + + OidcAuthMethodPrefix: { + Type: resource.AuthMethod, + Subtype: UnknownSubtype, + }, + OidcAccountPrefix: { + Type: resource.Account, + Subtype: UnknownSubtype, + }, + OidcManagedGroupPrefix: { + Type: resource.ManagedGroup, + Subtype: UnknownSubtype, + }, + + LdapManagedGroupPrefix: { + Type: resource.ManagedGroup, + Subtype: UnknownSubtype, + }, + LdapAuthMethodPrefix: { + Type: resource.AuthMethod, + Subtype: UnknownSubtype, + }, + LdapAccountPrefix: { + Type: resource.Account, + Subtype: UnknownSubtype, + }, + + ProjectPrefix: { + Type: resource.Scope, + Subtype: UnknownSubtype, + }, + OrgPrefix: { + Type: resource.Scope, + Subtype: UnknownSubtype, + }, + GlobalPrefix: { + Type: resource.Scope, + Subtype: UnknownSubtype, + }, + + UserPrefix: { + Type: resource.User, + Subtype: UnknownSubtype, + }, + GroupPrefix: { + Type: resource.Group, + Subtype: UnknownSubtype, + }, + RolePrefix: { + Type: resource.Role, + Subtype: UnknownSubtype, + }, + + StaticCredentialStorePrefix: { + Type: resource.CredentialStore, + Subtype: UnknownSubtype, + }, + StaticCredentialStorePreviousPrefix: { + Type: resource.CredentialStore, + Subtype: UnknownSubtype, + }, + + VaultCredentialStorePrefix: { + Type: resource.CredentialStore, + Subtype: UnknownSubtype, + }, + VaultCredentialLibraryPrefix: { + Type: resource.CredentialLibrary, + Subtype: UnknownSubtype, + }, + VaultSshCertificateCredentialLibraryPrefix: { + Type: resource.CredentialLibrary, + Subtype: UnknownSubtype, + }, + VaultDynamicCredentialPrefix: { + Type: resource.Credential, + Subtype: UnknownSubtype, + }, + + UsernamePasswordCredentialPrefix: { + Type: resource.Credential, + Subtype: UnknownSubtype, + }, + UsernamePasswordCredentialPreviousPrefix: { + Type: resource.Credential, + Subtype: UnknownSubtype, + }, + SshPrivateKeyCredentialPrefix: { + Type: resource.Credential, + Subtype: UnknownSubtype, + }, + JsonCredentialPrefix: { + Type: resource.Credential, + Subtype: UnknownSubtype, + }, + + StaticHostCatalogPrefix: { + Type: resource.HostCatalog, + Subtype: UnknownSubtype, + }, + StaticHostSetPrefix: { + Type: resource.HostSet, + Subtype: UnknownSubtype, + }, + StaticHostPrefix: { + Type: resource.Host, + Subtype: UnknownSubtype, + }, + + PluginHostCatalogPrefix: { + Type: resource.HostCatalog, + Subtype: UnknownSubtype, + }, + PluginHostCatalogPreviousPrefix: { + Type: resource.HostCatalog, + Subtype: UnknownSubtype, + }, + PluginHostSetPrefix: { + Type: resource.HostSet, + Subtype: UnknownSubtype, + }, + PluginHostSetPreviousPrefix: { + Type: resource.HostSet, + Subtype: UnknownSubtype, + }, + PluginHostPrefix: { + Type: resource.Host, + Subtype: UnknownSubtype, + }, + PluginHostPreviousPrefix: { + Type: resource.Host, + Subtype: UnknownSubtype, + }, + + SessionPrefix: { + Type: resource.Session, + Subtype: UnknownSubtype, + }, + + TcpTargetPrefix: { + Type: resource.Target, + Subtype: UnknownSubtype, + }, + SshTargetPrefix: { + Type: resource.Target, + Subtype: UnknownSubtype, + }, + + WorkerPrefix: { + Type: resource.Worker, + Subtype: UnknownSubtype, + }, + + PluginStorageBucketPrefix: { + Type: resource.StorageBucket, + Subtype: UnknownSubtype, + }, + + SessionRecordingPrefix: { + Type: resource.SessionRecording, + Subtype: UnknownSubtype, + }, } var resourceTypeToPrefixes map[resource.Type][]string = func() map[resource.Type][]string { ret := make(map[resource.Type][]string) for k, v := range prefixToResourceType { - ret[v] = append(ret[v], k) + ret[v.Type] = append(ret[v.Type], k) } return ret }() -// ResourceTypeFromPrefix takes in a resource ID (or a prefix) and returns the -// corresponding resource typ -func ResourceTypeFromPrefix(in string) resource.Type { +// RegisterPrefixToResourceInfo is called from various packages to register +// which prefixes belong to them, what types those represent, and any +// domain and subtype information. This lets the subtypes stay in different +// packages (important for the reflection introspection we do) while not +// creating import loops. +// +// If called more than once for the same prefix, this function will panic. +func RegisterPrefixToResourceInfo(prefix string, res resource.Type, domain string, subtype Subtype) { + if subtype == UnknownSubtype { + panic("cannot be called with a subtype of Unknown") + } + resInfo, ok := prefixToResourceType[prefix] + if !ok && domain != "test" { + panic(fmt.Sprintf("prefix %q being registered to domain %q type %q subtype %q but did not already exist in map", prefix, domain, res.String(), subtype.String())) + } + if domain != "test" && + (resInfo.Domain != "" || + resInfo.Subtype != UnknownSubtype) { + panic(fmt.Sprintf("prefix %q being registered to domain %q type %q subtype %q but was already registered to domain %q type %q subtype %q", prefix, domain, res.String(), subtype.String(), resInfo.Domain, resInfo.Type.String(), resInfo.Subtype.String())) + } + resInfo.Type = res + resInfo.Subtype = subtype + resInfo.Domain = domain + prefixToResourceType[prefix] = resInfo +} + +// ResourceInfoFromPrefix takes in a resource ID (or a prefix) and returns the +// corresponding resource info +func ResourceInfoFromPrefix(in string) ResourceInfo { // If full ID, trim to just prefix in, _, _ = strings.Cut(in, "_") return prefixToResourceType[in] @@ -186,3 +361,13 @@ func ResourceTypeFromPrefix(in string) resource.Type { func ResourcePrefixesFromType(in resource.Type) []string { return resourceTypeToPrefixes[in] } + +func PrefixesFromDomain(domain string) []string { + res := make([]string, 0, 8) + for k, v := range prefixToResourceType { + if v.Domain == domain { + res = append(res, k) + } + } + return res +} diff --git a/globals/prefixes_test.go b/globals/prefixes_test.go index 94c3f2a94..97b12438c 100644 --- a/globals/prefixes_test.go +++ b/globals/prefixes_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestResourceTypeFromPrefix(t *testing.T) { +func TestResourceInfoFromPrefix(t *testing.T) { // Test a random sampling vals := map[string]resource.Type{ VaultCredentialLibraryPrefix: resource.CredentialLibrary, @@ -21,8 +21,8 @@ func TestResourceTypeFromPrefix(t *testing.T) { } for prefix, typ := range vals { - assert.Equal(t, typ, ResourceTypeFromPrefix(prefix)) - assert.Equal(t, typ, ResourceTypeFromPrefix(fmt.Sprintf("%s_foobar", prefix))) - assert.Equal(t, resource.Unknown, ResourceTypeFromPrefix(fmt.Sprintf("%sfoobar", prefix))) + assert.Equal(t, typ, ResourceInfoFromPrefix(prefix).Type) + assert.Equal(t, typ, ResourceInfoFromPrefix(fmt.Sprintf("%s_foobar", prefix)).Type) + assert.Equal(t, resource.Unknown, ResourceInfoFromPrefix(fmt.Sprintf("%sfoobar", prefix)).Type) } } diff --git a/globals/subtypes.go b/globals/subtypes.go new file mode 100644 index 000000000..bc3be1146 --- /dev/null +++ b/globals/subtypes.go @@ -0,0 +1,16 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package globals + +// Subtype variables identify a boundary resource subtype. +type Subtype string + +const ( + UnknownSubtype Subtype = "unknown" +) + +// String returns the string representation of a Subtype +func (t Subtype) String() string { + return string(t) +} diff --git a/internal/auth/ldap/ids.go b/internal/auth/ldap/ids.go index 29aa69113..1b4e807cc 100644 --- a/internal/auth/ldap/ids.go +++ b/internal/auth/ldap/ids.go @@ -10,17 +10,17 @@ import ( "github.com/hashicorp/boundary/internal/auth" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/hashicorp/boundary/internal/types/resource" ) func init() { - if err := subtypes.Register(auth.Domain, Subtype, globals.LdapAuthMethodPrefix, globals.LdapAccountPrefix, globals.LdapManagedGroupPrefix); err != nil { - panic(err) - } + globals.RegisterPrefixToResourceInfo(globals.LdapAuthMethodPrefix, resource.AuthMethod, auth.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.LdapAccountPrefix, resource.Account, auth.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.LdapManagedGroupPrefix, resource.ManagedGroup, auth.Domain, Subtype) } const ( - Subtype = subtypes.Subtype("ldap") + Subtype = globals.Subtype("ldap") ) func newAuthMethodId(ctx context.Context) (string, error) { diff --git a/internal/auth/oidc/ids.go b/internal/auth/oidc/ids.go index 7c1e63a5d..7635d5744 100644 --- a/internal/auth/oidc/ids.go +++ b/internal/auth/oidc/ids.go @@ -10,17 +10,17 @@ import ( "github.com/hashicorp/boundary/internal/auth" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/hashicorp/boundary/internal/types/resource" ) func init() { - if err := subtypes.Register(auth.Domain, Subtype, globals.OidcAuthMethodPrefix, globals.OidcAccountPrefix, globals.OidcManagedGroupPrefix); err != nil { - panic(err) - } + globals.RegisterPrefixToResourceInfo(globals.OidcAuthMethodPrefix, resource.AuthMethod, auth.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.OidcAccountPrefix, resource.Account, auth.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.OidcManagedGroupPrefix, resource.ManagedGroup, auth.Domain, Subtype) } const ( - Subtype = subtypes.Subtype("oidc") + Subtype = globals.Subtype("oidc") ) func newAuthMethodId(ctx context.Context) (string, error) { diff --git a/internal/auth/password/public_ids.go b/internal/auth/password/public_ids.go index 505dc529e..49d1aed35 100644 --- a/internal/auth/password/public_ids.go +++ b/internal/auth/password/public_ids.go @@ -10,18 +10,18 @@ import ( "github.com/hashicorp/boundary/internal/auth" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/hashicorp/boundary/internal/types/resource" ) func init() { - if err := subtypes.Register(auth.Domain, Subtype, globals.PasswordAuthMethodPrefix, globals.PasswordAccountPreviousPrefix, globals.PasswordAccountPrefix); err != nil { - panic(err) - } + globals.RegisterPrefixToResourceInfo(globals.PasswordAuthMethodPrefix, resource.AuthMethod, auth.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.PasswordAccountPreviousPrefix, resource.Account, auth.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.PasswordAccountPrefix, resource.Account, auth.Domain, Subtype) } // PublicId prefixes for the resources in the password package. const ( - Subtype = subtypes.Subtype("password") + Subtype = globals.Subtype("password") ) func newAuthMethodId(ctx context.Context) (string, error) { diff --git a/internal/cmd/base/base.go b/internal/cmd/base/base.go index 2a9321ad5..6772d4ab9 100644 --- a/internal/cmd/base/base.go +++ b/internal/cmd/base/base.go @@ -142,12 +142,14 @@ type Command struct { } // New returns a new instance of a base.Command type -func NewCommand(ui cli.Ui) *Command { +func NewCommand(ui cli.Ui, opt ...Option) *Command { + opts := getOpts(opt...) ctx, cancel := context.WithCancel(context.Background()) ret := &Command{ UI: ui, ShutdownCh: MakeShutdownCh(), Context: ctx, + FlagId: opts.withImplicitId, } go func() { <-ret.ShutdownCh diff --git a/internal/cmd/base/option.go b/internal/cmd/base/option.go index 68f69df0b..a748018b4 100644 --- a/internal/cmd/base/option.go +++ b/internal/cmd/base/option.go @@ -44,6 +44,7 @@ type Options struct { withStatusCode int withHostPlugin func() (string, plugin.HostPluginServiceClient) withEventGating bool + withImplicitId string } func getDefaultOptions() Options { @@ -200,3 +201,11 @@ func WithEventGating(with bool) Option { o.withEventGating = with } } + +// WithImplicitId is used when creating the command if we are implicitly +// overriding the ID via a top-level read/update/delete command +func WithImplicitId(with string) Option { + return func(o *Options) { + o.withImplicitId = with + } +} diff --git a/internal/cmd/commands.go b/internal/cmd/commands.go index c158c5d7d..922f40c31 100644 --- a/internal/cmd/commands.go +++ b/internal/cmd/commands.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/boundary/internal/cmd/commands/credentialstorescmd" "github.com/hashicorp/boundary/internal/cmd/commands/database" "github.com/hashicorp/boundary/internal/cmd/commands/dev" + "github.com/hashicorp/boundary/internal/cmd/commands/genericcmd" "github.com/hashicorp/boundary/internal/cmd/commands/groupscmd" "github.com/hashicorp/boundary/internal/cmd/commands/hostcatalogscmd" "github.com/hashicorp/boundary/internal/cmd/commands/hostscmd" @@ -40,6 +41,10 @@ import ( var Commands map[string]cli.CommandFactory func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) { + var opts []base.Option + if runOpts.ImplicitId != "" { + opts = append(opts, base.WithImplicitId(runOpts.ImplicitId)) + } Commands = map[string]cli.CommandFactory{ "server": func() (cli.Command, error) { return &server.Command{ @@ -57,1268 +62,1277 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) { }, "version": func() (cli.Command, error) { return &version.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "authenticate": func() (cli.Command, error) { return &authenticate.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "authenticate password": func() (cli.Command, error) { return &authenticate.PasswordCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "authenticate oidc": func() (cli.Command, error) { return &authenticate.OidcCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "authenticate ldap": func() (cli.Command, error) { return &authenticate.LdapCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "accounts": func() (cli.Command, error) { return &accountscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "accounts read": func() (cli.Command, error) { return &accountscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "accounts delete": func() (cli.Command, error) { return &accountscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "accounts list": func() (cli.Command, error) { return &accountscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "accounts set-password": func() (cli.Command, error) { return &accountscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "set-password", }, nil }, "accounts change-password": func() (cli.Command, error) { return &accountscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "change-password", }, nil }, "accounts create": func() (cli.Command, error) { return &accountscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "accounts create password": func() (cli.Command, error) { return &accountscmd.PasswordCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "accounts create oidc": func() (cli.Command, error) { return &accountscmd.OidcCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "accounts create ldap": func() (cli.Command, error) { return &accountscmd.LdapCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "accounts update": func() (cli.Command, error) { return &accountscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "accounts update password": func() (cli.Command, error) { return &accountscmd.PasswordCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "accounts update oidc": func() (cli.Command, error) { return &accountscmd.OidcCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "accounts update ldap": func() (cli.Command, error) { return &accountscmd.LdapCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "auth-methods": func() (cli.Command, error) { return &authmethodscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "auth-methods read": func() (cli.Command, error) { return &authmethodscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "auth-methods delete": func() (cli.Command, error) { return &authmethodscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "auth-methods list": func() (cli.Command, error) { return &authmethodscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "auth-methods create": func() (cli.Command, error) { return &authmethodscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "auth-methods create password": func() (cli.Command, error) { return &authmethodscmd.PasswordCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "auth-methods create oidc": func() (cli.Command, error) { return &authmethodscmd.OidcCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "auth-methods create ldap": func() (cli.Command, error) { return &authmethodscmd.LdapCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "auth-methods update": func() (cli.Command, error) { return &authmethodscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "auth-methods update password": func() (cli.Command, error) { return &authmethodscmd.PasswordCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "auth-methods update oidc": func() (cli.Command, error) { return &authmethodscmd.OidcCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "auth-methods update ldap": func() (cli.Command, error) { return &authmethodscmd.LdapCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "auth-methods change-state oidc": func() (cli.Command, error) { return &authmethodscmd.OidcCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "change-state", }, nil }, "auth-tokens": func() (cli.Command, error) { return &authtokenscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "auth-tokens read": func() (cli.Command, error) { return &authtokenscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "auth-tokens delete": func() (cli.Command, error) { return &authtokenscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "auth-tokens list": func() (cli.Command, error) { return &authtokenscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "config": func() (cli.Command, error) { return &config.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "config encrypt": func() (cli.Command, error) { return &config.EncryptDecryptCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "encrypt", }, nil }, "config decrypt": func() (cli.Command, error) { return &config.EncryptDecryptCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "decrypt", }, nil }, "config get-token": func() (cli.Command, error) { return &config.TokenCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "get-token", }, nil }, "config autocomplete": func() (cli.Command, error) { return &config.AutocompleteCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "base", }, nil }, "config autocomplete install": func() (cli.Command, error) { return &config.AutocompleteCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "install", }, nil }, "config autocomplete uninstall": func() (cli.Command, error) { return &config.AutocompleteCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "uninstall", }, nil }, "connect": func() (cli.Command, error) { return &connect.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "connect", }, nil }, "connect http": func() (cli.Command, error) { return &connect.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "http", }, nil }, "connect kube": func() (cli.Command, error) { return &connect.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "kube", }, nil }, "connect postgres": func() (cli.Command, error) { return &connect.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "postgres", }, nil }, "connect rdp": func() (cli.Command, error) { return &connect.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "rdp", }, nil }, "connect ssh": func() (cli.Command, error) { return &connect.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "ssh", }, nil }, "database": func() (cli.Command, error) { return &database.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "database init": func() (cli.Command, error) { return &database.InitCommand{ - Server: base.NewServer(base.NewCommand(ui)), + Server: base.NewServer(base.NewCommand(ui, opts...)), }, nil }, "database migrate": func() (cli.Command, error) { return &database.MigrateCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "credential-libraries": func() (cli.Command, error) { return &credentiallibrariescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "credential-libraries read": func() (cli.Command, error) { return &credentiallibrariescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "credential-libraries delete": func() (cli.Command, error) { return &credentiallibrariescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "credential-libraries list": func() (cli.Command, error) { return &credentiallibrariescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "credential-libraries create": func() (cli.Command, error) { return &credentiallibrariescmd.Command{ - Command: base.NewCommand(ui), - Func: "create", - }, nil - }, - "credential-libraries create vault": func() (cli.Command, error) { - return &credentiallibrariescmd.VaultCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "credential-libraries create vault-generic": func() (cli.Command, error) { return &credentiallibrariescmd.VaultGenericCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "credential-libraries create vault-ssh-certificate": func() (cli.Command, error) { return &credentiallibrariescmd.VaultSshCertificateCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "credential-libraries update": func() (cli.Command, error) { return &credentiallibrariescmd.Command{ - Command: base.NewCommand(ui), - Func: "update", - }, nil - }, - "credential-libraries update vault": func() (cli.Command, error) { - return &credentiallibrariescmd.VaultGenericCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "credential-libraries update vault-generic": func() (cli.Command, error) { return &credentiallibrariescmd.VaultGenericCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "credential-libraries update vault-ssh-certificate": func() (cli.Command, error) { return &credentiallibrariescmd.VaultSshCertificateCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "credential-stores": func() (cli.Command, error) { return &credentialstorescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "credential-stores read": func() (cli.Command, error) { return &credentialstorescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "credential-stores delete": func() (cli.Command, error) { return &credentialstorescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "credential-stores list": func() (cli.Command, error) { return &credentialstorescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "credential-stores create": func() (cli.Command, error) { return &credentialstorescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "credential-stores create vault": func() (cli.Command, error) { return &credentialstorescmd.VaultCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "credential-stores create static": func() (cli.Command, error) { return &credentialstorescmd.StaticCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "credential-stores update": func() (cli.Command, error) { return &credentialstorescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "credential-stores update vault": func() (cli.Command, error) { return &credentialstorescmd.VaultCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "credential-stores update static": func() (cli.Command, error) { return &credentialstorescmd.StaticCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "credentials": func() (cli.Command, error) { return &credentialscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "credentials read": func() (cli.Command, error) { return &credentialscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "credentials delete": func() (cli.Command, error) { return &credentialscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "credentials list": func() (cli.Command, error) { return &credentialscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "credentials create": func() (cli.Command, error) { return &credentialscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "credentials create username-password": func() (cli.Command, error) { return &credentialscmd.UsernamePasswordCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "credentials create ssh-private-key": func() (cli.Command, error) { return &credentialscmd.SshPrivateKeyCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "credentials create json": func() (cli.Command, error) { return &credentialscmd.JsonCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "credentials update": func() (cli.Command, error) { return &credentialscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "credentials update username-password": func() (cli.Command, error) { return &credentialscmd.UsernamePasswordCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "credentials update ssh-private-key": func() (cli.Command, error) { return &credentialscmd.SshPrivateKeyCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "credentials update json": func() (cli.Command, error) { return &credentialscmd.JsonCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, + "delete": func() (cli.Command, error) { + return &genericcmd.Command{ + Command: base.NewCommand(ui, opts...), + Func: "delete", + }, nil + }, + "groups": func() (cli.Command, error) { return &groupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "groups create": func() (cli.Command, error) { return &groupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "groups update": func() (cli.Command, error) { return &groupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "groups read": func() (cli.Command, error) { return &groupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "groups delete": func() (cli.Command, error) { return &groupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "groups list": func() (cli.Command, error) { return &groupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "groups add-members": func() (cli.Command, error) { return &groupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "add-members", }, nil }, "groups set-members": func() (cli.Command, error) { return &groupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "set-members", }, nil }, "groups remove-members": func() (cli.Command, error) { return &groupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "remove-members", }, nil }, "host-catalogs": func() (cli.Command, error) { return &hostcatalogscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "host-catalogs read": func() (cli.Command, error) { return &hostcatalogscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "host-catalogs delete": func() (cli.Command, error) { return &hostcatalogscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "host-catalogs list": func() (cli.Command, error) { return &hostcatalogscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "host-catalogs create": func() (cli.Command, error) { return &hostcatalogscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "host-catalogs create static": func() (cli.Command, error) { return &hostcatalogscmd.StaticCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "host-catalogs create plugin": func() (cli.Command, error) { return &hostcatalogscmd.PluginCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "host-catalogs update": func() (cli.Command, error) { return &hostcatalogscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "host-catalogs update static": func() (cli.Command, error) { return &hostcatalogscmd.StaticCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "host-catalogs update plugin": func() (cli.Command, error) { return &hostcatalogscmd.PluginCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "host-sets": func() (cli.Command, error) { return &hostsetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "host-sets read": func() (cli.Command, error) { return &hostsetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "host-sets delete": func() (cli.Command, error) { return &hostsetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "host-sets list": func() (cli.Command, error) { return &hostsetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "host-sets create": func() (cli.Command, error) { return &hostsetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "host-sets create static": func() (cli.Command, error) { return &hostsetscmd.StaticCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "host-sets create plugin": func() (cli.Command, error) { return &hostsetscmd.PluginCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "host-sets update": func() (cli.Command, error) { return &hostsetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "host-sets update static": func() (cli.Command, error) { return &hostsetscmd.StaticCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "host-sets update plugin": func() (cli.Command, error) { return &hostsetscmd.PluginCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "host-sets add-hosts": func() (cli.Command, error) { return &hostsetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "add-hosts", }, nil }, "host-sets remove-hosts": func() (cli.Command, error) { return &hostsetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "remove-hosts", }, nil }, "host-sets set-hosts": func() (cli.Command, error) { return &hostsetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "set-hosts", }, nil }, "hosts": func() (cli.Command, error) { return &hostscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "hosts read": func() (cli.Command, error) { return &hostscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "hosts delete": func() (cli.Command, error) { return &hostscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "hosts list": func() (cli.Command, error) { return &hostscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "hosts create": func() (cli.Command, error) { return &hostscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "hosts create static": func() (cli.Command, error) { return &hostscmd.StaticCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "hosts update": func() (cli.Command, error) { return &hostscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "hosts update static": func() (cli.Command, error) { return &hostscmd.StaticCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "logout": func() (cli.Command, error) { return &logout.LogoutCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "managed-groups": func() (cli.Command, error) { return &managedgroupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "managed-groups read": func() (cli.Command, error) { return &managedgroupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "managed-groups delete": func() (cli.Command, error) { return &managedgroupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "managed-groups list": func() (cli.Command, error) { return &managedgroupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "managed-groups create": func() (cli.Command, error) { return &managedgroupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "managed-groups create oidc": func() (cli.Command, error) { return &managedgroupscmd.OidcCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "managed-groups create ldap": func() (cli.Command, error) { return &managedgroupscmd.LdapCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "managed-groups update": func() (cli.Command, error) { return &managedgroupscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "managed-groups update oidc": func() (cli.Command, error) { return &managedgroupscmd.OidcCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "managed-groups update ldap": func() (cli.Command, error) { return &managedgroupscmd.LdapCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, + "read": func() (cli.Command, error) { + return &genericcmd.Command{ + Command: base.NewCommand(ui, opts...), + Func: "read", + }, nil + }, + "roles": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "roles create": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "roles update": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "roles read": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "roles delete": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "roles list": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "roles add-principals": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "add-principals", }, nil }, "roles set-principals": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "set-principals", }, nil }, "roles remove-principals": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "remove-principals", }, nil }, "roles add-grants": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "add-grants", }, nil }, "roles set-grants": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "set-grants", }, nil }, "roles remove-grants": func() (cli.Command, error) { return &rolescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "remove-grants", }, nil }, "scopes": func() (cli.Command, error) { return &scopescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "scopes create": func() (cli.Command, error) { return &scopescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "scopes read": func() (cli.Command, error) { return &scopescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "scopes update": func() (cli.Command, error) { return &scopescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "scopes delete": func() (cli.Command, error) { return &scopescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "scopes list": func() (cli.Command, error) { return &scopescmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "scopes list-keys": func() (cli.Command, error) { return &scopescmd.ListKeysCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "scopes rotate-keys": func() (cli.Command, error) { return &scopescmd.RotateKeysCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "scopes list-key-version-destruction-jobs": func() (cli.Command, error) { return &scopescmd.ListKeyVersionDestructionJobsCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "scopes destroy-key-version": func() (cli.Command, error) { return &scopescmd.DestroyKeyVersionCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "sessions": func() (cli.Command, error) { return &sessionscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "sessions read": func() (cli.Command, error) { return &sessionscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "sessions list": func() (cli.Command, error) { return &sessionscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "sessions cancel": func() (cli.Command, error) { return &sessionscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "cancel", }, nil }, "session-recordings": func() (cli.Command, error) { return &sessionrecordingscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "session-recordings read": func() (cli.Command, error) { return &sessionrecordingscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "session-recordings list": func() (cli.Command, error) { return &sessionrecordingscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "session-recordings download": func() (cli.Command, error) { return &sessionrecordingscmd.DownloadCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "storage-buckets": func() (cli.Command, error) { return &storagebucketscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "storage-buckets read": func() (cli.Command, error) { return &storagebucketscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "storage-buckets delete": func() (cli.Command, error) { return &storagebucketscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "storage-buckets list": func() (cli.Command, error) { return &storagebucketscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "storage-buckets create": func() (cli.Command, error) { return &storagebucketscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "storage-buckets update": func() (cli.Command, error) { return &storagebucketscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "targets": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "targets authorize-session": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "authorize-session", }, nil }, "targets read": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "targets delete": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "targets list": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "targets create": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "targets create tcp": func() (cli.Command, error) { return &targetscmd.TcpCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "targets create ssh": func() (cli.Command, error) { return &targetscmd.SshCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "targets update": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "targets update tcp": func() (cli.Command, error) { return &targetscmd.TcpCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "targets update ssh": func() (cli.Command, error) { return &targetscmd.SshCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "targets add-host-sources": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "add-host-sources", }, nil }, "targets remove-host-sources": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "remove-host-sources", }, nil }, "targets set-host-sources": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "set-host-sources", }, nil }, "targets add-credential-sources": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "add-credential-sources", }, nil }, "targets remove-credential-sources": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "remove-credential-sources", }, nil }, "targets set-credential-sources": func() (cli.Command, error) { return &targetscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "set-credential-sources", }, nil }, + "update": func() (cli.Command, error) { + return &genericcmd.Command{ + Command: base.NewCommand(ui, opts...), + Func: "update", + }, nil + }, + "users": func() (cli.Command, error) { return &userscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "users create": func() (cli.Command, error) { return &userscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "users read": func() (cli.Command, error) { return &userscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "users update": func() (cli.Command, error) { return &userscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "users delete": func() (cli.Command, error) { return &userscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "users list": func() (cli.Command, error) { return &userscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "users add-accounts": func() (cli.Command, error) { return &userscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "add-accounts", }, nil }, "users set-accounts": func() (cli.Command, error) { return &userscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "set-accounts", }, nil }, "users remove-accounts": func() (cli.Command, error) { return &userscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "remove-accounts", }, nil }, "workers": func() (cli.Command, error) { return &workerscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "workers create": func() (cli.Command, error) { return &workerscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "workers create worker-led": func() (cli.Command, error) { return &workerscmd.WorkerLedCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "workers create controller-led": func() (cli.Command, error) { return &workerscmd.ControllerLedCommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "create", }, nil }, "workers read": func() (cli.Command, error) { return &workerscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "workers update": func() (cli.Command, error) { return &workerscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "update", }, nil }, "workers delete": func() (cli.Command, error) { return &workerscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "delete", }, nil }, "workers list": func() (cli.Command, error) { return &workerscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "list", }, nil }, "workers add-worker-tags": func() (cli.Command, error) { return &workerscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "add-worker-tags", }, nil }, "workers set-worker-tags": func() (cli.Command, error) { return &workerscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "set-worker-tags", }, nil }, "workers remove-worker-tags": func() (cli.Command, error) { return &workerscmd.Command{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "remove-worker-tags", }, nil }, "workers certificate-authority": func() (cli.Command, error) { return &workerscmd.WorkerCACommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), }, nil }, "workers certificate-authority read": func() (cli.Command, error) { return &workerscmd.WorkerCACommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "read", }, nil }, "workers certificate-authority reinitialize": func() (cli.Command, error) { return &workerscmd.WorkerCACommand{ - Command: base.NewCommand(ui), + Command: base.NewCommand(ui, opts...), Func: "reinitialize", }, nil }, diff --git a/internal/cmd/commands/authenticate/authenticate.go b/internal/cmd/commands/authenticate/authenticate.go index affb0f4fe..9ca5f7c0b 100644 --- a/internal/cmd/commands/authenticate/authenticate.go +++ b/internal/cmd/commands/authenticate/authenticate.go @@ -24,7 +24,7 @@ type Command struct { } func (c *Command) Synopsis() string { - return wordwrap.WrapString("Authenticate the Boundary command-line client", base.TermWidth) + return wordwrap.WrapString("Authenticate the local client", base.TermWidth) } func (c *Command) Help() string { diff --git a/internal/cmd/commands/config/config.go b/internal/cmd/commands/config/config.go index 2435295b2..fc2e6d8da 100644 --- a/internal/cmd/commands/config/config.go +++ b/internal/cmd/commands/config/config.go @@ -15,7 +15,7 @@ type Command struct { } func (c *Command) Synopsis() string { - return "Manage resources related to Boundary's local configuration" + return "Manage the local client's configuration" } func (c *Command) Help() string { diff --git a/internal/cmd/commands/genericcmd/generic.go b/internal/cmd/commands/genericcmd/generic.go new file mode 100644 index 000000000..625eb22de --- /dev/null +++ b/internal/cmd/commands/genericcmd/generic.go @@ -0,0 +1,44 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package genericcmd + +import ( + "fmt" + + "github.com/hashicorp/boundary/internal/cmd/base" + "github.com/mitchellh/cli" +) + +var _ cli.Command = (*Command)(nil) + +type Command struct { + *base.Command + + Func string +} + +func (c *Command) Synopsis() string { + return fmt.Sprintf("Run a generic %s command against a resource", c.Func) +} + +func (c *Command) Help() string { + aAn := "a" + if c.Func == "update" { + aAn = "an" + } + return base.WrapForHelpText([]string{ + fmt.Sprintf("Usage: boundary %s [resource ID] [args]", c.Func), + "", + fmt.Sprintf(" This command runs %s %s command against the given resource ID. Arguments are the same as the type-specific command.", aAn, c.Func), + "", + fmt.Sprintf(" Note: this command forwards to a type-specific command; help/error/cURL output from that command may show the full command syntax."), + }) +} + +func (c *Command) Run(args []string) int { + if len(args) > 0 { + return cli.RunResultHelp + } + return base.CommandSuccess +} diff --git a/internal/cmd/common/flags.go b/internal/cmd/common/flags.go index 97e6177d8..387cb595c 100644 --- a/internal/cmd/common/flags.go +++ b/internal/cmd/common/flags.go @@ -54,9 +54,10 @@ func PopulateCommonFlags(c *base.Command, f *base.FlagSet, resourceType string, }) case "id": f.StringVar(&base.StringVar{ - Name: "id", - Target: &c.FlagId, - Usage: fmt.Sprintf("ID of the %s on which to operate.", resourceType), + Name: "id", + Target: &c.FlagId, + Default: c.FlagId, + Usage: fmt.Sprintf("ID of the %s on which to operate.", resourceType), }) case "name": f.StringVar(&base.StringVar{ diff --git a/internal/cmd/main.go b/internal/cmd/main.go index 474d30799..6d0114281 100644 --- a/internal/cmd/main.go +++ b/internal/cmd/main.go @@ -8,15 +8,17 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "os" "sort" + "strconv" "strings" "text/tabwriter" "github.com/fatih/color" "github.com/hashicorp/boundary/api" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/cmd/base" + "github.com/hashicorp/boundary/internal/types/resource" colorable "github.com/mattn/go-colorable" "github.com/mitchellh/cli" ) @@ -85,10 +87,55 @@ func setupEnv(args []string) (retArgs []string, format string, outputCurlString return args, format, outputCurlString } +func handleHighLevelShortcuts(args []string, runOpts *RunOptions) []string { + switch len(args) { + case 0, 1: + return args + } + + switch strings.ToLower(args[0]) { + case "read", "update", "delete": + default: + return args + } + + // At this point we know it's something we want to handle in this function + info := globals.ResourceInfoFromPrefix(args[1]) + if info.Type == resource.Unknown { + return args + } + + newArgs := make([]string, 0, len(args)+5) + newArgs = append(newArgs, + // Start with the plural of the resource type ("credential-libraries") + info.Type.PluralString(), + // Add the action to take ("update") + args[0], + ) + // If it's update, add the subtype + if info.Subtype != globals.UnknownSubtype && + strings.ToLower(args[0]) == "update" { + newArgs = append(newArgs, + strings.ReplaceAll(info.Subtype.String(), "_", "-"), + ) + } + + // Make sure we override the ID in commands + runOpts.ImplicitId = args[1] + + // Now add the rest of the args + newArgs = append(newArgs, + args[2:]..., + ) + + return newArgs +} + type RunOptions struct { - Stdout io.Writer - Stderr io.Writer - Address string + Stdout io.Writer + Stderr io.Writer + Address string + ImplicitId string } func Run(args []string) int { @@ -134,7 +181,7 @@ func RunCustom(args []string, runOpts *RunOptions) int { uiErrWriter := runOpts.Stderr if outputCurlString { - uiErrWriter = ioutil.Discard + uiErrWriter = io.Discard } ui := &base.BoundaryUI{ @@ -169,6 +216,29 @@ func RunCustom(args []string, runOpts *RunOptions) int { return 1 } + // For autocompletion we need to manage the COMP_LINE var. That means + // reading args out of it now and then setting updated args back. + compLine := os.Getenv("COMP_LINE") + if compLine != "" { + point, err := strconv.Atoi(os.Getenv("COMP_POINT")) + if err != nil { + point = len(compLine) + } + if point != 0 && point < len(compLine) { + compLine = compLine[:point] + } + args = strings.Split(compLine, " ") + args = args[1:] // elide "boundary" since the function below expects it to not be there + } + + args = handleHighLevelShortcuts(args, runOpts) + + // Set args back + if compLine != "" { + // We need to add back "boundary" as well + os.Setenv("COMP_LINE", strings.Join(append([]string{"boundary"}, args...), " ")) + } + initCommands(ui, serverCmdUi, runOpts) hiddenCommands := []string{"version"} @@ -222,15 +292,38 @@ func groupedHelpFunc(f cli.HelpFunc) cli.HelpFunc { fmt.Fprintf(tw, "Usage: boundary [args]\n") - otherCommands := make([]string, 0, len(commands)) + genericCommands := make([]string, 0, 3) + clientCommands := make([]string, 0, 6) + typeSpecificCommands := make([]string, 0, len(commands)-cap(genericCommands)-cap(clientCommands)) for k := range commands { - otherCommands = append(otherCommands, k) + switch k { + case "authenticate", "config", "connect", "dev", "logout", "server": + clientCommands = append(clientCommands, k) + case "read", "update", "delete": + genericCommands = append(genericCommands, k) + default: + typeSpecificCommands = append(typeSpecificCommands, k) + } } - sort.Strings(otherCommands) + sort.Strings(clientCommands) fmt.Fprintf(tw, "\n") - fmt.Fprintf(tw, "Commands:\n") - for _, v := range otherCommands { + fmt.Fprintf(tw, "Local/Client Commands:\n") + for _, v := range clientCommands { + printCommand(tw, v, commands[v]) + } + + sort.Strings(genericCommands) + fmt.Fprintf(tw, "\n") + fmt.Fprintf(tw, "Generic Commands:\n") + for _, v := range genericCommands { + printCommand(tw, v, commands[v]) + } + + sort.Strings(typeSpecificCommands) + fmt.Fprintf(tw, "\n") + fmt.Fprintf(tw, "Type-Specific Commands:\n") + for _, v := range typeSpecificCommands { printCommand(tw, v, commands[v]) } diff --git a/internal/cmd/main_test.go b/internal/cmd/main_test.go new file mode 100644 index 000000000..bc6251804 --- /dev/null +++ b/internal/cmd/main_test.go @@ -0,0 +1,73 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestHandleHighLevelShortcuts(t *testing.T) { + t.Parallel() + tests := []struct { + name string + in []string + out []string + expRunOpts bool + }{ + { + name: "zero length", + }, + { + name: "one length", + in: []string{"foo"}, + out: []string{"foo"}, + }, + { + name: "not a match", + in: []string{"foo", "bar"}, + out: []string{"foo", "bar"}, + }, + { + name: "unhandled prefix", + in: []string{"read", "bar"}, + out: []string{"read", "bar"}, + }, + { + name: "handled read", + in: []string{"read", "hst_1234567890"}, + out: []string{"hosts", "read"}, + expRunOpts: true, + }, + { + name: "handled delete", + in: []string{"delete", "clvlt_1234567890"}, + out: []string{"credential-libraries", "delete"}, + expRunOpts: true, + }, + { + name: "handled update", + in: []string{"update", "g_1234567890"}, + out: []string{"groups", "update"}, + expRunOpts: true, + }, + { + name: "handled subtype update", + in: []string{"update", "credspk_1234567890"}, + out: []string{"credentials", "update", "ssh-private-key"}, + expRunOpts: true, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + var runOpts RunOptions + out := handleHighLevelShortcuts(tc.in, &runOpts) + assert.EqualValues(t, tc.out, out) + if tc.expRunOpts { + assert.Equal(t, tc.in[1], runOpts.ImplicitId) + } + }) + } +} diff --git a/internal/credential/public_ids.go b/internal/credential/public_ids.go index 44865930b..291e34d0d 100644 --- a/internal/credential/public_ids.go +++ b/internal/credential/public_ids.go @@ -9,27 +9,22 @@ import ( "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/hashicorp/boundary/internal/types/resource" ) func init() { - if err := subtypes.Register(Domain, UsernamePasswordSubtype, globals.UsernamePasswordCredentialPrefix, globals.UsernamePasswordCredentialPreviousPrefix); err != nil { - panic(err) - } - if err := subtypes.Register(Domain, SshPrivateKeySubtype, globals.SshPrivateKeyCredentialPrefix); err != nil { - panic(err) - } - if err := subtypes.Register(Domain, JsonSubtype, globals.JsonCredentialPrefix); err != nil { - panic(err) - } + globals.RegisterPrefixToResourceInfo(globals.UsernamePasswordCredentialPrefix, resource.Credential, Domain, UsernamePasswordSubtype) + globals.RegisterPrefixToResourceInfo(globals.UsernamePasswordCredentialPreviousPrefix, resource.Credential, Domain, UsernamePasswordSubtype) + globals.RegisterPrefixToResourceInfo(globals.SshPrivateKeyCredentialPrefix, resource.Credential, Domain, SshPrivateKeySubtype) + globals.RegisterPrefixToResourceInfo(globals.JsonCredentialPrefix, resource.Credential, Domain, JsonSubtype) } const ( - UsernamePasswordSubtype = subtypes.Subtype("username_password") + UsernamePasswordSubtype = globals.Subtype("username_password") - SshPrivateKeySubtype = subtypes.Subtype("ssh_private_key") + SshPrivateKeySubtype = globals.Subtype("ssh_private_key") - JsonSubtype = subtypes.Subtype("json") + JsonSubtype = globals.Subtype("json") ) func NewUsernamePasswordCredentialId(ctx context.Context) (string, error) { diff --git a/internal/credential/static/public_ids.go b/internal/credential/static/public_ids.go index 2aa535a77..de5af1878 100644 --- a/internal/credential/static/public_ids.go +++ b/internal/credential/static/public_ids.go @@ -10,18 +10,17 @@ import ( "github.com/hashicorp/boundary/internal/credential" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/hashicorp/boundary/internal/types/resource" ) func init() { - if err := subtypes.Register(credential.Domain, Subtype, globals.StaticCredentialStorePrefix, globals.StaticCredentialStorePreviousPrefix); err != nil { - panic(err) - } + globals.RegisterPrefixToResourceInfo(globals.StaticCredentialStorePrefix, resource.CredentialStore, credential.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.StaticCredentialStorePreviousPrefix, resource.CredentialStore, credential.Domain, Subtype) } // PublicId prefixes for the resources in the static package. const ( - Subtype = subtypes.Subtype("static") + Subtype = globals.Subtype("static") ) func newCredentialStoreId(ctx context.Context) (string, error) { diff --git a/internal/credential/static/repository_credential.go b/internal/credential/static/repository_credential.go index b9e7eeaeb..82c3c951d 100644 --- a/internal/credential/static/repository_credential.go +++ b/internal/credential/static/repository_credential.go @@ -8,12 +8,12 @@ import ( "fmt" "strings" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/credential" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/oplog" - "github.com/hashicorp/boundary/internal/types/subtypes" "github.com/hashicorp/go-dbw" ) @@ -289,7 +289,7 @@ func (r *Repository) LookupCredential(ctx context.Context, publicId string, _ .. var cred credential.Static - switch subtypes.SubtypeFromId(credential.Domain, publicId) { + switch globals.ResourceInfoFromPrefix(publicId).Subtype { case credential.UsernamePasswordSubtype: upCred := allocUsernamePasswordCredential() upCred.PublicId = publicId @@ -792,7 +792,7 @@ func (r *Repository) DeleteCredential(ctx context.Context, projectId, id string, var input any var md oplog.Metadata - switch subtypes.SubtypeFromId(credential.Domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case credential.UsernamePasswordSubtype: c := allocUsernamePasswordCredential() c.PublicId = id diff --git a/internal/credential/vault/public_ids.go b/internal/credential/vault/public_ids.go index b54e11fe2..cdea3f7ae 100644 --- a/internal/credential/vault/public_ids.go +++ b/internal/credential/vault/public_ids.go @@ -10,26 +10,21 @@ import ( "github.com/hashicorp/boundary/internal/credential" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/hashicorp/boundary/internal/types/resource" ) func init() { - if err := subtypes.Register(credential.Domain, Subtype, globals.VaultCredentialStorePrefix, globals.VaultDynamicCredentialPrefix); err != nil { - panic(err) - } - if err := subtypes.Register(credential.Domain, GenericLibrarySubtype, globals.VaultCredentialLibraryPrefix); err != nil { - panic(err) - } - if err := subtypes.Register(credential.Domain, SSHCertificateLibrarySubtype, globals.VaultSshCertificateCredentialLibraryPrefix); err != nil { - panic(err) - } + globals.RegisterPrefixToResourceInfo(globals.VaultCredentialStorePrefix, resource.CredentialStore, credential.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.VaultDynamicCredentialPrefix, resource.Credential, credential.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.VaultCredentialLibraryPrefix, resource.CredentialLibrary, credential.Domain, GenericLibrarySubtype) + globals.RegisterPrefixToResourceInfo(globals.VaultSshCertificateCredentialLibraryPrefix, resource.CredentialLibrary, credential.Domain, SSHCertificateLibrarySubtype) } // PublicId prefixes for the resources in the vault package. const ( - Subtype = subtypes.Subtype("vault") - GenericLibrarySubtype = subtypes.Subtype("vault-generic") - SSHCertificateLibrarySubtype = subtypes.Subtype("vault-ssh-certificate") + Subtype = globals.Subtype("vault") + GenericLibrarySubtype = globals.Subtype("vault-generic") + SSHCertificateLibrarySubtype = globals.Subtype("vault-ssh-certificate") ) func newCredentialStoreId(ctx context.Context) (string, error) { diff --git a/internal/daemon/controller/auth/auth.go b/internal/daemon/controller/auth/auth.go index 21823f69f..0fc8b5920 100644 --- a/internal/daemon/controller/auth/auth.go +++ b/internal/daemon/controller/auth/auth.go @@ -31,7 +31,6 @@ import ( "github.com/hashicorp/boundary/internal/types/action" "github.com/hashicorp/boundary/internal/types/resource" "github.com/hashicorp/boundary/internal/types/scope" - "github.com/hashicorp/boundary/internal/types/subtypes" "github.com/hashicorp/boundary/internal/util" "github.com/hashicorp/boundary/internal/util/template" "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" @@ -555,7 +554,7 @@ func (v verifier) performAuthCheck(ctx context.Context) ( const domain = "auth" var acct auth.Account var err error - switch subtypes.SubtypeFromId(domain, *userData.Account.Id) { + switch globals.ResourceInfoFromPrefix(*userData.Account.Id).Subtype { case password.Subtype: repo, repoErr := v.passwordAuthRepoFn() if repoErr != nil { diff --git a/internal/daemon/controller/handlers/accounts/account_service.go b/internal/daemon/controller/handlers/accounts/account_service.go index 62c263249..c6c0baada 100644 --- a/internal/daemon/controller/handlers/accounts/account_service.go +++ b/internal/daemon/controller/handlers/accounts/account_service.go @@ -69,7 +69,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources - IdActions = map[subtypes.Subtype]action.ActionSet{ + IdActions = map[globals.Subtype]action.ActionSet{ password.Subtype: { action.NoOp, action.Read, @@ -165,7 +165,7 @@ func (s Service) ListAccounts(ctx context.Context, req *pbs.ListAccountsRequest) } for _, acct := range ul { res.Id = acct.GetPublicId() - authorizedActions := authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, acct.GetPublicId())], requestauth.WithResource(&res)).Strings() + authorizedActions := authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(acct.GetPublicId()).Subtype], requestauth.WithResource(&res)).Strings() if len(authorizedActions) == 0 { continue } @@ -226,7 +226,7 @@ func (s Service) GetAccount(ctx context.Context, req *pbs.GetAccountRequest) (*p outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, acct.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(acct.GetPublicId()).Subtype]).Strings())) } if outputFields.Has(globals.ManagedGroupIdsField) { outputOpts = append(outputOpts, handlers.WithManagedGroupIds(mgIds)) @@ -268,7 +268,7 @@ func (s Service) CreateAccount(ctx context.Context, req *pbs.CreateAccountReques outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, acct.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(acct.GetPublicId()).Subtype]).Strings())) } item, err := toProto(ctx, acct, outputOpts...) @@ -307,7 +307,7 @@ func (s Service) UpdateAccount(ctx context.Context, req *pbs.UpdateAccountReques outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, acct.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(acct.GetPublicId()).Subtype]).Strings())) } item, err := toProto(ctx, acct, outputOpts...) @@ -362,7 +362,7 @@ func (s Service) ChangePassword(ctx context.Context, req *pbs.ChangePasswordRequ outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, acct.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(acct.GetPublicId()).Subtype]).Strings())) } item, err := toProto(ctx, acct, outputOpts...) @@ -401,7 +401,7 @@ func (s Service) SetPassword(ctx context.Context, req *pbs.SetPasswordRequest) ( outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, acct.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, acct.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(acct.GetPublicId()).Subtype]).Strings())) } item, err := toProto(ctx, acct, outputOpts...) @@ -417,7 +417,7 @@ func (s Service) SetPassword(ctx context.Context, req *pbs.SetPasswordRequest) ( func (s Service) getFromRepo(ctx context.Context, id string) (auth.Account, []string, error) { var acct auth.Account var mgIds []string - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case password.Subtype: repo, err := s.pwRepoFn() if err != nil { @@ -592,7 +592,7 @@ func (s Service) createInRepo(ctx context.Context, am auth.AuthMethod, item *pb. return nil, errors.New(ctx, errors.InvalidParameter, op, "missing item") } var out auth.Account - switch subtypes.SubtypeFromId(domain, am.GetPublicId()) { + switch globals.ResourceInfoFromPrefix(am.GetPublicId()).Subtype { case password.Subtype: am, err := s.createPwInRepo(ctx, am, item) if err != nil { @@ -752,7 +752,7 @@ func (s Service) updateLdapInRepo(ctx context.Context, scopeId, amId, id string, func (s Service) updateInRepo(ctx context.Context, scopeId, authMethodId string, req *pbs.UpdateAccountRequest) (auth.Account, error) { const op = "accounts.(Service).updateInRepo" var out auth.Account - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case password.Subtype: a, err := s.updatePwInRepo(ctx, scopeId, authMethodId, req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem()) if err != nil { @@ -788,7 +788,7 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, const op = "accounts.(Service).deleteFromRepo" var rows int var err error - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case password.Subtype: repo, iErr := s.pwRepoFn() if iErr != nil { @@ -821,7 +821,7 @@ func (s Service) listFromRepo(ctx context.Context, authMethodId string) ([]auth. const op = "accounts.(Service).listFromRepo" var outUl []auth.Account - switch subtypes.SubtypeFromId(domain, authMethodId) { + switch globals.ResourceInfoFromPrefix(authMethodId).Subtype { case password.Subtype: pwRepo, err := s.pwRepoFn() if err != nil { @@ -933,7 +933,7 @@ func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Ty case action.List, action.Create: parentId = id default: - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case password.Subtype: acct, err := pwRepo.LookupAccount(ctx, id) if err != nil { @@ -972,7 +972,7 @@ func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Ty } var authMeth auth.AuthMethod - switch subtypes.SubtypeFromId(domain, parentId) { + switch globals.ResourceInfoFromPrefix(parentId).Subtype { case password.Subtype: am, err := pwRepo.LookupAuthMethod(ctx, parentId) if err != nil { @@ -1174,7 +1174,7 @@ func validateCreateRequest(ctx context.Context, req *pbs.CreateAccountRequest) e if req.GetItem().GetAuthMethodId() == "" { badFields[authMethodIdField] = "This field is required." } - switch subtypes.SubtypeFromId(domain, req.GetItem().GetAuthMethodId()) { + switch globals.ResourceInfoFromPrefix(req.GetItem().GetAuthMethodId()).Subtype { case password.Subtype: if req.GetItem().GetType() != "" && req.GetItem().GetType() != password.Subtype.String() { badFields[typeField] = "Doesn't match the parent resource's type." @@ -1255,7 +1255,7 @@ func validateUpdateRequest(ctx context.Context, req *pbs.UpdateAccountRequest) e } return handlers.ValidateUpdateRequest(req, req.GetItem(), func() map[string]string { badFields := map[string]string{} - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case password.Subtype: if req.GetItem().GetType() != "" && req.GetItem().GetType() != password.Subtype.String() { badFields[typeField] = "Cannot modify the resource type." diff --git a/internal/daemon/controller/handlers/accounts/account_service_test.go b/internal/daemon/controller/handlers/accounts/account_service_test.go index 990c83e73..cafc57c1e 100644 --- a/internal/daemon/controller/handlers/accounts/account_service_test.go +++ b/internal/daemon/controller/handlers/accounts/account_service_test.go @@ -26,7 +26,6 @@ import ( "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/types/action" "github.com/hashicorp/boundary/internal/types/scope" - "github.com/hashicorp/boundary/internal/types/subtypes" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/accounts" scopepb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" "github.com/stretchr/testify/assert" @@ -280,7 +279,7 @@ func TestGet(t *testing.T) { t.Run(tc.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - if subtypes.SubtypeFromId(domain, tc.req.Id) == oidc.Subtype { + if globals.ResourceInfoFromPrefix(tc.req.Id).Subtype == oidc.Subtype { // Set up managed groups before getting. First get the current // managed group to make sure we have the right version. oidcRepo, err := oidcRepoFn() diff --git a/internal/daemon/controller/handlers/authmethods/authmethod_service.go b/internal/daemon/controller/handlers/authmethods/authmethod_service.go index 29f2f9ecd..834ca8769 100644 --- a/internal/daemon/controller/handlers/authmethods/authmethod_service.go +++ b/internal/daemon/controller/handlers/authmethods/authmethod_service.go @@ -64,7 +64,7 @@ const ( var ( // IdActions contains the set of actions that can be performed on // individual resources - IdActions = make(map[subtypes.Subtype]action.ActionSet) + IdActions = make(map[globals.Subtype]action.ActionSet) // CollectionActions contains the set of actions that can be performed on // this collection @@ -167,7 +167,7 @@ func (s Service) ListAuthMethods(ctx context.Context, req *pbs.ListAuthMethodsRe for _, am := range ul { res.Id = am.GetPublicId() res.ScopeId = am.GetScopeId() - authorizedActions := authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, am.GetPublicId())], requestauth.WithResource(&res)).Strings() + authorizedActions := authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(am.GetPublicId()).Subtype], requestauth.WithResource(&res)).Strings() if len(authorizedActions) == 0 { continue } @@ -234,7 +234,7 @@ func (s Service) GetAuthMethod(ctx context.Context, req *pbs.GetAuthMethodReques outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, am.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(am.GetPublicId()).Subtype]).Strings())) } if outputFields.Has(globals.AuthorizedCollectionActionsField) { collectionActions, err := requestauth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, am.GetPublicId()) @@ -279,7 +279,7 @@ func (s Service) CreateAuthMethod(ctx context.Context, req *pbs.CreateAuthMethod outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, am.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(am.GetPublicId()).Subtype]).Strings())) } if outputFields.Has(globals.AuthorizedCollectionActionsField) { collectionActions, err := requestauth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, am.GetPublicId()) @@ -329,7 +329,7 @@ func (s Service) UpdateAuthMethod(ctx context.Context, req *pbs.UpdateAuthMethod outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, am.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(am.GetPublicId()).Subtype]).Strings())) } if outputFields.Has(globals.AuthorizedCollectionActionsField) { collectionActions, err := requestauth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, am.GetPublicId()) @@ -383,7 +383,7 @@ func (s Service) ChangeState(ctx context.Context, req *pbs.ChangeStateRequest) ( outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, am.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(am.GetPublicId()).Subtype]).Strings())) } if outputFields.Has(globals.AuthorizedCollectionActionsField) { collectionActions, err := requestauth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, am.GetPublicId()) @@ -424,7 +424,7 @@ func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest) return nil, err } - switch subtypes.SubtypeFromId(domain, req.GetAuthMethodId()) { + switch globals.ResourceInfoFromPrefix(req.GetAuthMethodId()).Subtype { case password.Subtype: if err := validateAuthenticatePasswordRequest(req); err != nil { return nil, err @@ -444,7 +444,7 @@ func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest) return nil, authResults.Error } - switch subtypes.SubtypeFromId(domain, req.GetAuthMethodId()) { + switch globals.ResourceInfoFromPrefix(req.GetAuthMethodId()).Subtype { case password.Subtype: return s.authenticatePassword(ctx, req, &authResults) @@ -459,7 +459,7 @@ func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest) func (s Service) getFromRepo(ctx context.Context, id string) (auth.AuthMethod, error) { var lookupErr error var am auth.AuthMethod - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case password.Subtype: repo, err := s.pwRepoFn() if err != nil { @@ -549,8 +549,8 @@ func (s Service) listFromRepo(ctx context.Context, scopeIds []string, authResult func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.AuthMethod) (auth.AuthMethod, error) { const op = "authmethods.(Service).createInRepo" var out auth.AuthMethod - switch subtypes.SubtypeFromType(domain, item.GetType()) { - case password.Subtype: + switch item.GetType() { + case password.Subtype.String(): am, err := s.createPwInRepo(ctx, scopeId, item) if err != nil { return nil, errors.Wrap(ctx, err, op) @@ -559,7 +559,7 @@ func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Auth return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create auth method but no error returned from repository.") } out = am - case oidc.Subtype: + case oidc.Subtype.String(): am, err := s.createOidcInRepo(ctx, scopeId, item) if err != nil { return nil, errors.Wrap(ctx, err, op) @@ -568,7 +568,7 @@ func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.Auth return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to create auth method but no error returned from repository.") } out = am - case ldap.Subtype: + case ldap.Subtype.String(): am, err := s.createLdapInRepo(ctx, scopeId, item) if err != nil { return nil, errors.Wrap(ctx, err, op) @@ -587,7 +587,7 @@ func (s Service) updateInRepo(ctx context.Context, scopeId string, req *pbs.Upda var am auth.AuthMethod var dryRun bool - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case password.Subtype: pam, err := s.updatePwInRepo(ctx, scopeId, req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem()) if err != nil { @@ -635,7 +635,7 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, const op = "authmethods.(Service).deleteFromRepo" var rows int var dErr error - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case password.Subtype: repo, err := s.pwRepoFn() if err != nil { @@ -656,7 +656,7 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, } rows, dErr = repo.DeleteAuthMethod(ctx, id) default: - return false, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("invalid auth method subtype: %q", subtypes.SubtypeFromId(domain, id))) + return false, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("invalid auth method subtype: %q", globals.ResourceInfoFromPrefix(id).Subtype.String())) } if dErr != nil { @@ -672,7 +672,7 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, func (s Service) changeStateInRepo(ctx context.Context, req *pbs.ChangeStateRequest) (auth.AuthMethod, error) { const op = "authmethod_service.(Service).changeStateInRepo" - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case oidc.Subtype: repo, err := s.oidcRepoFn() if err != nil { @@ -731,7 +731,7 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) reque } default: var authMeth auth.AuthMethod - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case password.Subtype: repo, err := s.pwRepoFn() if err != nil { @@ -987,10 +987,10 @@ func validateCreateRequest(ctx context.Context, req *pbs.CreateAuthMethodRequest if req.GetItem().GetIsPrimary() { badFields[isPrimaryField] = "This field is read only." } - switch subtypes.SubtypeFromType(domain, req.GetItem().GetType()) { - case password.Subtype: + switch req.GetItem().GetType() { + case password.Subtype.String(): // Password attributes are not required when creating a password auth method. - case oidc.Subtype: + case oidc.Subtype.String(): attrs := req.GetItem().GetOidcAuthMethodsAttributes() if attrs == nil { // OIDC attributes are required when creating an OIDC auth method. @@ -1066,7 +1066,7 @@ func validateCreateRequest(ctx context.Context, req *pbs.CreateAuthMethodRequest } } } - case ldap.Subtype: + case ldap.Subtype.String(): if len(req.GetItem().GetLdapAuthMethodsAttributes().GetUrls()) == 0 { badFields[urlsField] = "At least one URL is required" } @@ -1088,13 +1088,13 @@ func validateUpdateRequest(ctx context.Context, req *pbs.UpdateAuthMethodRequest if handlers.MaskContains(req.GetUpdateMask().GetPaths(), isPrimaryField) { badFields[isPrimaryField] = "This field is read only." } - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case password.Subtype: - if req.GetItem().GetType() != "" && subtypes.SubtypeFromType(domain, req.GetItem().GetType()) != password.Subtype { + if req.GetItem().GetType() != "" && req.GetItem().GetType() != password.Subtype.String() { badFields[typeField] = "Cannot modify the resource type." } case oidc.Subtype: - if req.GetItem().GetType() != "" && subtypes.SubtypeFromType(domain, req.GetItem().GetType()) != oidc.Subtype { + if req.GetItem().GetType() != "" && req.GetItem().GetType() != oidc.Subtype.String() { badFields[typeField] = "Cannot modify the resource type." } attrs := req.GetItem().GetOidcAuthMethodsAttributes() @@ -1198,7 +1198,7 @@ func validateUpdateRequest(ctx context.Context, req *pbs.UpdateAuthMethodRequest } } case ldap.Subtype: - if req.GetItem().GetType() != "" && subtypes.SubtypeFromType(domain, req.GetItem().GetType()) != ldap.Subtype { + if req.GetItem().GetType() != "" && req.GetItem().GetType() != ldap.Subtype.String() { badFields[typeField] = "Cannot modify the resource type." } validateLdapAttributes(ctx, req.GetItem().GetLdapAuthMethodsAttributes(), badFields) @@ -1241,7 +1241,7 @@ func validateChangeStateRequest(ctx context.Context, req *pbs.ChangeStateRequest if req == nil { return errors.New(ctx, errors.InvalidParameter, op, "Missing request") } - if st := subtypes.SubtypeFromId(domain, req.GetId()); st != oidc.Subtype { + if st := globals.ResourceInfoFromPrefix(req.GetId()).Subtype; st != oidc.Subtype { return handlers.NotFoundErrorf("This endpoint is only available for the %q Auth Method type.", oidc.Subtype.String()) } badFields := make(map[string]string) @@ -1276,7 +1276,7 @@ func validateAuthenticateRequest(ctx context.Context, req *pbs.AuthenticateReque if strings.TrimSpace(req.GetAuthMethodId()) == "" { badFields[authMethodIdField] = "This is a required field." } else { - st := subtypes.SubtypeFromId(domain, req.GetAuthMethodId()) + st := globals.ResourceInfoFromPrefix(req.GetAuthMethodId()).Subtype switch st { case password.Subtype, oidc.Subtype, ldap.Subtype: default: @@ -1380,7 +1380,7 @@ func transformAuthenticateRequestAttributes(msg proto.Message) error { if attrs == nil { return nil } - switch subtypes.SubtypeFromId(domain, authRequest.GetAuthMethodId()) { + switch globals.ResourceInfoFromPrefix(authRequest.GetAuthMethodId()).Subtype { case password.Subtype: newAttrs := &pbs.PasswordLoginAttributes{} if err := handlers.StructToProto(attrs, newAttrs); err != nil { diff --git a/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go b/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go index e12447baa..dbbe0e26b 100644 --- a/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go +++ b/internal/daemon/controller/handlers/credentiallibraries/credentiallibrary_service.go @@ -277,7 +277,7 @@ func (s Service) UpdateCredentialLibrary(ctx context.Context, req *pbs.UpdateCre } var currentCredentialType globals.CredentialType var mo vault.MappingOverride - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case vault.SSHCertificateLibrarySubtype: cur, err := repo.LookupSSHCertificateCredentialLibrary(ctx, req.Id) if err != nil { @@ -374,7 +374,7 @@ func (s Service) getFromRepo(ctx context.Context, id string) (credential.Library if err != nil { return nil, errors.Wrap(ctx, err, op) } - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case vault.GenericLibrarySubtype: cs, err := repo.LookupCredentialLibrary(ctx, id) if err != nil && !errors.IsNotFoundError(err) { @@ -400,8 +400,8 @@ func (s Service) getFromRepo(ctx context.Context, id string) (credential.Library func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.CredentialLibrary) (credential.Library, error) { const op = "credentiallibraries.(Service).createInRepo" var out credential.Library - switch subtypes.SubtypeFromType(domain, item.GetType()) { - case vault.SSHCertificateLibrarySubtype: + switch item.GetType() { + case vault.SSHCertificateLibrarySubtype.String(): cl, err := toStorageVaultSSHCertificateLibrary(ctx, item.GetCredentialStoreId(), item) if err != nil { return nil, errors.Wrap(ctx, err, op) @@ -470,7 +470,7 @@ func (s Service) updateInRepo( if err != nil { return nil, errors.Wrap(ctx, err, op) } - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case vault.SSHCertificateLibrarySubtype: dbMasks = append(dbMasks, sshCertMaskManager.Translate(masks)...) if getMapUpdate(criticalOptionsField, masks) { @@ -522,7 +522,7 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, return false, err } rows := 0 - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case vault.SSHCertificateLibrarySubtype: rows, err = repo.DeleteSSHCertificateCredentialLibrary(ctx, scopeId, id) default: @@ -554,7 +554,7 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth. default: opts = append(opts, auth.WithId(id)) parentId = id - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case vault.GenericLibrarySubtype: cl, err := repo.LookupCredentialLibrary(ctx, id) if err != nil { @@ -590,7 +590,7 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth. opts = append(opts, auth.WithPin(parentId)) - switch subtypes.SubtypeFromId(domain, parentId) { + switch globals.ResourceInfoFromPrefix(parentId).Subtype { case vault.Subtype: cs, err := repo.LookupCredentialStore(ctx, parentId) if err != nil { @@ -627,7 +627,7 @@ func toProto(ctx context.Context, in credential.Library, opt ...handlers.Option) out.CredentialStoreId = in.GetStoreId() } if outputFields.Has(globals.TypeField) { - out.Type = subtypes.SubtypeFromId(domain, in.GetPublicId()).String() + out.Type = globals.ResourceInfoFromPrefix(in.GetPublicId()).Subtype.String() } if outputFields.Has(globals.DescriptionField) && in.GetDescription() != "" { out.Description = wrapperspb.String(in.GetDescription()) @@ -650,7 +650,7 @@ func toProto(ctx context.Context, in credential.Library, opt ...handlers.Option) if outputFields.Has(globals.AuthorizedActionsField) { out.AuthorizedActions = opts.WithAuthorizedActions } - switch subtypes.SubtypeFromId(domain, in.GetPublicId()) { + switch globals.ResourceInfoFromPrefix(in.GetPublicId()).Subtype { case vault.GenericLibrarySubtype: vaultIn, ok := in.(*vault.CredentialLibrary) if !ok { @@ -879,7 +879,7 @@ func toStorageVaultSSHCertificateLibrary(ctx context.Context, storeId string, in // - There are no conflicting parameters provided func validateGetRequest(req *pbs.GetCredentialLibraryRequest) error { prefix := "" - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case vault.SSHCertificateLibrarySubtype: prefix = globals.VaultSshCertificateCredentialLibraryPrefix default: @@ -891,7 +891,7 @@ func validateGetRequest(req *pbs.GetCredentialLibraryRequest) error { func validateCreateRequest(req *pbs.CreateCredentialLibraryRequest) error { return handlers.ValidateCreateRequest(req.GetItem(), func() map[string]string { badFields := map[string]string{} - switch subtypes.SubtypeFromId(domain, req.GetItem().GetCredentialStoreId()) { + switch globals.ResourceInfoFromPrefix(req.GetItem().GetCredentialStoreId()).Subtype { case vault.Subtype: var t string if version.SupportsFeature(version.Binary, version.CredentialLibraryVaultSubtype) { @@ -901,7 +901,7 @@ func validateCreateRequest(req *pbs.CreateCredentialLibraryRequest) error { // subtype of vault-generic based on the credential store's subtype. // To support the deprecated subtype 'vault.Subtype', convert it // to vault-generic. - if t == "" || subtypes.SubtypeFromType(domain, t) == vault.Subtype { + if t == "" || t == vault.Subtype.String() { // fallback to assuming subtype from credential store. t = vault.GenericLibrarySubtype.String() req.GetItem().Type = t @@ -927,13 +927,13 @@ func validateCreateRequest(req *pbs.CreateCredentialLibraryRequest) error { } } - if subtypes.SubtypeFromType(domain, t) != vault.GenericLibrarySubtype && - subtypes.SubtypeFromType(domain, t) != vault.SSHCertificateLibrarySubtype { + if t != vault.GenericLibrarySubtype.String() && + t != vault.SSHCertificateLibrarySubtype.String() { badFields[globals.CredentialStoreIdField] = fmt.Sprintf("Type must be a vault subtype %q or %q", vault.GenericLibrarySubtype.String(), vault.SSHCertificateLibrarySubtype.String()) } - switch subtypes.SubtypeFromType(domain, req.GetItem().GetType()) { - case vault.GenericLibrarySubtype: + switch req.GetItem().GetType() { + case vault.GenericLibrarySubtype.String(): isValidCred := false ct := req.GetItem().GetCredentialType() for _, t := range validCredentialTypesVaultGeneric { @@ -964,7 +964,7 @@ func validateCreateRequest(req *pbs.CreateCredentialLibraryRequest) error { badFields[httpRequestBodyField] = fmt.Sprintf("Field can only be set if %q is set to the value 'POST'.", httpMethodField) } validateMapping(badFields, globals.CredentialType(req.GetItem().GetCredentialType()), req.GetItem().CredentialMappingOverrides.AsMap()) - case vault.SSHCertificateLibrarySubtype: + case vault.SSHCertificateLibrarySubtype.String(): if req.GetItem().GetCredentialType() != "" { badFields[globals.CredentialTypeField] = fmt.Sprintf("This field is read only and cannot be set.") } @@ -1001,7 +1001,7 @@ func validateCreateRequest(req *pbs.CreateCredentialLibraryRequest) error { func validateUpdateRequest(req *pbs.UpdateCredentialLibraryRequest, currentCredentialType globals.CredentialType) error { prefix := "" - st := subtypes.SubtypeFromId(domain, req.GetId()) + st := globals.ResourceInfoFromPrefix(req.GetId()).Subtype switch st { case vault.GenericLibrarySubtype: prefix = globals.VaultCredentialLibraryPrefix @@ -1012,7 +1012,7 @@ func validateUpdateRequest(req *pbs.UpdateCredentialLibraryRequest, currentCrede badFields := map[string]string{} switch st { case vault.GenericLibrarySubtype: - if req.GetItem().GetType() != "" && subtypes.SubtypeFromType(domain, req.GetItem().GetType()) != vault.GenericLibrarySubtype { + if req.GetItem().GetType() != "" && req.GetItem().GetType() != vault.GenericLibrarySubtype.String() { badFields[globals.TypeField] = "Cannot modify resource type." } if req.GetItem().GetCredentialType() != "" && req.GetItem().GetCredentialType() != string(currentCredentialType) { @@ -1036,7 +1036,7 @@ func validateUpdateRequest(req *pbs.UpdateCredentialLibraryRequest, currentCrede validateMapping(badFields, currentCredentialType, req.GetItem().CredentialMappingOverrides.AsMap()) } case vault.SSHCertificateLibrarySubtype: - if req.GetItem().GetType() != "" && subtypes.SubtypeFromType(domain, req.GetItem().GetType()) != vault.SSHCertificateLibrarySubtype { + if req.GetItem().GetType() != "" && req.GetItem().GetType() != vault.SSHCertificateLibrarySubtype.String() { badFields[globals.TypeField] = "Cannot modify resource type." } if req.GetItem().GetCredentialType() != "" && req.GetItem().GetCredentialType() != string(currentCredentialType) { diff --git a/internal/daemon/controller/handlers/credentials/credential_service.go b/internal/daemon/controller/handlers/credentials/credential_service.go index 16e49294f..117e0b88c 100644 --- a/internal/daemon/controller/handlers/credentials/credential_service.go +++ b/internal/daemon/controller/handlers/credentials/credential_service.go @@ -413,7 +413,7 @@ func (s Service) updateInRepo( var dbMasks []string item := proto.Clone(in).(*pb.Credential) - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case credential.UsernamePasswordSubtype: dbMasks = append(dbMasks, upMaskManager.Translate(masks)...) if len(dbMasks) == 0 { @@ -808,7 +808,7 @@ func validateCreateRequest(req *pbs.CreateCredentialRequest) error { func validateUpdateRequest(req *pbs.UpdateCredentialRequest) error { return handlers.ValidateUpdateRequest(req, req.GetItem(), func() map[string]string { badFields := map[string]string{} - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case credential.UsernamePasswordSubtype: attrs := req.GetItem().GetUsernamePasswordAttributes() if handlers.MaskContains(req.GetUpdateMask().GetPaths(), usernameField) && attrs.GetUsername().GetValue() == "" { diff --git a/internal/daemon/controller/handlers/credentialstores/credentialstore_service.go b/internal/daemon/controller/handlers/credentialstores/credentialstore_service.go index 5180102de..4a0b96b39 100644 --- a/internal/daemon/controller/handlers/credentialstores/credentialstore_service.go +++ b/internal/daemon/controller/handlers/credentialstores/credentialstore_service.go @@ -394,7 +394,7 @@ func (s Service) listFromRepo(ctx context.Context, scopeIds []string) ([]credent func (s Service) getFromRepo(ctx context.Context, id string) (credential.Store, error) { const op = "credentialstores.(Service).getFromRepo" - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case vault.Subtype: repo, err := s.vaultRepoFn() if err != nil { @@ -475,7 +475,7 @@ func (s Service) updateInRepo(ctx context.Context, projId, id string, mask []str return nil, handlers.InvalidArgumentErrorf("No valid fields included in the update mask.", map[string]string{"update_mask": "No valid fields provided in the update mask."}) } - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case vault.Subtype: cs, err := toStorageVaultStore(ctx, projId, item) if err != nil { @@ -518,7 +518,7 @@ func (s Service) deleteFromRepo(ctx context.Context, id string) (bool, error) { const op = "credentialstores.(Service).deleteFromRepo" var rows int - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case vault.Subtype: repo, err := s.vaultRepoFn() if err != nil { @@ -581,7 +581,7 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth. return res } default: - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case vault.Subtype: cs, err := vaultRepo.LookupCredentialStore(ctx, id) if err != nil { @@ -630,7 +630,7 @@ func toProto(ctx context.Context, in credential.Store, opt ...handlers.Option) ( out.ScopeId = in.GetProjectId() } if outputFields.Has(globals.TypeField) { - out.Type = subtypes.SubtypeFromId(domain, in.GetPublicId()).String() + out.Type = globals.ResourceInfoFromPrefix(in.GetPublicId()).Subtype.String() } if outputFields.Has(globals.DescriptionField) && in.GetDescription() != "" { out.Description = wrapperspb.String(in.GetDescription()) @@ -657,7 +657,7 @@ func toProto(ctx context.Context, in credential.Store, opt ...handlers.Option) ( out.AuthorizedCollectionActions = opts.WithAuthorizedCollectionActions } if outputFields.Has(globals.AttributesField) { - switch subtypes.SubtypeFromId(domain, in.GetPublicId()) { + switch globals.ResourceInfoFromPrefix(in.GetPublicId()).Subtype { case vault.Subtype: vaultIn, ok := in.(*vault.CredentialStore) if !ok { @@ -790,8 +790,8 @@ func validateCreateRequest(ctx context.Context, req *pbs.CreateCredentialStoreRe if !handlers.ValidId(handlers.Id(req.GetItem().GetScopeId()), scope.Project.Prefix()) { badFields["scope_id"] = "This field must be a valid project scope id." } - switch subtypes.SubtypeFromType(domain, req.GetItem().GetType()) { - case vault.Subtype: + switch req.GetItem().GetType() { + case vault.Subtype.String(): attrs := req.GetItem().GetVaultCredentialStoreAttributes() if attrs == nil { badFields[globals.AttributesField] = "Attributes are required for creating a vault credential store" @@ -828,7 +828,7 @@ func validateCreateRequest(ctx context.Context, req *pbs.CreateCredentialStoreRe if len(cs) > 0 && pk == nil { badFields[clientCertField] = "Cannot set a client certificate without a private key." } - case static.Subtype: + case static.Subtype.String(): // No additional validation required for static credential store default: badFields[globals.TypeField] = "This is a required field and must be a known credential store type." @@ -840,9 +840,9 @@ func validateCreateRequest(ctx context.Context, req *pbs.CreateCredentialStoreRe func validateUpdateRequest(ctx context.Context, req *pbs.UpdateCredentialStoreRequest) error { return handlers.ValidateUpdateRequest(req, req.GetItem(), func() map[string]string { badFields := map[string]string{} - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case vault.Subtype: - if req.GetItem().GetType() != "" && subtypes.SubtypeFromType(domain, req.GetItem().GetType()) != vault.Subtype { + if req.GetItem().GetType() != "" && req.GetItem().GetType() != vault.Subtype.String() { badFields["type"] = "Cannot modify resource type." } attrs := req.GetItem().GetVaultCredentialStoreAttributes() @@ -903,7 +903,7 @@ func validateListRequest(ctx context.Context, req *pbs.ListCredentialStoresReque func calculateAuthorizedCollectionActions(ctx context.Context, authResults auth.VerifyResults, id string) (map[string]*structpb.ListValue, error) { var collectionActions map[string]*structpb.ListValue var err error - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case vault.Subtype: collectionActions, err = auth.CalculateAuthorizedCollectionActions(ctx, authResults, vaultCollectionTypeMap, authResults.Scope.Id, id) diff --git a/internal/daemon/controller/handlers/host_catalogs/host_catalog_service.go b/internal/daemon/controller/handlers/host_catalogs/host_catalog_service.go index c93e00f9c..9dbb2d462 100644 --- a/internal/daemon/controller/handlers/host_catalogs/host_catalog_service.go +++ b/internal/daemon/controller/handlers/host_catalogs/host_catalog_service.go @@ -57,7 +57,7 @@ var ( action.List, } - collectionTypeMap = map[subtypes.Subtype]map[resource.Type]action.ActionSet{ + collectionTypeMap = map[globals.Subtype]map[resource.Type]action.ActionSet{ static.Subtype: { resource.HostSet: host_sets.CollectionActions, resource.Host: hosts.CollectionActions, @@ -183,7 +183,7 @@ func (s Service) ListHostCatalogs(ctx context.Context, req *pbs.ListHostCatalogs outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authorizedActions)) } if outputFields.Has(globals.AuthorizedCollectionActionsField) { - var subtype subtypes.Subtype + var subtype globals.Subtype switch item.(type) { case *static.HostCatalog: subtype = static.Subtype @@ -253,7 +253,7 @@ 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) { - var subtype subtypes.Subtype + var subtype globals.Subtype switch hc.(type) { case *static.HostCatalog: subtype = static.Subtype @@ -310,7 +310,7 @@ 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) { - var subtype subtypes.Subtype + var subtype globals.Subtype switch hc.(type) { case *static.HostCatalog: subtype = static.Subtype @@ -373,7 +373,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) { - var subtype subtypes.Subtype + var subtype globals.Subtype switch hc.(type) { case *static.HostCatalog: subtype = static.Subtype @@ -415,7 +415,7 @@ func (s Service) DeleteHostCatalog(ctx context.Context, req *pbs.DeleteHostCatal func (s Service) getFromRepo(ctx context.Context, id string) (host.Catalog, *plugins.PluginInfo, error) { var plg *plugins.PluginInfo var cat host.Catalog - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case static.Subtype: repo, err := s.staticRepoFn() if err != nil { @@ -537,8 +537,8 @@ func (s Service) createPluginInRepo(ctx context.Context, projId string, req *pbs func (s Service) createInRepo(ctx context.Context, projId string, req *pbs.CreateHostCatalogRequest) (hc host.Catalog, info *plugins.PluginInfo, err error) { var plg *plugins.PluginInfo - switch subtypes.SubtypeFromType(domain, req.GetItem().GetType()) { - case static.Subtype: + switch req.GetItem().GetType() { + case static.Subtype.String(): hc, err = s.createStaticInRepo(ctx, projId, req.GetItem()) default: hc, plg, err = s.createPluginInRepo(ctx, projId, req) @@ -601,7 +601,7 @@ func (s Service) updatePluginInRepo(ctx context.Context, projId, id string, mask func (s Service) updateInRepo(ctx context.Context, projId string, req *pbs.UpdateHostCatalogRequest) (hc host.Catalog, plg *plugins.PluginInfo, err error) { const op = "host_catalogs.(Service).updateInRepo" - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case static.Subtype: hc, err = s.updateStaticInRepo(ctx, projId, req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem()) case hostplugin.Subtype: @@ -613,7 +613,7 @@ func (s Service) updateInRepo(ctx context.Context, projId string, req *pbs.Updat func (s Service) deleteFromRepo(ctx context.Context, id string) (bool, error) { const op = "host_catalogs.(Service).deleteFromRepo" rows := 0 - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case static.Subtype: repo, err := s.staticRepoFn() if err != nil { @@ -659,7 +659,7 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth. return res } default: - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case static.Subtype: repo, err := s.staticRepoFn() if err != nil { @@ -843,9 +843,9 @@ func validateCreateRequest(req *pbs.CreateHostCatalogRequest) error { if req.GetItem().GetSecretsHmac() != "" { badFields[globals.SecretsHmacField] = "This is a read only field." } - switch subtypes.SubtypeFromType(domain, req.GetItem().GetType()) { - case static.Subtype: - case hostplugin.Subtype: + switch req.GetItem().GetType() { + case static.Subtype.String(): + case hostplugin.Subtype.String(): if req.GetItem().GetPlugin() != nil { badFields[globals.PluginField] = "This is a read only field." } @@ -870,16 +870,16 @@ func validateUpdateRequest(req *pbs.UpdateHostCatalogRequest) error { if req.GetItem().GetSecretsHmac() != "" { badFields[globals.SecretsHmacField] = "This is a read only field." } - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case static.Subtype: - if req.GetItem().GetType() != "" && subtypes.SubtypeFromType(domain, req.GetItem().GetType()) != static.Subtype { + if req.GetItem().GetType() != "" && req.GetItem().GetType() != static.Subtype.String() { badFields[globals.TypeField] = "Cannot modify resource type." } if req.GetItem().GetPlugin() != nil { badFields[globals.PluginField] = "This field is unused for this type of host catalog." } case hostplugin.Subtype: - if req.GetItem().GetType() != "" && subtypes.SubtypeFromType(domain, req.GetItem().GetType()) != hostplugin.Subtype { + if req.GetItem().GetType() != "" && req.GetItem().GetType() != hostplugin.Subtype.String() { badFields[globals.TypeField] = "Cannot modify resource type." } if req.GetItem().GetPlugin() != nil { diff --git a/internal/daemon/controller/handlers/host_catalogs/host_catalog_service_test.go b/internal/daemon/controller/handlers/host_catalogs/host_catalog_service_test.go index 21cdf8af2..f6c8c8a8a 100644 --- a/internal/daemon/controller/handlers/host_catalogs/host_catalog_service_test.go +++ b/internal/daemon/controller/handlers/host_catalogs/host_catalog_service_test.go @@ -28,7 +28,6 @@ import ( "github.com/hashicorp/boundary/internal/plugin/loopback" "github.com/hashicorp/boundary/internal/scheduler" "github.com/hashicorp/boundary/internal/types/scope" - "github.com/hashicorp/boundary/internal/types/subtypes" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostcatalogs" "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/plugins" scopepb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" @@ -46,7 +45,7 @@ import ( "github.com/stretchr/testify/require" ) -var authorizedCollectionActions = map[subtypes.Subtype]map[string]*structpb.ListValue{ +var authorizedCollectionActions = map[globals.Subtype]map[string]*structpb.ListValue{ static.Subtype: { "host-sets": { Values: []*structpb.Value{ diff --git a/internal/daemon/controller/handlers/host_sets/host_set_service.go b/internal/daemon/controller/handlers/host_sets/host_set_service.go index 7e01cf404..a6d498970 100644 --- a/internal/daemon/controller/handlers/host_sets/host_set_service.go +++ b/internal/daemon/controller/handlers/host_sets/host_set_service.go @@ -35,11 +35,11 @@ import ( ) var ( - maskManager = map[subtypes.Subtype]handlers.MaskManager{} + maskManager = map[globals.Subtype]handlers.MaskManager{} // IdActions contains the set of actions that can be performed on // individual resources - idActionsTypeMap = map[subtypes.Subtype]action.ActionSet{ + idActionsTypeMap = map[globals.Subtype]action.ActionSet{ static.Subtype: { action.NoOp, action.Read, @@ -140,7 +140,7 @@ func (s Service) ListHostSetsWithOptions(ctx context.Context, req *pbs.ListHostS } for _, item := range hl { res.Id = item.GetPublicId() - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, res.Id)] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(res.Id).Subtype] authorizedActions := authResults.FetchActionSetForId(ctx, item.GetPublicId(), idActions, auth.WithResource(&res)).Strings() if len(authorizedActions) == 0 { continue @@ -204,7 +204,7 @@ func (s Service) GetHostSet(ctx context.Context, req *pbs.GetHostSetRequest) (*p outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, req.GetId())] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(req.GetId()).Subtype] outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, hs.GetPublicId(), idActions).Strings())) } if plg != nil { @@ -246,7 +246,7 @@ func (s Service) CreateHostSet(ctx context.Context, req *pbs.CreateHostSetReques outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, req.GetItem().GetHostCatalogId())] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(req.GetItem().GetHostCatalogId()).Subtype] outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, hs.GetPublicId(), idActions).Strings())) } if plg != nil { @@ -294,7 +294,7 @@ func (s Service) UpdateHostSet(ctx context.Context, req *pbs.UpdateHostSetReques outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, req.GetId())] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(req.GetId()).Subtype] outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, hs.GetPublicId(), idActions).Strings())) } @@ -349,7 +349,7 @@ func (s Service) AddHostSetHosts(ctx context.Context, req *pbs.AddHostSetHostsRe outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, req.GetId())] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(req.GetId()).Subtype] outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, hs.GetPublicId(), idActions).Strings())) } @@ -387,7 +387,7 @@ func (s Service) SetHostSetHosts(ctx context.Context, req *pbs.SetHostSetHostsRe outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, req.GetId())] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(req.GetId()).Subtype] outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, hs.GetPublicId(), idActions).Strings())) } @@ -426,7 +426,7 @@ func (s Service) RemoveHostSetHosts(ctx context.Context, req *pbs.RemoveHostSetH outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, req.GetId())] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(req.GetId()).Subtype] outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, hs.GetPublicId(), idActions).Strings())) } @@ -442,7 +442,7 @@ func (s Service) getFromRepo(ctx context.Context, id string) (host.Set, []host.H var hs host.Set var hl []host.Host var plg *plugins.PluginInfo - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case static.Subtype: repo, err := s.staticRepoFn() if err != nil { @@ -492,7 +492,7 @@ func (s Service) createInRepo(ctx context.Context, projectId, catalogId string, } var hSet host.Set var plg *plugins.PluginInfo - switch subtypes.SubtypeFromId(domain, catalogId) { + switch globals.ResourceInfoFromPrefix(catalogId).Subtype { case static.Subtype: h, err := toStorageStaticSet(ctx, catalogId, item) if err != nil { @@ -596,7 +596,7 @@ func (s Service) updatePluginInRepo(ctx context.Context, projectId string, req * func (s Service) updateInRepo(ctx context.Context, projectId, catalogId string, req *pbs.UpdateHostSetRequest) (hs host.Set, hosts []host.Host, plg *plugins.PluginInfo, err error) { const op = "host_sets.(Service).updateInRepo" - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case static.Subtype: hs, hosts, err = s.updateStaticInRepo(ctx, projectId, catalogId, req) case hostplugin.Subtype: @@ -608,7 +608,7 @@ func (s Service) updateInRepo(ctx context.Context, projectId, catalogId string, func (s Service) deleteFromRepo(ctx context.Context, projectId, id string) (bool, error) { const op = "host_sets.(Service).deleteFromRepo" rows := 0 - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case static.Subtype: repo, err := s.staticRepoFn() if err != nil { @@ -635,7 +635,7 @@ func (s Service) listFromRepo(ctx context.Context, catalogId string, opt ...host const op = "host_sets.(Service).listFromRepo" var plg *plugins.PluginInfo var sets []host.Set - switch subtypes.SubtypeFromId(domain, catalogId) { + switch globals.ResourceInfoFromPrefix(catalogId).Subtype { case static.Subtype: repo, err := s.staticRepoFn() if err != nil { @@ -760,7 +760,7 @@ func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Ty parentId = id default: var set host.Set - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case static.Subtype: ss, _, err := staticRepo.LookupSet(ctx, id) if err != nil { @@ -789,7 +789,7 @@ func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Ty } var cat host.Catalog - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case static.Subtype: cs, err := staticRepo.LookupCatalog(ctx, parentId) if err != nil { @@ -970,7 +970,7 @@ func validateCreateRequest(ctx context.Context, req *pbs.CreateHostSetRequest) e badFields[globals.PreferredEndpointsField] = fmt.Errorf("Error parsing preferred endpoints: %w.", err).Error() } } - switch subtypes.SubtypeFromId(domain, req.GetItem().GetHostCatalogId()) { + switch globals.ResourceInfoFromPrefix(req.GetItem().GetHostCatalogId()).Subtype { case static.Subtype: if req.GetItem().GetType() != "" && req.GetItem().GetType() != static.Subtype.String() { badFields[globals.TypeField] = "Doesn't match the parent resource's type." @@ -1001,7 +1001,7 @@ func validateUpdateRequest(ctx context.Context, req *pbs.UpdateHostSetRequest) e badFields[globals.PreferredEndpointsField] = fmt.Errorf("Error parsing preferred endpoints: %w.", err).Error() } } - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case static.Subtype: if req.GetItem().GetType() != "" && req.GetItem().GetType() != static.Subtype.String() { badFields[globals.TypeField] = "Cannot modify the resource type." diff --git a/internal/daemon/controller/handlers/host_sets/host_set_service_test.go b/internal/daemon/controller/handlers/host_sets/host_set_service_test.go index 9bf703d86..3184a12ac 100644 --- a/internal/daemon/controller/handlers/host_sets/host_set_service_test.go +++ b/internal/daemon/controller/handlers/host_sets/host_set_service_test.go @@ -28,7 +28,6 @@ import ( "github.com/hashicorp/boundary/internal/plugin/loopback" "github.com/hashicorp/boundary/internal/scheduler" "github.com/hashicorp/boundary/internal/types/scope" - "github.com/hashicorp/boundary/internal/types/subtypes" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostsets" "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/plugins" "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" @@ -45,7 +44,7 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -var testAuthorizedActions = map[subtypes.Subtype][]string{ +var testAuthorizedActions = map[globals.Subtype][]string{ static.Subtype: {"no-op", "read", "update", "delete", "add-hosts", "set-hosts", "remove-hosts"}, hostplugin.Subtype: {"no-op", "read", "update", "delete"}, } diff --git a/internal/daemon/controller/handlers/hosts/host_service.go b/internal/daemon/controller/handlers/hosts/host_service.go index 4dfd964e9..77ff09758 100644 --- a/internal/daemon/controller/handlers/hosts/host_service.go +++ b/internal/daemon/controller/handlers/hosts/host_service.go @@ -36,7 +36,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources - idActionsTypeMap = map[subtypes.Subtype]action.ActionSet{ + idActionsTypeMap = map[globals.Subtype]action.ActionSet{ static.Subtype: { action.NoOp, action.Read, @@ -121,7 +121,7 @@ func (s Service) ListHosts(ctx context.Context, req *pbs.ListHostsRequest) (*pbs } for _, item := range hl { res.Id = item.GetPublicId() - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, res.Id)] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(res.Id).Subtype] authorizedActions := authResults.FetchActionSetForId(ctx, item.GetPublicId(), idActions, auth.WithResource(&res)).Strings() if len(authorizedActions) == 0 { continue @@ -188,7 +188,7 @@ func (s Service) GetHost(ctx context.Context, req *pbs.GetHostRequest) (*pbs.Get outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, req.GetId())] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(req.GetId()).Subtype] outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, h.GetPublicId(), idActions).Strings())) } outputOpts = append(outputOpts, handlers.WithHostSetIds(h.GetSetIds())) @@ -227,7 +227,7 @@ func (s Service) CreateHost(ctx context.Context, req *pbs.CreateHostRequest) (*p outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, req.GetItem().GetHostCatalogId())] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(req.GetItem().GetHostCatalogId()).Subtype] outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, h.GetPublicId(), idActions).Strings())) } @@ -269,7 +269,7 @@ func (s Service) UpdateHost(ctx context.Context, req *pbs.UpdateHostRequest) (*p outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - idActions := idActionsTypeMap[subtypes.SubtypeFromId(domain, req.GetId())] + idActions := idActionsTypeMap[globals.ResourceInfoFromPrefix(req.GetId()).Subtype] outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, h.GetPublicId(), idActions).Strings())) } outputOpts = append(outputOpts, handlers.WithHostSetIds(h.GetSetIds())) @@ -301,7 +301,7 @@ func (s Service) DeleteHost(ctx context.Context, req *pbs.DeleteHostRequest) (*p func (s Service) getFromRepo(ctx context.Context, id string) (host.Host, *plugins.PluginInfo, error) { var h host.Host var plg *plugins.PluginInfo - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case static.Subtype: repo, err := s.staticRepoFn() if err != nil { @@ -416,7 +416,7 @@ func (s Service) deleteFromRepo(ctx context.Context, projectId, id string) (bool func (s Service) listFromRepo(ctx context.Context, catalogId string) ([]host.Host, *plugins.PluginInfo, error) { var hosts []host.Host var plg *plugins.PluginInfo - switch subtypes.SubtypeFromId(domain, catalogId) { + switch globals.ResourceInfoFromPrefix(catalogId).Subtype { case static.Subtype: repo, err := s.staticRepoFn() if err != nil { @@ -465,7 +465,7 @@ func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Ty case action.List, action.Create: parentId = id default: - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case static.Subtype: h, err := staticRepo.LookupHost(ctx, id) if err != nil { @@ -493,7 +493,7 @@ func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Ty } var cat host.Catalog - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case static.Subtype: stcat, err := staticRepo.LookupCatalog(ctx, parentId) if err != nil { @@ -619,8 +619,8 @@ func toProto(ctx context.Context, in host.Host, opt ...handlers.Option) (*pb.Hos func validateGetRequest(req *pbs.GetHostRequest) error { return handlers.ValidateGetRequest(func() map[string]string { badFields := map[string]string{} - ct := subtypes.SubtypeFromId(domain, req.GetId()) - if ct == subtypes.UnknownSubtype { + ct := globals.ResourceInfoFromPrefix(req.GetId()).Subtype + if ct == globals.UnknownSubtype { badFields["id"] = "Improperly formatted identifier used." } return badFields @@ -633,7 +633,7 @@ func validateCreateRequest(req *pbs.CreateHostRequest) error { if !handlers.ValidId(handlers.Id(req.GetItem().GetHostCatalogId()), globals.StaticHostCatalogPrefix) { badFields["host_catalog_id"] = "The field is incorrectly formatted." } - switch subtypes.SubtypeFromId(domain, req.GetItem().GetHostCatalogId()) { + switch globals.ResourceInfoFromPrefix(req.GetItem().GetHostCatalogId()).Subtype { case static.Subtype: if req.GetItem().GetType() != "" && req.GetItem().GetType() != static.Subtype.String() { badFields[globals.TypeField] = "Doesn't match the parent resource's type." @@ -675,7 +675,7 @@ func validateCreateRequest(req *pbs.CreateHostRequest) error { func validateUpdateRequest(req *pbs.UpdateHostRequest) error { return handlers.ValidateUpdateRequest(req, req.GetItem(), func() map[string]string { badFields := map[string]string{} - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case static.Subtype: if req.GetItem().GetType() != "" && req.GetItem().GetType() != static.Subtype.String() { badFields[globals.TypeField] = "Cannot modify the resource type." @@ -715,7 +715,7 @@ func validateUpdateRequest(req *pbs.UpdateHostRequest) error { func validateDeleteRequest(req *pbs.DeleteHostRequest) error { return handlers.ValidateDeleteRequest(func() map[string]string { badFields := map[string]string{} - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case hostplugin.Subtype: badFields[globals.IdField] = "Cannot manually delete this type of host." } diff --git a/internal/daemon/controller/handlers/hosts/host_service_test.go b/internal/daemon/controller/handlers/hosts/host_service_test.go index 3ac4a886c..13dd0189c 100644 --- a/internal/daemon/controller/handlers/hosts/host_service_test.go +++ b/internal/daemon/controller/handlers/hosts/host_service_test.go @@ -27,7 +27,6 @@ import ( "github.com/hashicorp/boundary/internal/plugin/loopback" "github.com/hashicorp/boundary/internal/scheduler" "github.com/hashicorp/boundary/internal/types/scope" - "github.com/hashicorp/boundary/internal/types/subtypes" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hosts" "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/plugins" "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" @@ -42,7 +41,7 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -var testAuthorizedActions = map[subtypes.Subtype][]string{ +var testAuthorizedActions = map[globals.Subtype][]string{ static.Subtype: {"no-op", "read", "update", "delete"}, hostplugin.Subtype: {"no-op", "read"}, } diff --git a/internal/daemon/controller/handlers/managed_groups/managed_group_service.go b/internal/daemon/controller/handlers/managed_groups/managed_group_service.go index 24aacee5f..bbaf59586 100644 --- a/internal/daemon/controller/handlers/managed_groups/managed_group_service.go +++ b/internal/daemon/controller/handlers/managed_groups/managed_group_service.go @@ -44,7 +44,7 @@ var ( // IdActions contains the set of actions that can be performed on // individual resources - IdActions = map[subtypes.Subtype]action.ActionSet{ + IdActions = map[globals.Subtype]action.ActionSet{ oidc.Subtype: { action.NoOp, action.Read, @@ -137,7 +137,7 @@ func (s Service) ListManagedGroups(ctx context.Context, req *pbs.ListManagedGrou } for _, mg := range ul { res.Id = mg.GetPublicId() - authorizedActions := authResults.FetchActionSetForId(ctx, mg.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, mg.GetPublicId())], requestauth.WithResource(&res)).Strings() + authorizedActions := authResults.FetchActionSetForId(ctx, mg.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(mg.GetPublicId()).Subtype], requestauth.WithResource(&res)).Strings() if len(authorizedActions) == 0 { continue } @@ -198,7 +198,7 @@ func (s Service) GetManagedGroup(ctx context.Context, req *pbs.GetManagedGroupRe outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, mg.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, mg.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, mg.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(mg.GetPublicId()).Subtype]).Strings())) } if outputFields.Has(globals.MemberIdsField) { outputOpts = append(outputOpts, handlers.WithMemberIds(memberIds)) @@ -240,7 +240,7 @@ func (s Service) CreateManagedGroup(ctx context.Context, req *pbs.CreateManagedG outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, mg.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, mg.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, mg.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(mg.GetPublicId()).Subtype]).Strings())) } item, err := toProto(ctx, mg, outputOpts...) @@ -279,7 +279,7 @@ func (s Service) UpdateManagedGroup(ctx context.Context, req *pbs.UpdateManagedG outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, mg.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, mg.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, mg.GetPublicId(), IdActions[globals.ResourceInfoFromPrefix(mg.GetPublicId()).Subtype]).Strings())) } item, err := toProto(ctx, mg, outputOpts...) @@ -309,7 +309,7 @@ func (s Service) DeleteManagedGroup(ctx context.Context, req *pbs.DeleteManagedG func (s Service) getFromRepo(ctx context.Context, id string) (auth.ManagedGroup, []string, error) { var out auth.ManagedGroup var memberIds []string - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case oidc.Subtype: repo, err := s.oidcRepoFn() if err != nil { @@ -432,7 +432,7 @@ func (s Service) createInRepo(ctx context.Context, am auth.AuthMethod, item *pb. return nil, errors.New(ctx, errors.InvalidParameter, op, "missing item") } var out auth.ManagedGroup - switch subtypes.SubtypeFromId(domain, am.GetPublicId()) { + switch globals.ResourceInfoFromPrefix(am.GetPublicId()).Subtype { case oidc.Subtype: am, err := s.createOidcInRepo(ctx, am, item) if err != nil { @@ -534,7 +534,7 @@ func (s Service) updateLdapInRepo(ctx context.Context, scopeId, amId, id string, func (s Service) updateInRepo(ctx context.Context, scopeId, authMethodId string, req *pbs.UpdateManagedGroupRequest) (auth.ManagedGroup, error) { const op = "managed_groups.(Service).updateInRepo" var out auth.ManagedGroup - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case oidc.Subtype: mg, err := s.updateOidcInRepo(ctx, scopeId, authMethodId, req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem()) if err != nil { @@ -561,7 +561,7 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, const op = "managed_groups.(Service).deleteFromRepo" var rows int var err error - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case oidc.Subtype: repo, iErr := s.oidcRepoFn() if iErr != nil { @@ -588,7 +588,7 @@ func (s Service) listFromRepo(ctx context.Context, authMethodId string) ([]auth. const op = "managed_groups.(Service).listFromRepo" var outUl []auth.ManagedGroup - switch subtypes.SubtypeFromId(domain, authMethodId) { + switch globals.ResourceInfoFromPrefix(authMethodId).Subtype { case oidc.Subtype: oidcRepo, err := s.oidcRepoFn() if err != nil { @@ -637,7 +637,7 @@ func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Ty case action.List, action.Create: parentId = id default: - switch subtypes.SubtypeFromId(domain, id) { + switch globals.ResourceInfoFromPrefix(id).Subtype { case oidc.Subtype: grp, err := oidcRepo.LookupManagedGroup(ctx, id) if err != nil { @@ -668,7 +668,7 @@ func (s Service) parentAndAuthResult(ctx context.Context, id string, a action.Ty } var authMeth auth.AuthMethod - switch subtypes.SubtypeFromId(domain, parentId) { + switch globals.ResourceInfoFromPrefix(parentId).Subtype { case oidc.Subtype: am, err := oidcRepo.LookupAuthMethod(ctx, parentId) if err != nil { @@ -799,7 +799,7 @@ func validateCreateRequest(ctx context.Context, req *pbs.CreateManagedGroupReque if req.GetItem().GetAuthMethodId() == "" { badFields[globals.AuthMethodIdField] = "This field is required." } - switch subtypes.SubtypeFromId(domain, req.GetItem().GetAuthMethodId()) { + switch globals.ResourceInfoFromPrefix(req.GetItem().GetAuthMethodId()).Subtype { case oidc.Subtype: if req.GetItem().GetType() != "" && req.GetItem().GetType() != oidc.Subtype.String() { badFields[globals.TypeField] = "Doesn't match the parent resource's type." @@ -842,7 +842,7 @@ func validateUpdateRequest(ctx context.Context, req *pbs.UpdateManagedGroupReque } return handlers.ValidateUpdateRequest(req, req.GetItem(), func() map[string]string { badFields := map[string]string{} - switch subtypes.SubtypeFromId(domain, req.GetId()) { + switch globals.ResourceInfoFromPrefix(req.GetId()).Subtype { case oidc.Subtype: if req.GetItem().GetType() != "" && req.GetItem().GetType() != oidc.Subtype.String() { badFields[globals.TypeField] = "Cannot modify the resource type." diff --git a/internal/daemon/controller/handlers/targets/credentials.go b/internal/daemon/controller/handlers/targets/credentials.go index 06c31a4dc..24af14609 100644 --- a/internal/daemon/controller/handlers/targets/credentials.go +++ b/internal/daemon/controller/handlers/targets/credentials.go @@ -16,7 +16,6 @@ import ( "github.com/hashicorp/boundary/internal/errors" serverpb "github.com/hashicorp/boundary/internal/gen/controller/servers/services" "github.com/hashicorp/boundary/internal/session" - "github.com/hashicorp/boundary/internal/types/subtypes" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" @@ -137,7 +136,7 @@ func dynamicToSessionCredential(ctx context.Context, cred credential.Dynamic) (* Name: l.GetName(), Description: l.GetDescription(), CredentialStoreId: l.GetStoreId(), - Type: subtypes.SubtypeFromId(credentialDomain, l.GetPublicId()).String(), + Type: globals.ResourceInfoFromPrefix(l.GetPublicId()).Subtype.String(), CredentialType: credType, }, Secret: &pb.SessionSecret{ diff --git a/internal/daemon/controller/handlers/targets/registry.go b/internal/daemon/controller/handlers/targets/registry.go index c25a8ea1d..3aac06e03 100644 --- a/internal/daemon/controller/handlers/targets/registry.go +++ b/internal/daemon/controller/handlers/targets/registry.go @@ -8,10 +8,10 @@ import ( "fmt" "sync" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/daemon/controller/handlers" "github.com/hashicorp/boundary/internal/session" "github.com/hashicorp/boundary/internal/target" - "github.com/hashicorp/boundary/internal/types/subtypes" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets" "google.golang.org/protobuf/proto" ) @@ -52,7 +52,7 @@ type registry struct { *sync.Map } -func (r registry) get(s subtypes.Subtype) (*registryEntry, error) { +func (r registry) get(s globals.Subtype) (*registryEntry, error) { v, ok := r.Load(s) if !ok { return nil, fmt.Errorf("subtype %q not registered", s) @@ -65,7 +65,7 @@ func (r registry) get(s subtypes.Subtype) (*registryEntry, error) { return re, nil } -func (r registry) maskManager(s subtypes.Subtype) (handlers.MaskManager, error) { +func (r registry) maskManager(s globals.Subtype) (handlers.MaskManager, error) { re, err := r.get(s) if err != nil { return nil, err @@ -77,7 +77,7 @@ func (r registry) maskManager(s subtypes.Subtype) (handlers.MaskManager, error) // newAttribute creates an Attribute for the given subtype. It delegates the // allocation of the Attribute to the registered attrFunc for the given // subtype. An error is returned if the provided subtype is not registered -func (r registry) newAttribute(s subtypes.Subtype, m any) (Attributes, error) { +func (r registry) newAttribute(s globals.Subtype, m any) (Attributes, error) { re, err := r.get(s) if err != nil { return nil, err @@ -92,7 +92,7 @@ func (r registry) newAttribute(s subtypes.Subtype, m any) (Attributes, error) { // setting of the specific attribute type to the registered setAttributeFunc for // the given subtype. An error is returned if the provided subtype is not // registered. -func (r registry) setAttributes(s subtypes.Subtype, in target.Target, out *pb.Target) error { +func (r registry) setAttributes(s globals.Subtype, in target.Target, out *pb.Target) error { re, err := r.get(s) if err != nil { return err @@ -106,7 +106,7 @@ var subtypeRegistry = registry{ } // Register registers a subtype for used by the service handler. -func Register(s subtypes.Subtype, maskManager handlers.MaskManager, af attributeFunc, sf setAttributeFunc, vsf validateSessionStateFunc) { +func Register(s globals.Subtype, maskManager handlers.MaskManager, af attributeFunc, sf setAttributeFunc, vsf validateSessionStateFunc) { if _, existed := subtypeRegistry.LoadOrStore(s, ®istryEntry{ maskManager: maskManager, attrFunc: af, diff --git a/internal/daemon/controller/handlers/targets/target_service.go b/internal/daemon/controller/handlers/targets/target_service.go index fb1679f8d..0469cef8f 100644 --- a/internal/daemon/controller/handlers/targets/target_service.go +++ b/internal/daemon/controller/handlers/targets/target_service.go @@ -95,7 +95,7 @@ var ( action.List, } - validateCredentialSourcesFn = func(context.Context, subtypes.Subtype, []target.CredentialSource) error { return nil } + validateCredentialSourcesFn = func(context.Context, globals.Subtype, []target.CredentialSource) error { return nil } ValidateIngressWorkerFilterFn = IngressWorkerFilterUnsupported AuthorizeSessionWorkerFilterFn = AuthorizeSessionWithWorkerFilter PostSessionAuthorizationCallback = DefaultPostSessionAuthorizationCallback @@ -799,7 +799,7 @@ func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSession var endpoints []*host.Endpoint for _, hSource := range hostSources { hsId := hSource.Id() - switch subtypes.SubtypeFromId(hostDomain, hsId) { + switch globals.ResourceInfoFromPrefix(hsId).Subtype { case static.Subtype: eps, err := staticHostRepo.Endpoints(ctx, hsId) if err != nil { @@ -2038,7 +2038,7 @@ func validateAuthorizeSessionRequest(req *pbs.AuthorizeSessionRequest) error { } } if req.GetHostId() != "" { - switch subtypes.SubtypeFromId(hostDomain, req.GetHostId()) { + switch globals.ResourceInfoFromPrefix(req.GetHostId()).Subtype { case static.Subtype, plugin.Subtype: default: badFields[globals.HostIdField] = "Incorrectly formatted identifier." diff --git a/internal/daemon/controller/handlers/targets/tcp/target_service_test.go b/internal/daemon/controller/handlers/targets/tcp/target_service_test.go index d7d64a15a..2b41fff62 100644 --- a/internal/daemon/controller/handlers/targets/tcp/target_service_test.go +++ b/internal/daemon/controller/handlers/targets/tcp/target_service_test.go @@ -3410,7 +3410,7 @@ func TestAuthorizeSession_Errors(t *testing.T) { h.Address = fmt.Sprintf("%s:54321", h.GetAddress()) repo, err := staticHostRepoFn() require.NoError(t, err) - h, _, err = repo.UpdateHost(ctx, hc.GetProjectId(), h, h.GetVersion(), []string{"address"}) + _, _, err = repo.UpdateHost(ctx, hc.GetProjectId(), h, h.GetVersion(), []string{"address"}) require.NoError(t, err) return apiTar.GetItem().GetVersion() } diff --git a/internal/host/plugin/ids.go b/internal/host/plugin/ids.go index 97acd296f..38de6cdce 100644 --- a/internal/host/plugin/ids.go +++ b/internal/host/plugin/ids.go @@ -10,18 +10,21 @@ import ( "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/host" - "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/hashicorp/boundary/internal/types/resource" ) func init() { - if err := subtypes.Register(host.Domain, Subtype, globals.PluginHostCatalogPrefix, globals.PluginHostCatalogPreviousPrefix, globals.PluginHostSetPrefix, globals.PluginHostSetPreviousPrefix, globals.PluginHostPrefix, globals.PluginHostPreviousPrefix); err != nil { - panic(err) - } + globals.RegisterPrefixToResourceInfo(globals.PluginHostCatalogPrefix, resource.HostCatalog, host.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.PluginHostCatalogPreviousPrefix, resource.HostCatalog, host.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.PluginHostSetPrefix, resource.HostSet, host.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.PluginHostSetPreviousPrefix, resource.HostSet, host.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.PluginHostPrefix, resource.Host, host.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.PluginHostPreviousPrefix, resource.Host, host.Domain, Subtype) } // PublicId prefixes for the resources in the plugin package. const ( - Subtype = subtypes.Subtype("plugin") + Subtype = globals.Subtype("plugin") ) func newHostCatalogId(ctx context.Context) (string, error) { diff --git a/internal/host/static/public_ids.go b/internal/host/static/public_ids.go index 9fcd4f138..91e8af6be 100644 --- a/internal/host/static/public_ids.go +++ b/internal/host/static/public_ids.go @@ -10,18 +10,18 @@ import ( "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/host" - "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/hashicorp/boundary/internal/types/resource" ) func init() { - if err := subtypes.Register(host.Domain, Subtype, globals.StaticHostCatalogPrefix, globals.StaticHostSetPrefix, globals.StaticHostPrefix); err != nil { - panic(err) - } + globals.RegisterPrefixToResourceInfo(globals.StaticHostCatalogPrefix, resource.HostCatalog, host.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.StaticHostSetPrefix, resource.HostSet, host.Domain, Subtype) + globals.RegisterPrefixToResourceInfo(globals.StaticHostPrefix, resource.Host, host.Domain, Subtype) } // PublicId prefixes for the resources in the static package. const ( - Subtype = subtypes.Subtype("static") + Subtype = globals.Subtype("static") ) func newHostCatalogId(ctx context.Context) (string, error) { diff --git a/internal/perms/acl.go b/internal/perms/acl.go index be0d7d99e..9974e105e 100644 --- a/internal/perms/acl.go +++ b/internal/perms/acl.go @@ -207,7 +207,7 @@ func (a ACL) Allowed(r Resource, aType action.Type, userId string, opt ...Option case grant.id == r.Id && grant.id != "" && grant.id != "*" && - (grant.typ == resource.Unknown || grant.typ == globals.ResourceTypeFromPrefix(grant.id)) && + (grant.typ == resource.Unknown || grant.typ == globals.ResourceInfoFromPrefix(grant.id).Type) && !action.List.IsActionOrParent(aType) && !action.Create.IsActionOrParent(aType): @@ -306,7 +306,7 @@ func (a ACL) ListPermissions(requestedScopes map[string]*scopes.ScopeInfo, grants := a.scopeMap[scopeId] for _, grant := range grants { // This grant doesn't match what we're looking for, ignore. - if grant.typ != requestedType && grant.typ != resource.All && globals.ResourceTypeFromPrefix(grant.id) != requestedType { + if grant.typ != requestedType && grant.typ != resource.All && globals.ResourceInfoFromPrefix(grant.id).Type != requestedType { continue } diff --git a/internal/perms/grants.go b/internal/perms/grants.go index e3fa53539..56ad5f372 100644 --- a/internal/perms/grants.go +++ b/internal/perms/grants.go @@ -439,10 +439,10 @@ func Parse(ctx context.Context, scopeId, grantString string, opt ...Option) (Gra var seenType resource.Type for i, id := range grantIds { if i == 0 { - seenType = globals.ResourceTypeFromPrefix(id) + seenType = globals.ResourceInfoFromPrefix(id).Type continue } - if seenType != globals.ResourceTypeFromPrefix(id) { + if seenType != globals.ResourceInfoFromPrefix(id).Type { return Grant{}, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("input grant string %q contains ids of differently-typed resources", grantString)) } } @@ -524,7 +524,7 @@ func Parse(ctx context.Context, scopeId, grantString string, opt ...Option) (Gra // the second example the type corresponding to the ID must have the // specified type as a child type; in the third the ID must be a // type that has child types. - idType := globals.ResourceTypeFromPrefix(grantIds[i]) + idType := globals.ResourceInfoFromPrefix(grantIds[i]).Type if idType == resource.Unknown { return Grant{}, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("parsed grant string %q contains an id %q of an unknown resource type", grant.CanonicalString(), grantIds[i])) } diff --git a/internal/storage/plugin/ids.go b/internal/storage/plugin/ids.go index 16ad140e8..1d48e5828 100644 --- a/internal/storage/plugin/ids.go +++ b/internal/storage/plugin/ids.go @@ -9,19 +9,17 @@ import ( "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/hashicorp/boundary/internal/types/resource" ) const StorageDomain = "storage" func init() { - if err := subtypes.Register(StorageDomain, Subtype, globals.PluginStorageBucketPrefix); err != nil { - panic(err) - } + globals.RegisterPrefixToResourceInfo(globals.PluginStorageBucketPrefix, resource.StorageBucket, StorageDomain, Subtype) } const ( - Subtype = subtypes.Subtype("plugin") + Subtype = globals.Subtype("plugin") ) func newStorageBucketId(ctx context.Context) (string, error) { diff --git a/internal/target/options.go b/internal/target/options.go index 69aec6b0c..2185b0e1f 100644 --- a/internal/target/options.go +++ b/internal/target/options.go @@ -7,9 +7,9 @@ import ( "net" "time" + "github.com/hashicorp/boundary/globals" intglobals "github.com/hashicorp/boundary/internal/globals" "github.com/hashicorp/boundary/internal/perms" - "github.com/hashicorp/boundary/internal/types/subtypes" ) // GetOpts - iterate the inbound Options and return a struct @@ -35,7 +35,7 @@ type options struct { WithProjectIds []string WithProjectName string WithUserId string - WithType subtypes.Subtype + WithType globals.Subtype WithHostSources []string WithCredentialLibraries []*CredentialLibrary WithStaticCredentials []*StaticCredential @@ -148,7 +148,7 @@ func WithUserId(userId string) Option { } // WithType provides an option to search by a target type -func WithType(t subtypes.Subtype) Option { +func WithType(t globals.Subtype) Option { return func(o *options) { o.WithType = t } diff --git a/internal/target/options_test.go b/internal/target/options_test.go index 42b1c8075..25eaa88a7 100644 --- a/internal/target/options_test.go +++ b/internal/target/options_test.go @@ -6,10 +6,10 @@ package target import ( "testing" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/credential" "github.com/hashicorp/boundary/internal/perms" "github.com/hashicorp/boundary/internal/target/store" - "github.com/hashicorp/boundary/internal/types/subtypes" "github.com/stretchr/testify/assert" ) @@ -103,7 +103,7 @@ func Test_GetOpts(t *testing.T) { assert.Equal(opts, testOpts) }) t.Run("WithType", func(t *testing.T) { - subtype := subtypes.Subtype("testtype") + subtype := globals.Subtype("testtype") assert := assert.New(t) opts := GetOpts(WithType(subtype)) testOpts := getDefaultOptions() diff --git a/internal/target/registry.go b/internal/target/registry.go index aa69547c6..f1badbe3f 100644 --- a/internal/target/registry.go +++ b/internal/target/registry.go @@ -8,11 +8,12 @@ import ( "fmt" "sync" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/errors" - "github.com/hashicorp/boundary/internal/types/subtypes" + "github.com/hashicorp/boundary/internal/types/resource" ) -const domain = "target" +const Domain = "target" // NewFunc is a function that creates a Target with the provided project and options. type NewFunc func(ctx context.Context, projectId string, opt ...Option) (Target, error) @@ -57,12 +58,12 @@ type registryEntry struct { } type registry struct { - m map[subtypes.Subtype]*registryEntry + m map[globals.Subtype]*registryEntry sync.RWMutex } -func (r *registry) set(s subtypes.Subtype, entry *registryEntry) { +func (r *registry) set(s globals.Subtype, entry *registryEntry) { r.Lock() defer r.Unlock() @@ -71,14 +72,12 @@ func (r *registry) set(s subtypes.Subtype, entry *registryEntry) { panic(fmt.Sprintf("target subtype %s already registered", s)) } - if err := subtypes.Register(domain, s, entry.prefix); err != nil { - panic(err) - } + globals.RegisterPrefixToResourceInfo(entry.prefix, resource.Target, Domain, s) r.m[s] = entry } -func (r *registry) get(s subtypes.Subtype) (*registryEntry, bool) { +func (r *registry) get(s globals.Subtype) (*registryEntry, bool) { r.RLock() defer r.RUnlock() @@ -89,7 +88,7 @@ func (r *registry) get(s subtypes.Subtype) (*registryEntry, bool) { return nil, ok } -func (r *registry) newFunc(s subtypes.Subtype) (NewFunc, bool) { +func (r *registry) newFunc(s globals.Subtype) (NewFunc, bool) { entry, ok := r.get(s) if !ok { return nil, ok @@ -97,7 +96,7 @@ func (r *registry) newFunc(s subtypes.Subtype) (NewFunc, bool) { return entry.targetHooks.NewTarget, ok } -func (r *registry) allocFunc(s subtypes.Subtype) (AllocFunc, bool) { +func (r *registry) allocFunc(s globals.Subtype) (AllocFunc, bool) { entry, ok := r.get(s) if !ok { return nil, ok @@ -105,7 +104,7 @@ func (r *registry) allocFunc(s subtypes.Subtype) (AllocFunc, bool) { return entry.targetHooks.AllocTarget, ok } -func (r *registry) vetFunc(s subtypes.Subtype) (VetFunc, bool) { +func (r *registry) vetFunc(s globals.Subtype) (VetFunc, bool) { entry, ok := r.get(s) if !ok { return nil, ok @@ -113,7 +112,7 @@ func (r *registry) vetFunc(s subtypes.Subtype) (VetFunc, bool) { return entry.targetHooks.Vet, ok } -func (r *registry) vetForUpdateFunc(s subtypes.Subtype) (VetForUpdateFunc, bool) { +func (r *registry) vetForUpdateFunc(s globals.Subtype) (VetForUpdateFunc, bool) { entry, ok := r.get(s) if !ok { return nil, ok @@ -121,7 +120,7 @@ func (r *registry) vetForUpdateFunc(s subtypes.Subtype) (VetForUpdateFunc, bool) return entry.targetHooks.VetForUpdate, ok } -func (r *registry) vetCredentialSourcesFunc(s subtypes.Subtype) (VetCredentialSourcesFunc, bool) { +func (r *registry) vetCredentialSourcesFunc(s globals.Subtype) (VetCredentialSourcesFunc, bool) { entry, ok := r.get(s) if !ok { return nil, ok @@ -130,7 +129,7 @@ func (r *registry) vetCredentialSourcesFunc(s subtypes.Subtype) (VetCredentialSo return entry.targetHooks.VetCredentialSources, ok } -func (r *registry) idPrefix(s subtypes.Subtype) (string, bool) { +func (r *registry) idPrefix(s globals.Subtype) (string, bool) { entry, ok := r.get(s) if !ok { return "", ok @@ -139,28 +138,28 @@ func (r *registry) idPrefix(s subtypes.Subtype) (string, bool) { } var subtypeRegistry = registry{ - m: make(map[subtypes.Subtype]*registryEntry), + m: make(map[globals.Subtype]*registryEntry), } // SubtypeFromType returns the Subtype from the provided string or if // no Subtype was registered with that string Unknown is returned. -func SubtypeFromType(t string) subtypes.Subtype { - return subtypes.SubtypeFromType(domain, t) +func SubtypeFromType(t string) globals.Subtype { + return globals.Subtype(t) } // SubtypeFromId returns the Subtype from the provided id if the id's prefix // was registered with a Subtype. Otherwise Unknown is returned. -func SubtypeFromId(id string) subtypes.Subtype { - return subtypes.SubtypeFromId(domain, id) +func SubtypeFromId(id string) globals.Subtype { + return globals.ResourceInfoFromPrefix(id).Subtype } // Prefixes returns the list of all known target Prefixes. func Prefixes() []string { - return subtypes.Prefixes(domain) + return globals.PrefixesFromDomain(Domain) } // New creates a Target of the given subtype and projectId. -func New(ctx context.Context, subtype subtypes.Subtype, projectId string, opt ...Option) (Target, error) { +func New(ctx context.Context, subtype globals.Subtype, projectId string, opt ...Option) (Target, error) { const op = "target.New" nf, ok := subtypeRegistry.newFunc(subtype) if !ok { @@ -172,7 +171,7 @@ func New(ctx context.Context, subtype subtypes.Subtype, projectId string, opt .. // Register registers repository hooks and the prefixes for a provided Subtype. Register // panics if the subtype has already been registered or if any of the // prefixes are associated with another subtype. -func Register(s subtypes.Subtype, th targetHooks, prefix string) { +func Register(s globals.Subtype, th targetHooks, prefix string) { subtypeRegistry.set(s, ®istryEntry{ targetHooks: th, prefix: prefix, diff --git a/internal/target/repository_credential_source.go b/internal/target/repository_credential_source.go index 9f84034e7..0c267c27e 100644 --- a/internal/target/repository_credential_source.go +++ b/internal/target/repository_credential_source.go @@ -9,12 +9,12 @@ import ( "fmt" "strings" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/credential" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/oplog" - "github.com/hashicorp/boundary/internal/types/subtypes" "github.com/hashicorp/go-secure-stdlib/strutil" ) @@ -536,7 +536,7 @@ func fetchCredentialSources(ctx context.Context, r db.Reader, targetId string) ( return ret, nil } -func (r *Repository) createSources(ctx context.Context, tId string, tSubtype subtypes.Subtype, credSources CredentialSources) ([]*CredentialLibrary, []*StaticCredential, error) { +func (r *Repository) createSources(ctx context.Context, tId string, tSubtype globals.Subtype, credSources CredentialSources) ([]*CredentialLibrary, []*StaticCredential, error) { const op = "target.(Repository).createSources" // Get a list of unique ids being attached to the target, to be used for looking up the source type (library or static) diff --git a/internal/target/target.go b/internal/target/target.go index 34dcffe67..255fb53e3 100644 --- a/internal/target/target.go +++ b/internal/target/target.go @@ -8,12 +8,12 @@ import ( goerrs "errors" "fmt" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/boundary" "github.com/hashicorp/boundary/internal/db/timestamp" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/oplog" "github.com/hashicorp/boundary/internal/target/store" - "github.com/hashicorp/boundary/internal/types/subtypes" ) // Target is a commmon interface for all target subtypes @@ -25,7 +25,7 @@ type Target interface { GetName() string GetDescription() string GetVersion() uint32 - GetType() subtypes.Subtype + GetType() globals.Subtype GetCreateTime() *timestamp.Timestamp GetUpdateTime() *timestamp.Timestamp GetSessionMaxSeconds() uint32 @@ -140,8 +140,8 @@ func (t targetView) GetUserId() string { return "" } -func (t *targetView) Subtype() subtypes.Subtype { - return subtypes.Subtype(t.Type) +func (t *targetView) Subtype() globals.Subtype { + return globals.Subtype(t.Type) } // targetSubtype converts the target view to the concrete subtype diff --git a/internal/target/targettest/target.go b/internal/target/targettest/target.go index 8c4e98d7e..0a1b70e78 100644 --- a/internal/target/targettest/target.go +++ b/internal/target/targettest/target.go @@ -18,13 +18,12 @@ import ( "github.com/hashicorp/boundary/internal/oplog" "github.com/hashicorp/boundary/internal/target" "github.com/hashicorp/boundary/internal/target/targettest/store" - "github.com/hashicorp/boundary/internal/types/subtypes" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" ) const ( - Subtype = subtypes.Subtype("tcp") + Subtype = globals.Subtype("tcp") ) // Target is a target.Target used for tests. @@ -103,7 +102,7 @@ func (t *Target) GetVersion() uint32 { return t.Version } -func (t *Target) GetType() subtypes.Subtype { +func (t *Target) GetType() globals.Subtype { return Subtype } diff --git a/internal/target/tcp/target.go b/internal/target/tcp/target.go index d710ff3a4..3257bffaf 100644 --- a/internal/target/tcp/target.go +++ b/internal/target/tcp/target.go @@ -11,19 +11,19 @@ import ( "fmt" "strings" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/db/timestamp" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/oplog" "github.com/hashicorp/boundary/internal/target" "github.com/hashicorp/boundary/internal/target/tcp/store" - "github.com/hashicorp/boundary/internal/types/subtypes" "google.golang.org/protobuf/proto" ) const ( defaultTableName = "target_tcp" - Subtype = subtypes.Subtype("tcp") + Subtype = globals.Subtype("tcp") ) // Target is a resources that represets a networked service @@ -132,7 +132,7 @@ func (t *Target) Oplog(op oplog.OpType) oplog.Metadata { return metadata } -func (t *Target) GetType() subtypes.Subtype { +func (t *Target) GetType() globals.Subtype { return Subtype } diff --git a/internal/types/subtypes/attribute_transform.go b/internal/types/subtypes/attribute_transform.go index 2cb8adeeb..ff124fc31 100644 --- a/internal/types/subtypes/attribute_transform.go +++ b/internal/types/subtypes/attribute_transform.go @@ -6,13 +6,14 @@ package subtypes import ( "fmt" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/daemon/controller/handlers" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/known/structpb" ) -func convertAttributesToSubtype(msg proto.Message, st Subtype) error { +func convertAttributesToSubtype(msg proto.Message, st globals.Subtype) error { r := msg.ProtoReflect() d := r.Descriptor() @@ -55,7 +56,7 @@ func convertAttributesToSubtype(msg proto.Message, st Subtype) error { return nil } -func convertAttributesToDefault(msg proto.Message, st Subtype) error { +func convertAttributesToDefault(msg proto.Message, st globals.Subtype) error { r := msg.ProtoReflect() d := r.Descriptor() diff --git a/internal/types/subtypes/attributes.go b/internal/types/subtypes/attributes.go index 19709e500..bf52ce66f 100644 --- a/internal/types/subtypes/attributes.go +++ b/internal/types/subtypes/attributes.go @@ -7,6 +7,7 @@ import ( "fmt" "sync" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" @@ -33,7 +34,7 @@ func init() { }) } -type fieldMap map[Subtype]protoreflect.FieldDescriptor +type fieldMap map[globals.Subtype]protoreflect.FieldDescriptor type attributeRegistry struct { sync.RWMutex @@ -72,7 +73,7 @@ func (ak *attributeRegistry) register(d protoreflect.MessageDescriptor) error { opts := f.Options().(*descriptorpb.FieldOptions) st := proto.GetExtension(opts, protooptions.E_Subtype).(string) if st != "" { - km[Subtype(st)] = f + km[globals.Subtype(st)] = f } } @@ -99,7 +100,7 @@ func (ak *attributeRegistry) register(d protoreflect.MessageDescriptor) error { // attributeField retrieves the FieldDescriptor for a given subtype's // attribute fields. If the corresponding protobuf message has not been // registered it will return an error. -func (ak *attributeRegistry) attributeField(d protoreflect.MessageDescriptor, t Subtype) (protoreflect.FieldDescriptor, error) { +func (ak *attributeRegistry) attributeField(d protoreflect.MessageDescriptor, t globals.Subtype) (protoreflect.FieldDescriptor, error) { ak.RLock() defer ak.RUnlock() @@ -124,6 +125,6 @@ func (ak *attributeRegistry) attributeField(d protoreflect.MessageDescriptor, t // attributeField is used by the AttributeTransformInterceptor to retrieve // the proto FieldDescriptor for a given subtype. -func attributeField(d protoreflect.MessageDescriptor, t Subtype) (protoreflect.FieldDescriptor, error) { +func attributeField(d protoreflect.MessageDescriptor, t globals.Subtype) (protoreflect.FieldDescriptor, error) { return globalAttributeRegistry.attributeField(d, t) } diff --git a/internal/types/subtypes/attributes_test.go b/internal/types/subtypes/attributes_test.go index 6746b8d9b..f1cf6384d 100644 --- a/internal/types/subtypes/attributes_test.go +++ b/internal/types/subtypes/attributes_test.go @@ -6,6 +6,7 @@ package subtypes import ( "testing" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/gen/testing/attribute" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -17,7 +18,7 @@ func TestProtoAttributeKey(t *testing.T) { cases := []struct { name string msg proto.Message - subtype Subtype + subtype globals.Subtype expected protoreflect.FullName }{ { @@ -35,7 +36,7 @@ func TestProtoAttributeKey(t *testing.T) { { "TestResource/unknown", &attribute.TestResource{}, - UnknownSubtype, + globals.UnknownSubtype, "testing.attribute.v1.TestResource.attributes", }, } @@ -54,7 +55,7 @@ func TestProtoAttributeKeyErrors(t *testing.T) { cases := []struct { name string msg proto.Message - subtype Subtype + subtype globals.Subtype expectedErr string }{ { @@ -72,7 +73,7 @@ func TestProtoAttributeKeyErrors(t *testing.T) { { "TestNoAttributes/unknown", &attribute.TestNoAttributes{}, - UnknownSubtype, + globals.UnknownSubtype, "proto message testing.attribute.v1.TestNoAttributes not registered", }, } diff --git a/internal/types/subtypes/interceptor.go b/internal/types/subtypes/interceptor.go index f2b4d125c..b7519d1d7 100644 --- a/internal/types/subtypes/interceptor.go +++ b/internal/types/subtypes/interceptor.go @@ -7,31 +7,14 @@ import ( "context" "errors" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/daemon/controller/handlers" - "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/types/descriptorpb" ) -func messageDomain(m proto.Message) string { - r := m.ProtoReflect() - fd := r.Descriptor().ParentFile() - if fd == nil { - return "" - } - - opts, ok := fd.Options().(*descriptorpb.FileOptions) - if !ok { - return "" - } - - domain := proto.GetExtension(opts, protooptions.E_Domain).(string) - return domain -} - // transformRequestAttributes will modify the request proto.Message, setting // any subtype attribute fields into the corresponding strongly-typed struct // for the subtype. It looks for some specific structure in the proto.Message @@ -98,8 +81,6 @@ func messageDomain(m proto.Message) string { // Also note that for any of the id based lookups to function, the file that contains // the proto.Message definition must set the "domain" custom option. func transformRequestAttributes(req proto.Message) error { - domain := messageDomain(req) - r := req.ProtoReflect() fields := r.Descriptor().Fields() @@ -114,7 +95,7 @@ func transformRequestAttributes(req proto.Message) error { return m.Get(fd).String() } - var st Subtype + var st globals.Subtype switch { case itemField != nil: itemR := itemField.Message() @@ -134,18 +115,18 @@ func transformRequestAttributes(req proto.Message) error { switch { case idField != nil && id != "": - st = SubtypeFromId(domain, id) + st = globals.ResourceInfoFromPrefix(id).Subtype case sourceIdField != nil && sourceId != "": - st = SubtypeFromId(domain, sourceId) + st = globals.ResourceInfoFromPrefix(sourceId).Subtype case typeField != nil && t != "": - st = Subtype(t) + st = globals.Subtype(t) default: // need either type or id return nil } return convertAttributesToSubtype(item, st) case idField != nil && attributesField != nil: id := r.Get(idField).String() - st = SubtypeFromId(domain, id) + st = globals.ResourceInfoFromPrefix(id).Subtype return convertAttributesToSubtype(req, st) } return nil @@ -172,7 +153,7 @@ func transformResponseItemAttributes(item proto.Message) error { return nil } - st := Subtype(item.ProtoReflect().Get(typeField).String()) + st := globals.Subtype(item.ProtoReflect().Get(typeField).String()) return convertAttributesToDefault(item, st) } diff --git a/internal/types/subtypes/interceptor_test.go b/internal/types/subtypes/interceptor_test.go index d17d708b8..a5c64215d 100644 --- a/internal/types/subtypes/interceptor_test.go +++ b/internal/types/subtypes/interceptor_test.go @@ -7,8 +7,10 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/daemon/controller/handlers" "github.com/hashicorp/boundary/internal/gen/testing/attribute" + "github.com/hashicorp/boundary/internal/types/resource" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" @@ -17,8 +19,8 @@ import ( ) func init() { - Register("test", Subtype("sub_resource"), "trsr") - Register("test", Subtype("resource_plugin"), "trrp") + globals.RegisterPrefixToResourceInfo("trsr", resource.Unknown, "test", globals.Subtype("sub_resource")) + globals.RegisterPrefixToResourceInfo("trrp", resource.Unknown, "test", globals.Subtype("resource_plugin")) } func TestTransformRequestAttributes(t *testing.T) { diff --git a/internal/types/subtypes/registry.go b/internal/types/subtypes/registry.go index a90ffa227..43d1a67bf 100644 --- a/internal/types/subtypes/registry.go +++ b/internal/types/subtypes/registry.go @@ -10,26 +10,15 @@ import ( "strings" "sync" + "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/errors" ) -// Subtype variables identify a boundary resource subtype. -type Subtype string - -const ( - UnknownSubtype Subtype = "unknown" -) - -// String returns the string representation of a Subtype -func (t Subtype) String() string { - return string(t) -} - // Registry stores a collection of boundary resource subtypes along with their // prefixes and allows for translating prefixes back to registered subtypes. type Registry struct { - subtypesPrefixes map[string]Subtype - knownSubtypes map[Subtype]any + subtypesPrefixes map[string]globals.Subtype + knownSubtypes map[globals.Subtype]any sync.RWMutex } @@ -37,39 +26,39 @@ type Registry struct { // NewRegistry creates a new boundary resource subtype registry. func NewRegistry() *Registry { return &Registry{ - subtypesPrefixes: make(map[string]Subtype), - knownSubtypes: make(map[Subtype]any), + subtypesPrefixes: make(map[string]globals.Subtype), + knownSubtypes: make(map[globals.Subtype]any), } } // SubtypeFromType returns the Subtype from the provided string or if // no Subtype was registered with that string Unknown is returned. -func (r *Registry) SubtypeFromType(t string) Subtype { +func (r *Registry) SubtypeFromType(t string) globals.Subtype { r.RLock() defer r.RUnlock() - st := Subtype(t) + st := globals.Subtype(t) if _, ok := r.knownSubtypes[st]; !ok { - return UnknownSubtype + return globals.UnknownSubtype } return st } // SubtypeFromId returns the Subtype from the provided id if the id's prefix // was registered with a Subtype. Otherwise Unknown is returned. -func (r *Registry) SubtypeFromId(id string) Subtype { +func (r *Registry) SubtypeFromId(id string) globals.Subtype { r.RLock() defer r.RUnlock() i := strings.Index(id, "_") if i == -1 { - return UnknownSubtype + return globals.UnknownSubtype } prefix := id[:i] subtype, ok := r.subtypesPrefixes[prefix] if !ok { - return UnknownSubtype + return globals.UnknownSubtype } return subtype } @@ -89,7 +78,7 @@ func (r *Registry) Prefixes() []string { // Register registers all the prefixes for a provided Subtype. Register returns // an error if the subtype has already been registered or if any of the // prefixes are associated with another subtype. -func (r *Registry) Register(ctx context.Context, subtype Subtype, prefixes ...string) error { +func (r *Registry) Register(ctx context.Context, subtype globals.Subtype, prefixes ...string) error { r.Lock() defer r.Unlock() diff --git a/internal/types/subtypes/registry_global.go b/internal/types/subtypes/registry_global.go deleted file mode 100644 index e454aa83a..000000000 --- a/internal/types/subtypes/registry_global.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package subtypes - -import ( - "context" - "fmt" - "strings" - "sync" - - "github.com/hashicorp/boundary/internal/errors" -) - -var globalRegistry = newRegistry() - -// newGlobalRegistry creates a new boundary resource subtype registry. -func newRegistry() *registry { - return ®istry{ - subtypesPrefixes: make(map[string]map[string]Subtype), - knownSubtypes: make(map[string]map[Subtype]any), - } -} - -// registry stores a collection of boundary resource subtypes along with their -// prefixes and allows for translating prefixes back to registered subtypes. -type registry struct { - subtypesPrefixes map[string]map[string]Subtype - knownSubtypes map[string]map[Subtype]any - - sync.RWMutex -} - -// SubtypeFromType returns the Subtype from the provided string or if -// no Subtype was registered with that string Unknown is returned. -func (r *registry) subtypeFromType(domain, t string) Subtype { - r.RLock() - defer r.RUnlock() - - knownSubtypes, ok := r.knownSubtypes[domain] - if !ok { - return UnknownSubtype - } - - st := Subtype(t) - if _, ok := knownSubtypes[st]; !ok { - return UnknownSubtype - } - return st -} - -// SubtypeFromId returns the Subtype from the provided id if the id's prefix -// was registered with a Subtype. Otherwise Unknown is returned. -func (r *registry) subtypeFromId(domain, id string) Subtype { - r.RLock() - defer r.RUnlock() - - i := strings.Index(id, "_") - if i == -1 { - return UnknownSubtype - } - prefix := id[:i] - - subtypePrefixes, ok := r.subtypesPrefixes[domain] - if !ok { - return UnknownSubtype - } - - subtype, ok := subtypePrefixes[prefix] - if !ok { - return UnknownSubtype - } - return subtype -} - -func (r *registry) prefixes(domain string) []string { - r.RLock() - defer r.RUnlock() - - subtypePrefixes, ok := r.subtypesPrefixes[domain] - if !ok { - return nil - } - - ret := make([]string, 0, len(subtypePrefixes)) - for p := range subtypePrefixes { - ret = append(ret, p) - } - return ret -} - -// Register registers all the prefixes for a provided Subtype. Register returns -// an error if the subtype has already been registered or if any of the -// prefixes are associated with another subtype. -func (r *registry) register(ctx context.Context, domain string, subtype Subtype, prefixes ...string) error { - r.Lock() - defer r.Unlock() - - const op = "subtypes.(registry).register" - - knownSubtypes, present := r.knownSubtypes[domain] - if !present { - knownSubtypes = make(map[Subtype]any) - r.knownSubtypes[domain] = knownSubtypes - r.subtypesPrefixes[domain] = make(map[string]Subtype) - } - - if _, present := knownSubtypes[subtype]; present { - return errors.New( - ctx, - errors.SubtypeAlreadyRegistered, - op, - fmt.Sprintf("subtype %q already registered in domain %s", subtype, domain), - ) - } - knownSubtypes[subtype] = nil - - for _, prefix := range prefixes { - prefix = strings.TrimSpace(prefix) - if st, ok := r.subtypesPrefixes[domain][prefix]; ok { - return errors.New( - ctx, - errors.SubtypeAlreadyRegistered, - op, - fmt.Sprintf("prefix %q is already registered to subtype %q in domain %s", prefix, st, domain), - ) - } - r.subtypesPrefixes[domain][prefix] = subtype - } - return nil -} - -// SubtypeFromType returns the Subtype from the provided string or if -// no Subtype was registered with that string Unknown is returned. -func SubtypeFromType(domain, t string) Subtype { - return globalRegistry.subtypeFromType(domain, t) -} - -// SubtypeFromId returns the Subtype from the provided id if the id's prefix -// was registered with a Subtype. Otherwise Unknown is returned. -func SubtypeFromId(domain, id string) Subtype { - return globalRegistry.subtypeFromId(domain, id) -} - -// Prefixes returns the list of all known Prefixes for a domain. -func Prefixes(domain string) []string { - return globalRegistry.prefixes(domain) -} - -// Register registers all the prefixes for a provided Subtype. Register returns -// an error if the subtype has already been registered or if any of the -// prefixes are associated with another subtype. -func Register(domain string, subtype Subtype, prefixes ...string) error { - ctx := context.TODO() - return globalRegistry.register(ctx, domain, subtype, prefixes...) -} diff --git a/internal/types/subtypes/registry_test.go b/internal/types/subtypes/registry_test.go deleted file mode 100644 index 5f843da28..000000000 --- a/internal/types/subtypes/registry_test.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: BUSL-1.1 - -package subtypes_test - -import ( - "context" - "testing" - - "github.com/hashicorp/boundary/internal/types/subtypes" - "github.com/stretchr/testify/assert" -) - -func TestSubtypeFromId(t *testing.T) { - testSubtype := subtypes.Subtype("test") - r := subtypes.NewRegistry() - r.Register(context.Background(), testSubtype, "tttst") - tests := []struct { - name string - given string - want subtypes.Subtype - }{ - {"empty-string", "", subtypes.UnknownSubtype}, - {"no-prefix-delimiter", "tttst1234", subtypes.UnknownSubtype}, - {"prefix-first", "_tttst_1234", subtypes.UnknownSubtype}, - {"unknown-prefix", "kaz_1234", subtypes.UnknownSubtype}, - {"prefix-no-id", "tttst_", testSubtype}, - {"vault-prefix", "tttst_1234", testSubtype}, - {"prefix-no-delimiter-no-id", "tttst", subtypes.UnknownSubtype}, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - got := r.SubtypeFromId(tt.given) - assert.Equalf(t, tt.want, got, "given: %s", tt.given) - if got != tt.want { - t.Errorf("(%s): expected %s, actual %s", tt.given, tt.want, got) - } - }) - } -} - -func TestSubtypeFromType(t *testing.T) { - testSubtype := subtypes.Subtype("test") - r := subtypes.NewRegistry() - r.Register(context.Background(), testSubtype, "tttst") - tests := []struct { - name string - given string - want subtypes.Subtype - }{ - {"empty-string", "", subtypes.UnknownSubtype}, - {"correct-string", "test", testSubtype}, - {"captialized", "TEST", subtypes.UnknownSubtype}, - {"typo", "testt", subtypes.UnknownSubtype}, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - got := r.SubtypeFromType(tt.given) - assert.Equalf(t, tt.want, got, "given: %s", tt.given) - if got != tt.want { - t.Errorf("(%s): expected %s, actual %s", tt.given, tt.want, got) - } - }) - } -} - -func TestRegister(t *testing.T) { - r := subtypes.NewRegistry() - ctx := context.Background() - assert.NoError(t, r.Register(ctx, "test", "testprefix")) - // registering multiple subtypes should be fine. - assert.NoError(t, r.Register(ctx, "second", "secondprefix")) - // registering another prefix with a different subtype errors. - assert.Error(t, r.Register(ctx, "third", "testprefix")) - // Registering the same subtype twice errors. - assert.Error(t, r.Register(ctx, "test", "repeatedprefix")) -}