diff --git a/cmd/boundary/package_registry_oss.go b/cmd/boundary/package_registry_oss.go index 65616ff18..b43025f1c 100644 --- a/cmd/boundary/package_registry_oss.go +++ b/cmd/boundary/package_registry_oss.go @@ -2,5 +2,6 @@ package main import ( // Enable tcp target support. + _ "github.com/hashicorp/boundary/internal/servers/controller/handlers/targets/tcp" _ "github.com/hashicorp/boundary/internal/target/tcp" ) diff --git a/internal/cmd/commands/server/worker_shutdown_reload_test.go b/internal/cmd/commands/server/worker_shutdown_reload_test.go index 3699e693a..5c0b05e01 100644 --- a/internal/cmd/commands/server/worker_shutdown_reload_test.go +++ b/internal/cmd/commands/server/worker_shutdown_reload_test.go @@ -20,6 +20,8 @@ import ( "github.com/mitchellh/cli" "github.com/stretchr/testify/require" "go.uber.org/atomic" + + _ "github.com/hashicorp/boundary/internal/servers/controller/handlers/targets/tcp" ) const shutdownReloadApiAddr = "http://127.0.0.1:9203" diff --git a/internal/servers/controller/handlers/targets/options.go b/internal/servers/controller/handlers/targets/options.go new file mode 100644 index 000000000..887a2cff3 --- /dev/null +++ b/internal/servers/controller/handlers/targets/options.go @@ -0,0 +1,44 @@ +package targets + +import ( + "github.com/hashicorp/boundary/internal/target" + "google.golang.org/protobuf/types/known/structpb" +) + +func getOpts(opt ...option) options { + opts := getDefaultOptions() + for _, o := range opt { + o(&opts) + } + return opts +} + +// Option - how Options are passed as arguments +type option func(*options) + +// options = how options are represented +type options struct { + withTarget target.Target + withStruct *structpb.Struct +} + +func getDefaultOptions() options { + return options{ + withTarget: nil, + withStruct: nil, + } +} + +// withTarget provides an option to provide a target.Target. +func withTarget(t target.Target) option { + return func(o *options) { + o.withTarget = t + } +} + +// withStruct provides an option to provide a structpb.Struct. +func withStruct(s *structpb.Struct) option { + return func(o *options) { + o.withStruct = s + } +} diff --git a/internal/servers/controller/handlers/targets/registry.go b/internal/servers/controller/handlers/targets/registry.go new file mode 100644 index 000000000..61f279f31 --- /dev/null +++ b/internal/servers/controller/handlers/targets/registry.go @@ -0,0 +1,101 @@ +package targets + +import ( + "fmt" + "sync" + + "github.com/hashicorp/boundary/internal/servers/controller/handlers" + "github.com/hashicorp/boundary/internal/target" + "github.com/hashicorp/boundary/internal/types/subtypes" + "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 + // Vet validates the Attributes and returns a map of fields to error messages + // if any fields are invalid. + Vet() map[string]string +} + +type attributeFunc func(target.Target) Attributes + +type registryEntry struct { + maskManager handlers.MaskManager + attrFunc attributeFunc +} + +type registry struct { + sync.Map +} + +func (r registry) get(s subtypes.Subtype) (*registryEntry, error) { + 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 +} + +func (r registry) maskManager(s subtypes.Subtype) (handlers.MaskManager, error) { + 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 +// subtype. An error is returned if the provided subtype is not registered. It +// supports the options of: +// +// - withTarget: The Attribute will be initialized based on the given +// target.Target. This initialization is delegated to the attrFunc. +// +// - withStruct: The Attribute will be initialized based on the given +// structpb.Struct. This is *not* delegated. +// +// These two options are mutually exclusive. If both are provided, and error is returned. +// If no options are provided an empty Attribute will be returned. +func (r registry) newAttribute(s subtypes.Subtype, opt ...option) (Attributes, error) { + re, err := r.get(s) + if err != nil { + return nil, err + } + + opts := getOpts(opt...) + if opts.withTarget != nil && opts.withStruct != nil { + return nil, fmt.Errorf("cannot use both withTarget and withStruct") + } + + attr := re.attrFunc(opts.withTarget) + if opts.withStruct != nil { + if err := handlers.StructToProto(opts.withStruct, attr); err != nil { + return nil, fmt.Errorf("Provided attributes don't match expected format.") + } + } + + return attr, nil +} + +var subtypeRegistry = registry{} + +// Register registers a subtype for used by the service handler. +func Register(s subtypes.Subtype, maskManager handlers.MaskManager, af attributeFunc) { + if _, existed := subtypeRegistry.LoadOrStore(s, ®istryEntry{ + maskManager: maskManager, + attrFunc: af, + }); existed { + panic(fmt.Sprintf("subtype %s already registered", s)) + } +} diff --git a/internal/servers/controller/handlers/targets/target_service.go b/internal/servers/controller/handlers/targets/target_service.go index ee01be7b3..2d9da18b5 100644 --- a/internal/servers/controller/handlers/targets/target_service.go +++ b/internal/servers/controller/handlers/targets/target_service.go @@ -10,7 +10,6 @@ import ( "net/url" "strings" - "github.com/golang/protobuf/ptypes/wrappers" "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/credential" "github.com/hashicorp/boundary/internal/credential/vault" @@ -30,8 +29,6 @@ import ( "github.com/hashicorp/boundary/internal/servers/controller/handlers" "github.com/hashicorp/boundary/internal/session" "github.com/hashicorp/boundary/internal/target" - "github.com/hashicorp/boundary/internal/target/tcp" - tcpStore "github.com/hashicorp/boundary/internal/target/tcp/store" "github.com/hashicorp/boundary/internal/types/action" "github.com/hashicorp/boundary/internal/types/resource" "github.com/hashicorp/boundary/internal/types/scope" @@ -48,8 +45,6 @@ import ( ) var ( - maskManager handlers.MaskManager - // IdActions contains the set of actions that can be performed on // individual resources IdActions = action.ActionSet{ @@ -77,16 +72,6 @@ var ( } ) -func init() { - var err error - if maskManager, err = handlers.NewMaskManager( - handlers.MaskDestination{&tcpStore.Target{}}, - handlers.MaskSource{&pb.Target{}, &pb.TcpTargetAttributes{}}, - ); err != nil { - panic(err) - } -} - // Service handles request as described by the pbs.TargetServiceServer interface. type Service struct { pbs.UnimplementedTargetServiceServer @@ -1191,14 +1176,14 @@ func (s Service) createInRepo(ctx context.Context, item *pb.Target) (target.Targ if item.GetWorkerFilter() != nil { opts = append(opts, target.WithWorkerFilter(item.GetWorkerFilter().GetValue())) } - tcpAttrs := &pb.TcpTargetAttributes{} - if err := handlers.StructToProto(item.GetAttributes(), tcpAttrs); err != nil { - return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.InvalidArgument, "Provided attributes don't match expected format.") + + attr, err := subtypeRegistry.newAttribute(target.SubtypeFromType(item.GetType()), withStruct(item.GetAttributes())) + if err != nil { + return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.InvalidArgument, err.Error()) } - if tcpAttrs.GetDefaultPort().GetValue() != 0 { - opts = append(opts, target.WithDefaultPort(tcpAttrs.GetDefaultPort().GetValue())) - } - u, err := tcp.New(item.GetScopeId(), opts...) + opts = append(opts, attr.Options()...) + + u, err := target.New(ctx, target.SubtypeFromType(item.GetType()), item.GetScopeId(), opts...) if err != nil { return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to build target for creation: %v.", err) } @@ -1234,19 +1219,28 @@ func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []st if filter := item.GetWorkerFilter(); filter != nil { opts = append(opts, target.WithWorkerFilter(item.GetWorkerFilter().GetValue())) } - tcpAttrs := &pb.TcpTargetAttributes{} - if err := handlers.StructToProto(item.GetAttributes(), tcpAttrs); err != nil { - return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.InvalidArgument, "Provided attributes don't match expected format.") - } - if tcpAttrs.GetDefaultPort().GetValue() != 0 { - opts = append(opts, target.WithDefaultPort(tcpAttrs.GetDefaultPort().GetValue())) + subtype := target.SubtypeFromId(id) + + attr, err := subtypeRegistry.newAttribute(subtype, withStruct(item.GetAttributes())) + if err != nil { + return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.InvalidArgument, err.Error()) } + + opts = append(opts, attr.Options()...) + version := item.GetVersion() - u, err := tcp.New(scopeId, opts...) + + u, err := target.New(ctx, subtype, scopeId, opts...) if err != nil { return nil, nil, nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to build target for update: %v.", err) } - u.PublicId = id + u.SetPublicId(ctx, id) + + maskManager, err := subtypeRegistry.maskManager(subtype) + if err != nil { + return nil, nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to update target")) + } + dbMask := maskManager.Translate(mask) if len(dbMask) == 0 { return nil, nil, nil, handlers.InvalidArgumentErrorf("No valid fields included in the update mask.", map[string]string{"update_mask": "No valid paths provided in the update mask."}) @@ -1595,11 +1589,12 @@ func toProto(ctx context.Context, in target.Target, hostSources []target.HostSou } } if outputFields.Has(globals.AttributesField) { - attrs := &pb.TcpTargetAttributes{} - if in.GetDefaultPort() > 0 { - attrs.DefaultPort = &wrappers.UInt32Value{Value: in.GetDefaultPort()} + attr, err := subtypeRegistry.newAttribute(in.GetType(), withTarget(in)) + if err != nil { + return nil, errors.Wrap(ctx, err, op) } - st, err := handlers.ProtoToStruct(attrs) + + st, err := handlers.ProtoToStruct(attr) if err != nil { return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "failed building password attribute struct: %v", err) } @@ -1614,7 +1609,7 @@ func toProto(ctx context.Context, in target.Target, hostSources []target.HostSou // * All required parameters are set // * There are no conflicting parameters provided func validateGetRequest(req *pbs.GetTargetRequest) error { - return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, tcp.TargetPrefix) + return handlers.ValidateGetRequest(handlers.NoopValidatorFn, req, target.Prefixes()...) } func validateCreateRequest(req *pbs.CreateTargetRequest) error { @@ -1638,16 +1633,6 @@ func validateCreateRequest(req *pbs.CreateTargetRequest) error { if req.GetItem().GetSessionMaxSeconds() != nil && req.GetItem().GetSessionMaxSeconds().GetValue() == 0 { badFields[globals.SessionMaxSecondsField] = "This must be greater than zero." } - switch target.SubtypeFromType(req.GetItem().GetType()) { - case tcp.Subtype: - tcpAttrs := &pb.TcpTargetAttributes{} - if err := handlers.StructToProto(req.GetItem().GetAttributes(), tcpAttrs); err != nil { - badFields[globals.AttributesField] = "Attribute fields do not match the expected format." - } - if tcpAttrs.GetDefaultPort() != nil && tcpAttrs.GetDefaultPort().GetValue() == 0 { - badFields["attributes.default_port"] = "This optional field cannot be set to 0." - } - } if req.GetItem().GetType() == "" { badFields[globals.TypeField] = "This is a required field." } else if target.SubtypeFromType(req.GetItem().GetType()) == "" { @@ -1658,6 +1643,21 @@ func validateCreateRequest(req *pbs.CreateTargetRequest) error { badFields[globals.WorkerFilterField] = "Unable to successfully parse filter expression." } } + + subtype := target.SubtypeFromType(req.GetItem().GetType()) + _, err := subtypeRegistry.get(subtype) + if err != nil { + badFields[globals.TypeField] = "Unknown type provided." + } else { + a, err := subtypeRegistry.newAttribute(subtype, withStruct(req.GetItem().GetAttributes())) + if err != nil { + badFields[globals.AttributesField] = "Attribute fields do not match the expected format." + } else { + for k, v := range a.Vet() { + badFields[k] = v + } + } + } return badFields }) } @@ -1680,30 +1680,35 @@ func validateUpdateRequest(req *pbs.UpdateTargetRequest) error { if req.GetItem().GetSessionMaxSeconds() != nil && req.GetItem().GetSessionMaxSeconds().GetValue() == 0 { badFields[globals.SessionMaxSecondsField] = "This must be greater than zero." } - switch target.SubtypeFromId(req.GetItem().GetType()) { - case tcp.Subtype: - if req.GetItem().GetType() != "" && target.SubtypeFromType(req.GetItem().GetType()) != tcp.Subtype { - badFields[globals.TypeField] = "Cannot modify the resource type." - } - tcpAttrs := &pb.TcpTargetAttributes{} - if err := handlers.StructToProto(req.GetItem().GetAttributes(), tcpAttrs); err != nil { - badFields[globals.AttributesField] = "Attribute fields do not match the expected format." - } - if tcpAttrs.GetDefaultPort() != nil && tcpAttrs.GetDefaultPort().GetValue() == 0 { - badFields["attributes.default_port"] = "This optional field cannot be set to 0." - } - } if filter := req.GetItem().GetWorkerFilter(); filter != nil { if _, err := bexpr.CreateEvaluator(filter.GetValue()); err != nil { badFields[globals.WorkerFilterField] = "Unable to successfully parse filter expression." } } + subtype := target.SubtypeFromId(req.GetId()) + _, err := subtypeRegistry.get(subtype) + if err != nil { + badFields[globals.TypeField] = "Unknown type provided." + } else { + if req.GetItem().GetType() != "" && target.SubtypeFromType(req.GetItem().GetType()) != subtype { + badFields[globals.TypeField] = "Cannot modify the resource type." + } + + a, err := subtypeRegistry.newAttribute(subtype, withStruct(req.GetItem().GetAttributes())) + if err != nil { + badFields[globals.AttributesField] = "Attribute fields do not match the expected format." + } else { + for k, v := range a.Vet() { + badFields[k] = v + } + } + } return badFields - }, tcp.TargetPrefix) + }, target.Prefixes()...) } func validateDeleteRequest(req *pbs.DeleteTargetRequest) error { - return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, tcp.TargetPrefix) + return handlers.ValidateDeleteRequest(handlers.NoopValidatorFn, req, target.Prefixes()...) } func validateListRequest(req *pbs.ListTargetsRequest) error { @@ -1723,7 +1728,7 @@ func validateListRequest(req *pbs.ListTargetsRequest) error { func validateAddSetsRequest(req *pbs.AddTargetHostSetsRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1747,7 +1752,7 @@ func validateAddSetsRequest(req *pbs.AddTargetHostSetsRequest) error { func validateSetSetsRequest(req *pbs.SetTargetHostSetsRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1768,7 +1773,7 @@ func validateSetSetsRequest(req *pbs.SetTargetHostSetsRequest) error { func validateRemoveSetsRequest(req *pbs.RemoveTargetHostSetsRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1792,7 +1797,7 @@ func validateRemoveSetsRequest(req *pbs.RemoveTargetHostSetsRequest) error { func validateAddHostSourcesRequest(req *pbs.AddTargetHostSourcesRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1816,7 +1821,7 @@ func validateAddHostSourcesRequest(req *pbs.AddTargetHostSourcesRequest) error { func validateSetHostSourcesRequest(req *pbs.SetTargetHostSourcesRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1837,7 +1842,7 @@ func validateSetHostSourcesRequest(req *pbs.SetTargetHostSourcesRequest) error { func validateRemoveHostSourcesRequest(req *pbs.RemoveTargetHostSourcesRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1861,7 +1866,7 @@ func validateRemoveHostSourcesRequest(req *pbs.RemoveTargetHostSourcesRequest) e func validateAddLibrariesRequest(req *pbs.AddTargetCredentialLibrariesRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1884,7 +1889,7 @@ func validateAddLibrariesRequest(req *pbs.AddTargetCredentialLibrariesRequest) e func validateSetLibrariesRequest(req *pbs.SetTargetCredentialLibrariesRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1904,7 +1909,7 @@ func validateSetLibrariesRequest(req *pbs.SetTargetCredentialLibrariesRequest) e func validateRemoveLibrariesRequest(req *pbs.RemoveTargetCredentialLibrariesRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1927,7 +1932,7 @@ func validateRemoveLibrariesRequest(req *pbs.RemoveTargetCredentialLibrariesRequ func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1957,7 +1962,7 @@ func validateAddCredentialSourcesRequest(req *pbs.AddTargetCredentialSourcesRequ func validateSetCredentialSourcesRequest(req *pbs.SetTargetCredentialSourcesRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -1983,7 +1988,7 @@ func validateSetCredentialSourcesRequest(req *pbs.SetTargetCredentialSourcesRequ func validateRemoveCredentialSourcesRequest(req *pbs.RemoveTargetCredentialSourcesRequest) error { badFields := map[string]string{} - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if req.GetVersion() == 0 { @@ -2017,7 +2022,7 @@ func validateAuthorizeSessionRequest(req *pbs.AuthorizeSessionRequest) error { scopeIdEmpty := req.GetScopeId() == "" scopeNameEmpty := req.GetScopeName() == "" if nameEmpty { - if !handlers.ValidId(handlers.Id(req.GetId()), tcp.TargetPrefix) { + if !handlers.ValidId(handlers.Id(req.GetId()), target.Prefixes()...) { badFields[globals.IdField] = "Incorrectly formatted identifier." } if !scopeIdEmpty { diff --git a/internal/servers/controller/handlers/targets/target_service_test.go b/internal/servers/controller/handlers/targets/tcp/target_service_test.go similarity index 88% rename from internal/servers/controller/handlers/targets/target_service_test.go rename to internal/servers/controller/handlers/targets/tcp/target_service_test.go index 33c278252..15963bfa4 100644 --- a/internal/servers/controller/handlers/targets/target_service_test.go +++ b/internal/servers/controller/handlers/targets/tcp/target_service_test.go @@ -1,4 +1,4 @@ -package targets_test +package tcp_test import ( "context" @@ -53,6 +53,8 @@ import ( "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/wrapperspb" + + _ "github.com/hashicorp/boundary/internal/servers/controller/handlers/targets/tcp" ) var testAuthorizedActions = []string{ @@ -115,14 +117,15 @@ func TestGet(t *testing.T) { hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0] hs := static.TestSets(t, conn, hc.GetPublicId(), 2) - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})) + ctx := context.Background() + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})) pTar := &pb.Target{ Id: tar.GetPublicId(), ScopeId: proj.GetPublicId(), Name: wrapperspb.String("test"), - CreatedTime: tar.CreateTime.GetTimestamp(), - UpdatedTime: tar.UpdateTime.GetTimestamp(), + CreatedTime: tar.GetCreateTime().GetTimestamp(), + UpdatedTime: tar.GetUpdateTime().GetTimestamp(), Scope: &scopes.ScopeInfo{Id: proj.GetPublicId(), Type: scope.Project.String(), ParentScopeId: o.GetPublicId()}, Type: tcp.Subtype.String(), HostSetIds: []string{hs[0].GetPublicId(), hs[1].GetPublicId()}, @@ -205,12 +208,13 @@ func TestList(t *testing.T) { otherHc := static.TestCatalogs(t, conn, otherProj.GetPublicId(), 1)[0] hss := static.TestSets(t, conn, hc.GetPublicId(), 2) otherHss := static.TestSets(t, conn, otherHc.GetPublicId(), 2) + ctx := context.Background() var wantTars []*pb.Target var totalTars []*pb.Target for i := 0; i < 5; i++ { name := fmt.Sprintf("tar%d", i) - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), name, target.WithHostSources([]string{hss[0].GetPublicId(), hss[1].GetPublicId()})) + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), name, target.WithHostSources([]string{hss[0].GetPublicId(), hss[1].GetPublicId()})) wantTars = append(wantTars, &pb.Target{ Id: tar.GetPublicId(), ScopeId: proj.GetPublicId(), @@ -226,7 +230,7 @@ func TestList(t *testing.T) { AuthorizedActions: testAuthorizedActions, }) totalTars = append(totalTars, wantTars[i]) - tar = tcp.TestTarget(t, conn, otherProj.GetPublicId(), name, target.WithHostSources([]string{otherHss[0].GetPublicId(), otherHss[1].GetPublicId()})) + tar = tcp.TestTarget(ctx, t, conn, otherProj.GetPublicId(), name, target.WithHostSources([]string{otherHss[0].GetPublicId(), otherHss[1].GetPublicId()})) totalTars = append(totalTars, &pb.Target{ Id: tar.GetPublicId(), ScopeId: otherProj.GetPublicId(), @@ -333,8 +337,9 @@ func TestDelete(t *testing.T) { return iamRepo, nil } + ctx := context.Background() _, proj := iam.TestScopes(t, iamRepo) - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test") s, err := testService(t, conn, kms, wrapper) require.NoError(t, err, "Couldn't create a new target service.") @@ -390,6 +395,7 @@ func TestDelete_twice(t *testing.T) { wrapper := db.TestWrapper(t) kms := kms.TestKms(t, conn, wrapper) + ctx := context.Background() iamRepo := iam.TestRepo(t, conn, wrapper) iamRepoFn := func() (*iam.Repository, error) { return iamRepo, nil @@ -397,14 +403,14 @@ func TestDelete_twice(t *testing.T) { _, proj := iam.TestScopes(t, iamRepo) - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test") s, err := testService(t, conn, kms, wrapper) require.NoError(err, "Couldn't create a new target service.") req := &pbs.DeleteTargetRequest{ Id: tar.GetPublicId(), } - ctx := auth.DisabledAuthTestContext(iamRepoFn, proj.GetPublicId()) + ctx = auth.DisabledAuthTestContext(iamRepoFn, proj.GetPublicId()) _, gErr := s.DeleteTarget(ctx, req) assert.NoError(gErr, "First attempt") _, gErr = s.DeleteTarget(ctx, req) @@ -588,7 +594,10 @@ func TestUpdate(t *testing.T) { {Id: hs[1].GetPublicId(), HostCatalogId: hs[1].GetCatalogId()}, } - tar, err := tcp.New(proj.GetPublicId(), target.WithName("default"), target.WithDescription("default")) + ctx := context.Background() + ttar, err := target.New(ctx, tcp.Subtype, proj.GetPublicId(), target.WithName("default"), target.WithDescription("default")) + require.NoError(t, err) + tar := ttar.(*tcp.Target) tar.DefaultPort = 2 require.NoError(t, err) gtar, _, _, err := repo.CreateTarget(context.Background(), tar) @@ -958,7 +967,9 @@ func TestUpdate_BadVersion(t *testing.T) { repo, err := repoFn() require.NoError(t, err, "Couldn't create new target repo.") - tar, err := tcp.New(proj.GetPublicId(), target.WithName("default"), target.WithDescription("default")) + ctx := context.Background() + ttar, err := target.New(ctx, tcp.Subtype, proj.GetPublicId(), target.WithName("default"), target.WithDescription("default")) + tar := ttar.(*tcp.Target) tar.DefaultPort = 2 require.NoError(t, err) gtar, _, _, err := repo.CreateTarget(context.Background(), tar) @@ -1004,40 +1015,41 @@ func TestAddTargetHostSets(t *testing.T) { pluginHs := plugin.TestSet(t, conn, kms, sche, pluginHc, map[string]plgpb.HostPluginServiceClient{ plg.GetPublicId(): plugin.NewWrappingPluginClient(&plugin.TestPluginServer{}), }) + ctx := context.Background() addCases := []struct { name string - tar *tcp.Target + tar target.Target addHostSets []string resultHostSets []string }{ { name: "Add set on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty"), addHostSets: []string{hs[1].GetPublicId()}, resultHostSets: []string{hs[1].GetPublicId()}, }, { name: "Add set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "populated", target.WithHostSources([]string{hs[0].GetPublicId()})), addHostSets: []string{hs[1].GetPublicId()}, resultHostSets: []string{hs[0].GetPublicId(), hs[1].GetPublicId()}, }, { name: "Add duplicated sets on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "duplicated", target.WithHostSources([]string{hs[0].GetPublicId()})), addHostSets: []string{hs[1].GetPublicId(), hs[1].GetPublicId()}, resultHostSets: []string{hs[0].GetPublicId(), hs[1].GetPublicId()}, }, { name: "Add plugin set on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "plugin empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "plugin empty"), addHostSets: []string{pluginHs.GetPublicId()}, resultHostSets: []string{pluginHs.GetPublicId()}, }, { name: "Add plugin set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "plugin populated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "plugin populated", target.WithHostSources([]string{hs[0].GetPublicId()})), addHostSets: []string{pluginHs.GetPublicId()}, resultHostSets: []string{hs[0].GetPublicId(), pluginHs.GetPublicId()}, }, @@ -1060,7 +1072,7 @@ func TestAddTargetHostSets(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test") failCases := []struct { name string @@ -1140,45 +1152,46 @@ func TestSetTargetHostSets(t *testing.T) { plg.GetPublicId(): plugin.NewWrappingPluginClient(&plugin.TestPluginServer{}), }) + ctx := context.Background() setCases := []struct { name string - tar *tcp.Target + tar target.Target setHostSets []string resultHostSets []string }{ { name: "Set on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty"), setHostSets: []string{hs[1].GetPublicId()}, resultHostSets: []string{hs[1].GetPublicId()}, }, { name: "Set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "populated", target.WithHostSources([]string{hs[0].GetPublicId()})), setHostSets: []string{hs[1].GetPublicId()}, resultHostSets: []string{hs[1].GetPublicId()}, }, { name: "Set duplicate host set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "duplicate", target.WithHostSources([]string{hs[0].GetPublicId()})), setHostSets: []string{hs[1].GetPublicId(), hs[1].GetPublicId()}, resultHostSets: []string{hs[1].GetPublicId()}, }, { name: "Set empty on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "another populated", target.WithHostSources([]string{hs[0].GetPublicId()})), setHostSets: []string{}, resultHostSets: nil, }, { name: "Set plugin set on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "plugin empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "plugin empty"), setHostSets: []string{pluginHs.GetPublicId()}, resultHostSets: []string{pluginHs.GetPublicId()}, }, { name: "Set plugin set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "plugin populated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "plugin populated", target.WithHostSources([]string{hs[0].GetPublicId()})), setHostSets: []string{pluginHs.GetPublicId()}, resultHostSets: []string{pluginHs.GetPublicId()}, }, @@ -1197,7 +1210,7 @@ func TestSetTargetHostSets(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test name") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test name") failCases := []struct { name string @@ -1269,40 +1282,41 @@ func TestRemoveTargetHostSets(t *testing.T) { plg.GetPublicId(): plugin.NewWrappingPluginClient(&plugin.TestPluginServer{}), }) + ctx := context.Background() removeCases := []struct { name string - tar *tcp.Target + tar target.Target removeHosts []string resultHosts []string wantErr bool }{ { name: "Remove from empty", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty"), removeHosts: []string{hs[1].GetPublicId()}, wantErr: true, }, { name: "Remove 1 of 2 sets", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove partial", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), removeHosts: []string{hs[1].GetPublicId()}, resultHosts: []string{hs[0].GetPublicId()}, }, { name: "Remove 1 duplicate set of 2 sets", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove duplicate", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), removeHosts: []string{hs[1].GetPublicId(), hs[1].GetPublicId()}, resultHosts: []string{hs[0].GetPublicId()}, }, { name: "Remove all hosts from set", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove all", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), removeHosts: []string{hs[0].GetPublicId(), hs[1].GetPublicId()}, resultHosts: []string{}, }, { name: "Remove 1 plugin of 2 sets", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove plugin partial", target.WithHostSources([]string{hs[0].GetPublicId(), pluginHs.GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove plugin partial", target.WithHostSources([]string{hs[0].GetPublicId(), pluginHs.GetPublicId()})), removeHosts: []string{pluginHs.GetPublicId()}, resultHosts: []string{hs[0].GetPublicId()}, }, @@ -1329,7 +1343,7 @@ func TestRemoveTargetHostSets(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "testing") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "testing") failCases := []struct { name string @@ -1410,39 +1424,40 @@ func TestAddTargetHostSources(t *testing.T) { plg.GetPublicId(): plugin.NewWrappingPluginClient(&plugin.TestPluginServer{}), }) + ctx := context.Background() addCases := []struct { name string - tar *tcp.Target + tar target.Target addHostSources []string resultHostSources []string }{ { name: "Add set on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty"), addHostSources: []string{hs[1].GetPublicId()}, resultHostSources: []string{hs[1].GetPublicId()}, }, { name: "Add set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "populated", target.WithHostSources([]string{hs[0].GetPublicId()})), addHostSources: []string{hs[1].GetPublicId()}, resultHostSources: []string{hs[0].GetPublicId(), hs[1].GetPublicId()}, }, { name: "Add duplicated sets on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "duplicated", target.WithHostSources([]string{hs[0].GetPublicId()})), addHostSources: []string{hs[1].GetPublicId(), hs[1].GetPublicId()}, resultHostSources: []string{hs[0].GetPublicId(), hs[1].GetPublicId()}, }, { name: "Add plugin set on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "plugin empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "plugin empty"), addHostSources: []string{pluginHs.GetPublicId()}, resultHostSources: []string{pluginHs.GetPublicId()}, }, { name: "Add plugin set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "plugin populated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "plugin populated", target.WithHostSources([]string{hs[0].GetPublicId()})), addHostSources: []string{pluginHs.GetPublicId()}, resultHostSources: []string{hs[0].GetPublicId(), pluginHs.GetPublicId()}, }, @@ -1465,7 +1480,7 @@ func TestAddTargetHostSources(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test") failCases := []struct { name string @@ -1545,39 +1560,40 @@ func TestSetTargetHostSources(t *testing.T) { plg.GetPublicId(): plugin.NewWrappingPluginClient(&plugin.TestPluginServer{}), }) + ctx := context.Background() setCases := []struct { name string - tar *tcp.Target + tar target.Target setHostSources []string resultHostSources []string }{ { name: "Set on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty"), setHostSources: []string{hs[1].GetPublicId()}, resultHostSources: []string{hs[1].GetPublicId()}, }, { name: "Set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "populated", target.WithHostSources([]string{hs[0].GetPublicId()})), setHostSources: []string{hs[1].GetPublicId()}, resultHostSources: []string{hs[1].GetPublicId()}, }, { name: "Set plugin set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "plugin populated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "plugin populated", target.WithHostSources([]string{hs[0].GetPublicId()})), setHostSources: []string{pluginHs.GetPublicId()}, resultHostSources: []string{pluginHs.GetPublicId()}, }, { name: "Set duplicate host set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "duplicate", target.WithHostSources([]string{hs[0].GetPublicId()})), setHostSources: []string{hs[1].GetPublicId(), hs[1].GetPublicId()}, resultHostSources: []string{hs[1].GetPublicId()}, }, { name: "Set empty on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithHostSources([]string{hs[0].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "another populated", target.WithHostSources([]string{hs[0].GetPublicId()})), setHostSources: []string{}, resultHostSources: nil, }, @@ -1596,7 +1612,7 @@ func TestSetTargetHostSources(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test name") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test name") failCases := []struct { name string @@ -1668,40 +1684,41 @@ func TestRemoveTargetHostSources(t *testing.T) { plg.GetPublicId(): plugin.NewWrappingPluginClient(&plugin.TestPluginServer{}), }) + ctx := context.Background() removeCases := []struct { name string - tar *tcp.Target + tar target.Target removeHostSources []string resultHostSources []string wantErr bool }{ { name: "Remove from empty", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty"), removeHostSources: []string{hs[1].GetPublicId()}, wantErr: true, }, { name: "Remove 1 of 2 sets", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove partial", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), removeHostSources: []string{hs[1].GetPublicId()}, resultHostSources: []string{hs[0].GetPublicId()}, }, { name: "Remove 1 plugin set of 2 sets", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove plugin partial", target.WithHostSources([]string{hs[0].GetPublicId(), pluginHs.GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove plugin partial", target.WithHostSources([]string{hs[0].GetPublicId(), pluginHs.GetPublicId()})), removeHostSources: []string{pluginHs.GetPublicId()}, resultHostSources: []string{hs[0].GetPublicId()}, }, { name: "Remove 1 duplicate set of 2 sets", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove duplicate", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), removeHostSources: []string{hs[1].GetPublicId(), hs[1].GetPublicId()}, resultHostSources: []string{hs[0].GetPublicId()}, }, { name: "Remove all hosts from set", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove all", target.WithHostSources([]string{hs[0].GetPublicId(), hs[1].GetPublicId()})), removeHostSources: []string{hs[0].GetPublicId(), hs[1].GetPublicId()}, resultHostSources: []string{}, }, @@ -1728,7 +1745,7 @@ func TestRemoveTargetHostSources(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "testing") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "testing") failCases := []struct { name string @@ -1802,27 +1819,28 @@ func TestAddTargetLibraries(t *testing.T) { store := vault.TestCredentialStores(t, conn, wrapper, proj.GetPublicId(), 1)[0] cls := vault.TestCredentialLibraries(t, conn, wrapper, store.GetPublicId(), 2) + ctx := context.Background() addCases := []struct { name string - tar *tcp.Target + tar target.Target addLibraries []string resultLibraryIds []string }{ { name: "Add library on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty for libraries"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty for libraries"), addLibraries: []string{cls[1].GetPublicId()}, resultLibraryIds: []string{cls[1].GetPublicId()}, }, { name: "Add library on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated for libraries", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "populated for libraries", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), addLibraries: []string{cls[1].GetPublicId()}, resultLibraryIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()}, }, { name: "Add duplicated libraries on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated for libraries", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "duplicated for libraries", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), addLibraries: []string{cls[1].GetPublicId(), cls[1].GetPublicId()}, resultLibraryIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()}, }, @@ -1853,7 +1871,7 @@ func TestAddTargetLibraries(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test") failCases := []struct { name string @@ -1937,34 +1955,35 @@ func TestSetTargetLibraries(t *testing.T) { } } + ctx := context.Background() setCases := []struct { name string - tar *tcp.Target + tar target.Target setLibraries []string resultLibraryIds []string resultLibraries []*pb.CredentialLibrary }{ { name: "Set on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty"), setLibraries: []string{cls[1].GetPublicId()}, resultLibraryIds: []string{cls[1].GetPublicId()}, }, { name: "Set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), setLibraries: []string{cls[1].GetPublicId()}, resultLibraryIds: []string{cls[1].GetPublicId()}, }, { name: "Set duplicate libraries on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), setLibraries: []string{cls[1].GetPublicId(), cls[1].GetPublicId()}, resultLibraryIds: []string{cls[1].GetPublicId()}, }, { name: "Set empty on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "another populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), setLibraries: []string{}, resultLibraryIds: nil, }, @@ -1998,7 +2017,7 @@ func TestSetTargetLibraries(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test name") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test name") failCases := []struct { name string @@ -2063,28 +2082,29 @@ func TestRemoveTargetLibraries(t *testing.T) { store := vault.TestCredentialStores(t, conn, wrapper, proj.GetPublicId(), 1)[0] cls := vault.TestCredentialLibraries(t, conn, wrapper, store.GetPublicId(), 2) + ctx := context.Background() removeCases := []struct { name string - tar *tcp.Target + tar target.Target removeLibs []string resultLibIds []string wantErr bool }{ { name: "Remove from empty", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty"), removeLibs: []string{cls[1].GetPublicId()}, wantErr: true, }, { name: "Remove 1 of 2 libraries", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), removeLibs: []string{cls[1].GetPublicId()}, resultLibIds: []string{cls[0].GetPublicId()}, }, { name: "Remove 1 duplicate set of 2 libraries", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), removeLibs: []string{ cls[1].GetPublicId(), cls[1].GetPublicId(), }, @@ -2092,7 +2112,7 @@ func TestRemoveTargetLibraries(t *testing.T) { }, { name: "Remove all libraries from target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove all", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), removeLibs: []string{ cls[0].GetPublicId(), cls[1].GetPublicId(), }, @@ -2119,7 +2139,7 @@ func TestRemoveTargetLibraries(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "testing") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "testing") failCases := []struct { name string @@ -2199,27 +2219,28 @@ func TestAddTargetSources(t *testing.T) { store := vault.TestCredentialStores(t, conn, wrapper, proj.GetPublicId(), 1)[0] cls := vault.TestCredentialLibraries(t, conn, wrapper, store.GetPublicId(), 2) + ctx := context.Background() addCases := []struct { name string - tar *tcp.Target + tar target.Target addSources []string resultSourceIds []string }{ { name: "Add source on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty for sources"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty for sources"), addSources: []string{cls[1].GetPublicId()}, resultSourceIds: []string{cls[1].GetPublicId()}, }, { name: "Add source on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated for sources", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "populated for sources", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), addSources: []string{cls[1].GetPublicId()}, resultSourceIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()}, }, { name: "Add duplicated sources on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicated for sources", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "duplicated for sources", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), addSources: []string{cls[1].GetPublicId(), cls[1].GetPublicId()}, resultSourceIds: []string{cls[0].GetPublicId(), cls[1].GetPublicId()}, }, @@ -2250,7 +2271,7 @@ func TestAddTargetSources(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test") failCases := []struct { name string @@ -2334,34 +2355,35 @@ func TestSetTargetCredentialSources(t *testing.T) { } } + ctx := context.Background() setCases := []struct { name string - tar *tcp.Target + tar target.Target setCredentialSources []string resultCredentialSourceIds []string resultCredentialSources []*pb.CredentialLibrary }{ { name: "Set on empty target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty"), setCredentialSources: []string{cls[1].GetPublicId()}, resultCredentialSourceIds: []string{cls[1].GetPublicId()}, }, { name: "Set on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), setCredentialSources: []string{cls[1].GetPublicId()}, resultCredentialSourceIds: []string{cls[1].GetPublicId()}, }, { name: "Set duplicate sources on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), setCredentialSources: []string{cls[1].GetPublicId(), cls[1].GetPublicId()}, resultCredentialSourceIds: []string{cls[1].GetPublicId()}, }, { name: "Set empty on populated target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "another populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "another populated", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose)})), setCredentialSources: []string{}, resultCredentialSourceIds: nil, }, @@ -2395,7 +2417,7 @@ func TestSetTargetCredentialSources(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "test name") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "test name") failCases := []struct { name string @@ -2460,28 +2482,29 @@ func TestRemoveTargetCredentialSources(t *testing.T) { store := vault.TestCredentialStores(t, conn, wrapper, proj.GetPublicId(), 1)[0] cls := vault.TestCredentialLibraries(t, conn, wrapper, store.GetPublicId(), 2) + ctx := context.Background() removeCases := []struct { name string - tar *tcp.Target + tar target.Target removeCredentialSources []string resultCredentialSourceIds []string wantErr bool }{ { name: "Remove from empty", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "empty"), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "empty"), removeCredentialSources: []string{cls[1].GetPublicId()}, wantErr: true, }, { name: "Remove 1 of 2 sources", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove partial", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), removeCredentialSources: []string{cls[1].GetPublicId()}, resultCredentialSourceIds: []string{cls[0].GetPublicId()}, }, { name: "Remove 1 duplicate set of 2 sources", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove duplicate", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), removeCredentialSources: []string{ cls[1].GetPublicId(), cls[1].GetPublicId(), }, @@ -2489,7 +2512,7 @@ func TestRemoveTargetCredentialSources(t *testing.T) { }, { name: "Remove all sources from target", - tar: tcp.TestTarget(t, conn, proj.GetPublicId(), "remove all", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), + tar: tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "remove all", target.WithCredentialLibraries([]*target.CredentialLibrary{target.TestNewCredentialLibrary("", cls[0].GetPublicId(), credential.ApplicationPurpose), target.TestNewCredentialLibrary("", cls[1].GetPublicId(), credential.ApplicationPurpose)})), removeCredentialSources: []string{ cls[0].GetPublicId(), cls[1].GetPublicId(), }, @@ -2516,7 +2539,7 @@ func TestRemoveTargetCredentialSources(t *testing.T) { }) } - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), "testing") + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), "testing") failCases := []struct { name string @@ -2714,7 +2737,7 @@ func TestAuthorizeSession(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), tc.name) + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), tc.name) apiTar, err := s.AddTargetHostSets(ctx, &pbs.AddTargetHostSetsRequest{ Id: tar.GetPublicId(), Version: tar.GetVersion(), @@ -2878,7 +2901,7 @@ func TestAuthorizeSession_Errors(t *testing.T) { sec, tok := v.CreateToken(t, vault.WithPolicies([]string{"default", "database"})) store := vault.TestCredentialStore(t, conn, wrapper, proj.GetPublicId(), v.Addr, tok, sec.Auth.Accessor) - workerExists := func(tar *tcp.Target) (version uint32) { + workerExists := func(tar target.Target) (version uint32) { workerService := workers.NewWorkerServiceServer(serversRepoFn, sessionRepoFn, &sync.Map{}, kms) _, err := workerService.Status(context.Background(), &spbs.StatusRequest{ Worker: &spb.Server{ @@ -2890,7 +2913,7 @@ func TestAuthorizeSession_Errors(t *testing.T) { return tar.GetVersion() } - hostSetNoHostExists := func(tar *tcp.Target) (version uint32) { + hostSetNoHostExists := func(tar target.Target) (version uint32) { hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0] hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0] @@ -2903,7 +2926,7 @@ func TestAuthorizeSession_Errors(t *testing.T) { return tr.GetItem().GetVersion() } - hostExists := func(tar *tcp.Target) (version uint32) { + hostExists := func(tar target.Target) (version uint32) { hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0] h := static.TestHosts(t, conn, hc.GetPublicId(), 1)[0] hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0] @@ -2917,7 +2940,7 @@ func TestAuthorizeSession_Errors(t *testing.T) { return apiTar.GetItem().GetVersion() } - libraryExists := func(tar *tcp.Target) (version uint32) { + libraryExists := func(tar target.Target) (version uint32) { credService, err := credentiallibraries.NewService(credentialRepoFn, iamRepoFn) require.NoError(t, err) clsResp, err := credService.CreateCredentialLibrary(ctx, &pbs.CreateCredentialLibraryRequest{Item: &credpb.CredentialLibrary{ @@ -2939,7 +2962,7 @@ func TestAuthorizeSession_Errors(t *testing.T) { return tr.GetItem().GetVersion() } - misConfiguredlibraryExists := func(tar *tcp.Target) (version uint32) { + misConfiguredlibraryExists := func(tar target.Target) (version uint32) { credService, err := credentiallibraries.NewService(credentialRepoFn, iamRepoFn) require.NoError(t, err) clsResp, err := credService.CreateCredentialLibrary(ctx, &pbs.CreateCredentialLibraryRequest{Item: &credpb.CredentialLibrary{ @@ -2963,37 +2986,37 @@ func TestAuthorizeSession_Errors(t *testing.T) { cases := []struct { name string - setup []func(*tcp.Target) uint32 + setup []func(target.Target) uint32 err bool }{ { // This one must be run first since it relies on the DB not having any worker details name: "no worker", - setup: []func(tcpTarget *tcp.Target) uint32{hostExists, libraryExists}, + setup: []func(tcpTarget target.Target) uint32{hostExists, libraryExists}, err: true, }, { name: "success", - setup: []func(tcpTarget *tcp.Target) uint32{workerExists, hostExists, libraryExists}, + setup: []func(tcpTarget target.Target) uint32{workerExists, hostExists, libraryExists}, }, { name: "no hosts", - setup: []func(tcpTarget *tcp.Target) uint32{workerExists, hostSetNoHostExists, libraryExists}, + setup: []func(tcpTarget target.Target) uint32{workerExists, hostSetNoHostExists, libraryExists}, err: true, }, { name: "bad library configuration", - setup: []func(tcpTarget *tcp.Target) uint32{workerExists, hostExists, misConfiguredlibraryExists}, + setup: []func(tcpTarget target.Target) uint32{workerExists, hostExists, misConfiguredlibraryExists}, err: true, }, } for i, tc := range cases { t.Run(tc.name, func(t *testing.T) { - tar := tcp.TestTarget(t, conn, proj.GetPublicId(), fmt.Sprintf("test-%d", i)) + tar := tcp.TestTarget(ctx, t, conn, proj.GetPublicId(), fmt.Sprintf("test-%d", i)) for _, fn := range tc.setup { ver := fn(tar) - tar.Version = ver + tar.SetVersion(ver) } res, err := s.AuthorizeSession(ctx, &pbs.AuthorizeSessionRequest{ diff --git a/internal/servers/controller/handlers/targets/tcp/tcp.go b/internal/servers/controller/handlers/targets/tcp/tcp.go new file mode 100644 index 000000000..1fca85bbc --- /dev/null +++ b/internal/servers/controller/handlers/targets/tcp/tcp.go @@ -0,0 +1,57 @@ +package tcp + +import ( + "github.com/golang/protobuf/ptypes/wrappers" + "github.com/hashicorp/boundary/internal/servers/controller/handlers" + "github.com/hashicorp/boundary/internal/servers/controller/handlers/targets" + "github.com/hashicorp/boundary/internal/target" + "github.com/hashicorp/boundary/internal/target/tcp" + "github.com/hashicorp/boundary/internal/target/tcp/store" + pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets" +) + +type attribute struct { + *pb.TcpTargetAttributes +} + +func (a *attribute) Options() []target.Option { + var opts []target.Option + if a.GetDefaultPort().GetValue() != 0 { + opts = append(opts, target.WithDefaultPort(a.GetDefaultPort().GetValue())) + } + return opts +} + +func (a *attribute) Vet() map[string]string { + badFields := map[string]string{} + if a.GetDefaultPort() != nil && a.GetDefaultPort().GetValue() == 0 { + badFields["attributes.default_port"] = "This optional field cannot be set to 0." + } + return badFields +} + +func newAttribute(t target.Target) targets.Attributes { + a := &attribute{ + &pb.TcpTargetAttributes{}, + } + if t != nil { + if t.GetDefaultPort() > 0 { + a.DefaultPort = &wrappers.UInt32Value{Value: t.GetDefaultPort()} + } + } + return a +} + +func init() { + var maskManager handlers.MaskManager + var err error + + if maskManager, err = handlers.NewMaskManager( + handlers.MaskDestination{&store.Target{}}, + handlers.MaskSource{&pb.Target{}, &pb.TcpTargetAttributes{}}, + ); err != nil { + panic(err) + } + + targets.Register(tcp.Subtype, maskManager, newAttribute) +} diff --git a/internal/session/testing.go b/internal/session/testing.go index 7a96e2778..ac23b25f2 100644 --- a/internal/session/testing.go +++ b/internal/session/testing.go @@ -133,7 +133,7 @@ func TestSessionParams(t *testing.T, conn *db.DB, wrapper wrapping.Wrapper, iamR sets := static.TestSets(t, conn, cats[0].PublicId, 1) _ = static.TestSetMembers(t, conn, sets[0].PublicId, hosts) - tcpTarget := tcp.TestTarget(t, conn, proj.PublicId, "test target") + tcpTarget := tcp.TestTarget(ctx, t, conn, proj.PublicId, "test target") kms := kms.TestKms(t, conn, wrapper) targetRepo, err := target.NewRepository(rw, rw, kms) @@ -155,10 +155,10 @@ func TestSessionParams(t *testing.T, conn *db.DB, wrapper wrapping.Wrapper, iamR return ComposedOf{ UserId: user.PublicId, HostId: hosts[0].PublicId, - TargetId: tcpTarget.PublicId, + TargetId: tcpTarget.GetPublicId(), HostSetId: sets[0].PublicId, AuthTokenId: at.PublicId, - ScopeId: tcpTarget.ScopeId, + ScopeId: tcpTarget.GetScopeId(), Endpoint: "tcp://127.0.0.1:22", ExpirationTime: ×tamp.Timestamp{Timestamp: expTime}, ConnectionLimit: tcpTarget.GetSessionConnectionLimit(), diff --git a/internal/tests/api/targets/target_test.go b/internal/tests/api/targets/target_test.go index a5d901228..bcad5e1fa 100644 --- a/internal/tests/api/targets/target_test.go +++ b/internal/tests/api/targets/target_test.go @@ -17,6 +17,8 @@ import ( "github.com/hashicorp/boundary/internal/target/tcp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + _ "github.com/hashicorp/boundary/internal/servers/controller/handlers/targets/tcp" ) func TestHostSetASD(t *testing.T) { diff --git a/internal/tests/cluster/package_registry_test.go b/internal/tests/cluster/package_registry_test.go new file mode 100644 index 000000000..4ca900c60 --- /dev/null +++ b/internal/tests/cluster/package_registry_test.go @@ -0,0 +1,7 @@ +package cluster + +import ( + // Enable tcp target support. + _ "github.com/hashicorp/boundary/internal/servers/controller/handlers/targets/tcp" + _ "github.com/hashicorp/boundary/internal/target/tcp" +)