-
Notifications
You must be signed in to change notification settings - Fork 47
Refactoring flavors
Ondrej Fabry edited this page Jul 17, 2018
·
19 revisions
Easy to get simple stuff working
- minimal code needed to start even with single plugin
Provide options to customize plugins
- allow dependencies and configuration to be changed
Using sane defaults as fallback for plugin dependencies
- app should allow using plugins without setting all of their dependencies explicitly
Customized plugin dependencies
- app uses customized instances for some of its deps
- plugin deps that were set will use custom dep instead of default
- plugin deps that were removed will not use default
- plugin deps that were not customized will use default values
- the app will use customized instance of the plugin
- some other plugins can still use default instance
Global plugin instances
- app uses default instances defined in plugin packages
- the default deps for plugins will be set when plugin is found
- all plugins only use default instances defined in their packages
Changing global instance
- app replaces default instance of some plugin to custom instance
- plugin deps that were not customized will use default values
- the app will use customized default instance as direct dep
- or it can use some plugin that has the default instance as dep
- all plugins will now use new customized default instance
-
NewPlugin()
function to create new plugin instances -
DefaultPlugin
variable providing global default instance -
Option
function that can customize plugin instance-
UseDeps()
option to set plugin deps -
UseConf()
option to set plugin config
-
-
Deps
struct defining deps of plugins -
SetDefaults()
method to fill default deps
- setting global instance as default dep for other plugins that have global instance has to happen after possible changes of the instance and not in constructors
-
changing the global instance
DefaultPlugin
to custom one will not be changed in other global instances that use it as default dep- this is because global instances are created before
main
and copy the pointer - this forces default deps to be set after all initialization is done during which the global instances might be changed
- another workaround would be to use pointers to interfaces/pointers
- this is because global instances are created before
-
setting some dep to
nil
viaUseDeps
option will be overriden bySetDefaults
function- this is because it cannot differentiate between undefined dep and disabled one
- this could be solved by defining option to disable specific dep
define global variable
Disabled
to represent disabled instance and set defaults would replace this withnil
instead of default value
- constructors take arbitrary number of options
- options are all applied in constructor
- recursively lookup deps of plugins to find all plugins
- add optional method to fill to defaults
-
Default global instances
- can be used by multiple plugins
- can be set to custom plugin instance
-
New plugin
- create new instance
- loop over given options
- call the options
- UseDeps will set custom deps
- UseConf will set custom config
- UseDeps will set custom deps
- return instance
- call the options
- find all plugins recursively
- value must be non-nil
- check if type's kind is struct
- loop over fields
- must be exported
- if field implements Plugin interface
- field must be non-nil
- check if plugin is not already in list
- set defaults
- if field is plugin or field name is "Deps"
- call find plugins recursively
- add found plugins to list
- if is plugin
- add to list
- field must be non-nil
- return list
etcdDataSync := kvdbsync.NewPlugin(
kvdbsync.UseDeps(kvdbsync.Deps{
KvPlugin: etcd.DefaultPlugin,
ResyncOrch: resync.DefaultPlugin,
}),
)
p := &ExamplePlugin{
Log: logging.ForPlugin(PluginName),
PluginConfig: config.ForPlugin(PluginName),
ServiceLabel: servicelabel.DefaultPlugin,
Publisher: etcdDataSync,
Watcher: etcdDataSync,
exampleFinished: make(chan struct{}),
}
a := agent.NewAgent(
agent.AllPlugins(p),
agent.QuitOn(p.exampleFinished),
)
if err := a.Run(); err != nil {
log.Fatal(err)
}