Skip to content

Commit 7ec6989

Browse files
authored
Merge pull request #4 from dmcgowan/handle-skip-error
Properly handle skipped plugins in plugin get
2 parents b2f449e + fc07872 commit 7ec6989

2 files changed

Lines changed: 163 additions & 17 deletions

File tree

context.go

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -135,18 +135,28 @@ func (ps *Set) GetAll() []*Plugin {
135135
// GetByType should be used. If only one is expected, then to switch plugins,
136136
// disable or remove the unused plugins of the same type.
137137
func (i *InitContext) GetSingle(t Type) (interface{}, error) {
138-
pt, ok := i.plugins.byTypeAndID[t]
139-
if !ok || len(pt) == 0 {
140-
return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound)
141-
}
142-
if len(pt) > 1 {
143-
return nil, fmt.Errorf("multiple plugins registered for %s: %w", t, ErrPluginMultipleInstances)
138+
var (
139+
found bool
140+
instance interface{}
141+
)
142+
for _, v := range i.plugins.byTypeAndID[t] {
143+
i, err := v.Instance()
144+
if err != nil {
145+
if IsSkipPlugin(err) {
146+
continue
147+
}
148+
return i, err
149+
}
150+
if found {
151+
return nil, fmt.Errorf("multiple plugins registered for %s: %w", t, ErrPluginMultipleInstances)
152+
}
153+
instance = i
154+
found = true
144155
}
145-
var p *Plugin
146-
for _, v := range pt {
147-
p = v
156+
if !found {
157+
return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound)
148158
}
149-
return p.Instance()
159+
return instance, nil
150160
}
151161

152162
// Plugins returns plugin set
@@ -170,19 +180,20 @@ func (i *InitContext) GetByID(t Type, id string) (interface{}, error) {
170180

171181
// GetByType returns all plugins with the specific type.
172182
func (i *InitContext) GetByType(t Type) (map[string]interface{}, error) {
173-
pt, ok := i.plugins.byTypeAndID[t]
174-
if !ok {
175-
return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound)
176-
}
177-
178-
pi := make(map[string]interface{}, len(pt))
179-
for id, p := range pt {
183+
pi := map[string]interface{}{}
184+
for id, p := range i.plugins.byTypeAndID[t] {
180185
i, err := p.Instance()
181186
if err != nil {
187+
if IsSkipPlugin(err) {
188+
continue
189+
}
182190
return nil, err
183191
}
184192
pi[id] = i
185193
}
194+
if len(pi) == 0 {
195+
return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound)
196+
}
186197

187198
return pi, nil
188199
}

plugin_test.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package plugin
1818

1919
import (
20+
"errors"
21+
"fmt"
2022
"testing"
2123
)
2224

@@ -377,3 +379,136 @@ func TestPluginGraph(t *testing.T) {
377379
cmpOrdered(t, ordered, testcase.expectedURI)
378380
}
379381
}
382+
383+
func TestGetPlugins(t *testing.T) {
384+
otherError := fmt.Errorf("other error")
385+
plugins := NewPluginSet()
386+
for _, p := range []*Plugin{
387+
testPlugin("type1", "id1", "id1", nil),
388+
testPlugin("type1", "id2", "id2", ErrSkipPlugin),
389+
testPlugin("type2", "id3", "id3", ErrSkipPlugin),
390+
testPlugin("type3", "id4", "id4", nil),
391+
testPlugin("type4", "id5", "id5", nil),
392+
testPlugin("type4", "id6", "id6", nil),
393+
testPlugin("type5", "id7", "id7", otherError),
394+
} {
395+
plugins.Add(p)
396+
}
397+
398+
ic := InitContext{
399+
plugins: plugins,
400+
}
401+
402+
for _, tc := range []struct {
403+
pluginType string
404+
err error
405+
}{
406+
{"type1", nil},
407+
{"type2", ErrPluginNotFound},
408+
{"type3", nil},
409+
{"type4", ErrPluginMultipleInstances},
410+
{"type5", otherError},
411+
} {
412+
t.Run("GetSingle", func(t *testing.T) {
413+
instance, err := ic.GetSingle(Type(tc.pluginType))
414+
if err != nil {
415+
if tc.err == nil {
416+
t.Fatalf("unexpected error %v", err)
417+
} else if !errors.Is(err, tc.err) {
418+
t.Fatalf("unexpected error %v, expected %v", err, tc.err)
419+
}
420+
return
421+
} else if tc.err != nil {
422+
t.Fatalf("expected error %v, got no error", tc.err)
423+
}
424+
_, ok := instance.(string)
425+
if !ok {
426+
t.Fatalf("unexpected instance value %v", instance)
427+
}
428+
})
429+
}
430+
431+
for _, tc := range []struct {
432+
pluginType string
433+
expected []string
434+
err error
435+
}{
436+
{"type1", []string{"id1"}, nil},
437+
{"type2", nil, ErrPluginNotFound},
438+
{"type3", []string{"id4"}, nil},
439+
{"type4", []string{"id5", "id6"}, nil},
440+
{"type5", nil, otherError},
441+
} {
442+
t.Run("GetByType", func(t *testing.T) {
443+
m, err := ic.GetByType(Type(tc.pluginType))
444+
if err != nil {
445+
if tc.err == nil {
446+
t.Fatalf("unexpected error %v", err)
447+
} else if !errors.Is(err, tc.err) {
448+
t.Fatalf("unexpected error %v, expected %v", err, tc.err)
449+
}
450+
return
451+
} else if tc.err != nil {
452+
t.Fatalf("expected error %v, got no error", tc.err)
453+
}
454+
455+
if len(m) != len(tc.expected) {
456+
t.Fatalf("unexpected result %v, expected %v", m, tc.expected)
457+
}
458+
for _, v := range tc.expected {
459+
instance, ok := m[v]
460+
if !ok {
461+
t.Errorf("missing value for %q", v)
462+
continue
463+
}
464+
if instance.(string) != v {
465+
t.Errorf("unexpected value %v, expected %v", instance, v)
466+
}
467+
}
468+
})
469+
}
470+
471+
for _, tc := range []struct {
472+
pluginType string
473+
id string
474+
err error
475+
}{
476+
{"type1", "id1", nil},
477+
{"type1", "id2", ErrSkipPlugin},
478+
{"type2", "id3", ErrSkipPlugin},
479+
{"type3", "id4", nil},
480+
{"type4", "id5", nil},
481+
{"type4", "id6", nil},
482+
{"type5", "id7", otherError},
483+
} {
484+
t.Run("GetByID", func(t *testing.T) {
485+
instance, err := ic.GetByID(Type(tc.pluginType), tc.id)
486+
if err != nil {
487+
if tc.err == nil {
488+
t.Fatalf("unexpected error %v", err)
489+
} else if !errors.Is(err, tc.err) {
490+
t.Fatalf("unexpected error %v, expected %v", err, tc.err)
491+
}
492+
return
493+
} else if tc.err != nil {
494+
t.Fatalf("expected error %v, got no error", tc.err)
495+
}
496+
497+
if instance.(string) != tc.id {
498+
t.Errorf("unexpected value %v, expected %v", instance, tc.id)
499+
}
500+
})
501+
}
502+
503+
}
504+
505+
func testPlugin(t Type, id string, i interface{}, err error) *Plugin {
506+
return &Plugin{
507+
Registration: Registration{
508+
Type: t,
509+
ID: id,
510+
},
511+
instance: i,
512+
err: err,
513+
}
514+
}

0 commit comments

Comments
 (0)