2022-05-09 12:45:10 -07:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
2021-11-04 11:44:22 -04:00
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
2023-02-02 17:15:17 -08:00
|
|
|
|
2021-11-04 11:44:22 -04:00
|
|
|
package targets
|
|
|
|
|
|
|
|
|
|
import (
|
2023-05-25 15:52:03 -07:00
|
|
|
"context"
|
2021-11-04 11:44:22 -04:00
|
|
|
"fmt"
|
|
|
|
|
"sync"
|
|
|
|
|
|
2023-11-15 19:55:46 -05:00
|
|
|
"github.com/hashicorp/boundary/globals"
|
2022-05-09 12:45:10 -07:00
|
|
|
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
|
2023-05-25 15:52:03 -07:00
|
|
|
"github.com/hashicorp/boundary/internal/session"
|
2021-11-04 11:44:22 -04:00
|
|
|
"github.com/hashicorp/boundary/internal/target"
|
2022-04-13 16:27:48 -04:00
|
|
|
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets"
|
2021-11-04 11:44:22 -04:00
|
|
|
"google.golang.org/protobuf/proto"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Attributes represent the subtype specific request/response attributes.
|
|
|
|
|
type Attributes interface {
|
|
|
|
|
proto.Message
|
|
|
|
|
|
|
|
|
|
// Options create target.Options to be used to create a target.Target.
|
|
|
|
|
Options() []target.Option
|
2022-06-13 08:26:24 -07:00
|
|
|
|
2021-11-04 11:44:22 -04:00
|
|
|
// Vet validates the Attributes and returns a map of fields to error messages
|
|
|
|
|
// if any fields are invalid.
|
|
|
|
|
Vet() map[string]string
|
2022-06-13 08:26:24 -07:00
|
|
|
|
|
|
|
|
// VetForUpdate validates the Attributes for an updated resource with the
|
|
|
|
|
// provided mask paths and returns a map of fields to error messages if any
|
|
|
|
|
// fields are invalid.
|
|
|
|
|
VetForUpdate([]string) map[string]string
|
2021-11-04 11:44:22 -04:00
|
|
|
}
|
|
|
|
|
|
2022-10-25 18:29:38 -05:00
|
|
|
type attributeFunc func(any) Attributes
|
2022-04-13 16:27:48 -04:00
|
|
|
|
|
|
|
|
type setAttributeFunc func(target.Target, *pb.Target) error
|
2021-11-04 11:44:22 -04:00
|
|
|
|
2023-05-25 15:52:03 -07:00
|
|
|
// validateSessionStateFunc validates a session's state for the specific target
|
|
|
|
|
// type.
|
|
|
|
|
type validateSessionStateFunc func(context.Context, *session.Session) error
|
|
|
|
|
|
2021-11-04 11:44:22 -04:00
|
|
|
type registryEntry struct {
|
2023-05-25 15:52:03 -07:00
|
|
|
maskManager handlers.MaskManager
|
|
|
|
|
attrFunc attributeFunc
|
|
|
|
|
setAttrFunc setAttributeFunc
|
|
|
|
|
validateSessionStateFunc validateSessionStateFunc
|
2021-11-04 11:44:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type registry struct {
|
2022-10-25 21:33:31 -04:00
|
|
|
*sync.Map
|
2021-11-04 11:44:22 -04:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 19:55:46 -05:00
|
|
|
func (r registry) get(s globals.Subtype) (*registryEntry, error) {
|
2021-11-04 11:44:22 -04:00
|
|
|
v, ok := r.Load(s)
|
|
|
|
|
if !ok {
|
|
|
|
|
return nil, fmt.Errorf("subtype %q not registered", s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
re, ok := v.(*registryEntry)
|
|
|
|
|
if !ok {
|
|
|
|
|
return nil, fmt.Errorf("malformed registry subtypye %q registered as incorrect type %T", s, v)
|
|
|
|
|
}
|
|
|
|
|
return re, nil
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-15 19:55:46 -05:00
|
|
|
func (r registry) maskManager(s globals.Subtype) (handlers.MaskManager, error) {
|
2021-11-04 11:44:22 -04:00
|
|
|
re, err := r.get(s)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return re.maskManager, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// newAttribute creates an Attribute for the given subtype. It delegates the
|
|
|
|
|
// allocation of the Attribute to the registered attrFunc for the given
|
2022-04-13 16:27:48 -04:00
|
|
|
// subtype. An error is returned if the provided subtype is not registered
|
2023-11-15 19:55:46 -05:00
|
|
|
func (r registry) newAttribute(s globals.Subtype, m any) (Attributes, error) {
|
2021-11-04 11:44:22 -04:00
|
|
|
re, err := r.get(s)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-13 16:27:48 -04:00
|
|
|
attr := re.attrFunc(m)
|
|
|
|
|
|
|
|
|
|
return attr, nil
|
|
|
|
|
}
|
2021-11-04 11:44:22 -04:00
|
|
|
|
2022-04-13 16:27:48 -04:00
|
|
|
// setAttributes is used to set the Attrs field on a pb.Target. It delegates the
|
|
|
|
|
// 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.
|
2023-11-15 19:55:46 -05:00
|
|
|
func (r registry) setAttributes(s globals.Subtype, in target.Target, out *pb.Target) error {
|
2022-04-13 16:27:48 -04:00
|
|
|
re, err := r.get(s)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
2021-11-04 11:44:22 -04:00
|
|
|
}
|
|
|
|
|
|
2022-04-13 16:27:48 -04:00
|
|
|
return re.setAttrFunc(in, out)
|
2021-11-04 11:44:22 -04:00
|
|
|
}
|
|
|
|
|
|
2022-10-25 21:33:31 -04:00
|
|
|
var subtypeRegistry = registry{
|
|
|
|
|
Map: new(sync.Map),
|
|
|
|
|
}
|
2021-11-04 11:44:22 -04:00
|
|
|
|
|
|
|
|
// Register registers a subtype for used by the service handler.
|
2023-11-15 19:55:46 -05:00
|
|
|
func Register(s globals.Subtype, maskManager handlers.MaskManager, af attributeFunc, sf setAttributeFunc, vsf validateSessionStateFunc) {
|
2021-11-04 11:44:22 -04:00
|
|
|
if _, existed := subtypeRegistry.LoadOrStore(s, ®istryEntry{
|
2023-05-25 15:52:03 -07:00
|
|
|
maskManager: maskManager,
|
|
|
|
|
attrFunc: af,
|
|
|
|
|
setAttrFunc: sf,
|
|
|
|
|
validateSessionStateFunc: vsf,
|
2021-11-04 11:44:22 -04:00
|
|
|
}); existed {
|
|
|
|
|
panic(fmt.Sprintf("subtype %s already registered", s))
|
|
|
|
|
}
|
|
|
|
|
}
|