Skip to content

Commit 49a507e

Browse files
committed
PR feedback
1 parent f6e8702 commit 49a507e

File tree

3 files changed

+70
-29
lines changed

3 files changed

+70
-29
lines changed

cmd/config/plugins/add.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ in the category, the command fails with an error. To update an existing plugin,
8585
&c.flows,
8686
flagFlow,
8787
nil,
88-
"Flow to execute plugin in: request, response (can be repeated)",
88+
fmt.Sprintf(
89+
"Flow during which, the plugin should execute (%s) (can be repeated)",
90+
strings.Join(config.OrderedFlowNames(), ", "),
91+
),
8992
)
9093
_ = cobraCmd.MarkFlagRequired(flagFlow)
9194

@@ -128,16 +131,17 @@ func (c *AddCmd) run(cmd *cobra.Command, args []string) error {
128131
)
129132
}
130133

131-
flowsMap := config.ParseFlows(c.flows)
132-
if len(flowsMap) == 0 {
133-
return fmt.Errorf("at least one valid flow is required (must be 'request' or 'response')")
134+
flows := config.ParseFlowsDistinct(c.flows)
135+
if len(flows) == 0 {
136+
return fmt.Errorf(
137+
"at least one valid flow is required (%s)",
138+
strings.Join(config.OrderedFlowNames(), ", "),
139+
)
134140
}
135141

136-
parsedFlows := slices.Sorted(maps.Keys(flowsMap))
137-
138142
entry := config.PluginEntry{
139143
Name: pluginName,
140-
Flows: parsedFlows,
144+
Flows: slices.Sorted(maps.Keys(flows)),
141145
}
142146

143147
// Set optional fields only if they were provided.

internal/config/plugin_config.go

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,10 @@ func (f Flow) IsValid() bool {
9999
return ok
100100
}
101101

102-
// ParseFlows validates and reduces flow strings to a distinct set.
102+
// ParseFlowsDistinct validates and reduces flow strings to a distinct set.
103103
// Flow strings are normalized before validation.
104104
// Invalid flows are silently ignored. Returns an empty map if no valid flows are found.
105-
func ParseFlows(flags []string) map[Flow]struct{} {
105+
func ParseFlowsDistinct(flags []string) map[Flow]struct{} {
106106
valid := make(map[Flow]struct{}, len(flows))
107107

108108
for _, s := range flags {
@@ -244,12 +244,10 @@ func (e *PluginEntry) Validate() error {
244244
} else {
245245
seen := make(map[Flow]struct{})
246246
for _, flow := range e.Flows {
247-
// Check for valid flow values.
248247
if !flow.IsValid() {
249-
validationErrors = append(
250-
validationErrors,
251-
fmt.Errorf("invalid flow '%s', must be '%s' or '%s'", flow, FlowRequest, FlowResponse),
252-
)
248+
allowedFlows := strings.Join(OrderedFlowNames(), ", ")
249+
err := fmt.Errorf("invalid flow '%s' (allowed: %s)", flow, allowedFlows)
250+
validationErrors = append(validationErrors, err)
253251
}
254252

255253
// Check for duplicates.
@@ -386,7 +384,9 @@ func (p *PluginConfig) plugin(category Category, name string) (PluginEntry, bool
386384

387385
// upsertPlugin creates or updates a plugin entry.
388386
func (p *PluginConfig) upsertPlugin(category Category, entry PluginEntry) (context.UpsertResult, error) {
389-
if strings.TrimSpace(entry.Name) == "" {
387+
// Handle sanitizing the plugin name.
388+
entry.Name = strings.TrimSpace(entry.Name)
389+
if entry.Name == "" {
390390
return context.Noop, fmt.Errorf("plugin name cannot be empty")
391391
}
392392

@@ -399,11 +399,9 @@ func (p *PluginConfig) upsertPlugin(category Category, entry PluginEntry) (conte
399399
return context.Noop, err
400400
}
401401

402-
name := strings.TrimSpace(entry.Name)
403-
404402
// Check if plugin already exists.
405403
for i, existing := range *slice {
406-
if existing.Name != name {
404+
if existing.Name != entry.Name {
407405
continue
408406
}
409407

@@ -526,10 +524,22 @@ func OrderedCategories() Categories {
526524
return slices.Clone(orderedCategories)
527525
}
528526

527+
// OrderedFlowNames returns the names of allowed flows in order.
528+
func OrderedFlowNames() []string {
529+
flows := slices.Sorted(maps.Keys(flows))
530+
531+
flowNames := make([]string, len(flows))
532+
for i, f := range flows {
533+
flowNames[i] = string(f)
534+
}
535+
536+
return flowNames
537+
}
538+
529539
// Set is used by Cobra to set the category value from a string.
530540
// NOTE: This is also required by Cobra as part of implementing flag.Value.
531541
func (c *Category) Set(v string) error {
532-
v = strings.ToLower(strings.TrimSpace(v))
542+
v = filter.NormalizeString(v)
533543
allowed := OrderedCategories()
534544

535545
for _, a := range allowed {

internal/config/plugin_config_test.go

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ import (
88
"github.com/mozilla-ai/mcpd/v2/internal/context"
99
)
1010

11+
func testPluginStringPtr(t *testing.T, s string) *string {
12+
t.Helper()
13+
return &s
14+
}
15+
16+
func testPluginBoolPtr(t *testing.T, b bool) *bool {
17+
t.Helper()
18+
return &b
19+
}
20+
1121
func TestPluginEntry_Validate(t *testing.T) {
1222
t.Parallel()
1323

@@ -395,6 +405,7 @@ func TestPluginConfig_upsertPlugin(t *testing.T) {
395405
entry PluginEntry
396406
wantResult context.UpsertResult
397407
wantErr bool
408+
wantName string
398409
}{
399410
{
400411
name: "create new plugin",
@@ -404,6 +415,7 @@ func TestPluginConfig_upsertPlugin(t *testing.T) {
404415
Name: "jwt-auth",
405416
Flows: []Flow{FlowRequest},
406417
},
418+
wantName: "jwt-auth",
407419
wantResult: context.Created,
408420
wantErr: false,
409421
},
@@ -419,6 +431,7 @@ func TestPluginConfig_upsertPlugin(t *testing.T) {
419431
Name: "jwt-auth",
420432
Flows: []Flow{FlowRequest, FlowResponse},
421433
},
434+
wantName: "jwt-auth",
422435
wantResult: context.Updated,
423436
wantErr: false,
424437
},
@@ -434,6 +447,7 @@ func TestPluginConfig_upsertPlugin(t *testing.T) {
434447
Name: "jwt-auth",
435448
Flows: []Flow{FlowRequest},
436449
},
450+
wantName: "jwt-auth",
437451
wantResult: context.Noop,
438452
wantErr: false,
439453
},
@@ -459,6 +473,18 @@ func TestPluginConfig_upsertPlugin(t *testing.T) {
459473
wantResult: context.Noop,
460474
wantErr: true,
461475
},
476+
{
477+
name: "trim whitespace",
478+
initial: &PluginConfig{},
479+
category: CategoryAuthentication,
480+
entry: PluginEntry{
481+
Name: " jwt-auth ",
482+
Flows: []Flow{FlowRequest},
483+
},
484+
wantName: "jwt-auth",
485+
wantResult: context.Created,
486+
wantErr: false,
487+
},
462488
}
463489

464490
for _, tc := range tests {
@@ -471,6 +497,10 @@ func TestPluginConfig_upsertPlugin(t *testing.T) {
471497
require.Error(t, err)
472498
} else {
473499
require.NoError(t, err)
500+
501+
updated, found := tc.initial.plugin(tc.category, tc.wantName)
502+
require.True(t, found)
503+
require.Equal(t, tc.wantName, updated.Name)
474504
}
475505

476506
require.Equal(t, tc.wantResult, result)
@@ -790,7 +820,7 @@ func TestFlow_IsValid(t *testing.T) {
790820
}
791821
}
792822

793-
func TestParseFlows(t *testing.T) {
823+
func TestParseFlowsDistinct(t *testing.T) {
794824
t.Parallel()
795825

796826
tests := []struct {
@@ -866,18 +896,15 @@ func TestParseFlows(t *testing.T) {
866896
t.Run(tc.name, func(t *testing.T) {
867897
t.Parallel()
868898

869-
result := ParseFlows(tc.input)
899+
result := ParseFlowsDistinct(tc.input)
870900
require.Equal(t, tc.expected, result)
871901
})
872902
}
873903
}
874904

875-
func testPluginStringPtr(t *testing.T, s string) *string {
876-
t.Helper()
877-
return &s
878-
}
879-
880-
func testPluginBoolPtr(t *testing.T, b bool) *bool {
881-
t.Helper()
882-
return &b
905+
func TestAddCmd_OrderedFlowNames(t *testing.T) {
906+
flows := OrderedFlowNames()
907+
require.Len(t, flows, 2)
908+
require.Equal(t, "request", flows[0])
909+
require.Equal(t, "response", flows[1])
883910
}

0 commit comments

Comments
 (0)