Add mechanism for plugin to normalize attributes (#2376)
* Add mechanism for plugin to normalize attributes This introduces a new normalization call to the plugin RPC service. If implemented, the plugin will be given the attributes prior to saving them in a create/update call, and can perform any normalization needed, e.g. ensuring that a parameter passed in is represented in a canonical way. As an example, the CLI allows a user of the AWS plugin to pass in a string, but canonically it is a string slice, and should be returned that way as well. Not by chance, this is the exact behavior of the testing implementation of this function. This does not update any individual plugin, but rather sets the controller-side logic up for plugins to support this functionality.
This commit is contained in:
1 parent
d4fce6fbe1
commit
7364d84835
9 files changed
+1013
-331
No files matched your search
@@ -19,6 +19,10 @@ func NewWrappingPluginClient(s plgpb.HostPluginServiceServer) *WrappingPluginCli
|
||||
return &WrappingPluginClient{Server: s}
|
||||
}
|
||||
|
||||
func (tpc *WrappingPluginClient) NormalizeCatalogData(ctx context.Context, req *plgpb.NormalizeCatalogDataRequest, opts ...grpc.CallOption) (*plgpb.NormalizeCatalogDataResponse, error) {
|
||||
return tpc.Server.NormalizeCatalogData(ctx, req)
|
||||
}
|
||||
|
||||
func (tpc *WrappingPluginClient) OnCreateCatalog(ctx context.Context, req *plgpb.OnCreateCatalogRequest, opts ...grpc.CallOption) (*plgpb.OnCreateCatalogResponse, error) {
|
||||
return tpc.Server.OnCreateCatalog(ctx, req)
|
||||
}
|
||||
@@ -31,6 +35,10 @@ func (tpc *WrappingPluginClient) OnDeleteCatalog(ctx context.Context, req *plgpb
|
||||
return tpc.Server.OnDeleteCatalog(ctx, req)
|
||||
}
|
||||
|
||||
func (tpc *WrappingPluginClient) NormalizeSetData(ctx context.Context, req *plgpb.NormalizeSetDataRequest, opts ...grpc.CallOption) (*plgpb.NormalizeSetDataResponse, error) {
|
||||
return tpc.Server.NormalizeSetData(ctx, req)
|
||||
}
|
||||
|
||||
func (tpc *WrappingPluginClient) OnCreateSet(ctx context.Context, req *plgpb.OnCreateSetRequest, opts ...grpc.CallOption) (*plgpb.OnCreateSetResponse, error) {
|
||||
return tpc.Server.OnCreateSet(ctx, req)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
hostplugin "github.com/hashicorp/boundary/internal/plugin/host"
|
||||
"github.com/hashicorp/boundary/internal/scheduler"
|
||||
"github.com/hashicorp/boundary/internal/util"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostcatalogs"
|
||||
pbset "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostsets"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
@@ -25,6 +26,38 @@ import (
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
// normalizeCatalogAttributes allows a plugin to normalize attributes before
|
||||
// they are saved
|
||||
func normalizeCatalogAttributes(ctx context.Context, plgClient plgpb.HostPluginServiceClient, plgHc *pb.HostCatalog) error {
|
||||
const op = "plugin.(Repository).normalizeCatalogAttributes"
|
||||
switch {
|
||||
case util.IsNil(plgClient):
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "plugin client is nil")
|
||||
case plgHc == nil:
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "host catalog is nil")
|
||||
case plgHc.GetAttributes() == nil:
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, err := plgClient.NormalizeCatalogData(ctx, &plgpb.NormalizeCatalogDataRequest{
|
||||
Attributes: plgHc.GetAttributes(),
|
||||
})
|
||||
switch {
|
||||
case err == nil:
|
||||
if ret.Attributes != nil {
|
||||
plgHc.Attrs = &pb.HostCatalog_Attributes{
|
||||
Attributes: ret.Attributes,
|
||||
}
|
||||
}
|
||||
case status.Code(err) == codes.Unimplemented:
|
||||
// Do nothing
|
||||
default:
|
||||
return errors.Wrap(ctx, err, op, errors.WithMsg("error asking plugin to normalize catalog data"))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateCatalog inserts c into the repository and returns a new
|
||||
// HostCatalog containing the catalog's PublicId. c must contain a valid
|
||||
// ScopeID and PluginID. c must not contain a PublicId. The PublicId is
|
||||
@@ -90,6 +123,12 @@ func (r *Repository) CreateCatalog(ctx context.Context, c *HostCatalog, _ ...Opt
|
||||
return nil, nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("plugin %q not available", c.GetPluginId()))
|
||||
}
|
||||
|
||||
if plgHc.GetAttributes() != nil {
|
||||
if err := normalizeCatalogAttributes(ctx, plgClient, plgHc); err != nil {
|
||||
return nil, nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
}
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, c.ScopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get oplog wrapper"))
|
||||
@@ -321,6 +360,17 @@ func (r *Repository) UpdateCatalog(ctx context.Context, c *HostCatalog, version
|
||||
return nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
if updateAttributes {
|
||||
if newPlgHc.GetAttributes() != nil {
|
||||
if err := normalizeCatalogAttributes(ctx, plgClient, newPlgHc); err != nil {
|
||||
return nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if newCatalog.Attributes, err = proto.Marshal(newPlgHc.GetAttributes()); err != nil {
|
||||
return nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbWrapper, err := r.kms.GetWrapper(ctx, newCatalog.ScopeId, kms.KeyPurposeDatabase)
|
||||
if err != nil {
|
||||
return nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get db wrapper"))
|
||||
|
||||
@@ -14,12 +14,14 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/host/plugin/store"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/libs/patchstruct"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
hostplg "github.com/hashicorp/boundary/internal/plugin/host"
|
||||
hostplugin "github.com/hashicorp/boundary/internal/plugin/host"
|
||||
"github.com/hashicorp/boundary/internal/scheduler"
|
||||
"github.com/hashicorp/boundary/internal/scheduler/job"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
@@ -38,6 +40,8 @@ func TestRepository_CreateCatalog(t *testing.T) {
|
||||
plg := hostplg.TestPlugin(t, conn, "test")
|
||||
unimplementedPlugin := hostplg.TestPlugin(t, conn, "unimplemented")
|
||||
|
||||
const normalizeToSliceKey = "normalize_to_slice"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
in *HostCatalog
|
||||
@@ -181,8 +185,9 @@ func TestRepository_CreateCatalog(t *testing.T) {
|
||||
PluginId: plg.GetPublicId(),
|
||||
Attributes: func() []byte {
|
||||
st, err := structpb.NewStruct(map[string]interface{}{
|
||||
"k1": "foo",
|
||||
"nilkey": nil,
|
||||
"k1": "foo",
|
||||
"nilkey": nil,
|
||||
normalizeToSliceKey: "normalizeme",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
b, err := proto.Marshal(st)
|
||||
@@ -249,16 +254,38 @@ func TestRepository_CreateCatalog(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require, assert := require.New(t), assert.New(t)
|
||||
kmsCache := kms.TestKms(t, conn, wrapper)
|
||||
|
||||
// gotPluginAttrs tracks which attributes a plugin has received through a closure and can be compared in the
|
||||
// test against the expected values sent to the plugin.
|
||||
var gotPluginAttrs *structpb.Struct
|
||||
var origPluginAttrs, gotPluginAttrs *structpb.Struct
|
||||
if tt.in != nil && tt.in.HostCatalog != nil && len(tt.in.Attributes) > 0 {
|
||||
origPluginAttrs = new(structpb.Struct)
|
||||
require.NoError(proto.Unmarshal(tt.in.Attributes, origPluginAttrs))
|
||||
}
|
||||
|
||||
var pluginCalled bool
|
||||
plgm := map[string]plgpb.HostPluginServiceClient{
|
||||
plg.GetPublicId(): &WrappingPluginClient{
|
||||
Server: &TestPluginServer{
|
||||
NormalizeCatalogDataFn: func(_ context.Context, req *plgpb.NormalizeCatalogDataRequest) (*plgpb.NormalizeCatalogDataResponse, error) {
|
||||
if req.Attributes == nil {
|
||||
return new(plgpb.NormalizeCatalogDataResponse), nil
|
||||
}
|
||||
var attrs struct {
|
||||
NormalizeToSlice string `mapstructure:"normalize_to_slice"`
|
||||
}
|
||||
require.NoError(mapstructure.Decode(req.Attributes.AsMap(), &attrs))
|
||||
if attrs.NormalizeToSlice == "" {
|
||||
return new(plgpb.NormalizeCatalogDataResponse), nil
|
||||
}
|
||||
retAttrs := proto.Clone(req.Attributes).(*structpb.Struct)
|
||||
retAttrs.Fields[normalizeToSliceKey] = structpb.NewListValue(&structpb.ListValue{
|
||||
Values: []*structpb.Value{structpb.NewStringValue(attrs.NormalizeToSlice)},
|
||||
})
|
||||
return &plgpb.NormalizeCatalogDataResponse{Attributes: retAttrs}, nil
|
||||
},
|
||||
OnCreateCatalogFn: func(_ context.Context, req *plgpb.OnCreateCatalogRequest) (*plgpb.OnCreateCatalogResponse, error) {
|
||||
pluginCalled = true
|
||||
gotPluginAttrs = req.GetCatalog().GetAttributes()
|
||||
@@ -284,7 +311,7 @@ func TestRepository_CreateCatalog(t *testing.T) {
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.NoError(err)
|
||||
assert.Empty(tt.in.PublicId)
|
||||
assert.NotNil(got)
|
||||
assertPluginBasedPublicId(t, HostCatalogPrefix, got.PublicId)
|
||||
@@ -293,11 +320,25 @@ func TestRepository_CreateCatalog(t *testing.T) {
|
||||
assert.Equal(tt.want.Description, got.Description)
|
||||
assert.Equal(got.CreateTime, got.UpdateTime)
|
||||
|
||||
// wantedPluginAttributes := &structpb.Struct{}
|
||||
// require.NoError(t, proto.Unmarshal(tt.want.GetAttributes(), wantedPluginAttributes))
|
||||
gotB, err := proto.Marshal(gotPluginAttrs)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(tt.want.GetAttributes(), gotB)
|
||||
if origPluginAttrs != nil {
|
||||
if normalizeVal := origPluginAttrs.Fields[normalizeToSliceKey]; normalizeVal != nil {
|
||||
gotVal := gotPluginAttrs.Fields[normalizeToSliceKey]
|
||||
require.NotNil(gotVal)
|
||||
listVal := gotVal.GetListValue()
|
||||
require.NotNil(listVal)
|
||||
require.Len(listVal.Values, 1)
|
||||
assert.Equal(normalizeVal.GetStringValue(), listVal.Values[0].GetStringValue())
|
||||
origPluginAttrs.Fields[normalizeToSliceKey] = structpb.NewListValue(listVal)
|
||||
tt.want.Attributes, err = proto.Marshal(origPluginAttrs)
|
||||
require.NoError(err)
|
||||
tt.want.Attributes, err = patchstruct.PatchBytes([]byte{}, tt.want.Attributes)
|
||||
require.NoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
wantedPluginAttributes := &structpb.Struct{}
|
||||
require.NoError(proto.Unmarshal(tt.want.GetAttributes(), wantedPluginAttributes))
|
||||
assert.Empty(cmp.Diff(wantedPluginAttributes, gotPluginAttrs, protocmp.Transform()))
|
||||
|
||||
assert.NoError(db.TestVerifyOplog(t, rw, got.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)))
|
||||
|
||||
@@ -305,20 +346,20 @@ func TestRepository_CreateCatalog(t *testing.T) {
|
||||
err = rw.LookupWhere(ctx, &cSecret, "catalog_id=?", []interface{}{got.GetPublicId()})
|
||||
if tt.wantSecret == nil {
|
||||
assert.Nil(got.Secrets)
|
||||
require.Error(t, err)
|
||||
require.True(t, errors.IsNotFoundError(err))
|
||||
require.Error(err)
|
||||
require.True(errors.IsNotFoundError(err))
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, cSecret.Secret)
|
||||
require.NotEmpty(t, cSecret.CtSecret)
|
||||
require.NoError(err)
|
||||
require.Empty(cSecret.Secret)
|
||||
require.NotEmpty(cSecret.CtSecret)
|
||||
|
||||
dbWrapper, err := kmsCache.GetWrapper(ctx, got.GetScopeId(), kms.KeyPurposeDatabase)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, cSecret.decrypt(ctx, dbWrapper))
|
||||
require.NoError(err)
|
||||
require.NoError(cSecret.decrypt(ctx, dbWrapper))
|
||||
|
||||
st := &structpb.Struct{}
|
||||
require.NoError(t, proto.Unmarshal(cSecret.Secret, st))
|
||||
require.NoError(proto.Unmarshal(cSecret.Secret, st))
|
||||
assert.Empty(cmp.Diff(tt.wantSecret, st, protocmp.Transform()))
|
||||
})
|
||||
}
|
||||
@@ -431,6 +472,15 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
_, projectScope := iam.TestScopes(t, iam.TestRepo(t, dbConn, dbWrapper))
|
||||
_, projectScopeAlt := iam.TestScopes(t, iam.TestRepo(t, dbConn, dbWrapper))
|
||||
|
||||
// Set up two existing catalogs for duplicate tests, one in the
|
||||
// same scope that we are working in mostly, and another in a
|
||||
// different one. Both are project scopes.
|
||||
const (
|
||||
testDuplicateCatalogNameProjectScope = "duplicate-catalog-name-project-scope"
|
||||
testDuplicateCatalogNameAltScope = "duplicate-catalog-name-alt-scope"
|
||||
normalizeToSliceKey = "normalize_to_slice"
|
||||
)
|
||||
|
||||
// Define a plugin "manager", basically just a map with a mock
|
||||
// plugin in it. This also includes functionality to capture the
|
||||
// state, and set an error and the returned secrets to nil. Note
|
||||
@@ -444,6 +494,23 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
testPluginMap := map[string]plgpb.HostPluginServiceClient{
|
||||
testPlugin.GetPublicId(): &WrappingPluginClient{
|
||||
Server: &TestPluginServer{
|
||||
NormalizeCatalogDataFn: func(_ context.Context, req *plgpb.NormalizeCatalogDataRequest) (*plgpb.NormalizeCatalogDataResponse, error) {
|
||||
if req.Attributes == nil {
|
||||
return new(plgpb.NormalizeCatalogDataResponse), nil
|
||||
}
|
||||
var attrs struct {
|
||||
NormalizeToSlice string `mapstructure:"normalize_to_slice"`
|
||||
}
|
||||
require.NoError(t, mapstructure.Decode(req.Attributes.AsMap(), &attrs))
|
||||
if attrs.NormalizeToSlice == "" {
|
||||
return new(plgpb.NormalizeCatalogDataResponse), nil
|
||||
}
|
||||
retAttrs := proto.Clone(req.Attributes).(*structpb.Struct)
|
||||
retAttrs.Fields[normalizeToSliceKey] = structpb.NewListValue(&structpb.ListValue{
|
||||
Values: []*structpb.Value{structpb.NewStringValue(attrs.NormalizeToSlice)},
|
||||
})
|
||||
return &plgpb.NormalizeCatalogDataResponse{Attributes: retAttrs}, nil
|
||||
},
|
||||
OnUpdateCatalogFn: func(_ context.Context, req *plgpb.OnUpdateCatalogRequest) (*plgpb.OnUpdateCatalogResponse, error) {
|
||||
gotOnUpdateCatalogRequest = req
|
||||
respSecrets := req.GetNewCatalog().GetSecrets()
|
||||
@@ -458,14 +525,6 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
// Set up two existing catalogs for duplicate tests, one in the
|
||||
// same scope that we are working in mostly, and another in a
|
||||
// different one. Both are project scopes.
|
||||
const (
|
||||
testDuplicateCatalogNameProjectScope = "duplicate-catalog-name-project-scope"
|
||||
testDuplicateCatalogNameAltScope = "duplicate-catalog-name-alt-scope"
|
||||
)
|
||||
|
||||
// Project scope
|
||||
existingProjectScopeCatalog := TestCatalog(t, dbConn, projectScope.PublicId, testPlugin.GetPublicId())
|
||||
existingProjectScopeCatalog.Name = testDuplicateCatalogNameProjectScope
|
||||
@@ -597,6 +656,7 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
require := require.New(t)
|
||||
st := &structpb.Struct{}
|
||||
require.NoError(proto.Unmarshal(gotCatalog.Attributes, st))
|
||||
assert.Equal(want, st.AsMap())
|
||||
assert.Empty(cmp.Diff(mustStruct(want), st, protocmp.Transform()))
|
||||
}
|
||||
}
|
||||
@@ -932,7 +992,8 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
{
|
||||
name: "update attributes (overwrite)",
|
||||
changeFuncs: []changeHostCatalogFunc{changeAttributes(map[string]interface{}{
|
||||
"foo": "baz",
|
||||
"foo": "baz",
|
||||
normalizeToSliceKey: "normalizeme",
|
||||
})},
|
||||
version: 2,
|
||||
fieldMask: []string{"attributes"},
|
||||
@@ -943,10 +1004,12 @@ func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
"foo": "bar",
|
||||
}),
|
||||
checkUpdateCatalogRequestNewAttributes(map[string]interface{}{
|
||||
"foo": "baz",
|
||||
"foo": "baz",
|
||||
normalizeToSliceKey: []any{"normalizeme"},
|
||||
}),
|
||||
checkAttributes(map[string]interface{}{
|
||||
"foo": "baz",
|
||||
"foo": "baz",
|
||||
normalizeToSliceKey: []any{"normalizeme"},
|
||||
}),
|
||||
checkSecrets(map[string]interface{}{
|
||||
"one": "two",
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
hostplugin "github.com/hashicorp/boundary/internal/plugin/host"
|
||||
"github.com/hashicorp/boundary/internal/scheduler"
|
||||
"github.com/hashicorp/boundary/internal/util"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostsets"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -25,6 +26,38 @@ import (
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
// normalizeCatalogAttributes allows a plugin to normalize set attributes before
|
||||
// they are saved
|
||||
func normalizeSetAttributes(ctx context.Context, plgClient plgpb.HostPluginServiceClient, plgHs *pb.HostSet) error {
|
||||
const op = "plugin.(Repository).normalizeSetAttributes"
|
||||
switch {
|
||||
case util.IsNil(plgClient):
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "plugin client is nil")
|
||||
case plgHs == nil:
|
||||
return errors.New(ctx, errors.InvalidParameter, op, "host set is nil")
|
||||
case plgHs.GetAttributes() == nil:
|
||||
return nil
|
||||
}
|
||||
|
||||
ret, err := plgClient.NormalizeSetData(ctx, &plgpb.NormalizeSetDataRequest{
|
||||
Attributes: plgHs.GetAttributes(),
|
||||
})
|
||||
switch {
|
||||
case err == nil:
|
||||
if ret.Attributes != nil {
|
||||
plgHs.Attrs = &pb.HostSet_Attributes{
|
||||
Attributes: ret.Attributes,
|
||||
}
|
||||
}
|
||||
case status.Code(err) == codes.Unimplemented:
|
||||
// Do nothing
|
||||
default:
|
||||
return errors.Wrap(ctx, err, op, errors.WithMsg("error asking plugin to normalize set data"))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateSet inserts s into the repository and returns a new HostSet
|
||||
// containing the host set's PublicId. s is not changed. s must contain a
|
||||
// valid CatalogId. s must not contain a PublicId. The PublicId is
|
||||
@@ -92,6 +125,12 @@ func (r *Repository) CreateSet(ctx context.Context, scopeId string, s *HostSet,
|
||||
return nil, nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
if plgHs.GetAttributes() != nil {
|
||||
if err := normalizeSetAttributes(ctx, plgClient, plgHs); err != nil {
|
||||
return nil, nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
}
|
||||
|
||||
var preferredEndpoints []interface{}
|
||||
if s.PreferredEndpoints != nil {
|
||||
preferredEndpoints = make([]interface{}, 0, len(s.PreferredEndpoints))
|
||||
@@ -334,6 +373,17 @@ func (r *Repository) UpdateSet(ctx context.Context, scopeId string, s *HostSet,
|
||||
return nil, nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
if updateAttributes {
|
||||
if newPlgSet.GetAttributes() != nil {
|
||||
if err := normalizeSetAttributes(ctx, plgClient, newPlgSet); err != nil {
|
||||
return nil, nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
if newSet.Attributes, err = proto.Marshal(newPlgSet.GetAttributes()); err != nil {
|
||||
return nil, nil, nil, db.NoRowsAffected, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the preferred endpoints to write out.
|
||||
var preferredEndpoints []interface{}
|
||||
if endpointOp == endpointOpUpdate {
|
||||
|
||||
@@ -17,10 +17,12 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/host/plugin/store"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/libs/patchstruct"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
hostplg "github.com/hashicorp/boundary/internal/plugin/host"
|
||||
"github.com/hashicorp/boundary/internal/scheduler"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/proto"
|
||||
@@ -44,6 +46,8 @@ func TestRepository_CreateSet(t *testing.T) {
|
||||
unimplementedPluginCatalog := TestCatalog(t, conn, prj.PublicId, plg.GetPublicId())
|
||||
attrs := []byte{}
|
||||
|
||||
const normalizeToSliceKey = "normalize_to_slice"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
in *HostSet
|
||||
@@ -233,8 +237,9 @@ func TestRepository_CreateSet(t *testing.T) {
|
||||
Description: ("test-description-repo"),
|
||||
Attributes: func() []byte {
|
||||
st, err := structpb.NewStruct(map[string]interface{}{
|
||||
"k1": "foo",
|
||||
"removed": nil,
|
||||
"k1": "foo",
|
||||
"removed": nil,
|
||||
normalizeToSliceKey: "normalizeme",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
b, err := proto.Marshal(st)
|
||||
@@ -262,14 +267,37 @@ func TestRepository_CreateSet(t *testing.T) {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
var pluginReceivedAttrs *structpb.Struct
|
||||
var origPluginAttrs, pluginReceivedAttrs *structpb.Struct
|
||||
if tt.in != nil && tt.in.HostSet != nil && len(tt.in.Attributes) > 0 {
|
||||
origPluginAttrs = new(structpb.Struct)
|
||||
require.NoError(proto.Unmarshal(tt.in.Attributes, origPluginAttrs))
|
||||
}
|
||||
var pluginCalled bool
|
||||
plgm := map[string]plgpb.HostPluginServiceClient{
|
||||
plg.GetPublicId(): NewWrappingPluginClient(TestPluginServer{OnCreateSetFn: func(ctx context.Context, req *plgpb.OnCreateSetRequest) (*plgpb.OnCreateSetResponse, error) {
|
||||
pluginCalled = true
|
||||
pluginReceivedAttrs = req.GetSet().GetAttributes()
|
||||
return &plgpb.OnCreateSetResponse{}, nil
|
||||
}}),
|
||||
plg.GetPublicId(): NewWrappingPluginClient(TestPluginServer{
|
||||
NormalizeSetDataFn: func(_ context.Context, req *plgpb.NormalizeSetDataRequest) (*plgpb.NormalizeSetDataResponse, error) {
|
||||
if req.Attributes == nil {
|
||||
return new(plgpb.NormalizeSetDataResponse), nil
|
||||
}
|
||||
var attrs struct {
|
||||
NormalizeToSlice string `mapstructure:"normalize_to_slice"`
|
||||
}
|
||||
require.NoError(mapstructure.Decode(req.Attributes.AsMap(), &attrs))
|
||||
if attrs.NormalizeToSlice == "" {
|
||||
return new(plgpb.NormalizeSetDataResponse), nil
|
||||
}
|
||||
retAttrs := proto.Clone(req.Attributes).(*structpb.Struct)
|
||||
retAttrs.Fields[normalizeToSliceKey] = structpb.NewListValue(&structpb.ListValue{
|
||||
Values: []*structpb.Value{structpb.NewStringValue(attrs.NormalizeToSlice)},
|
||||
})
|
||||
return &plgpb.NormalizeSetDataResponse{Attributes: retAttrs}, nil
|
||||
},
|
||||
OnCreateSetFn: func(ctx context.Context, req *plgpb.OnCreateSetRequest) (*plgpb.OnCreateSetResponse, error) {
|
||||
pluginCalled = true
|
||||
pluginReceivedAttrs = req.GetSet().GetAttributes()
|
||||
return &plgpb.OnCreateSetResponse{}, nil
|
||||
},
|
||||
}),
|
||||
unimplementedPlugin.GetPublicId(): NewWrappingPluginClient(TestPluginServer{OnCreateSetFn: func(ctx context.Context, req *plgpb.OnCreateSetRequest) (*plgpb.OnCreateSetResponse, error) {
|
||||
pluginCalled = true
|
||||
pluginReceivedAttrs = req.GetSet().GetAttributes()
|
||||
@@ -294,6 +322,23 @@ func TestRepository_CreateSet(t *testing.T) {
|
||||
assert.Equal(tt.want.Name, got.GetName())
|
||||
assert.Equal(tt.want.Description, got.GetDescription())
|
||||
assert.Equal(got.GetCreateTime(), got.GetUpdateTime())
|
||||
|
||||
if origPluginAttrs != nil {
|
||||
if normalizeVal := origPluginAttrs.Fields[normalizeToSliceKey]; normalizeVal != nil {
|
||||
gotVal := pluginReceivedAttrs.Fields[normalizeToSliceKey]
|
||||
require.NotNil(gotVal)
|
||||
listVal := gotVal.GetListValue()
|
||||
require.NotNil(listVal)
|
||||
require.Len(listVal.Values, 1)
|
||||
assert.Equal(normalizeVal.GetStringValue(), listVal.Values[0].GetStringValue())
|
||||
origPluginAttrs.Fields[normalizeToSliceKey] = structpb.NewListValue(listVal)
|
||||
tt.want.Attributes, err = proto.Marshal(origPluginAttrs)
|
||||
require.NoError(err)
|
||||
tt.want.Attributes, err = patchstruct.PatchBytes([]byte{}, tt.want.Attributes)
|
||||
require.NoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
wantedPluginAttributes := &structpb.Struct{}
|
||||
require.NoError(proto.Unmarshal(tt.want.Attributes, wantedPluginAttributes))
|
||||
assert.Empty(cmp.Diff(wantedPluginAttributes, pluginReceivedAttrs, protocmp.Transform()))
|
||||
@@ -427,6 +472,8 @@ func TestRepository_UpdateSet(t *testing.T) {
|
||||
err = dbRW.Create(ctx, testCatalogSecret)
|
||||
require.NoError(t, err)
|
||||
|
||||
const normalizeToSliceKey = "normalize_to_slice"
|
||||
|
||||
// Create a test duplicate set. We don't use this set, it just
|
||||
// exists to ensure that we can test for conflicts when setting
|
||||
// the name.
|
||||
@@ -1007,7 +1054,8 @@ func TestRepository_UpdateSet(t *testing.T) {
|
||||
name: "update attributes (overwrite)",
|
||||
startingSet: setupHostSet,
|
||||
changeFuncs: []changeHostSetFunc{changeAttributes(map[string]interface{}{
|
||||
"foo": "baz",
|
||||
"foo": "baz",
|
||||
normalizeToSliceKey: "normalizeme",
|
||||
})},
|
||||
fieldMask: []string{"attributes"},
|
||||
wantCheckPluginReqFuncs: []checkPluginReqFunc{
|
||||
@@ -1015,7 +1063,8 @@ func TestRepository_UpdateSet(t *testing.T) {
|
||||
"foo": "bar",
|
||||
}),
|
||||
checkUpdateSetRequestNewAttributes(map[string]interface{}{
|
||||
"foo": "baz",
|
||||
"foo": "baz",
|
||||
normalizeToSliceKey: []any{"normalizeme"},
|
||||
}),
|
||||
checkUpdateSetRequestPersistedSecrets(map[string]interface{}{
|
||||
"one": "two",
|
||||
@@ -1024,7 +1073,8 @@ func TestRepository_UpdateSet(t *testing.T) {
|
||||
wantCheckSetFuncs: []checkHostSetFunc{
|
||||
checkVersion(3),
|
||||
checkAttributes(map[string]interface{}{
|
||||
"foo": "baz",
|
||||
"foo": "baz",
|
||||
normalizeToSliceKey: []any{"normalizeme"},
|
||||
}),
|
||||
checkNeedSync(true),
|
||||
checkVerifySetOplog(oplog.OpType_OP_TYPE_UPDATE),
|
||||
@@ -1147,6 +1197,23 @@ func TestRepository_UpdateSet(t *testing.T) {
|
||||
testPluginMap := map[string]plgpb.HostPluginServiceClient{
|
||||
testPlugin.GetPublicId(): &WrappingPluginClient{
|
||||
Server: &TestPluginServer{
|
||||
NormalizeSetDataFn: func(_ context.Context, req *plgpb.NormalizeSetDataRequest) (*plgpb.NormalizeSetDataResponse, error) {
|
||||
if req.Attributes == nil {
|
||||
return new(plgpb.NormalizeSetDataResponse), nil
|
||||
}
|
||||
var attrs struct {
|
||||
NormalizeToSlice string `mapstructure:"normalize_to_slice"`
|
||||
}
|
||||
require.NoError(mapstructure.Decode(req.Attributes.AsMap(), &attrs))
|
||||
if attrs.NormalizeToSlice == "" {
|
||||
return new(plgpb.NormalizeSetDataResponse), nil
|
||||
}
|
||||
retAttrs := proto.Clone(req.Attributes).(*structpb.Struct)
|
||||
retAttrs.Fields[normalizeToSliceKey] = structpb.NewListValue(&structpb.ListValue{
|
||||
Values: []*structpb.Value{structpb.NewStringValue(attrs.NormalizeToSlice)},
|
||||
})
|
||||
return &plgpb.NormalizeSetDataResponse{Attributes: retAttrs}, nil
|
||||
},
|
||||
OnUpdateSetFn: func(_ context.Context, req *plgpb.OnUpdateSetRequest) (*plgpb.OnUpdateSetResponse, error) {
|
||||
gotOnUpdateCallCount++
|
||||
for _, check := range tt.wantCheckPluginReqFuncs {
|
||||
|
||||
@@ -233,16 +233,25 @@ var _ plgpb.HostPluginServiceServer = (*TestPluginServer)(nil)
|
||||
|
||||
// TestPluginServer provides a host plugin service server where each method can be overwritten for tests.
|
||||
type TestPluginServer struct {
|
||||
OnCreateCatalogFn func(context.Context, *plgpb.OnCreateCatalogRequest) (*plgpb.OnCreateCatalogResponse, error)
|
||||
OnUpdateCatalogFn func(context.Context, *plgpb.OnUpdateCatalogRequest) (*plgpb.OnUpdateCatalogResponse, error)
|
||||
OnDeleteCatalogFn func(context.Context, *plgpb.OnDeleteCatalogRequest) (*plgpb.OnDeleteCatalogResponse, error)
|
||||
OnCreateSetFn func(context.Context, *plgpb.OnCreateSetRequest) (*plgpb.OnCreateSetResponse, error)
|
||||
OnUpdateSetFn func(context.Context, *plgpb.OnUpdateSetRequest) (*plgpb.OnUpdateSetResponse, error)
|
||||
OnDeleteSetFn func(context.Context, *plgpb.OnDeleteSetRequest) (*plgpb.OnDeleteSetResponse, error)
|
||||
ListHostsFn func(context.Context, *plgpb.ListHostsRequest) (*plgpb.ListHostsResponse, error)
|
||||
NormalizeCatalogDataFn func(context.Context, *plgpb.NormalizeCatalogDataRequest) (*plgpb.NormalizeCatalogDataResponse, error)
|
||||
OnCreateCatalogFn func(context.Context, *plgpb.OnCreateCatalogRequest) (*plgpb.OnCreateCatalogResponse, error)
|
||||
OnUpdateCatalogFn func(context.Context, *plgpb.OnUpdateCatalogRequest) (*plgpb.OnUpdateCatalogResponse, error)
|
||||
OnDeleteCatalogFn func(context.Context, *plgpb.OnDeleteCatalogRequest) (*plgpb.OnDeleteCatalogResponse, error)
|
||||
NormalizeSetDataFn func(context.Context, *plgpb.NormalizeSetDataRequest) (*plgpb.NormalizeSetDataResponse, error)
|
||||
OnCreateSetFn func(context.Context, *plgpb.OnCreateSetRequest) (*plgpb.OnCreateSetResponse, error)
|
||||
OnUpdateSetFn func(context.Context, *plgpb.OnUpdateSetRequest) (*plgpb.OnUpdateSetResponse, error)
|
||||
OnDeleteSetFn func(context.Context, *plgpb.OnDeleteSetRequest) (*plgpb.OnDeleteSetResponse, error)
|
||||
ListHostsFn func(context.Context, *plgpb.ListHostsRequest) (*plgpb.ListHostsResponse, error)
|
||||
plgpb.UnimplementedHostPluginServiceServer
|
||||
}
|
||||
|
||||
func (t TestPluginServer) NormalizeCatalogData(ctx context.Context, req *plgpb.NormalizeCatalogDataRequest) (*plgpb.NormalizeCatalogDataResponse, error) {
|
||||
if t.NormalizeCatalogDataFn == nil {
|
||||
return t.UnimplementedHostPluginServiceServer.NormalizeCatalogData(ctx, req)
|
||||
}
|
||||
return t.NormalizeCatalogDataFn(ctx, req)
|
||||
}
|
||||
|
||||
func (t TestPluginServer) OnCreateCatalog(ctx context.Context, req *plgpb.OnCreateCatalogRequest) (*plgpb.OnCreateCatalogResponse, error) {
|
||||
if t.OnCreateCatalogFn == nil {
|
||||
return t.UnimplementedHostPluginServiceServer.OnCreateCatalog(ctx, req)
|
||||
@@ -264,6 +273,13 @@ func (t TestPluginServer) OnDeleteCatalog(ctx context.Context, req *plgpb.OnDele
|
||||
return t.OnDeleteCatalogFn(ctx, req)
|
||||
}
|
||||
|
||||
func (t TestPluginServer) NormalizeSetData(ctx context.Context, req *plgpb.NormalizeSetDataRequest) (*plgpb.NormalizeSetDataResponse, error) {
|
||||
if t.NormalizeSetDataFn == nil {
|
||||
return t.UnimplementedHostPluginServiceServer.NormalizeSetData(ctx, req)
|
||||
}
|
||||
return t.NormalizeSetDataFn(ctx, req)
|
||||
}
|
||||
|
||||
func (t TestPluginServer) OnCreateSet(ctx context.Context, req *plgpb.OnCreateSetRequest) (*plgpb.OnCreateSetResponse, error) {
|
||||
if t.OnCreateSetFn == nil {
|
||||
return t.UnimplementedHostPluginServiceServer.OnCreateSet(ctx, req)
|
||||
|
||||
@@ -10,8 +10,17 @@ option go_package = "github.com/hashicorp/boundary/sdk/pbs/plugin;plugin";
|
||||
|
||||
// HostPluginService describes the service for host plugins.
|
||||
service HostPluginService {
|
||||
// OnCreateCatalog is a hook that runs when a host catalog is
|
||||
// created.
|
||||
// NormalizeCatalogData is a hook that passes attributes to the plugin and
|
||||
// allows those values to be normalized prior to creating or updating those
|
||||
// values in the host catalog data.
|
||||
//
|
||||
// NormalizeCatalogData is called before:
|
||||
// * OnCreateCatalog
|
||||
// * OnUpdateCatalog
|
||||
rpc NormalizeCatalogData(NormalizeCatalogDataRequest) returns (NormalizeCatalogDataResponse);
|
||||
|
||||
// OnCreateCatalog is a hook that runs when a
|
||||
// host catalog is created.
|
||||
rpc OnCreateCatalog(OnCreateCatalogRequest) returns (OnCreateCatalogResponse);
|
||||
|
||||
// OnUpdateCatalog is a hook that runs when a host catalog is
|
||||
@@ -22,6 +31,15 @@ service HostPluginService {
|
||||
// deleted.
|
||||
rpc OnDeleteCatalog(OnDeleteCatalogRequest) returns (OnDeleteCatalogResponse);
|
||||
|
||||
// NormalizeSetData is a hook that passes attributes to the plugin and
|
||||
// allows those values to be normalized prior to creating or updating those
|
||||
// values in the host set data.
|
||||
//
|
||||
// NormalizeSetData is called before:
|
||||
// * OnCreateSet
|
||||
// * OnUpdateSet
|
||||
rpc NormalizeSetData(NormalizeSetDataRequest) returns (NormalizeSetDataResponse);
|
||||
|
||||
// OnCreateSet is a hook that runs when a host set is created.
|
||||
rpc OnCreateSet(OnCreateSetRequest) returns (OnCreateSetResponse);
|
||||
|
||||
@@ -35,6 +53,17 @@ service HostPluginService {
|
||||
rpc ListHosts(ListHostsRequest) returns (ListHostsResponse);
|
||||
}
|
||||
|
||||
message NormalizeCatalogDataRequest {
|
||||
// The incoming attributes in the create or update request.
|
||||
google.protobuf.Struct attributes = 100;
|
||||
}
|
||||
|
||||
message NormalizeCatalogDataResponse {
|
||||
// Outgoing attributes. If nil, no changes will be recorded. If non-nil, the
|
||||
// values here will be used in place of the original set of attributes.
|
||||
google.protobuf.Struct attributes = 100;
|
||||
}
|
||||
|
||||
message OnCreateCatalogRequest {
|
||||
// The host catalog to create. The request may contain optional
|
||||
// secret data to help authenticate the request against a cloud
|
||||
@@ -84,6 +113,17 @@ message OnDeleteCatalogRequest {
|
||||
|
||||
message OnDeleteCatalogResponse {}
|
||||
|
||||
message NormalizeSetDataRequest {
|
||||
// The incoming attributes in the create or update request.
|
||||
google.protobuf.Struct attributes = 100;
|
||||
}
|
||||
|
||||
message NormalizeSetDataResponse {
|
||||
// Outgoing attributes. If nil, no changes will be recorded. If non-nil, the
|
||||
// values here will be used in place of the original set of attributes.
|
||||
google.protobuf.Struct attributes = 100;
|
||||
}
|
||||
|
||||
message OnCreateSetRequest {
|
||||
// The host catalog that the set belongs to.
|
||||
controller.api.resources.hostcatalogs.v1.HostCatalog catalog = 10;
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -18,8 +18,16 @@ const _ = grpc.SupportPackageIsVersion7
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type HostPluginServiceClient interface {
|
||||
// OnCreateCatalog is a hook that runs when a host catalog is
|
||||
// created.
|
||||
// NormalizeCatalogData is a hook that passes attributes to the plugin and
|
||||
// allows those values to be normalized prior to creating or updating those
|
||||
// values in the host catalog data.
|
||||
//
|
||||
// NormalizeCatalogData is called before:
|
||||
// * OnCreateCatalog
|
||||
// * OnUpdateCatalog
|
||||
NormalizeCatalogData(ctx context.Context, in *NormalizeCatalogDataRequest, opts ...grpc.CallOption) (*NormalizeCatalogDataResponse, error)
|
||||
// OnCreateCatalog is a hook that runs when a
|
||||
// host catalog is created.
|
||||
OnCreateCatalog(ctx context.Context, in *OnCreateCatalogRequest, opts ...grpc.CallOption) (*OnCreateCatalogResponse, error)
|
||||
// OnUpdateCatalog is a hook that runs when a host catalog is
|
||||
// updated.
|
||||
@@ -27,6 +35,14 @@ type HostPluginServiceClient interface {
|
||||
// OnDeleteCatalog is a hook that runs when a host catalog is
|
||||
// deleted.
|
||||
OnDeleteCatalog(ctx context.Context, in *OnDeleteCatalogRequest, opts ...grpc.CallOption) (*OnDeleteCatalogResponse, error)
|
||||
// NormalizeSetData is a hook that passes attributes to the plugin and
|
||||
// allows those values to be normalized prior to creating or updating those
|
||||
// values in the host set data.
|
||||
//
|
||||
// NormalizeSetData is called before:
|
||||
// * OnCreateSet
|
||||
// * OnUpdateSet
|
||||
NormalizeSetData(ctx context.Context, in *NormalizeSetDataRequest, opts ...grpc.CallOption) (*NormalizeSetDataResponse, error)
|
||||
// OnCreateSet is a hook that runs when a host set is created.
|
||||
OnCreateSet(ctx context.Context, in *OnCreateSetRequest, opts ...grpc.CallOption) (*OnCreateSetResponse, error)
|
||||
// OnUpdateSet is a hook that runs when a host set is updated.
|
||||
@@ -45,6 +61,15 @@ func NewHostPluginServiceClient(cc grpc.ClientConnInterface) HostPluginServiceCl
|
||||
return &hostPluginServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *hostPluginServiceClient) NormalizeCatalogData(ctx context.Context, in *NormalizeCatalogDataRequest, opts ...grpc.CallOption) (*NormalizeCatalogDataResponse, error) {
|
||||
out := new(NormalizeCatalogDataResponse)
|
||||
err := c.cc.Invoke(ctx, "/plugin.v1.HostPluginService/NormalizeCatalogData", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *hostPluginServiceClient) OnCreateCatalog(ctx context.Context, in *OnCreateCatalogRequest, opts ...grpc.CallOption) (*OnCreateCatalogResponse, error) {
|
||||
out := new(OnCreateCatalogResponse)
|
||||
err := c.cc.Invoke(ctx, "/plugin.v1.HostPluginService/OnCreateCatalog", in, out, opts...)
|
||||
@@ -72,6 +97,15 @@ func (c *hostPluginServiceClient) OnDeleteCatalog(ctx context.Context, in *OnDel
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *hostPluginServiceClient) NormalizeSetData(ctx context.Context, in *NormalizeSetDataRequest, opts ...grpc.CallOption) (*NormalizeSetDataResponse, error) {
|
||||
out := new(NormalizeSetDataResponse)
|
||||
err := c.cc.Invoke(ctx, "/plugin.v1.HostPluginService/NormalizeSetData", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *hostPluginServiceClient) OnCreateSet(ctx context.Context, in *OnCreateSetRequest, opts ...grpc.CallOption) (*OnCreateSetResponse, error) {
|
||||
out := new(OnCreateSetResponse)
|
||||
err := c.cc.Invoke(ctx, "/plugin.v1.HostPluginService/OnCreateSet", in, out, opts...)
|
||||
@@ -112,8 +146,16 @@ func (c *hostPluginServiceClient) ListHosts(ctx context.Context, in *ListHostsRe
|
||||
// All implementations must embed UnimplementedHostPluginServiceServer
|
||||
// for forward compatibility
|
||||
type HostPluginServiceServer interface {
|
||||
// OnCreateCatalog is a hook that runs when a host catalog is
|
||||
// created.
|
||||
// NormalizeCatalogData is a hook that passes attributes to the plugin and
|
||||
// allows those values to be normalized prior to creating or updating those
|
||||
// values in the host catalog data.
|
||||
//
|
||||
// NormalizeCatalogData is called before:
|
||||
// * OnCreateCatalog
|
||||
// * OnUpdateCatalog
|
||||
NormalizeCatalogData(context.Context, *NormalizeCatalogDataRequest) (*NormalizeCatalogDataResponse, error)
|
||||
// OnCreateCatalog is a hook that runs when a
|
||||
// host catalog is created.
|
||||
OnCreateCatalog(context.Context, *OnCreateCatalogRequest) (*OnCreateCatalogResponse, error)
|
||||
// OnUpdateCatalog is a hook that runs when a host catalog is
|
||||
// updated.
|
||||
@@ -121,6 +163,14 @@ type HostPluginServiceServer interface {
|
||||
// OnDeleteCatalog is a hook that runs when a host catalog is
|
||||
// deleted.
|
||||
OnDeleteCatalog(context.Context, *OnDeleteCatalogRequest) (*OnDeleteCatalogResponse, error)
|
||||
// NormalizeSetData is a hook that passes attributes to the plugin and
|
||||
// allows those values to be normalized prior to creating or updating those
|
||||
// values in the host set data.
|
||||
//
|
||||
// NormalizeSetData is called before:
|
||||
// * OnCreateSet
|
||||
// * OnUpdateSet
|
||||
NormalizeSetData(context.Context, *NormalizeSetDataRequest) (*NormalizeSetDataResponse, error)
|
||||
// OnCreateSet is a hook that runs when a host set is created.
|
||||
OnCreateSet(context.Context, *OnCreateSetRequest) (*OnCreateSetResponse, error)
|
||||
// OnUpdateSet is a hook that runs when a host set is updated.
|
||||
@@ -136,6 +186,9 @@ type HostPluginServiceServer interface {
|
||||
type UnimplementedHostPluginServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedHostPluginServiceServer) NormalizeCatalogData(context.Context, *NormalizeCatalogDataRequest) (*NormalizeCatalogDataResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method NormalizeCatalogData not implemented")
|
||||
}
|
||||
func (UnimplementedHostPluginServiceServer) OnCreateCatalog(context.Context, *OnCreateCatalogRequest) (*OnCreateCatalogResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OnCreateCatalog not implemented")
|
||||
}
|
||||
@@ -145,6 +198,9 @@ func (UnimplementedHostPluginServiceServer) OnUpdateCatalog(context.Context, *On
|
||||
func (UnimplementedHostPluginServiceServer) OnDeleteCatalog(context.Context, *OnDeleteCatalogRequest) (*OnDeleteCatalogResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OnDeleteCatalog not implemented")
|
||||
}
|
||||
func (UnimplementedHostPluginServiceServer) NormalizeSetData(context.Context, *NormalizeSetDataRequest) (*NormalizeSetDataResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method NormalizeSetData not implemented")
|
||||
}
|
||||
func (UnimplementedHostPluginServiceServer) OnCreateSet(context.Context, *OnCreateSetRequest) (*OnCreateSetResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OnCreateSet not implemented")
|
||||
}
|
||||
@@ -170,6 +226,24 @@ func RegisterHostPluginServiceServer(s grpc.ServiceRegistrar, srv HostPluginServ
|
||||
s.RegisterService(&HostPluginService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _HostPluginService_NormalizeCatalogData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(NormalizeCatalogDataRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HostPluginServiceServer).NormalizeCatalogData(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/plugin.v1.HostPluginService/NormalizeCatalogData",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HostPluginServiceServer).NormalizeCatalogData(ctx, req.(*NormalizeCatalogDataRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _HostPluginService_OnCreateCatalog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(OnCreateCatalogRequest)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -224,6 +298,24 @@ func _HostPluginService_OnDeleteCatalog_Handler(srv interface{}, ctx context.Con
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _HostPluginService_NormalizeSetData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(NormalizeSetDataRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HostPluginServiceServer).NormalizeSetData(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/plugin.v1.HostPluginService/NormalizeSetData",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HostPluginServiceServer).NormalizeSetData(ctx, req.(*NormalizeSetDataRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _HostPluginService_OnCreateSet_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(OnCreateSetRequest)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -303,6 +395,10 @@ var HostPluginService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "plugin.v1.HostPluginService",
|
||||
HandlerType: (*HostPluginServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "NormalizeCatalogData",
|
||||
Handler: _HostPluginService_NormalizeCatalogData_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "OnCreateCatalog",
|
||||
Handler: _HostPluginService_OnCreateCatalog_Handler,
|
||||
@@ -315,6 +411,10 @@ var HostPluginService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "OnDeleteCatalog",
|
||||
Handler: _HostPluginService_OnDeleteCatalog_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "NormalizeSetData",
|
||||
Handler: _HostPluginService_NormalizeSetData_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "OnCreateSet",
|
||||
Handler: _HostPluginService_OnCreateSet_Handler,
|
||||
|
||||
Reference in new issue
Block a user