feat(handlers/host_catalogs): Support plugin host catalog worker filter
This commit is contained in:
1 parent
7449fd6f2a
commit
b8046a3ef3
12 files changed
+368
-174
No files matched your search
@@ -72,15 +72,22 @@ var (
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
validateWorkerFilterFn = validateWorkerFilterUnsupported
|
||||
workerFilterToProto = false
|
||||
)
|
||||
|
||||
func validateWorkerFilterUnsupported(_ string) error {
|
||||
return fmt.Errorf("Worker filter on host catalogs is an Enterprise-only feature")
|
||||
}
|
||||
|
||||
const domain = "host"
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
if staticMaskManager, err = handlers.NewMaskManager(
|
||||
context.Background(),
|
||||
handlers.MaskDestination{&store.HostCatalog{}},
|
||||
handlers.MaskDestination{&store.HostCatalog{}, &store.UnimplementedCatalogFields{}},
|
||||
handlers.MaskSource{&pb.HostCatalog{}},
|
||||
); err != nil {
|
||||
panic(err)
|
||||
@@ -871,6 +878,11 @@ func toProto(ctx context.Context, in host.Catalog, opt ...handlers.Option) (*pb.
|
||||
if outputFields.Has(globals.SecretsHmacField) {
|
||||
out.SecretsHmac = base58.Encode(h.GetSecretsHmac())
|
||||
}
|
||||
if outputFields.Has(globals.WorkerFilterField) && h.GetWorkerFilter() != "" {
|
||||
if workerFilterToProto {
|
||||
out.WorkerFilter = wrapperspb.String(h.GetWorkerFilter())
|
||||
}
|
||||
}
|
||||
if outputFields.Has(globals.AttributesField) {
|
||||
attrs := &structpb.Struct{}
|
||||
err := proto.Unmarshal(h.Attributes, attrs)
|
||||
@@ -918,6 +930,9 @@ func toStoragePluginCatalog(ctx context.Context, projectId, plgId string, item *
|
||||
if secrets := item.GetSecrets(); secrets != nil {
|
||||
opts = append(opts, hostplugin.WithSecrets(secrets))
|
||||
}
|
||||
if workerFilter := item.GetWorkerFilter(); workerFilter != nil {
|
||||
opts = append(opts, hostplugin.WithWorkerFilter(workerFilter.GetValue()))
|
||||
}
|
||||
hc, err := hostplugin.NewHostCatalog(ctx, projectId, plgId, opts...)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("Unable to build host set for creation"))
|
||||
@@ -959,6 +974,12 @@ func validateCreateRequest(req *pbs.CreateHostCatalogRequest) error {
|
||||
badFields[globals.PluginIdField] = "Can't set the plugin name field along with this field."
|
||||
badFields[globals.PluginNameField] = "Can't set the plugin id field along with this field."
|
||||
}
|
||||
if req.GetItem().GetWorkerFilter() != nil {
|
||||
err := validateWorkerFilterFn(req.GetItem().GetWorkerFilter().GetValue())
|
||||
if err != nil {
|
||||
badFields[globals.WorkerFilterField] = err.Error()
|
||||
}
|
||||
}
|
||||
default:
|
||||
badFields[globals.TypeField] = fmt.Sprintf("This is a required field and must be either %q or %q.", static.Subtype.String(), hostplugin.Subtype.String())
|
||||
}
|
||||
@@ -987,6 +1008,12 @@ func validateUpdateRequest(req *pbs.UpdateHostCatalogRequest) error {
|
||||
if req.GetItem().GetPlugin() != nil {
|
||||
badFields[globals.PluginField] = "This is a read only field."
|
||||
}
|
||||
if req.GetItem().GetWorkerFilter() != nil {
|
||||
err := validateWorkerFilterFn(req.GetItem().GetWorkerFilter().GetValue())
|
||||
if err != nil {
|
||||
badFields[globals.WorkerFilterField] = err.Error()
|
||||
}
|
||||
}
|
||||
}
|
||||
return badFields
|
||||
}, globals.StaticHostCatalogPrefix, globals.PluginHostCatalogPrefix, globals.PluginHostCatalogPreviousPrefix)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package host_catalogs_test
|
||||
package host_catalogs
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/authtoken"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/auth"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/daemon/controller/handlers/host_catalogs"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
authpb "github.com/hashicorp/boundary/internal/gen/controller/auth"
|
||||
@@ -187,7 +186,7 @@ func TestGet_Static(t *testing.T) {
|
||||
req := proto.Clone(toMerge).(*pbs.GetHostCatalogRequest)
|
||||
proto.Merge(req, tc.req)
|
||||
|
||||
s, err := host_catalogs.NewService(ctx, staticRepoFn, pluginHostRepoFn, pluginRepoFn, iamRepoFn, catalogServiceFn, 1000)
|
||||
s, err := NewService(ctx, staticRepoFn, pluginHostRepoFn, pluginRepoFn, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(err, "Couldn't create a new host catalog service.")
|
||||
|
||||
got, gErr := s.GetHostCatalog(auth.DisabledAuthTestContext(iamRepoFn, proj.GetPublicId()), req)
|
||||
@@ -296,7 +295,7 @@ func TestGet_Plugin(t *testing.T) {
|
||||
req := proto.Clone(toMerge).(*pbs.GetHostCatalogRequest)
|
||||
proto.Merge(req, tc.req)
|
||||
|
||||
s, err := host_catalogs.NewService(ctx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
s, err := NewService(ctx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(err, "Couldn't create a new host catalog service.")
|
||||
|
||||
got, gErr := s.GetHostCatalog(auth.DisabledAuthTestContext(iamRepoFn, proj.GetPublicId()), req)
|
||||
@@ -483,7 +482,7 @@ func TestList(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
s, err := host_catalogs.NewService(ctx, repoFn, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
s, err := NewService(ctx, repoFn, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(err, "Couldn't create new auth_method service.")
|
||||
|
||||
// Test with non-anon user
|
||||
@@ -578,7 +577,7 @@ func TestListPagination(t *testing.T) {
|
||||
gr := iam.TestRole(t, conn, "global")
|
||||
_ = iam.TestUserRole(t, conn, gr.GetPublicId(), at.GetIamUserId())
|
||||
_ = iam.TestRoleGrant(t, conn, gr.GetPublicId(), "ids=*;type=*;actions=*")
|
||||
s, err := host_catalogs.NewService(ctx, staticRepoFn, pluginHostRepoFn, pluginRepoFn, iamRepoFn, catalogServiceFn, 1000)
|
||||
s, err := NewService(ctx, staticRepoFn, pluginHostRepoFn, pluginRepoFn, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(t, err)
|
||||
|
||||
var allCatalogs []*pb.HostCatalog
|
||||
@@ -937,7 +936,7 @@ func TestDelete_Static(t *testing.T) {
|
||||
}
|
||||
hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0]
|
||||
|
||||
s, err := host_catalogs.NewService(ctx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
s, err := NewService(ctx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(t, err, "Couldn't create a new host catalog service.")
|
||||
|
||||
cases := []struct {
|
||||
@@ -1012,7 +1011,7 @@ func TestDelete_Plugin(t *testing.T) {
|
||||
plg := plugin.TestPlugin(t, conn, "test")
|
||||
hc := hostplugin.TestCatalog(t, conn, proj.GetPublicId(), plg.GetPublicId())
|
||||
|
||||
s, err := host_catalogs.NewService(ctx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
s, err := NewService(ctx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(t, err, "Couldn't create a new host catalog service.")
|
||||
|
||||
cases := []struct {
|
||||
@@ -1087,7 +1086,7 @@ func TestDelete_twice(t *testing.T) {
|
||||
}
|
||||
hc := static.TestCatalogs(t, conn, proj.GetPublicId(), 1)[0]
|
||||
|
||||
s, err := host_catalogs.NewService(testCtx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
s, err := NewService(testCtx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(err, "Couldn't create a new host catalog service.")
|
||||
req := &pbs.DeleteHostCatalogRequest{
|
||||
Id: hc.GetPublicId(),
|
||||
@@ -1224,7 +1223,7 @@ func TestCreate_Static(t *testing.T) {
|
||||
req := proto.Clone(toMerge).(*pbs.CreateHostCatalogRequest)
|
||||
proto.Merge(req, tc.req)
|
||||
|
||||
s, err := host_catalogs.NewService(ctx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
s, err := NewService(ctx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(err, "Failed to create a new host catalog service.")
|
||||
|
||||
got, gErr := s.CreateHostCatalog(auth.DisabledAuthTestContext(iamRepoFn, proj.GetPublicId()), req)
|
||||
@@ -1267,7 +1266,6 @@ func TestCreate_Static(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreate_Plugin(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
@@ -1289,6 +1287,12 @@ func TestCreate_Plugin(t *testing.T) {
|
||||
return host.NewCatalogRepository(ctx, rw, rw)
|
||||
}
|
||||
|
||||
currentValidateWorkerFilterFn := validateWorkerFilterFn
|
||||
validateWorkerFilterFn = validateWorkerFilterUnsupported
|
||||
t.Cleanup(func() {
|
||||
validateWorkerFilterFn = currentValidateWorkerFilterFn
|
||||
})
|
||||
|
||||
name := "test"
|
||||
plg := plugin.TestPlugin(t, conn, name)
|
||||
pluginHostRepo := func() (*hostplugin.Repository, error) {
|
||||
@@ -1406,6 +1410,17 @@ func TestCreate_Plugin(t *testing.T) {
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Unsupported worker filter field",
|
||||
req: &pbs.CreateHostCatalogRequest{Item: &pb.HostCatalog{
|
||||
ScopeId: proj.GetPublicId(),
|
||||
Type: hostplugin.Subtype.String(),
|
||||
PluginId: plg.GetPublicId(),
|
||||
WorkerFilter: wrapperspb.String(`"dev" in "/tags/type"`),
|
||||
}},
|
||||
res: nil,
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
@@ -1413,7 +1428,7 @@ func TestCreate_Plugin(t *testing.T) {
|
||||
req := proto.Clone(toMerge).(*pbs.CreateHostCatalogRequest)
|
||||
proto.Merge(req, tc.req)
|
||||
|
||||
s, err := host_catalogs.NewService(ctx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
s, err := NewService(ctx, repo, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(err, "Failed to create a new host catalog service.")
|
||||
|
||||
got, gErr := s.CreateHostCatalog(auth.DisabledAuthTestContext(iamRepoFn, proj.GetPublicId()), req)
|
||||
@@ -1482,7 +1497,7 @@ func TestUpdate_Static(t *testing.T) {
|
||||
catalogServiceFn := func() (*host.CatalogRepository, error) {
|
||||
return host.NewCatalogRepository(ctx, rw, rw)
|
||||
}
|
||||
tested, err := host_catalogs.NewService(ctx, repoFn, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
tested, err := NewService(ctx, repoFn, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(t, err, "Failed to create a new host catalog service.")
|
||||
|
||||
hc, err := static.NewHostCatalog(ctx, proj.GetPublicId(), static.WithName("default"), static.WithDescription("default"))
|
||||
@@ -1840,7 +1855,6 @@ func TestUpdate_Static(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdate_Plugin(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCtx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
@@ -1873,7 +1887,14 @@ func TestUpdate_Plugin(t *testing.T) {
|
||||
catalogServiceFn := func() (*host.CatalogRepository, error) {
|
||||
return host.NewCatalogRepository(testCtx, rw, rw)
|
||||
}
|
||||
tested, err := host_catalogs.NewService(testCtx, repoFn, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
|
||||
currentValidateWorkerFilterFn := validateWorkerFilterFn
|
||||
validateWorkerFilterFn = validateWorkerFilterUnsupported
|
||||
t.Cleanup(func() {
|
||||
validateWorkerFilterFn = currentValidateWorkerFilterFn
|
||||
})
|
||||
|
||||
tested, err := NewService(testCtx, repoFn, pluginHostRepo, pluginRepo, iamRepoFn, catalogServiceFn, 1000)
|
||||
require.NoError(t, err, "Failed to create a new host catalog service.")
|
||||
|
||||
ctx := auth.DisabledAuthTestContext(iamRepoFn, proj.GetPublicId())
|
||||
@@ -1936,6 +1957,12 @@ func TestUpdate_Plugin(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
updateWorkerFilter := func(i *wrappers.StringValue) updateFn {
|
||||
return func(c *pb.HostCatalog) {
|
||||
c.WorkerFilter = i
|
||||
}
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
masks []string
|
||||
@@ -2058,6 +2085,15 @@ func TestUpdate_Plugin(t *testing.T) {
|
||||
},
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Add worker filter",
|
||||
masks: []string{"worker_filter"},
|
||||
changes: []updateFn{
|
||||
clearReadOnlyFields(),
|
||||
updateWorkerFilter(wrapperspb.String(`"dev" in "/tags/type"`)),
|
||||
},
|
||||
err: handlers.ApiErrorWithCode(codes.InvalidArgument),
|
||||
},
|
||||
{
|
||||
name: "Unset Name",
|
||||
masks: []string{"name"},
|
||||
|
||||
Reference in new issue
Block a user