Skip to content
This repository was archived by the owner on Jan 21, 2020. It is now read-only.

Commit ea9c59d

Browse files
author
David Chung
authored
testing refactor; implement metadata/ help for exported template functions (#386)
Signed-off-by: David Chung <[email protected]>
1 parent 2efa1fd commit ea9c59d

File tree

22 files changed

+517
-378
lines changed

22 files changed

+517
-378
lines changed

examples/flavor/swarm/flavor.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ type baseFlavor struct {
6464
initScript *template.Template
6565
}
6666

67+
// Funcs implements the template.FunctionExporter interface that allows the RPC server to expose help on the
68+
// functions it exports
69+
func (s *baseFlavor) Funcs() []template.Function {
70+
return (&templateContext{}).Funcs()
71+
}
72+
6773
// Validate checks the configuration of flavor plugin.
6874
func (s *baseFlavor) Validate(flavorProperties *types.Any, allocation group_types.AllocationMethod) error {
6975
if flavorProperties == nil {

pkg/rpc/client/info.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ type InfoClient struct {
2525
// GetInfo implements the Info interface and returns the metadata about the plugin
2626
func (i *InfoClient) GetInfo() (plugin.Info, error) {
2727
meta := plugin.Info{}
28-
resp, err := i.client.Get("http://d" + rpc.InfoURL)
28+
resp, err := i.client.Get("http://d" + rpc.APIURL)
2929
if err != nil {
3030
return meta, err
3131
}

pkg/rpc/flavor/rpc_multi_test.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
rpc_server "github.com/docker/infrakit/pkg/rpc/server"
1111
"github.com/docker/infrakit/pkg/spi/flavor"
1212
"github.com/docker/infrakit/pkg/spi/instance"
13+
testing_flavor "github.com/docker/infrakit/pkg/testing/flavor"
1314
"github.com/docker/infrakit/pkg/types"
1415
"github.com/stretchr/testify/require"
1516
)
@@ -33,13 +34,13 @@ func TestFlavorMultiPluginValidate(t *testing.T) {
3334

3435
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServerWithTypes(
3536
map[string]flavor.Plugin{
36-
"type1": &testPlugin{
37+
"type1": &testing_flavor.Plugin{
3738
DoValidate: func(flavorProperties *types.Any, allocation group_types.AllocationMethod) error {
3839
inputFlavorPropertiesActual1 <- flavorProperties
3940
return nil
4041
},
4142
},
42-
"type2": &testPlugin{
43+
"type2": &testing_flavor.Plugin{
4344
DoValidate: func(flavorProperties *types.Any, allocation group_types.AllocationMethod) error {
4445
inputFlavorPropertiesActual2 <- flavorProperties
4546
return errors.New("something-went-wrong")
@@ -82,7 +83,7 @@ func TestFlavorMultiPluginPrepare(t *testing.T) {
8283

8384
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServerWithTypes(
8485
map[string]flavor.Plugin{
85-
"type1": &testPlugin{
86+
"type1": &testing_flavor.Plugin{
8687
DoPrepare: func(
8788
flavorProperties *types.Any,
8889
instanceSpec instance.Spec,
@@ -94,7 +95,7 @@ func TestFlavorMultiPluginPrepare(t *testing.T) {
9495
return instanceSpec, nil
9596
},
9697
},
97-
"type2": &testPlugin{
98+
"type2": &testing_flavor.Plugin{
9899
DoPrepare: func(
99100
flavorProperties *types.Any,
100101
instanceSpec instance.Spec,
@@ -155,14 +156,14 @@ func TestFlavorMultiPluginHealthy(t *testing.T) {
155156

156157
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServerWithTypes(
157158
map[string]flavor.Plugin{
158-
"type1": &testPlugin{
159+
"type1": &testing_flavor.Plugin{
159160
DoHealthy: func(properties *types.Any, inst instance.Description) (flavor.Health, error) {
160161
inputPropertiesActual1 <- properties
161162
inputInstanceActual1 <- inst
162163
return flavor.Healthy, nil
163164
},
164165
},
165-
"type2": &testPlugin{
166+
"type2": &testing_flavor.Plugin{
166167
DoHealthy: func(flavorProperties *types.Any, inst instance.Description) (flavor.Health, error) {
167168
inputPropertiesActual2 <- flavorProperties
168169
inputInstanceActual2 <- inst
@@ -211,14 +212,14 @@ func TestFlavorMultiPluginDrain(t *testing.T) {
211212

212213
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServerWithTypes(
213214
map[string]flavor.Plugin{
214-
"type1": &testPlugin{
215+
"type1": &testing_flavor.Plugin{
215216
DoDrain: func(properties *types.Any, inst instance.Description) error {
216217
inputPropertiesActual1 <- properties
217218
inputInstanceActual1 <- inst
218219
return nil
219220
},
220221
},
221-
"type2": &testPlugin{
222+
"type2": &testing_flavor.Plugin{
222223
DoDrain: func(flavorProperties *types.Any, inst instance.Description) error {
223224
inputPropertiesActual2 <- flavorProperties
224225
inputInstanceActual2 <- inst

pkg/rpc/flavor/rpc_test.go

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
rpc_server "github.com/docker/infrakit/pkg/rpc/server"
1111
"github.com/docker/infrakit/pkg/spi/flavor"
1212
"github.com/docker/infrakit/pkg/spi/instance"
13+
testing_flavor "github.com/docker/infrakit/pkg/testing/flavor"
1314
"github.com/docker/infrakit/pkg/types"
1415
"github.com/stretchr/testify/require"
1516
"io/ioutil"
@@ -27,41 +28,14 @@ func tempSocket() string {
2728
return path.Join(dir, "flavor-impl-test")
2829
}
2930

30-
type testPlugin struct {
31-
DoValidate func(flavorProperties *types.Any, allocation group_types.AllocationMethod) error
32-
DoPrepare func(flavorProperties *types.Any, spec instance.Spec,
33-
allocation group_types.AllocationMethod) (instance.Spec, error)
34-
DoHealthy func(flavorProperties *types.Any, inst instance.Description) (flavor.Health, error)
35-
DoDrain func(flavorProperties *types.Any, inst instance.Description) error
36-
}
37-
38-
func (t *testPlugin) Validate(flavorProperties *types.Any, allocation group_types.AllocationMethod) error {
39-
return t.DoValidate(flavorProperties, allocation)
40-
}
41-
42-
func (t *testPlugin) Prepare(flavorProperties *types.Any,
43-
spec instance.Spec,
44-
allocation group_types.AllocationMethod) (instance.Spec, error) {
45-
46-
return t.DoPrepare(flavorProperties, spec, allocation)
47-
}
48-
49-
func (t *testPlugin) Healthy(flavorProperties *types.Any, inst instance.Description) (flavor.Health, error) {
50-
return t.DoHealthy(flavorProperties, inst)
51-
}
52-
53-
func (t *testPlugin) Drain(flavorProperties *types.Any, inst instance.Description) error {
54-
return t.DoDrain(flavorProperties, inst)
55-
}
56-
5731
func TestFlavorPluginValidate(t *testing.T) {
5832
socketPath := tempSocket()
5933
name := filepath.Base(socketPath)
6034

6135
inputFlavorPropertiesActual := make(chan *types.Any, 1)
6236
inputFlavorProperties := types.AnyString(`{"flavor":"zookeeper","role":"leader"}`)
6337

64-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
38+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_flavor.Plugin{
6539
DoValidate: func(flavorProperties *types.Any, allocation group_types.AllocationMethod) error {
6640
inputFlavorPropertiesActual <- flavorProperties
6741
return nil
@@ -83,7 +57,7 @@ func TestFlavorPluginValidateError(t *testing.T) {
8357
inputFlavorPropertiesActual := make(chan *types.Any, 1)
8458
inputFlavorProperties := types.AnyString(`{"flavor":"zookeeper","role":"leader"}`)
8559

86-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
60+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_flavor.Plugin{
8761
DoValidate: func(flavorProperties *types.Any, allocation group_types.AllocationMethod) error {
8862
inputFlavorPropertiesActual <- flavorProperties
8963
return errors.New("something-went-wrong")
@@ -111,7 +85,7 @@ func TestFlavorPluginPrepare(t *testing.T) {
11185
Tags: map[string]string{"foo": "bar"},
11286
}
11387

114-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
88+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_flavor.Plugin{
11589
DoPrepare: func(
11690
flavorProperties *types.Any,
11791
instanceSpec instance.Spec,
@@ -150,7 +124,7 @@ func TestFlavorPluginPrepareError(t *testing.T) {
150124
Tags: map[string]string{"foo": "bar"},
151125
}
152126

153-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
127+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_flavor.Plugin{
154128
DoPrepare: func(
155129
flavorProperties *types.Any,
156130
instanceSpec instance.Spec,
@@ -188,7 +162,7 @@ func TestFlavorPluginHealthy(t *testing.T) {
188162
ID: instance.ID("foo"),
189163
Tags: map[string]string{"foo": "bar"},
190164
}
191-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
165+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_flavor.Plugin{
192166
DoHealthy: func(properties *types.Any, inst instance.Description) (flavor.Health, error) {
193167
inputPropertiesActual <- properties
194168
inputInstanceActual <- inst
@@ -217,7 +191,7 @@ func TestFlavorPluginHealthyError(t *testing.T) {
217191
ID: instance.ID("foo"),
218192
Tags: map[string]string{"foo": "bar"},
219193
}
220-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
194+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_flavor.Plugin{
221195
DoHealthy: func(flavorProperties *types.Any, inst instance.Description) (flavor.Health, error) {
222196
inputPropertiesActual <- flavorProperties
223197
inputInstanceActual <- inst
@@ -246,7 +220,7 @@ func TestFlavorPluginDrain(t *testing.T) {
246220
ID: instance.ID("foo"),
247221
Tags: map[string]string{"foo": "bar"},
248222
}
249-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
223+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_flavor.Plugin{
250224
DoDrain: func(properties *types.Any, inst instance.Description) error {
251225
inputPropertiesActual <- properties
252226
inputInstanceActual <- inst
@@ -273,7 +247,7 @@ func TestFlavorPluginDrainError(t *testing.T) {
273247
ID: instance.ID("foo"),
274248
Tags: map[string]string{"foo": "bar"},
275249
}
276-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
250+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_flavor.Plugin{
277251
DoDrain: func(flavorProperties *types.Any, inst instance.Description) error {
278252
inputPropertiesActual <- flavorProperties
279253
inputInstanceActual <- inst

pkg/rpc/flavor/service.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/docker/infrakit/pkg/spi"
88
"github.com/docker/infrakit/pkg/spi/flavor"
9+
"github.com/docker/infrakit/pkg/template"
910
"github.com/docker/infrakit/pkg/types"
1011
)
1112

@@ -39,6 +40,43 @@ func (p *Flavor) VendorInfo() *spi.VendorInfo {
3940
return nil
4041
}
4142

43+
// Funcs implements the template.FunctionExporter method to expose help for plugin's template functions
44+
func (p *Flavor) Funcs() []template.Function {
45+
f, is := p.plugin.(template.FunctionExporter)
46+
if !is {
47+
return []template.Function{}
48+
}
49+
return f.Funcs()
50+
}
51+
52+
// Types implements server.TypedFunctionExporter
53+
func (p *Flavor) Types() []string {
54+
if p.typedPlugins == nil {
55+
return nil
56+
}
57+
list := []string{}
58+
for k := range p.typedPlugins {
59+
list = append(list, k)
60+
}
61+
return list
62+
}
63+
64+
// FuncsByType implements server.TypedFunctionExporter
65+
func (p *Flavor) FuncsByType(t string) []template.Function {
66+
if p.typedPlugins == nil {
67+
return nil
68+
}
69+
fp, has := p.typedPlugins[t]
70+
if !has {
71+
return nil
72+
}
73+
exp, is := fp.(template.FunctionExporter)
74+
if !is {
75+
return nil
76+
}
77+
return exp.Funcs()
78+
}
79+
4280
// SetExampleProperties sets the rpc request with any example properties/ custom type
4381
func (p *Flavor) SetExampleProperties(request interface{}) {
4482
// TODO(chungers) - support typed plugins

pkg/rpc/group/rpc_test.go

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,13 @@ import (
77
rpc_server "github.com/docker/infrakit/pkg/rpc/server"
88
"github.com/docker/infrakit/pkg/spi/group"
99
"github.com/docker/infrakit/pkg/spi/instance"
10+
testing_group "github.com/docker/infrakit/pkg/testing/group"
1011
"github.com/docker/infrakit/pkg/types"
1112
"github.com/stretchr/testify/require"
1213
"io/ioutil"
1314
"path"
1415
)
1516

16-
type testPlugin struct {
17-
DoCommitGroup func(grp group.Spec, pretend bool) (string, error)
18-
DoFreeGroup func(id group.ID) error
19-
DoDescribeGroup func(id group.ID) (group.Description, error)
20-
DoDestroyGroup func(id group.ID) error
21-
DoInspectGroups func() ([]group.Spec, error)
22-
}
23-
24-
func (t *testPlugin) CommitGroup(grp group.Spec, pretend bool) (string, error) {
25-
return t.DoCommitGroup(grp, pretend)
26-
}
27-
func (t *testPlugin) FreeGroup(id group.ID) error {
28-
return t.DoFreeGroup(id)
29-
}
30-
func (t *testPlugin) DescribeGroup(id group.ID) (group.Description, error) {
31-
return t.DoDescribeGroup(id)
32-
}
33-
func (t *testPlugin) DestroyGroup(id group.ID) error {
34-
return t.DoDestroyGroup(id)
35-
}
36-
func (t *testPlugin) InspectGroups() ([]group.Spec, error) {
37-
return t.DoInspectGroups()
38-
}
39-
4017
func must(p group.Plugin, err error) group.Plugin {
4118
if err != nil {
4219
panic(err)
@@ -62,7 +39,7 @@ func TestGroupPluginCommitGroup(t *testing.T) {
6239
Properties: types.AnyString(`{"foo":"bar"}`),
6340
}
6441

65-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
42+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_group.Plugin{
6643
DoCommitGroup: func(req group.Spec, pretend bool) (string, error) {
6744
groupSpecActual <- req
6845
return "commit details", nil
@@ -88,7 +65,7 @@ func TestGroupPluginCommitGroupError(t *testing.T) {
8865
Properties: types.AnyString(`{"foo":"bar"}`),
8966
}
9067

91-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
68+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_group.Plugin{
9269
DoCommitGroup: func(req group.Spec, pretend bool) (string, error) {
9370
groupSpecActual <- req
9471
return "", errors.New("error")
@@ -110,7 +87,7 @@ func TestGroupPluginFreeGroup(t *testing.T) {
11087

11188
id := group.ID("group")
11289
idActual := make(chan group.ID, 1)
113-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
90+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_group.Plugin{
11491
DoFreeGroup: func(req group.ID) error {
11592
idActual <- req
11693
return nil
@@ -130,7 +107,7 @@ func TestGroupPluginFreeGroupError(t *testing.T) {
130107

131108
id := group.ID("group")
132109
idActual := make(chan group.ID, 1)
133-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
110+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_group.Plugin{
134111
DoFreeGroup: func(req group.ID) error {
135112
idActual <- req
136113
return errors.New("no")
@@ -151,7 +128,7 @@ func TestGroupPluginDestroyGroup(t *testing.T) {
151128

152129
id := group.ID("group")
153130
idActual := make(chan group.ID, 1)
154-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
131+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_group.Plugin{
155132
DoDestroyGroup: func(req group.ID) error {
156133
idActual <- req
157134
return nil
@@ -171,7 +148,7 @@ func TestGroupPluginDestroyGroupError(t *testing.T) {
171148

172149
id := group.ID("group")
173150
idActual := make(chan group.ID, 1)
174-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
151+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_group.Plugin{
175152
DoDestroyGroup: func(req group.ID) error {
176153
idActual <- req
177154
return errors.New("no")
@@ -199,7 +176,7 @@ func TestGroupPluginInspectGroup(t *testing.T) {
199176
},
200177
}
201178

202-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
179+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_group.Plugin{
203180
DoDescribeGroup: func(req group.ID) (group.Description, error) {
204181
idActual <- req
205182
return desc, nil
@@ -225,7 +202,7 @@ func TestGroupPluginInspectGroupError(t *testing.T) {
225202
},
226203
}
227204

228-
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testPlugin{
205+
server, err := rpc_server.StartPluginAtPath(socketPath, PluginServer(&testing_group.Plugin{
229206
DoDescribeGroup: func(req group.ID) (group.Description, error) {
230207
idActual <- req
231208
return desc, errors.New("no")

pkg/rpc/info.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package rpc
22

33
const (
4-
// InfoURL is the well-known HTTP GET endpoint that retrieves description of the plugin's interfaces.
5-
InfoURL = "/info/api.json"
4+
// APIURL is the well-known HTTP GET endpoint that retrieves description of the plugin's interfaces.
5+
APIURL = "/info/api.json"
6+
7+
// FunctionsURL exposes the templates functions that are available via this plugin
8+
FunctionsURL = "/info/functions.json"
69
)
710

811
// InputExample is the interface implemented by the rpc implementations for

0 commit comments

Comments
 (0)