Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi plugins, plugin .conf filles #598

Merged
merged 14 commits into from
Apr 18, 2018
Merged

Multi plugins, plugin .conf filles #598

merged 14 commits into from
Apr 18, 2018

Conversation

vetinari
Copy link
Member

so https://github.com/aryszka/configfilter could be converted to a plugin ;-)

  • 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 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

so github.com/aryszka/configfilter could be converted to a plugin
* 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
@vetinari vetinari changed the title Multi plugins Multi plugins, plugin .conf filles Mar 26, 2018
@vetinari
Copy link
Member Author

vetinari commented Mar 27, 2018

looking at https://github.com/zalando-stups/skrop I wonder if we should now change the signature of the InitFilter from (opts []string) (filters.Spec, error) to (opts []string) ([]filters.Spec, error)...

...similar for the InitPredicate

@aryszka
Copy link
Contributor

aryszka commented Apr 7, 2018

@vetinari about InitFilters(opts []string) ([]filters.Spec, error)..

It would be nice, but how would the config arguments be assigned to the different filters? opts [][]string?

plugins.go Outdated
@@ -116,16 +107,98 @@ func findAndLoadPlugins(o *Options) error {
return nil
}

func (o *Options) LoadMultiPlugins(found map[string]string) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the methods matching Load.+Plugins? here should not be exported. Is there a reason for exporting them, or a use case for applications that import skipper? I see that they are already exported in the master, but maybe it's not late to change this, if there is no reasonable use case for it. What may it break if unexporting them all?

plugins.go Outdated
}

func loadMultiPlugin(sym plugin.Symbol, path string, args []string) (filters.Spec, routing.PredicateSpec, routing.DataClient, error) {
fn, ok := sym.(func([]string) (filters.Spec, routing.PredicateSpec, routing.DataClient, error))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would it be to have an InitPlugin(opts []string) ([]filters.Spec, []routing.Predicate, []routing.DataClient) generic method with slices of return values, that can return multiple of any filters, predicates and data clients? This could be the generic plugin interface, while we could still keep the InitFilter, InitPredicate and InitDataClient interfaces to support the implementations of simpler plugins, with a single return value.

plugins.go Outdated
return fmt.Errorf("failed to read config for %s: %s", path, err)
}

if sym, err := mod.Lookup("InitPlugin"); err == nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we give multiple passes for loading the plugins, and we drop the "found" file entries in the first pass, it may happen that a plugin implements both InitPlugin and InitFilter, and only the InitPlugin will be evaluated, not the InitFilter. To avoid any confusion, I would simply consider it an error when a plugin implements more than one of: InitPlugin, InitFilter, InitPredicate, InitDataClient.

plugins.go Outdated
if dc != nil {
o.CustomDataClients = append(o.CustomDataClients, dc)
}
fmt.Printf("mutlitype plugin %s loaded from %s (filter: %t, predicate: %t, dataclient: %t)\n",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We follow the convention of printing log messages to the stderr. Please, change 'fmt.Println' to log.Println, using logrus. (Logrus allows the user to override the output.)

skipper.go Outdated
@@ -368,6 +368,10 @@ type Options struct {
// what the []string should contain.
DataClientPlugins [][]string

// MultiPlugins combine multiple types of the above plugin types in one plugin (where
// necessary because of shared data between e.g. a filter and a data client).
MultiPlugins [][]string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we consider the multi plugin the generic form of plugins, we could also just call this option simply: Plugins. What do you think?

@aryszka
Copy link
Contributor

aryszka commented Apr 7, 2018

ok, see my other comment. What I suggest basically, there should be a possibility to define a generic InitPlugin(opts []string) ([]filters.Spec, []routing.PredicateSpec, []routing.DataClient), and we can leave the InitFilter, InitPredicate and InitDataClient cases as they are, only to support the easy implementation of the simplest plugins. Also, I would make it fail when more than one of these methods are implemented by a single plugin.

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
@vetinari
Copy link
Member Author

👍

1 similar comment
@aryszka
Copy link
Contributor

aryszka commented Apr 18, 2018

👍

@aryszka aryszka merged commit a2001b0 into master Apr 18, 2018
@aryszka aryszka deleted the multi-plugins branch April 18, 2018 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants