Files
threshold/internal/target/registry.go
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

179 lines
5.1 KiB
Go
Raw Normal View History

2022-07-20 16:24:46 -07:00
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
2023-02-02 17:15:17 -08:00
2021-09-29 13:13:49 -04:00
package target
import (
"context"
"fmt"
"sync"
"github.com/hashicorp/boundary/globals"
2021-11-04 11:37:32 -04:00
"github.com/hashicorp/boundary/internal/errors"
"github.com/hashicorp/boundary/internal/types/resource"
2021-09-29 13:13:49 -04:00
)
const Domain = "target"
2022-07-20 16:24:46 -07:00
// 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)
2021-11-04 11:37:32 -04:00
2021-09-29 13:13:49 -04:00
// AllocFunc is a function that creates an in-memory Target.
type AllocFunc func() Target
// VetFunc is a function that checks the given Target to ensure it can
// be used by the Repository.
type VetFunc func(context.Context, Target) error
// VetForUpdateFunc is a function that checks the given Target and field mask
// paths are valid and be used to update a target in the Repository.
type VetForUpdateFunc func(context.Context, Target, []string) error
// VetCredentialSourcesFunc is a function that checks the given CredentialLibraries
// and StaticCredentials to ensure that they are valid for a Target subtype.
type VetCredentialSourcesFunc func(context.Context, []*CredentialLibrary, []*StaticCredential) error
// targetHooks defines the interface containing all the hooks needed for
// managing target suptypes.
type targetHooks interface {
// NewTarget creates a new in memory target.
NewTarget(ctx context.Context, projectId string, opt ...Option) (Target, error)
// AllocTarget will allocate an empty target.
AllocTarget() Target
// Vet validates that the given Target has the proper fields and values
// for creation in the database for this type of target.
Vet(ctx context.Context, t Target) error
// VetForUpdate validates that the given Target has the proper fields
// and values for updating the database for this type of target given the
// field mask paths.
VetForUpdate(ctx context.Context, t Target, paths []string) error
// VetCredentialSources checks that the provided credential libriaries and
// static credentials are properly built for association with a target of this type.
VetCredentialSources(ctx context.Context, cls []*CredentialLibrary, creds []*StaticCredential) error
}
2021-09-29 13:13:49 -04:00
type registryEntry struct {
targetHooks targetHooks
prefix string
2021-09-29 13:13:49 -04:00
}
type registry struct {
m map[globals.Subtype]*registryEntry
2021-09-29 13:13:49 -04:00
sync.RWMutex
}
func (r *registry) set(s globals.Subtype, entry *registryEntry) {
2021-09-29 13:13:49 -04:00
r.Lock()
defer r.Unlock()
_, previouslySet := r.m[s]
if previouslySet {
panic(fmt.Sprintf("target subtype %s already registered", s))
}
globals.RegisterPrefixToResourceInfo(entry.prefix, resource.Target, Domain, s)
2021-09-29 13:13:49 -04:00
r.m[s] = entry
}
func (r *registry) get(s globals.Subtype) (*registryEntry, bool) {
2021-09-29 13:13:49 -04:00
r.RLock()
defer r.RUnlock()
entry, ok := r.m[s]
if ok {
return entry, ok
}
return nil, ok
}
func (r *registry) newFunc(s globals.Subtype) (NewFunc, bool) {
2021-11-04 11:37:32 -04:00
entry, ok := r.get(s)
if !ok {
return nil, ok
}
return entry.targetHooks.NewTarget, ok
2021-11-04 11:37:32 -04:00
}
func (r *registry) allocFunc(s globals.Subtype) (AllocFunc, bool) {
2021-09-29 13:13:49 -04:00
entry, ok := r.get(s)
if !ok {
return nil, ok
}
return entry.targetHooks.AllocTarget, ok
2021-09-29 13:13:49 -04:00
}
func (r *registry) vetFunc(s globals.Subtype) (VetFunc, bool) {
2021-09-29 13:13:49 -04:00
entry, ok := r.get(s)
if !ok {
return nil, ok
}
return entry.targetHooks.Vet, ok
}
func (r *registry) vetForUpdateFunc(s globals.Subtype) (VetForUpdateFunc, bool) {
entry, ok := r.get(s)
if !ok {
return nil, ok
}
return entry.targetHooks.VetForUpdate, ok
2021-09-29 13:13:49 -04:00
}
func (r *registry) vetCredentialSourcesFunc(s globals.Subtype) (VetCredentialSourcesFunc, bool) {
entry, ok := r.get(s)
if !ok {
return nil, ok
}
return entry.targetHooks.VetCredentialSources, ok
}
func (r *registry) idPrefix(s globals.Subtype) (string, bool) {
2021-09-29 13:13:49 -04:00
entry, ok := r.get(s)
if !ok {
return "", ok
}
return entry.prefix, ok
}
var subtypeRegistry = registry{
m: make(map[globals.Subtype]*registryEntry),
2021-09-29 13:13:49 -04:00
}
// SubtypeFromType returns the Subtype from the provided string or if
// no Subtype was registered with that string Unknown is returned.
func SubtypeFromType(t string) globals.Subtype {
return globals.Subtype(t)
2021-09-29 13:13:49 -04:00
}
// 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) globals.Subtype {
return globals.ResourceInfoFromPrefix(id).Subtype
2021-09-29 13:13:49 -04:00
}
2021-11-04 11:37:32 -04:00
// Prefixes returns the list of all known target Prefixes.
func Prefixes() []string {
return globals.PrefixesFromDomain(Domain)
2021-11-04 11:37:32 -04:00
}
2022-07-20 16:24:46 -07:00
// New creates a Target of the given subtype and projectId.
func New(ctx context.Context, subtype globals.Subtype, projectId string, opt ...Option) (Target, error) {
2021-11-04 11:37:32 -04:00
const op = "target.New"
nf, ok := subtypeRegistry.newFunc(subtype)
if !ok {
return nil, errors.New(ctx, errors.InvalidParameter, op, "unsupported subtype")
}
return nf(ctx, projectId, opt...)
2021-11-04 11:37:32 -04:00
}
2021-09-29 13:13:49 -04:00
// 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 globals.Subtype, th targetHooks, prefix string) {
2021-09-29 13:13:49 -04:00
subtypeRegistry.set(s, &registryEntry{
targetHooks: th,
prefix: prefix,
2021-09-29 13:13:49 -04:00
})
}