Skip to content

Commit a2001b0

Browse files
vetinariaryszka
authored andcommitted
Multi plugins, plugin .conf filles (zalando#598)
* load multiple types of plugins from one module so github.com/aryszka/configfilter could be converted to a plugin * add example multiplugin code * update * config files / multitype plugins / plugin tests * when loading a .so file, it is checked if there is also a .conf file with the same base, e.g. for `./plugins/noop.so` a config of `./plugins/noop.conf` is attempted to open. If it exists, each line in this file is passed as argument to the plugin loader function (leading and trailing spaces stripped, lines beginning with a `#` after space stripping are ignored). * add support for multitype plugins (this time with complete auto detection and `.conf` file support) * add some noop plugins in _test_plugins and add a make target to build and try loading as test * run check-plugins target on each travis run * drop unused stuff * unify * switch InitPlugin signature InitPlugin is now ``` InitPlugin(opts []string) ([]filters.Spec, []routing.Predicate, []routing.DataClient, error) ``` also: * any plugin which implements multiple Init* causes an error * use logrus * update .gitignore * ignore _test_plugins_fail * update docs * check-plugins also in shortcheck
1 parent ab7fd97 commit a2001b0

13 files changed

+617
-87
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@ vendor
1717
linter.log
1818
site/
1919
plugins/
20+
_test_plugins/*.so
21+
_test_plugins_fail/*.so

Makefile

+20-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
SOURCES = $(shell find . -name '*.go' -not -path "./vendor/*")
1+
SOURCES = $(shell find . -name '*.go' -not -path "./vendor/*" -and -not -path "./_test_plugins" -and -not -path "./_test_plugins_fail" )
22
PACKAGES = $(shell glide novendor || echo -n "./...")
33
CURRENT_VERSION = $(shell git describe --tags --always --dirty)
44
VERSION ?= $(CURRENT_VERSION)
@@ -7,6 +7,11 @@ NEXT_MINOR = $(shell go run packaging/version/version.go minor $(CURRENT
77
NEXT_PATCH = $(shell go run packaging/version/version.go patch $(CURRENT_VERSION))
88
COMMIT_HASH = $(shell git rev-parse --short HEAD)
99
TEST_ETCD_VERSION ?= v2.3.8
10+
TEST_PLUGINS = _test_plugins/filter_noop.so \
11+
_test_plugins/predicate_match_none.so \
12+
_test_plugins/dataclient_noop.so \
13+
_test_plugins/multitype_noop.so \
14+
_test_plugins_fail/fail.so
1015

1116
default: build
1217

@@ -34,22 +39,31 @@ install: $(SOURCES)
3439
go install -ldflags "-X main.version=$(VERSION) -X main.commit=$(COMMIT_HASH)" ./cmd/skipper
3540
go install -ldflags "-X main.version=$(VERSION) -X main.commit=$(COMMIT_HASH)" ./cmd/eskip
3641

37-
check: build
42+
check: build check-plugins
3843
# go test $(PACKAGES)
3944
#
4045
# due to vendoring and how go test ./... is not the same as go test ./a/... ./b/...
4146
# probably can be reverted once etcd is fully mocked away for tests
4247
#
4348
for p in $(PACKAGES); do go test $$p || break; done
4449

45-
shortcheck: build
50+
shortcheck: build check-plugins
4651
# go test -test.short -run ^Test $(PACKAGES)
4752
#
4853
# due to vendoring and how go test ./... is not the same as go test ./a/... ./b/...
4954
# probably can be reverted once etcd is fully mocked away for tests
5055
#
5156
for p in $(PACKAGES); do go test -test.short -run ^Test $$p || break -1; done
5257

58+
check-plugins: $(TEST_PLUGINS)
59+
go test -run LoadPlugins
60+
61+
_test_plugins/%.so: _test_plugins/%.go
62+
go build -buildmode=plugin -o $@ $<
63+
64+
_test_plugins_fail/%.so: _test_plugins_fail/%.go
65+
go build -buildmode=plugin -o $@ $<
66+
5367
bench: build
5468
# go test -bench . $(PACKAGES)
5569
#
@@ -64,6 +78,8 @@ lint: build
6478
clean:
6579
go clean -i ./...
6680
rm -rf .coverprofile-all .cover
81+
rm ./_test_plugins/*.so
82+
rm ./_test_plugins_fail/*.so
6783

6884
deps:
6985
go get -t github.com/zalando/skipper/...
@@ -156,5 +172,5 @@ else ifeq ($(TRAVIS_BRANCH)_$(TRAVIS_PULL_REQUEST), master_false)
156172
else ifeq ($(TRAVIS_BRANCH), master)
157173
make deps check-precommit
158174
else
159-
make deps shortcheck
175+
make deps shortcheck check-plugins
160176
endif

_test_plugins/dataclient_noop.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package main
2+
3+
import (
4+
"github.com/zalando/skipper/eskip"
5+
"github.com/zalando/skipper/routing"
6+
)
7+
8+
type DataClient string
9+
10+
func InitDataClient([]string) (routing.DataClient, error) {
11+
var dc DataClient = ""
12+
return dc, nil
13+
}
14+
15+
func (dc DataClient) LoadAll() ([]*eskip.Route, error) {
16+
return eskip.Parse(string(dc))
17+
}
18+
19+
func (dc DataClient) LoadUpdate() ([]*eskip.Route, []string, error) {
20+
return nil, nil, nil
21+
}

_test_plugins/filter_noop.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package main
2+
3+
import (
4+
"github.com/zalando/skipper/filters"
5+
)
6+
7+
type noopSpec struct{}
8+
9+
func InitFilter(opts []string) (filters.Spec, error) {
10+
return noopSpec{}, nil
11+
}
12+
13+
func (s noopSpec) Name() string {
14+
return "noop"
15+
}
16+
func (s noopSpec) CreateFilter(config []interface{}) (filters.Filter, error) {
17+
return noopFilter{}, nil
18+
}
19+
20+
type noopFilter struct{}
21+
22+
func (f noopFilter) Request(filters.FilterContext) {}
23+
func (f noopFilter) Response(filters.FilterContext) {}

_test_plugins/multitype_noop.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/zalando/skipper/filters"
7+
"github.com/zalando/skipper/routing"
8+
)
9+
10+
type noopSpec struct {
11+
Type string
12+
}
13+
14+
func InitPlugin(opts []string) ([]filters.Spec, []routing.PredicateSpec, []routing.DataClient, error) {
15+
return []filters.Spec{noopSpec{"noop"}}, []routing.PredicateSpec{noopSpec{"None"}}, nil, nil
16+
}
17+
18+
func (s noopSpec) Name() string {
19+
return s.Type
20+
}
21+
22+
func (s noopSpec) CreateFilter(config []interface{}) (filters.Filter, error) {
23+
return noop{}, nil
24+
}
25+
26+
func (s noopSpec) Create(config []interface{}) (routing.Predicate, error) {
27+
return noop{}, nil
28+
}
29+
30+
type noop struct{}
31+
32+
func (p noop) Request(filters.FilterContext) {}
33+
func (p noop) Response(filters.FilterContext) {}
34+
35+
func (p noop) Match(*http.Request) bool {
36+
return false
37+
}

_test_plugins/predicate_match_none.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package main
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/zalando/skipper/routing"
7+
)
8+
9+
type noneSpec struct{}
10+
11+
func InitPredicate(opts []string) (routing.PredicateSpec, error) {
12+
return noneSpec{}, nil
13+
}
14+
15+
func (s noneSpec) Name() string {
16+
return "None"
17+
}
18+
func (s noneSpec) Create(config []interface{}) (routing.Predicate, error) {
19+
return nonePredicate{}, nil
20+
}
21+
22+
type nonePredicate struct{}
23+
24+
func (p nonePredicate) Match(*http.Request) bool {
25+
return false
26+
}

_test_plugins_fail/fail.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package main
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/zalando/skipper/filters"
7+
"github.com/zalando/skipper/routing"
8+
)
9+
10+
// this fails to load, because it implements multiple Init* functions
11+
12+
func InitFilter(opts []string) (filters.Spec, error) {
13+
return noopSpec{}, nil
14+
}
15+
16+
func InitPredicate(opts []string) (routing.PredicateSpec, error) {
17+
return noneSpec{}, nil
18+
}
19+
20+
type noopSpec struct{}
21+
22+
func (s noopSpec) Name() string {
23+
return "noop"
24+
}
25+
func (s noopSpec) CreateFilter(config []interface{}) (filters.Filter, error) {
26+
return noopFilter{}, nil
27+
}
28+
29+
type noopFilter struct{}
30+
31+
func (f noopFilter) Request(filters.FilterContext) {}
32+
func (f noopFilter) Response(filters.FilterContext) {}
33+
34+
type noneSpec struct{}
35+
36+
func (s noneSpec) Name() string {
37+
return "None"
38+
}
39+
func (s noneSpec) Create(config []interface{}) (routing.Predicate, error) {
40+
return nonePredicate{}, nil
41+
}
42+
43+
type nonePredicate struct{}
44+
45+
func (p nonePredicate) Match(*http.Request) bool {
46+
return false
47+
}

cmd/skipper/main.go

+3
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ var (
211211
filterPlugins pluginFlags
212212
predicatePlugins pluginFlags
213213
dataclientPlugins pluginFlags
214+
multiPlugins pluginFlags
214215
)
215216

216217
func init() {
@@ -295,6 +296,7 @@ func init() {
295296
flag.Var(&filterPlugins, "filter-plugin", filterPluginUsage)
296297
flag.Var(&predicatePlugins, "predicate-plugin", predicatePluginUsage)
297298
flag.Var(&dataclientPlugins, "dataclient-plugin", dataclientPluginUsage)
299+
flag.Var(&multiPlugins, "multi-plugin", multiPluginUsage)
298300

299301
flag.Parse()
300302

@@ -418,6 +420,7 @@ func main() {
418420
FilterPlugins: filterPlugins.Get(),
419421
PredicatePlugins: predicatePlugins.Get(),
420422
DataClientPlugins: dataclientPlugins.Get(),
423+
Plugins: multiPlugins.Get(),
421424
}
422425

423426
if pluginDir != "" {

cmd/skipper/filterFlags.go cmd/skipper/pluginFlags.go

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const (
88
filterPluginUsage = "set a custom filter plugins to load, a comma separated list of name and arguments"
99
predicatePluginUsage = "set a custom predicate plugins to load, a comma separated list of name and arguments"
1010
dataclientPluginUsage = "set a custom dataclient plugins to load, a comma separated list of name and arguments"
11+
multiPluginUsage = "set a custom multitype plugins to load, a comma separated list of name and arguments"
1112
)
1213

1314
type pluginFlags struct {

0 commit comments

Comments
 (0)