Placeholder Plugin Providers for Repos and added testPlugin struct (#1532)

* Create minimalistic plugin map and test plugin.

* Pass secrets and attributes to the plugin when creating catalogs or sets.  Add tests for CreateSet and CreateCatalog repo methods.

* make fmt and extract out getPrivateCatalog and getCatalog helper methods.

* Exporting TestPluginServer so it can be used in the handlers.

* Keep separate persisted data from host catalogs lookups which facilitate passing it onto the plugins.

* Add TODO to merge get Catalog and get Persisted data.

* Adding tests for unimplemented being returned by the plugin.

* Use GetFields() instead of AsMap() to confirm attributes should be populated. Make clone consistent between catalog and sets.

Co-authored-by: Jeff Mitchell <jeffrey.mitchell@gmail.com>
This commit is contained in:
ToddandJeff Mitchell authored and GitHub committed 2021-09-21 09:18:49 -07:00
1 parent ea939a4445
commit bbfef2802f
30 files changed
+669 -227

No files matched your search

+2 -1
View File
@@ -24,6 +24,7 @@ import (
"github.com/hashicorp/boundary/internal/servers/controller/common"
"github.com/hashicorp/boundary/internal/session"
"github.com/hashicorp/boundary/internal/target"
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-secure-stdlib/mlock"
"github.com/patrickmn/go-cache"
@@ -136,7 +137,7 @@ func New(ctx context.Context, conf *Config) (*Controller, error) {
return static.NewRepository(dbase, dbase, c.kms)
}
c.PluginHostRepoFn = func() (*hostplugin.Repository, error) {
return hostplugin.NewRepository(dbase, dbase, c.kms)
return hostplugin.NewRepository(dbase, dbase, c.kms, map[string]plgpb.HostPluginServiceServer{})
}
c.HostPluginRepoFn = func() (*host.Repository, error) {
return host.NewRepository(dbase, dbase, c.kms)
@@ -2,7 +2,6 @@ package host_catalogs
import (
"context"
"encoding/json"
"fmt"
"strings"
@@ -26,6 +25,7 @@ import (
"github.com/hashicorp/boundary/internal/types/scope"
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostcatalogs"
"google.golang.org/grpc/codes"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
@@ -603,16 +603,13 @@ func toProto(ctx context.Context, in host.Catalog, opt ...handlers.Option) (*pb.
if outputFields.Has(globals.AttributesField) {
switch h := in.(type) {
case *plugin.HostCatalog:
attrs := map[string]interface{}{}
err := json.Unmarshal(h.Attributes, &attrs)
attrs := &structpb.Struct{}
err := proto.Unmarshal(h.Attributes, attrs)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
if len(attrs) > 0 {
out.Attributes, err = structpb.NewStruct(attrs)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
if len(attrs.GetFields()) > 0 {
out.Attributes = attrs
}
}
}
@@ -645,10 +642,10 @@ func toStoragePluginCatalog(ctx context.Context, scopeId, plgId string, item *pb
opts = append(opts, plugin.WithDescription(desc.GetValue()))
}
if attrs := item.GetAttributes(); attrs != nil {
opts = append(opts, plugin.WithAttributes(attrs.AsMap()))
opts = append(opts, plugin.WithAttributes(attrs))
}
if secrets := item.GetSecrets(); secrets != nil {
opts = append(opts, plugin.WithSecrets(secrets.AsMap()))
opts = append(opts, plugin.WithSecrets(secrets))
}
hc, err := plugin.NewHostCatalog(ctx, scopeId, plgId, opts...)
if err != nil {
@@ -23,6 +23,7 @@ import (
"github.com/hashicorp/boundary/internal/types/scope"
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostcatalogs"
scopepb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes"
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
"google.golang.org/genproto/protobuf/field_mask"
"google.golang.org/grpc/codes"
"google.golang.org/protobuf/proto"
@@ -62,7 +63,7 @@ func TestGet_Static(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
pluginHostRepo := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
pluginRepo := func() (*host.Repository, error) {
return host.NewRepository(rw, rw, kms)
@@ -151,7 +152,7 @@ func TestGet_Plugin(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
pluginHostRepo := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
pluginRepo := func() (*host.Repository, error) {
return host.NewRepository(rw, rw, kms)
@@ -240,7 +241,7 @@ func TestList(t *testing.T) {
return iam.TestRepo(t, conn, wrapper), nil
}
pluginHostRepo := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
pluginRepo := func() (*host.Repository, error) {
return host.NewRepository(rw, rw, kms)
@@ -433,7 +434,7 @@ func TestDelete(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
pluginHostRepo := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
pluginRepo := func() (*host.Repository, error) {
return host.NewRepository(rw, rw, kms)
@@ -503,7 +504,7 @@ func TestDelete_twice(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
pluginHostRepo := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
pluginRepo := func() (*host.Repository, error) {
return host.NewRepository(rw, rw, kms)
@@ -538,7 +539,7 @@ func TestCreate_Static(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
pluginHostRepo := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
pluginRepo := func() (*host.Repository, error) {
return host.NewRepository(rw, rw, kms)
@@ -688,9 +689,6 @@ func TestCreate_Plugin(t *testing.T) {
repo := func() (*static.Repository, error) {
return static.NewRepository(rw, rw, kms)
}
pluginHostRepo := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
}
pluginRepo := func() (*host.Repository, error) {
return host.NewRepository(rw, rw, kms)
}
@@ -700,6 +698,15 @@ func TestCreate_Plugin(t *testing.T) {
name := "test"
plg := host.TestPlugin(t, conn, name, name)
pluginHostRepo := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{
plg.GetPublicId(): &plugin.TestPluginServer{
OnCreateCatalogFn: func(ctx context.Context, req *plgpb.OnCreateCatalogRequest) (*plgpb.OnCreateCatalogResponse, error) {
return nil, nil
},
},
})
}
defaultHc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
defaultHcCreated := defaultHc.GetCreateTime().GetTimestamp().AsTime()
toMerge := &pbs.CreateHostCatalogRequest{}
@@ -845,7 +852,7 @@ func TestUpdate(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
pluginHostRepo := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
pluginRepo := func() (*host.Repository, error) {
return host.NewRepository(rw, rw, kms)
@@ -2,7 +2,6 @@ package host_sets
import (
"context"
"encoding/json"
"fmt"
"strings"
@@ -24,6 +23,7 @@ import (
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostsets"
"github.com/hashicorp/go-secure-stdlib/strutil"
"google.golang.org/grpc/codes"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
@@ -756,16 +756,13 @@ func toProto(ctx context.Context, in host.Set, hosts []host.Host, opt ...handler
out.PreferredEndpoints = h.GetPreferredEndpoints()
}
if outputFields.Has(globals.AttributesField) {
attrs := map[string]interface{}{}
err := json.Unmarshal(h.Attributes, &attrs)
attrs := &structpb.Struct{}
err := proto.Unmarshal(h.Attributes, attrs)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
if len(attrs) > 0 {
out.Attributes, err = structpb.NewStruct(attrs)
if err != nil {
return nil, errors.Wrap(ctx, err, op)
}
if len(attrs.GetFields()) > 0 {
out.Attributes = attrs
}
}
}
@@ -799,7 +796,7 @@ func toStoragePluginSet(ctx context.Context, catalogId string, item *pb.HostSet)
opts = append(opts, plugin.WithDescription(item.GetDescription().GetValue()))
}
if item.GetAttributes() != nil {
opts = append(opts, plugin.WithAttributes(item.GetAttributes().AsMap()))
opts = append(opts, plugin.WithAttributes(item.GetAttributes()))
}
if item.GetPreferredEndpoints() != nil {
opts = append(opts, plugin.WithPreferredEndpoints(item.GetPreferredEndpoints()))
@@ -23,6 +23,7 @@ import (
"github.com/hashicorp/boundary/internal/types/scope"
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostsets"
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes"
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/genproto/protobuf/field_mask"
@@ -54,7 +55,7 @@ func TestGet_Static(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
pluginRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0]
hs := static.TestSets(t, conn, hc.GetPublicId(), 1)[0]
@@ -147,14 +148,16 @@ func TestGet_Plugin(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
pluginRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
name := "test"
prefEndpoints := []string{"cidr:1.2.3.4", "cidr:2.3.4.5/24"}
plg := hostplugin.TestPlugin(t, conn, name, name)
hc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
hs := plugin.TestSet(t, conn, kms, hc, plugin.WithPreferredEndpoints(prefEndpoints))
hs := plugin.TestSet(t, conn, kms, hc, map[string]plgpb.HostPluginServiceServer{
plg.GetPublicId(): &plugin.TestPluginServer{},
}, plugin.WithPreferredEndpoints(prefEndpoints))
toMerge := &pbs.GetHostSetRequest{}
@@ -241,7 +244,7 @@ func TestList_Static(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
pluginRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
hcs := static.TestCatalogs(t, conn, proj.GetPublicId(), 2)
hc, hcNoHosts := hcs[0], hcs[1]
@@ -338,18 +341,21 @@ func TestList_Plugin(t *testing.T) {
repoFn := func() (*static.Repository, error) {
return static.NewRepository(rw, rw, kms)
}
pluginRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
}
name := "test"
plg := hostplugin.TestPlugin(t, conn, name, name)
plgm := map[string]plgpb.HostPluginServiceServer{
plg.GetPublicId(): &plugin.TestPluginServer{},
}
pluginRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms, plgm)
}
hc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
hcNoHosts := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
preferredEndpoints := []string{"cidr:1.2.3.4", "dns:*.foobar.com"}
var wantHs []*pb.HostSet
for i := 0; i < 10; i++ {
h := plugin.TestSet(t, conn, kms, hc, plugin.WithPreferredEndpoints(preferredEndpoints))
h := plugin.TestSet(t, conn, kms, hc, plgm, plugin.WithPreferredEndpoints(preferredEndpoints))
wantHs = append(wantHs, &pb.HostSet{
Id: h.GetPublicId(),
HostCatalogId: h.GetCatalogId(),
@@ -443,7 +449,7 @@ func TestDelete(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
pluginRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0]
h := static.TestSets(t, conn, hc.GetPublicId(), 1)[0]
@@ -522,7 +528,7 @@ func TestDelete_twice(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
plgRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0]
h := static.TestSets(t, conn, hc.GetPublicId(), 1)[0]
@@ -558,7 +564,7 @@ func TestCreate_Static(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
plgRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0]
@@ -700,11 +706,17 @@ func TestCreate_Plugin(t *testing.T) {
repoFn := func() (*static.Repository, error) {
return static.NewRepository(rw, rw, kms)
}
plgRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
}
name := "test"
plg := hostplugin.TestPlugin(t, conn, name, name)
plgRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{
plg.GetPublicId(): &plugin.TestPluginServer{
OnCreateSetFn: func(ctx context.Context, req *plgpb.OnCreateSetRequest) (*plgpb.OnCreateSetResponse, error) {
return nil, nil
},
},
})
}
hc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
testAttrs, err := structpb.NewStruct(map[string]interface{}{
@@ -956,7 +968,7 @@ func TestUpdate(t *testing.T) {
}
plgRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
tested, err := host_sets.NewService(repoFn, plgRepoFn)
require.NoError(t, err, "Failed to create a new host set service.")
@@ -1295,7 +1307,7 @@ func TestAddHostSetHosts(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
plgRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
s, err := host_sets.NewService(repoFn, plgRepoFn)
require.NoError(t, err, "Error when getting new host set service.")
@@ -1415,7 +1427,7 @@ func TestSetHostSetHosts(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
plgRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
s, err := host_sets.NewService(repoFn, plgRepoFn)
require.NoError(t, err, "Error when getting new host set service.")
@@ -1531,7 +1543,7 @@ func TestRemoveHostSetHosts(t *testing.T) {
return static.NewRepository(rw, rw, kms)
}
plgRepoFn := func() (*plugin.Repository, error) {
return plugin.NewRepository(rw, rw, kms)
return plugin.NewRepository(rw, rw, kms, map[string]plgpb.HostPluginServiceServer{})
}
s, err := host_sets.NewService(repoFn, plgRepoFn)
require.NoError(t, err, "Error when getting new host set service.")
@@ -38,6 +38,7 @@ import (
credpb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/credentiallibraries"
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes"
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets"
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
wrapping "github.com/hashicorp/go-kms-wrapping"
"github.com/jinzhu/gorm"
"github.com/stretchr/testify/assert"
@@ -983,7 +984,9 @@ func TestAddTargetHostSets(t *testing.T) {
plg := host.TestPlugin(t, conn, "test", "test")
pluginHc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
pluginHs := plugin.TestSet(t, conn, kms, pluginHc)
pluginHs := plugin.TestSet(t, conn, kms, pluginHc, map[string]plgpb.HostPluginServiceServer{
plg.GetPublicId(): &plugin.TestPluginServer{},
})
addCases := []struct {
name string
@@ -1115,7 +1118,9 @@ func TestSetTargetHostSets(t *testing.T) {
plg := host.TestPlugin(t, conn, "test", "test")
pluginHc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
pluginHs := plugin.TestSet(t, conn, kms, pluginHc)
pluginHs := plugin.TestSet(t, conn, kms, pluginHc, map[string]plgpb.HostPluginServiceServer{
plg.GetPublicId(): &plugin.TestPluginServer{},
})
setCases := []struct {
name string
@@ -1241,7 +1246,9 @@ func TestRemoveTargetHostSets(t *testing.T) {
plg := host.TestPlugin(t, conn, "test", "test")
pluginHc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
pluginHs := plugin.TestSet(t, conn, kms, pluginHc)
pluginHs := plugin.TestSet(t, conn, kms, pluginHc, map[string]plgpb.HostPluginServiceServer{
plg.GetPublicId(): &plugin.TestPluginServer{},
})
removeCases := []struct {
name string
@@ -1379,7 +1386,9 @@ func TestAddTargetHostSources(t *testing.T) {
plg := host.TestPlugin(t, conn, "test", "test")
pluginHc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
pluginHs := plugin.TestSet(t, conn, kms, pluginHc)
pluginHs := plugin.TestSet(t, conn, kms, pluginHc, map[string]plgpb.HostPluginServiceServer{
plg.GetPublicId(): &plugin.TestPluginServer{},
})
addCases := []struct {
name string
@@ -1511,7 +1520,9 @@ func TestSetTargetHostSources(t *testing.T) {
plg := host.TestPlugin(t, conn, "test", "test")
pluginHc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
pluginHs := plugin.TestSet(t, conn, kms, pluginHc)
pluginHs := plugin.TestSet(t, conn, kms, pluginHc, map[string]plgpb.HostPluginServiceServer{
plg.GetPublicId(): &plugin.TestPluginServer{},
})
setCases := []struct {
name string
@@ -1631,7 +1642,9 @@ func TestRemoveTargetHostSources(t *testing.T) {
plg := host.TestPlugin(t, conn, "test", "test")
pluginHc := plugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
pluginHs := plugin.TestSet(t, conn, kms, pluginHc)
pluginHs := plugin.TestSet(t, conn, kms, pluginHc, map[string]plgpb.HostPluginServiceServer{
plg.GetPublicId(): &plugin.TestPluginServer{},
})
removeCases := []struct {
name string