Add generic read/update/delete commands (#3992)

* Add generic read/update/delete commands

This adds three generic commands that use the resource prefix to
determine the subcommand to run and pass through args over to that
subcommand. Since this occurs very early on and to avoid loading
essentially every internal resource package, I moved subtype definitions
to globals.

This replaces #3967

Co-authored-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>

* De-duplicate Subtype code (#4031)

Co-authored-by: Timothy Messier <tim.messier@gmail.com>

---------

Co-authored-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
Co-authored-by: Timothy Messier <tim.messier@gmail.com>
This commit is contained in:
authored and GitHub committed 2023-11-15 19:55:46 -05:00
1 parent 5c84a8861a
commit b6df5693b5
59 files changed
+1032 -857

No files matched your search

+19
View File
@@ -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
-3
View File
@@ -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:]))
}
+227 -42
View File
@@ -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
}
+4 -4
View File
@@ -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)
}
}
+16
View File
@@ -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)
}
+5 -5
View File
@@ -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) {
+5 -5
View File
@@ -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) {
+5 -5
View File
@@ -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) {
+3 -1
View File
@@ -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
+9
View File
@@ -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
}
}
+237 -223
View File
File diff suppressed because it is too large. Load diff
@@ -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 {
+1 -1
View File
@@ -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 {
@@ -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
}
+4 -3
View File
@@ -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{
+103 -10
View File
@@ -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 <command> [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])
}
+73
View File
@@ -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)
}
})
}
}
+8 -13
View File
@@ -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) {
+4 -5
View File
@@ -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) {
@@ -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
+8 -13
View File
@@ -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) {
+1 -2
View File
@@ -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 {
@@ -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."
@@ -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()
@@ -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 {
@@ -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) {
@@ -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() == "" {
@@ -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)
@@ -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 {
@@ -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{
@@ -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."
@@ -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"},
}
@@ -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."
}
@@ -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"},
}
@@ -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."
@@ -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{
@@ -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, &registryEntry{
maskManager: maskManager,
attrFunc: af,
@@ -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."
@@ -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()
}
+8 -5
View File
@@ -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) {
+5 -5
View File
@@ -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) {
+2 -2
View File
@@ -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
}
+3 -3
View File
@@ -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]))
}
+3 -5
View File
@@ -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) {
+3 -3
View File
@@ -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
}
+2 -2
View File
@@ -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()
+21 -22
View File
@@ -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, &registryEntry{
targetHooks: th,
prefix: prefix,
@@ -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)
+4 -4
View File
@@ -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
+2 -3
View File
@@ -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
}
+3 -3
View File
@@ -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
}
@@ -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()
+5 -4
View File
@@ -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)
}
+5 -4
View File
@@ -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",
},
}
+7 -26
View File
@@ -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)
}
+4 -2
View File
@@ -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) {
+12 -23
View File
@@ -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()
-156
View File
@@ -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 &registry{
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...)
}
-79
View File
@@ -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"))
}