mirror of
https://github.com/kemko/nomad.git
synced 2026-01-05 01:45:44 +03:00
Merge pull request #5015 from hashicorp/f-plugin-versions
Add plugin API versioning to plugin loader and plugins
This commit is contained in:
@@ -9,7 +9,6 @@ import (
|
||||
"time"
|
||||
|
||||
log "github.com/hashicorp/go-hclog"
|
||||
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"github.com/hashicorp/nomad/nomad/structs/config"
|
||||
@@ -368,8 +367,8 @@ func (c *Config) ReadStringListToMapDefault(key, defaultValue string) map[string
|
||||
}
|
||||
|
||||
// NomadPluginConfig produces the NomadConfig struct which is sent to Nomad plugins
|
||||
func (c *Config) NomadPluginConfig() *base.ClientAgentConfig {
|
||||
return &base.ClientAgentConfig{
|
||||
func (c *Config) NomadPluginConfig() *base.AgentConfig {
|
||||
return &base.AgentConfig{
|
||||
Driver: &base.ClientDriverConfig{
|
||||
ClientMinPort: c.ClientMinPort,
|
||||
ClientMaxPort: c.ClientMaxPort,
|
||||
|
||||
@@ -40,7 +40,7 @@ type instanceManagerConfig struct {
|
||||
StoreReattach StorePluginReattachFn
|
||||
|
||||
// PluginConfig is the config passed to the launched plugins
|
||||
PluginConfig *base.ClientAgentConfig
|
||||
PluginConfig *base.AgentConfig
|
||||
|
||||
// Id is the ID of the plugin being managed
|
||||
Id *loader.PluginID
|
||||
@@ -70,7 +70,7 @@ type instanceManager struct {
|
||||
storeReattach StorePluginReattachFn
|
||||
|
||||
// pluginConfig is the config passed to the launched plugins
|
||||
pluginConfig *base.ClientAgentConfig
|
||||
pluginConfig *base.AgentConfig
|
||||
|
||||
// id is the ID of the plugin being managed
|
||||
id *loader.PluginID
|
||||
|
||||
@@ -63,7 +63,7 @@ type Config struct {
|
||||
Loader loader.PluginCatalog
|
||||
|
||||
// PluginConfig is the config passed to the launched plugins
|
||||
PluginConfig *base.ClientAgentConfig
|
||||
PluginConfig *base.AgentConfig
|
||||
|
||||
// Updater is used to update the node when device information changes
|
||||
Updater UpdateNodeDevicesFn
|
||||
@@ -91,7 +91,7 @@ type manager struct {
|
||||
loader loader.PluginCatalog
|
||||
|
||||
// pluginConfig is the config passed to the launched plugins
|
||||
pluginConfig *base.ClientAgentConfig
|
||||
pluginConfig *base.AgentConfig
|
||||
|
||||
// updater is used to update the node when device information changes
|
||||
updater UpdateNodeDevicesFn
|
||||
|
||||
@@ -121,7 +121,7 @@ func baseTestConfig(t *testing.T) (
|
||||
// Create the config
|
||||
config = &Config{
|
||||
Logger: testlog.HCLogger(t),
|
||||
PluginConfig: &base.ClientAgentConfig{},
|
||||
PluginConfig: &base.AgentConfig{},
|
||||
StatsInterval: 100 * time.Millisecond,
|
||||
State: state.NewMemDB(),
|
||||
Updater: updateFn,
|
||||
@@ -133,7 +133,7 @@ func baseTestConfig(t *testing.T) (
|
||||
|
||||
func configureCatalogWith(catalog *loader.MockCatalog, plugins map[*base.PluginInfoResponse]loader.PluginInstance) {
|
||||
|
||||
catalog.DispenseF = func(name, _ string, _ *base.ClientAgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
catalog.DispenseF = func(name, _ string, _ *base.AgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
for info, v := range plugins {
|
||||
if info.Name == name {
|
||||
return v, nil
|
||||
@@ -167,10 +167,10 @@ func configureCatalogWith(catalog *loader.MockCatalog, plugins map[*base.PluginI
|
||||
|
||||
func pluginInfoResponse(name string) *base.PluginInfoResponse {
|
||||
return &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginApiVersion: "v0.0.1",
|
||||
PluginVersion: "v0.0.1",
|
||||
Name: name,
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginApiVersions: []string{"v0.0.1"},
|
||||
PluginVersion: "v0.0.1",
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ func nvidiaAndIntelDefaultPlugins(catalog *loader.MockCatalog) {
|
||||
ReserveF: deviceReserveFn,
|
||||
StatsF: device.StaticStats([]*device.DeviceGroupStats{nvidiaDeviceGroupStats}),
|
||||
}
|
||||
pluginNvidia := loader.MockBasicExternalPlugin(deviceNvidia)
|
||||
pluginNvidia := loader.MockBasicExternalPlugin(deviceNvidia, device.ApiVersion010)
|
||||
|
||||
pluginInfoIntel := pluginInfoResponse("intel")
|
||||
deviceIntel := &device.MockDevicePlugin{
|
||||
@@ -222,7 +222,7 @@ func nvidiaAndIntelDefaultPlugins(catalog *loader.MockCatalog) {
|
||||
ReserveF: deviceReserveFn,
|
||||
StatsF: device.StaticStats([]*device.DeviceGroupStats{intelDeviceGroupStats}),
|
||||
}
|
||||
pluginIntel := loader.MockBasicExternalPlugin(deviceIntel)
|
||||
pluginIntel := loader.MockBasicExternalPlugin(deviceIntel, device.ApiVersion010)
|
||||
|
||||
// Configure the catalog with two plugins
|
||||
configureCatalogWith(catalog, map[*base.PluginInfoResponse]loader.PluginInstance{
|
||||
@@ -454,7 +454,7 @@ func TestManager_Shutdown(t *testing.T) {
|
||||
m.Shutdown()
|
||||
|
||||
for _, resp := range catalog.Catalog()[base.PluginTypeDevice] {
|
||||
pinst, _ := catalog.Dispense(resp.Name, resp.Type, &base.ClientAgentConfig{}, config.Logger)
|
||||
pinst, _ := catalog.Dispense(resp.Name, resp.Type, &base.AgentConfig{}, config.Logger)
|
||||
require.True(pinst.Exited())
|
||||
}
|
||||
}
|
||||
@@ -486,7 +486,7 @@ func TestManager_Run_ShutdownOld(t *testing.T) {
|
||||
|
||||
testutil.WaitForResult(func() (bool, error) {
|
||||
for _, resp := range catalog.Catalog()[base.PluginTypeDevice] {
|
||||
pinst, _ := catalog.Dispense(resp.Name, resp.Type, &base.ClientAgentConfig{}, config.Logger)
|
||||
pinst, _ := catalog.Dispense(resp.Name, resp.Type, &base.AgentConfig{}, config.Logger)
|
||||
if !pinst.Exited() {
|
||||
return false, fmt.Errorf("plugin %q not shutdown", resp.Name)
|
||||
}
|
||||
|
||||
@@ -565,7 +565,7 @@ func TestFingerprintManager_Run_DriverFailure(t *testing.T) {
|
||||
|
||||
dispenseCalls := 0
|
||||
loader := &loader.MockCatalog{
|
||||
DispenseF: func(name, pluginType string, cfg *base.ClientAgentConfig, logger log.Logger) (loader.PluginInstance, error) {
|
||||
DispenseF: func(name, pluginType string, cfg *base.AgentConfig, logger log.Logger) (loader.PluginInstance, error) {
|
||||
if pluginType == base.PluginTypeDriver && name == "raw_exec" {
|
||||
dispenseCalls++
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@ func (a *Agent) setupPlugins() error {
|
||||
|
||||
// Build the plugin loader
|
||||
config := &loader.PluginLoaderConfig{
|
||||
Logger: a.logger,
|
||||
PluginDir: a.config.PluginDir,
|
||||
Configs: a.config.Plugins,
|
||||
InternalPlugins: internal,
|
||||
Logger: a.logger,
|
||||
PluginDir: a.config.PluginDir,
|
||||
Configs: a.config.Plugins,
|
||||
InternalPlugins: internal,
|
||||
SupportedVersions: loader.AgentSupportedApiVersions,
|
||||
}
|
||||
l, err := loader.NewPluginLoader(config)
|
||||
if err != nil {
|
||||
|
||||
@@ -37,10 +37,10 @@ const (
|
||||
var (
|
||||
// pluginInfo describes the plugin
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginApiVersion: "0.0.1", // XXX This should be an array and should be consts
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the specification of the plugin's configuration
|
||||
@@ -111,10 +111,12 @@ func (d *NvidiaDevice) ConfigSchema() (*hclspec.Spec, error) {
|
||||
}
|
||||
|
||||
// SetConfig is used to set the configuration of the plugin.
|
||||
func (d *NvidiaDevice) SetConfig(data []byte, cfg *base.ClientAgentConfig) error {
|
||||
func (d *NvidiaDevice) SetConfig(cfg *base.Config) error {
|
||||
var config Config
|
||||
if err := base.MsgPackDecode(data, &config); err != nil {
|
||||
return err
|
||||
if len(cfg.PluginConfig) != 0 {
|
||||
if err := base.MsgPackDecode(cfg.PluginConfig, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, ignoredGPUId := range config.IgnoredGPUIDs {
|
||||
|
||||
@@ -122,10 +122,10 @@ var (
|
||||
|
||||
// pluginInfo is the response returned for the PluginInfo RPC
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersion: "0.0.1",
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersions: []string{drivers.ApiVersion010},
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the hcl specification returned by the ConfigSchema RPC
|
||||
@@ -502,10 +502,12 @@ func (d *Driver) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return configSpec, nil
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfig(data []byte, cfg *base.ClientAgentConfig) error {
|
||||
func (d *Driver) SetConfig(c *base.Config) error {
|
||||
var config DriverConfig
|
||||
if err := base.MsgPackDecode(data, &config); err != nil {
|
||||
return err
|
||||
if len(c.PluginConfig) != 0 {
|
||||
if err := base.MsgPackDecode(c.PluginConfig, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.config = &config
|
||||
@@ -517,8 +519,8 @@ func (d *Driver) SetConfig(data []byte, cfg *base.ClientAgentConfig) error {
|
||||
d.config.GC.imageDelayDuration = dur
|
||||
}
|
||||
|
||||
if cfg != nil {
|
||||
d.clientConfig = cfg.Driver
|
||||
if c.AgentConfig != nil {
|
||||
d.clientConfig = c.AgentConfig.Driver
|
||||
}
|
||||
|
||||
dockerClient, _, err := d.dockerClients()
|
||||
|
||||
@@ -169,8 +169,9 @@ func dockerDriverHarness(t *testing.T, cfg map[string]interface{}) *dtestutil.Dr
|
||||
}
|
||||
}
|
||||
plugLoader, err := loader.NewPluginLoader(&loader.PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: "./plugins",
|
||||
Logger: logger,
|
||||
PluginDir: "./plugins",
|
||||
SupportedVersions: loader.AgentSupportedApiVersions,
|
||||
InternalPlugins: map[loader.PluginID]*loader.InternalPluginConfig{
|
||||
PluginID: {
|
||||
Config: cfg,
|
||||
|
||||
@@ -49,10 +49,10 @@ var (
|
||||
|
||||
// pluginInfo is the response returned for the PluginInfo RPC
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersion: "0.0.1",
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersions: []string{drivers.ApiVersion010},
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the hcl specification returned by the ConfigSchema RPC
|
||||
@@ -136,9 +136,9 @@ func (d *Driver) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return configSpec, nil
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfig(_ []byte, cfg *base.ClientAgentConfig) error {
|
||||
if cfg != nil {
|
||||
d.nomadConfig = cfg.Driver
|
||||
func (d *Driver) SetConfig(cfg *base.Config) error {
|
||||
if cfg != nil && cfg.AgentConfig != nil {
|
||||
d.nomadConfig = cfg.AgentConfig.Driver
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -54,10 +54,10 @@ var (
|
||||
|
||||
// pluginInfo is the response returned for the PluginInfo RPC
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersion: "0.0.1",
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersions: []string{drivers.ApiVersion010},
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the hcl specification returned by the ConfigSchema RPC
|
||||
@@ -156,9 +156,9 @@ func (d *Driver) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return configSpec, nil
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfig(_ []byte, cfg *base.ClientAgentConfig) error {
|
||||
if cfg != nil {
|
||||
d.nomadConfig = cfg.Driver
|
||||
func (d *Driver) SetConfig(cfg *base.Config) error {
|
||||
if cfg != nil && cfg.AgentConfig != nil {
|
||||
d.nomadConfig = cfg.AgentConfig.Driver
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -62,10 +62,10 @@ func PluginLoader(opts map[string]string) (map[string]interface{}, error) {
|
||||
var (
|
||||
// pluginInfo is the response returned for the PluginInfo RPC
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersion: "0.0.1",
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersions: []string{drivers.ApiVersion010},
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the hcl specification returned by the ConfigSchema RPC
|
||||
@@ -200,15 +200,17 @@ func (d *Driver) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return configSpec, nil
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfig(data []byte, cfg *base.ClientAgentConfig) error {
|
||||
func (d *Driver) SetConfig(cfg *base.Config) error {
|
||||
var config Config
|
||||
if err := base.MsgPackDecode(data, &config); err != nil {
|
||||
return err
|
||||
if len(cfg.PluginConfig) != 0 {
|
||||
if err := base.MsgPackDecode(cfg.PluginConfig, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.config = &config
|
||||
if cfg != nil {
|
||||
d.nomadConfig = cfg.Driver
|
||||
if cfg.AgentConfig != nil {
|
||||
d.nomadConfig = cfg.AgentConfig.Driver
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -45,10 +45,10 @@ var (
|
||||
|
||||
// pluginInfo is the response returned for the PluginInfo RPC
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersion: "0.0.1",
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersions: []string{drivers.ApiVersion010},
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the hcl specification returned by the ConfigSchema RPC
|
||||
@@ -225,10 +225,12 @@ func (d *Driver) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return configSpec, nil
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfig(data []byte, cfg *base.ClientAgentConfig) error {
|
||||
func (d *Driver) SetConfig(cfg *base.Config) error {
|
||||
var config Config
|
||||
if err := base.MsgPackDecode(data, &config); err != nil {
|
||||
return err
|
||||
if len(cfg.PluginConfig) != 0 {
|
||||
if err := base.MsgPackDecode(cfg.PluginConfig, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.config = &config
|
||||
|
||||
@@ -74,10 +74,10 @@ var (
|
||||
|
||||
// pluginInfo is the response returned for the PluginInfo RPC
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersion: "0.0.1",
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersions: []string{drivers.ApiVersion010},
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the hcl specification returned by the ConfigSchema RPC
|
||||
@@ -167,9 +167,9 @@ func (d *Driver) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return configSpec, nil
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfig(_ []byte, cfg *base.ClientAgentConfig) error {
|
||||
if cfg != nil {
|
||||
d.nomadConfig = cfg.Driver
|
||||
func (d *Driver) SetConfig(cfg *base.Config) error {
|
||||
if cfg.AgentConfig != nil {
|
||||
d.nomadConfig = cfg.AgentConfig.Driver
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -63,10 +63,10 @@ func PluginLoader(opts map[string]string) (map[string]interface{}, error) {
|
||||
var (
|
||||
// pluginInfo is the response returned for the PluginInfo RPC
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersion: "0.0.1",
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersions: []string{drivers.ApiVersion010},
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the hcl specification returned by the ConfigSchema RPC
|
||||
@@ -174,15 +174,17 @@ func (d *Driver) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return configSpec, nil
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfig(data []byte, cfg *base.ClientAgentConfig) error {
|
||||
func (d *Driver) SetConfig(cfg *base.Config) error {
|
||||
var config Config
|
||||
if err := base.MsgPackDecode(data, &config); err != nil {
|
||||
return err
|
||||
if len(cfg.PluginConfig) != 0 {
|
||||
if err := base.MsgPackDecode(cfg.PluginConfig, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.config = &config
|
||||
if cfg != nil {
|
||||
d.nomadConfig = cfg.Driver
|
||||
if cfg.AgentConfig != nil {
|
||||
d.nomadConfig = cfg.AgentConfig.Driver
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -42,25 +42,30 @@ func TestRawExecDriver_SetConfig(t *testing.T) {
|
||||
harness := dtestutil.NewDriverHarness(t, d)
|
||||
defer harness.Kill()
|
||||
|
||||
bconfig := &basePlug.Config{}
|
||||
|
||||
// Disable raw exec.
|
||||
config := &Config{}
|
||||
|
||||
var data []byte
|
||||
require.NoError(basePlug.MsgPackEncode(&data, config))
|
||||
require.NoError(harness.SetConfig(data, nil))
|
||||
bconfig.PluginConfig = data
|
||||
require.NoError(harness.SetConfig(bconfig))
|
||||
require.Exactly(config, d.(*Driver).config)
|
||||
|
||||
config.Enabled = true
|
||||
config.NoCgroups = true
|
||||
data = []byte{}
|
||||
require.NoError(basePlug.MsgPackEncode(&data, config))
|
||||
require.NoError(harness.SetConfig(data, nil))
|
||||
bconfig.PluginConfig = data
|
||||
require.NoError(harness.SetConfig(bconfig))
|
||||
require.Exactly(config, d.(*Driver).config)
|
||||
|
||||
config.NoCgroups = false
|
||||
data = []byte{}
|
||||
require.NoError(basePlug.MsgPackEncode(&data, config))
|
||||
require.NoError(harness.SetConfig(data, nil))
|
||||
bconfig.PluginConfig = data
|
||||
require.NoError(harness.SetConfig(bconfig))
|
||||
require.Exactly(config, d.(*Driver).config)
|
||||
}
|
||||
|
||||
@@ -76,7 +81,10 @@ func TestRawExecDriver_Fingerprint(t *testing.T) {
|
||||
|
||||
var data []byte
|
||||
require.NoError(basePlug.MsgPackEncode(&data, config))
|
||||
require.NoError(harness.SetConfig(data, nil))
|
||||
bconfig := &basePlug.Config{
|
||||
PluginConfig: data,
|
||||
}
|
||||
require.NoError(harness.SetConfig(bconfig))
|
||||
|
||||
fingerCh, err := harness.Fingerprint(context.Background())
|
||||
require.NoError(err)
|
||||
@@ -168,7 +176,8 @@ func TestRawExecDriver_StartWaitStop(t *testing.T) {
|
||||
config := &Config{NoCgroups: true}
|
||||
var data []byte
|
||||
require.NoError(basePlug.MsgPackEncode(&data, config))
|
||||
require.NoError(harness.SetConfig(data, nil))
|
||||
bconfig := &basePlug.Config{PluginConfig: data}
|
||||
require.NoError(harness.SetConfig(bconfig))
|
||||
|
||||
task := &drivers.TaskConfig{
|
||||
ID: uuid.Generate(),
|
||||
@@ -234,7 +243,8 @@ func TestRawExecDriver_StartWaitRecoverWaitStop(t *testing.T) {
|
||||
config := &Config{NoCgroups: true}
|
||||
var data []byte
|
||||
require.NoError(basePlug.MsgPackEncode(&data, config))
|
||||
require.NoError(harness.SetConfig(data, nil))
|
||||
bconfig := &basePlug.Config{PluginConfig: data}
|
||||
require.NoError(harness.SetConfig(bconfig))
|
||||
|
||||
task := &drivers.TaskConfig{
|
||||
ID: uuid.Generate(),
|
||||
|
||||
@@ -86,10 +86,10 @@ func PluginLoader(opts map[string]string) (map[string]interface{}, error) {
|
||||
var (
|
||||
// pluginInfo is the response returned for the PluginInfo RPC
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersion: "0.0.1",
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDriver,
|
||||
PluginApiVersions: []string{drivers.ApiVersion010},
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the hcl specification returned by the ConfigSchema RPC
|
||||
@@ -216,15 +216,17 @@ func (d *Driver) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return configSpec, nil
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfig(data []byte, cfg *base.ClientAgentConfig) error {
|
||||
func (d *Driver) SetConfig(cfg *base.Config) error {
|
||||
var config Config
|
||||
if err := base.MsgPackDecode(data, &config); err != nil {
|
||||
return err
|
||||
if len(cfg.PluginConfig) != 0 {
|
||||
if err := base.MsgPackDecode(cfg.PluginConfig, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.config = &config
|
||||
if cfg != nil {
|
||||
d.nomadConfig = cfg.Driver
|
||||
if cfg.AgentConfig != nil {
|
||||
d.nomadConfig = cfg.AgentConfig.Driver
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -64,13 +64,15 @@ func TestRktDriver_SetConfig(t *testing.T) {
|
||||
|
||||
var data []byte
|
||||
require.NoError(basePlug.MsgPackEncode(&data, config))
|
||||
require.NoError(harness.SetConfig(data, nil))
|
||||
bconfig := &basePlug.Config{PluginConfig: data}
|
||||
require.NoError(harness.SetConfig(bconfig))
|
||||
require.Exactly(config, d.(*Driver).config)
|
||||
|
||||
config.VolumesEnabled = false
|
||||
data = []byte{}
|
||||
require.NoError(basePlug.MsgPackEncode(&data, config))
|
||||
require.NoError(harness.SetConfig(data, nil))
|
||||
bconfig = &basePlug.Config{PluginConfig: data}
|
||||
require.NoError(harness.SetConfig(bconfig))
|
||||
require.Exactly(config, d.(*Driver).config)
|
||||
|
||||
}
|
||||
@@ -446,7 +448,8 @@ func TestRktDriver_Start_Wait_Volume(t *testing.T) {
|
||||
|
||||
var data []byte
|
||||
require.NoError(basePlug.MsgPackEncode(&data, config))
|
||||
require.NoError(harness.SetConfig(data, nil))
|
||||
bconfig := &basePlug.Config{PluginConfig: data}
|
||||
require.NoError(harness.SetConfig(bconfig))
|
||||
|
||||
task := &drivers.TaskConfig{
|
||||
ID: uuid.Generate(),
|
||||
@@ -530,7 +533,8 @@ func TestRktDriver_Start_Wait_TaskMounts(t *testing.T) {
|
||||
|
||||
var data []byte
|
||||
require.NoError(basePlug.MsgPackEncode(&data, config))
|
||||
require.NoError(harness.SetConfig(data, nil))
|
||||
bconfig := &basePlug.Config{PluginConfig: data}
|
||||
require.NoError(harness.SetConfig(bconfig))
|
||||
|
||||
tmpvol, err := ioutil.TempDir("", "nomadtest_rktdriver_volumes")
|
||||
require.NoError(err)
|
||||
|
||||
@@ -15,7 +15,7 @@ type BasePlugin interface {
|
||||
|
||||
// SetConfig is used to set the configuration by passing a MessagePack
|
||||
// encoding of it.
|
||||
SetConfig(data []byte, config *ClientAgentConfig) error
|
||||
SetConfig(c *Config) error
|
||||
}
|
||||
|
||||
// PluginInfoResponse returns basic information about the plugin such that Nomad
|
||||
@@ -24,9 +24,9 @@ type PluginInfoResponse struct {
|
||||
// Type returns the plugins type
|
||||
Type string
|
||||
|
||||
// PluginApiVersion returns the version of the Nomad plugin API it is built
|
||||
// against.
|
||||
PluginApiVersion string
|
||||
// PluginApiVersions returns the versions of the Nomad plugin API that the
|
||||
// plugin supports.
|
||||
PluginApiVersions []string
|
||||
|
||||
// PluginVersion is the version of the plugin.
|
||||
PluginVersion string
|
||||
@@ -35,8 +35,21 @@ type PluginInfoResponse struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// ClientAgentConfig is the nomad client configuration sent to all plugins
|
||||
type ClientAgentConfig struct {
|
||||
// Config contains the configuration for the plugin.
|
||||
type Config struct {
|
||||
// ApiVersion is the negotiated plugin API version to use.
|
||||
ApiVersion string
|
||||
|
||||
// PluginConfig is the MessagePack encoding of the plugins user
|
||||
// configuration.
|
||||
PluginConfig []byte
|
||||
|
||||
// AgentConfig is the Nomad agents configuration as applicable to plugins
|
||||
AgentConfig *AgentConfig
|
||||
}
|
||||
|
||||
// AgentConfig is the Nomad agent's configuration sent to all plugins
|
||||
type AgentConfig struct {
|
||||
Driver *ClientDriverConfig
|
||||
}
|
||||
|
||||
@@ -51,7 +64,7 @@ type ClientDriverConfig struct {
|
||||
ClientMinPort uint
|
||||
}
|
||||
|
||||
func (c *ClientAgentConfig) toProto() *proto.NomadConfig {
|
||||
func (c *AgentConfig) toProto() *proto.NomadConfig {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -68,12 +81,12 @@ func (c *ClientAgentConfig) toProto() *proto.NomadConfig {
|
||||
return cfg
|
||||
}
|
||||
|
||||
func nomadConfigFromProto(pb *proto.NomadConfig) *ClientAgentConfig {
|
||||
func nomadConfigFromProto(pb *proto.NomadConfig) *AgentConfig {
|
||||
if pb == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
cfg := &ClientAgentConfig{}
|
||||
cfg := &AgentConfig{}
|
||||
if pb.Driver != nil {
|
||||
cfg.Driver = &ClientDriverConfig{
|
||||
ClientMaxPort: uint(pb.Driver.ClientMaxPort),
|
||||
|
||||
@@ -34,10 +34,10 @@ func (b *BasePluginClient) PluginInfo() (*PluginInfoResponse, error) {
|
||||
}
|
||||
|
||||
resp := &PluginInfoResponse{
|
||||
Type: ptype,
|
||||
PluginApiVersion: presp.GetPluginApiVersion(),
|
||||
PluginVersion: presp.GetPluginVersion(),
|
||||
Name: presp.GetName(),
|
||||
Type: ptype,
|
||||
PluginApiVersions: presp.GetPluginApiVersions(),
|
||||
PluginVersion: presp.GetPluginVersion(),
|
||||
Name: presp.GetName(),
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
@@ -52,11 +52,12 @@ func (b *BasePluginClient) ConfigSchema() (*hclspec.Spec, error) {
|
||||
return presp.GetSpec(), nil
|
||||
}
|
||||
|
||||
func (b *BasePluginClient) SetConfig(data []byte, config *ClientAgentConfig) error {
|
||||
func (b *BasePluginClient) SetConfig(c *Config) error {
|
||||
// Send the config
|
||||
_, err := b.Client.SetConfig(b.DoneCtx, &proto.SetConfigRequest{
|
||||
MsgpackConfig: data,
|
||||
NomadConfig: config.toProto(),
|
||||
MsgpackConfig: c.PluginConfig,
|
||||
NomadConfig: c.AgentConfig.toProto(),
|
||||
PluginApiVersion: c.ApiVersion,
|
||||
})
|
||||
|
||||
return err
|
||||
|
||||
@@ -16,27 +16,30 @@ func TestBasePlugin_PluginInfo_GRPC(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
|
||||
var (
|
||||
apiVersions = []string{"v0.1.0", "v0.1.1"}
|
||||
)
|
||||
|
||||
const (
|
||||
apiVersion = "v0.1.0"
|
||||
pluginVersion = "v0.2.1"
|
||||
pluginName = "mock"
|
||||
)
|
||||
|
||||
knownType := func() (*PluginInfoResponse, error) {
|
||||
info := &PluginInfoResponse{
|
||||
Type: PluginTypeDriver,
|
||||
PluginApiVersion: apiVersion,
|
||||
PluginVersion: pluginVersion,
|
||||
Name: pluginName,
|
||||
Type: PluginTypeDriver,
|
||||
PluginApiVersions: apiVersions,
|
||||
PluginVersion: pluginVersion,
|
||||
Name: pluginName,
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
unknownType := func() (*PluginInfoResponse, error) {
|
||||
info := &PluginInfoResponse{
|
||||
Type: "bad",
|
||||
PluginApiVersion: apiVersion,
|
||||
PluginVersion: pluginVersion,
|
||||
Name: pluginName,
|
||||
Type: "bad",
|
||||
PluginApiVersions: apiVersions,
|
||||
PluginVersion: pluginVersion,
|
||||
Name: pluginName,
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
@@ -63,7 +66,7 @@ func TestBasePlugin_PluginInfo_GRPC(t *testing.T) {
|
||||
|
||||
resp, err := impl.PluginInfo()
|
||||
require.NoError(err)
|
||||
require.Equal(apiVersion, resp.PluginApiVersion)
|
||||
require.Equal(apiVersions, resp.PluginApiVersions)
|
||||
require.Equal(pluginVersion, resp.PluginVersion)
|
||||
require.Equal(pluginName, resp.Name)
|
||||
require.Equal(PluginTypeDriver, resp.Type)
|
||||
@@ -118,8 +121,8 @@ func TestBasePlugin_SetConfig(t *testing.T) {
|
||||
ConfigSchemaF: func() (*hclspec.Spec, error) {
|
||||
return TestSpec, nil
|
||||
},
|
||||
SetConfigF: func(data []byte, cfg *ClientAgentConfig) error {
|
||||
receivedData = data
|
||||
SetConfigF: func(cfg *Config) error {
|
||||
receivedData = cfg.PluginConfig
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -147,7 +150,7 @@ func TestBasePlugin_SetConfig(t *testing.T) {
|
||||
})
|
||||
cdata, err := msgpack.Marshal(config, config.Type())
|
||||
require.NoError(err)
|
||||
require.NoError(impl.SetConfig(cdata, &ClientAgentConfig{}))
|
||||
require.NoError(impl.SetConfig(&Config{PluginConfig: cdata}))
|
||||
require.Equal(cdata, receivedData)
|
||||
|
||||
// Decode the value back
|
||||
|
||||
@@ -48,7 +48,7 @@ func (x PluginType) String() string {
|
||||
return proto.EnumName(PluginType_name, int32(x))
|
||||
}
|
||||
func (PluginType) EnumDescriptor() ([]byte, []int) {
|
||||
return fileDescriptor_base_6813a9f13eda45d4, []int{0}
|
||||
return fileDescriptor_base_f2480776612a8fbd, []int{0}
|
||||
}
|
||||
|
||||
// PluginInfoRequest is used to request the plugins basic information.
|
||||
@@ -62,7 +62,7 @@ func (m *PluginInfoRequest) Reset() { *m = PluginInfoRequest{} }
|
||||
func (m *PluginInfoRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*PluginInfoRequest) ProtoMessage() {}
|
||||
func (*PluginInfoRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_base_6813a9f13eda45d4, []int{0}
|
||||
return fileDescriptor_base_f2480776612a8fbd, []int{0}
|
||||
}
|
||||
func (m *PluginInfoRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PluginInfoRequest.Unmarshal(m, b)
|
||||
@@ -87,9 +87,9 @@ var xxx_messageInfo_PluginInfoRequest proto.InternalMessageInfo
|
||||
type PluginInfoResponse struct {
|
||||
// type indicates what type of plugin this is.
|
||||
Type PluginType `protobuf:"varint,1,opt,name=type,proto3,enum=hashicorp.nomad.plugins.base.proto.PluginType" json:"type,omitempty"`
|
||||
// plugin_api_version indicates the version of the Nomad Plugin API
|
||||
// this plugin is built against.
|
||||
PluginApiVersion string `protobuf:"bytes,2,opt,name=plugin_api_version,json=pluginApiVersion,proto3" json:"plugin_api_version,omitempty"`
|
||||
// plugin_api_versions indicates the versions of the Nomad Plugin API
|
||||
// this plugin supports.
|
||||
PluginApiVersions []string `protobuf:"bytes,2,rep,name=plugin_api_versions,json=pluginApiVersions,proto3" json:"plugin_api_versions,omitempty"`
|
||||
// plugin_version is the semver version of this individual plugin.
|
||||
// This is divorce from Nomad’s development and versioning.
|
||||
PluginVersion string `protobuf:"bytes,3,opt,name=plugin_version,json=pluginVersion,proto3" json:"plugin_version,omitempty"`
|
||||
@@ -104,7 +104,7 @@ func (m *PluginInfoResponse) Reset() { *m = PluginInfoResponse{} }
|
||||
func (m *PluginInfoResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*PluginInfoResponse) ProtoMessage() {}
|
||||
func (*PluginInfoResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_base_6813a9f13eda45d4, []int{1}
|
||||
return fileDescriptor_base_f2480776612a8fbd, []int{1}
|
||||
}
|
||||
func (m *PluginInfoResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_PluginInfoResponse.Unmarshal(m, b)
|
||||
@@ -131,11 +131,11 @@ func (m *PluginInfoResponse) GetType() PluginType {
|
||||
return PluginType_UNKNOWN
|
||||
}
|
||||
|
||||
func (m *PluginInfoResponse) GetPluginApiVersion() string {
|
||||
func (m *PluginInfoResponse) GetPluginApiVersions() []string {
|
||||
if m != nil {
|
||||
return m.PluginApiVersion
|
||||
return m.PluginApiVersions
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PluginInfoResponse) GetPluginVersion() string {
|
||||
@@ -163,7 +163,7 @@ func (m *ConfigSchemaRequest) Reset() { *m = ConfigSchemaRequest{} }
|
||||
func (m *ConfigSchemaRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ConfigSchemaRequest) ProtoMessage() {}
|
||||
func (*ConfigSchemaRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_base_6813a9f13eda45d4, []int{2}
|
||||
return fileDescriptor_base_f2480776612a8fbd, []int{2}
|
||||
}
|
||||
func (m *ConfigSchemaRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ConfigSchemaRequest.Unmarshal(m, b)
|
||||
@@ -196,7 +196,7 @@ func (m *ConfigSchemaResponse) Reset() { *m = ConfigSchemaResponse{} }
|
||||
func (m *ConfigSchemaResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ConfigSchemaResponse) ProtoMessage() {}
|
||||
func (*ConfigSchemaResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_base_6813a9f13eda45d4, []int{3}
|
||||
return fileDescriptor_base_f2480776612a8fbd, []int{3}
|
||||
}
|
||||
func (m *ConfigSchemaResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ConfigSchemaResponse.Unmarshal(m, b)
|
||||
@@ -228,17 +228,19 @@ type SetConfigRequest struct {
|
||||
// msgpack_config is the configuration encoded as MessagePack.
|
||||
MsgpackConfig []byte `protobuf:"bytes,1,opt,name=msgpack_config,json=msgpackConfig,proto3" json:"msgpack_config,omitempty"`
|
||||
// nomad_config is the nomad client configuration sent to all plugins.
|
||||
NomadConfig *NomadConfig `protobuf:"bytes,2,opt,name=nomad_config,json=nomadConfig,proto3" json:"nomad_config,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
NomadConfig *NomadConfig `protobuf:"bytes,2,opt,name=nomad_config,json=nomadConfig,proto3" json:"nomad_config,omitempty"`
|
||||
// plugin_api_version is the api version to use.
|
||||
PluginApiVersion string `protobuf:"bytes,3,opt,name=plugin_api_version,json=pluginApiVersion,proto3" json:"plugin_api_version,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SetConfigRequest) Reset() { *m = SetConfigRequest{} }
|
||||
func (m *SetConfigRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*SetConfigRequest) ProtoMessage() {}
|
||||
func (*SetConfigRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_base_6813a9f13eda45d4, []int{4}
|
||||
return fileDescriptor_base_f2480776612a8fbd, []int{4}
|
||||
}
|
||||
func (m *SetConfigRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SetConfigRequest.Unmarshal(m, b)
|
||||
@@ -272,6 +274,13 @@ func (m *SetConfigRequest) GetNomadConfig() *NomadConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SetConfigRequest) GetPluginApiVersion() string {
|
||||
if m != nil {
|
||||
return m.PluginApiVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NomadConfig is the client configuration sent to all plugins
|
||||
type NomadConfig struct {
|
||||
// driver specific configuration sent to all plugins
|
||||
@@ -285,7 +294,7 @@ func (m *NomadConfig) Reset() { *m = NomadConfig{} }
|
||||
func (m *NomadConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*NomadConfig) ProtoMessage() {}
|
||||
func (*NomadConfig) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_base_6813a9f13eda45d4, []int{5}
|
||||
return fileDescriptor_base_f2480776612a8fbd, []int{5}
|
||||
}
|
||||
func (m *NomadConfig) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NomadConfig.Unmarshal(m, b)
|
||||
@@ -330,7 +339,7 @@ func (m *NomadDriverConfig) Reset() { *m = NomadDriverConfig{} }
|
||||
func (m *NomadDriverConfig) String() string { return proto.CompactTextString(m) }
|
||||
func (*NomadDriverConfig) ProtoMessage() {}
|
||||
func (*NomadDriverConfig) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_base_6813a9f13eda45d4, []int{6}
|
||||
return fileDescriptor_base_f2480776612a8fbd, []int{6}
|
||||
}
|
||||
func (m *NomadDriverConfig) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NomadDriverConfig.Unmarshal(m, b)
|
||||
@@ -375,7 +384,7 @@ func (m *SetConfigResponse) Reset() { *m = SetConfigResponse{} }
|
||||
func (m *SetConfigResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*SetConfigResponse) ProtoMessage() {}
|
||||
func (*SetConfigResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_base_6813a9f13eda45d4, []int{7}
|
||||
return fileDescriptor_base_f2480776612a8fbd, []int{7}
|
||||
}
|
||||
func (m *SetConfigResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_SetConfigResponse.Unmarshal(m, b)
|
||||
@@ -551,41 +560,42 @@ var _BasePlugin_serviceDesc = grpc.ServiceDesc{
|
||||
Metadata: "plugins/base/proto/base.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("plugins/base/proto/base.proto", fileDescriptor_base_6813a9f13eda45d4) }
|
||||
func init() { proto.RegisterFile("plugins/base/proto/base.proto", fileDescriptor_base_f2480776612a8fbd) }
|
||||
|
||||
var fileDescriptor_base_6813a9f13eda45d4 = []byte{
|
||||
// 519 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x93, 0x5d, 0x6b, 0x1a, 0x4d,
|
||||
0x14, 0xc7, 0xb3, 0xea, 0x63, 0xc8, 0x51, 0x83, 0x99, 0x3c, 0x05, 0x11, 0x0a, 0x61, 0x69, 0x21,
|
||||
0x94, 0xb0, 0x4b, 0x6d, 0x6d, 0x7b, 0x99, 0x6a, 0xbc, 0x90, 0x12, 0x1b, 0xd6, 0xd6, 0x96, 0x52,
|
||||
0x90, 0x71, 0x9d, 0xb8, 0x43, 0x75, 0x66, 0xba, 0xb3, 0x86, 0xa6, 0xd0, 0xab, 0x5e, 0xe7, 0x43,
|
||||
0xf5, 0x9b, 0x95, 0x3d, 0x33, 0xab, 0x6b, 0x5f, 0xa8, 0x5e, 0xcd, 0xf1, 0x9c, 0xdf, 0xf9, 0x9f,
|
||||
0x17, 0xcf, 0xc2, 0x7d, 0x35, 0x5f, 0xce, 0xb8, 0xd0, 0xfe, 0x84, 0x6a, 0xe6, 0xab, 0x58, 0x26,
|
||||
0x12, 0x4d, 0x0f, 0x4d, 0xe2, 0x46, 0x54, 0x47, 0x3c, 0x94, 0xb1, 0xf2, 0x84, 0x5c, 0xd0, 0xa9,
|
||||
0x67, 0x71, 0x6f, 0xcd, 0x34, 0xcf, 0x67, 0x3c, 0x89, 0x96, 0x13, 0x2f, 0x94, 0x0b, 0x7f, 0x85,
|
||||
0xfb, 0x88, 0xfb, 0x99, 0xba, 0x8e, 0x68, 0xcc, 0xa6, 0x7e, 0x14, 0xce, 0xb5, 0x62, 0x61, 0xfa,
|
||||
0x8e, 0x53, 0xc3, 0x28, 0xb8, 0xc7, 0x70, 0x74, 0x85, 0x60, 0x5f, 0x5c, 0xcb, 0x80, 0x7d, 0x5e,
|
||||
0x32, 0x9d, 0xb8, 0x3f, 0x1c, 0x20, 0x79, 0xaf, 0x56, 0x52, 0x68, 0x46, 0x3a, 0x50, 0x4a, 0x6e,
|
||||
0x15, 0x6b, 0x38, 0x27, 0xce, 0xe9, 0x61, 0xcb, 0xf3, 0xfe, 0xdd, 0xa0, 0x67, 0x54, 0xde, 0xdc,
|
||||
0x2a, 0x16, 0x60, 0x2e, 0x39, 0x03, 0x62, 0xb0, 0x31, 0x55, 0x7c, 0x7c, 0xc3, 0x62, 0xcd, 0xa5,
|
||||
0x68, 0x14, 0x4e, 0x9c, 0xd3, 0x83, 0xa0, 0x6e, 0x22, 0x2f, 0x15, 0x1f, 0x19, 0x3f, 0x79, 0x08,
|
||||
0x87, 0x96, 0xce, 0xc8, 0x22, 0x92, 0x35, 0xe3, 0xcd, 0x30, 0x02, 0x25, 0x41, 0x17, 0xac, 0x51,
|
||||
0xc2, 0x20, 0xda, 0xee, 0x3d, 0x38, 0xee, 0x4a, 0x71, 0xcd, 0x67, 0xc3, 0x30, 0x62, 0x0b, 0x9a,
|
||||
0x8d, 0xf6, 0x1e, 0xfe, 0xdf, 0x74, 0xdb, 0xd9, 0xce, 0xa1, 0x94, 0x6e, 0x05, 0x67, 0xab, 0xb4,
|
||||
0xce, 0xfe, 0x3a, 0x9b, 0xd9, 0xa6, 0x67, 0xb7, 0xe9, 0x0d, 0x15, 0x0b, 0x03, 0xcc, 0x74, 0xef,
|
||||
0x1c, 0xa8, 0x0f, 0x59, 0x62, 0xd4, 0x6d, 0xb9, 0x74, 0x80, 0x85, 0x9e, 0x29, 0x1a, 0x7e, 0x1a,
|
||||
0x87, 0x18, 0xc0, 0x02, 0xd5, 0xa0, 0x66, 0xbd, 0x86, 0x26, 0x01, 0x54, 0xb1, 0x4c, 0x06, 0x15,
|
||||
0xb0, 0x0b, 0x7f, 0x9b, 0x0d, 0x0f, 0xd2, 0x80, 0x2d, 0x5a, 0x11, 0xeb, 0x1f, 0xee, 0x47, 0xa8,
|
||||
0xe4, 0x62, 0xe4, 0x12, 0xca, 0xd3, 0x98, 0xdf, 0xb0, 0xd8, 0x8e, 0xd8, 0xde, 0x5a, 0xfc, 0x02,
|
||||
0xd3, 0x6c, 0x09, 0x2b, 0xe2, 0x8e, 0xe1, 0xe8, 0xb7, 0x20, 0x79, 0x00, 0xb5, 0xee, 0x9c, 0x33,
|
||||
0x91, 0x5c, 0xd2, 0x2f, 0x57, 0x32, 0x4e, 0xb0, 0x54, 0x2d, 0xd8, 0x74, 0xe6, 0x28, 0x2e, 0x90,
|
||||
0x2a, 0x6c, 0x50, 0xc6, 0x99, 0x1e, 0x66, 0x6e, 0x9b, 0xe6, 0x5f, 0x7a, 0xf4, 0x18, 0x60, 0x7d,
|
||||
0x51, 0xa4, 0x02, 0xfb, 0x6f, 0x07, 0xaf, 0x06, 0xaf, 0xdf, 0x0d, 0xea, 0x7b, 0x04, 0xa0, 0x7c,
|
||||
0x11, 0xf4, 0x47, 0xbd, 0xa0, 0x5e, 0x40, 0xbb, 0x37, 0xea, 0x77, 0x7b, 0xf5, 0x62, 0xeb, 0xae,
|
||||
0x08, 0xd0, 0xa1, 0x9a, 0x99, 0x3c, 0xf2, 0x2d, 0x53, 0x48, 0x2f, 0x9b, 0xb4, 0xb7, 0xbf, 0xe1,
|
||||
0xdc, 0xf7, 0xd1, 0x7c, 0xb6, 0x6b, 0x9a, 0x69, 0xdf, 0xdd, 0x23, 0xdf, 0x1d, 0xa8, 0xe6, 0xef,
|
||||
0x8f, 0x3c, 0xdf, 0x46, 0xea, 0x0f, 0x87, 0xdc, 0x7c, 0xb1, 0x7b, 0xe2, 0xaa, 0x8b, 0xaf, 0x70,
|
||||
0xb0, 0xda, 0x2d, 0x79, 0xba, 0x8d, 0xd0, 0xaf, 0x87, 0xdd, 0x6c, 0xef, 0x98, 0x95, 0xd5, 0xee,
|
||||
0xec, 0x7f, 0xf8, 0x0f, 0x83, 0x93, 0x32, 0x3e, 0x4f, 0x7e, 0x06, 0x00, 0x00, 0xff, 0xff, 0x53,
|
||||
0xfe, 0xaa, 0x3a, 0x07, 0x05, 0x00, 0x00,
|
||||
var fileDescriptor_base_f2480776612a8fbd = []byte{
|
||||
// 535 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0x41, 0x8f, 0x12, 0x4d,
|
||||
0x10, 0xdd, 0x01, 0x3e, 0x36, 0x14, 0xb0, 0x81, 0xe6, 0x33, 0x21, 0x24, 0x26, 0x64, 0xa2, 0x09,
|
||||
0x31, 0x9b, 0x9e, 0x88, 0xa2, 0x1e, 0x57, 0x58, 0x0e, 0xc4, 0x2c, 0x6e, 0x06, 0x45, 0x63, 0x4c,
|
||||
0x48, 0x33, 0xf4, 0x32, 0x1d, 0xa1, 0xbb, 0x9d, 0x1e, 0x36, 0xae, 0x89, 0x27, 0xcf, 0xfe, 0x22,
|
||||
0x8f, 0xfe, 0x31, 0x33, 0xdd, 0x0d, 0x0c, 0xbb, 0x1a, 0xe1, 0x34, 0x45, 0xd5, 0x7b, 0xaf, 0xaa,
|
||||
0x1e, 0xd5, 0x70, 0x5f, 0x2e, 0x56, 0x73, 0xc6, 0x95, 0x37, 0x25, 0x8a, 0x7a, 0x32, 0x12, 0xb1,
|
||||
0xd0, 0x21, 0xd6, 0x21, 0x72, 0x43, 0xa2, 0x42, 0x16, 0x88, 0x48, 0x62, 0x2e, 0x96, 0x64, 0x86,
|
||||
0x2d, 0x1c, 0x6f, 0x31, 0x8d, 0xb3, 0x39, 0x8b, 0xc3, 0xd5, 0x14, 0x07, 0x62, 0xe9, 0x6d, 0xe0,
|
||||
0x9e, 0x86, 0x7b, 0x6b, 0x75, 0x15, 0x92, 0x88, 0xce, 0xbc, 0x30, 0x58, 0x28, 0x49, 0x83, 0xe4,
|
||||
0x3b, 0x49, 0x02, 0xa3, 0xe0, 0xd6, 0xa0, 0x7a, 0xa9, 0x81, 0x03, 0x7e, 0x25, 0x7c, 0xfa, 0x79,
|
||||
0x45, 0x55, 0xec, 0xfe, 0x72, 0x00, 0xa5, 0xb3, 0x4a, 0x0a, 0xae, 0x28, 0xea, 0x42, 0x2e, 0xbe,
|
||||
0x91, 0xb4, 0xee, 0x34, 0x9d, 0xd6, 0x49, 0x1b, 0xe3, 0x7f, 0x0f, 0x88, 0x8d, 0xca, 0x9b, 0x1b,
|
||||
0x49, 0x7d, 0xcd, 0x45, 0x18, 0x6a, 0x06, 0x36, 0x21, 0x92, 0x4d, 0xae, 0x69, 0xa4, 0x98, 0xe0,
|
||||
0xaa, 0x9e, 0x69, 0x66, 0x5b, 0x05, 0xbf, 0x6a, 0x4a, 0x2f, 0x25, 0x1b, 0xdb, 0x02, 0x7a, 0x08,
|
||||
0x27, 0x16, 0x6f, 0xb1, 0xf5, 0x6c, 0xd3, 0x69, 0x15, 0xfc, 0xb2, 0xc9, 0x5a, 0x1c, 0x42, 0x90,
|
||||
0xe3, 0x64, 0x49, 0xeb, 0x39, 0x5d, 0xd4, 0xb1, 0x7b, 0x0f, 0x6a, 0x3d, 0xc1, 0xaf, 0xd8, 0x7c,
|
||||
0x14, 0x84, 0x74, 0x49, 0xd6, 0xcb, 0xbd, 0x87, 0xff, 0x77, 0xd3, 0x76, 0xbb, 0x33, 0xc8, 0x25,
|
||||
0xbe, 0xe8, 0xed, 0x8a, 0xed, 0xd3, 0xbf, 0x6e, 0x67, 0xfc, 0xc4, 0xd6, 0x4f, 0x3c, 0x92, 0x34,
|
||||
0xf0, 0x35, 0xd3, 0xfd, 0xe9, 0x40, 0x65, 0x44, 0x63, 0xa3, 0x6e, 0xdb, 0x25, 0x0b, 0x2c, 0xd5,
|
||||
0x5c, 0x92, 0xe0, 0xd3, 0x24, 0xd0, 0x05, 0xdd, 0xa0, 0xe4, 0x97, 0x6d, 0xd6, 0xa0, 0x91, 0x0f,
|
||||
0x25, 0xdd, 0x66, 0x0d, 0xca, 0xe8, 0x29, 0xbc, 0x7d, 0x3c, 0x1e, 0x26, 0x05, 0xdb, 0xb4, 0xc8,
|
||||
0xb7, 0x3f, 0xd0, 0x29, 0xa0, 0xbb, 0x5e, 0x5b, 0xff, 0x2a, 0xb7, 0xad, 0x76, 0x3f, 0x42, 0x31,
|
||||
0xa5, 0x84, 0x2e, 0x20, 0x3f, 0x8b, 0xd8, 0x35, 0x8d, 0xac, 0x21, 0x9d, 0xbd, 0x47, 0x39, 0xd7,
|
||||
0x34, 0x3b, 0x90, 0x15, 0x71, 0x27, 0x50, 0xbd, 0x53, 0x44, 0x0f, 0xa0, 0xdc, 0x5b, 0x30, 0xca,
|
||||
0xe3, 0x0b, 0xf2, 0xe5, 0x52, 0x44, 0xb1, 0x6e, 0x55, 0xf6, 0x77, 0x93, 0x29, 0x14, 0xe3, 0x1a,
|
||||
0x95, 0xd9, 0x41, 0x99, 0x64, 0x72, 0xc8, 0x29, 0xef, 0xcd, 0x7f, 0xfa, 0xe8, 0x31, 0xc0, 0xf6,
|
||||
0x02, 0x51, 0x11, 0x8e, 0xdf, 0x0e, 0x5f, 0x0d, 0x5f, 0xbf, 0x1b, 0x56, 0x8e, 0x10, 0x40, 0xfe,
|
||||
0xdc, 0x1f, 0x8c, 0xfb, 0x7e, 0x25, 0xa3, 0xe3, 0xfe, 0x78, 0xd0, 0xeb, 0x57, 0xb2, 0xed, 0x1f,
|
||||
0x59, 0x80, 0x2e, 0x51, 0xd4, 0xf0, 0xd0, 0xb7, 0xb5, 0x42, 0xf2, 0x12, 0x50, 0x67, 0xff, 0x9b,
|
||||
0x4f, 0xbd, 0xa7, 0xc6, 0xb3, 0x43, 0x69, 0x66, 0x7c, 0xf7, 0x08, 0x7d, 0x77, 0xa0, 0x94, 0xbe,
|
||||
0x56, 0xf4, 0x7c, 0x1f, 0xa9, 0x3f, 0x9c, 0x7d, 0xe3, 0xc5, 0xe1, 0xc4, 0xcd, 0x14, 0x5f, 0xa1,
|
||||
0xb0, 0xf1, 0x16, 0x3d, 0xdd, 0x47, 0xe8, 0xf6, 0x33, 0x68, 0x74, 0x0e, 0x64, 0xad, 0x7b, 0x77,
|
||||
0x8f, 0x3f, 0xfc, 0xa7, 0x8b, 0xd3, 0xbc, 0xfe, 0x3c, 0xf9, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xcc,
|
||||
0x26, 0x80, 0xcf, 0x37, 0x05, 0x00, 0x00,
|
||||
}
|
||||
|
||||
@@ -33,9 +33,9 @@ message PluginInfoResponse {
|
||||
// type indicates what type of plugin this is.
|
||||
PluginType type = 1;
|
||||
|
||||
// plugin_api_version indicates the version of the Nomad Plugin API
|
||||
// this plugin is built against.
|
||||
string plugin_api_version = 2;
|
||||
// plugin_api_versions indicates the versions of the Nomad Plugin API
|
||||
// this plugin supports.
|
||||
repeated string plugin_api_versions = 2;
|
||||
|
||||
// plugin_version is the semver version of this individual plugin.
|
||||
// This is divorce from Nomad’s development and versioning.
|
||||
@@ -61,6 +61,9 @@ message SetConfigRequest {
|
||||
|
||||
// nomad_config is the nomad client configuration sent to all plugins.
|
||||
NomadConfig nomad_config = 2;
|
||||
|
||||
// plugin_api_version is the api version to use.
|
||||
string plugin_api_version = 3;
|
||||
}
|
||||
|
||||
// NomadConfig is the client configuration sent to all plugins
|
||||
|
||||
@@ -31,10 +31,10 @@ func (b *basePluginServer) PluginInfo(context.Context, *proto.PluginInfoRequest)
|
||||
}
|
||||
|
||||
presp := &proto.PluginInfoResponse{
|
||||
Type: ptype,
|
||||
PluginApiVersion: resp.PluginApiVersion,
|
||||
PluginVersion: resp.PluginVersion,
|
||||
Name: resp.Name,
|
||||
Type: ptype,
|
||||
PluginApiVersions: resp.PluginApiVersions,
|
||||
PluginVersion: resp.PluginVersion,
|
||||
Name: resp.Name,
|
||||
}
|
||||
|
||||
return presp, nil
|
||||
@@ -61,7 +61,7 @@ func (b *basePluginServer) SetConfig(ctx context.Context, req *proto.SetConfigRe
|
||||
|
||||
// Client configuration is filtered based on plugin type
|
||||
cfg := nomadConfigFromProto(req.GetNomadConfig())
|
||||
filteredCfg := new(ClientAgentConfig)
|
||||
filteredCfg := new(AgentConfig)
|
||||
|
||||
if cfg != nil {
|
||||
switch info.Type {
|
||||
@@ -70,8 +70,15 @@ func (b *basePluginServer) SetConfig(ctx context.Context, req *proto.SetConfigRe
|
||||
}
|
||||
}
|
||||
|
||||
// Build the config request
|
||||
c := &Config{
|
||||
ApiVersion: req.GetPluginApiVersion(),
|
||||
PluginConfig: req.GetMsgpackConfig(),
|
||||
AgentConfig: filteredCfg,
|
||||
}
|
||||
|
||||
// Set the config
|
||||
if err := b.impl.SetConfig(req.GetMsgpackConfig(), filteredCfg); err != nil {
|
||||
if err := b.impl.SetConfig(c); err != nil {
|
||||
return nil, fmt.Errorf("SetConfig failed: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ type TestConfig struct {
|
||||
|
||||
type PluginInfoFn func() (*PluginInfoResponse, error)
|
||||
type ConfigSchemaFn func() (*hclspec.Spec, error)
|
||||
type SetConfigFn func([]byte, *ClientAgentConfig) error
|
||||
type SetConfigFn func(*Config) error
|
||||
|
||||
// MockPlugin is used for testing.
|
||||
// Each function can be set as a closure to make assertions about how data
|
||||
@@ -61,8 +61,8 @@ type MockPlugin struct {
|
||||
|
||||
func (p *MockPlugin) PluginInfo() (*PluginInfoResponse, error) { return p.PluginInfoF() }
|
||||
func (p *MockPlugin) ConfigSchema() (*hclspec.Spec, error) { return p.ConfigSchemaF() }
|
||||
func (p *MockPlugin) SetConfig(data []byte, cfg *ClientAgentConfig) error {
|
||||
return p.SetConfigF(data, cfg)
|
||||
func (p *MockPlugin) SetConfig(cfg *Config) error {
|
||||
return p.SetConfigF(cfg)
|
||||
}
|
||||
|
||||
// Below are static implementations of the base plugin functions
|
||||
@@ -89,5 +89,5 @@ func TestConfigSchema() ConfigSchemaFn {
|
||||
|
||||
// NoopSetConfig is a noop implementation of set config
|
||||
func NoopSetConfig() SetConfigFn {
|
||||
return func(_ []byte, _ *ClientAgentConfig) error { return nil }
|
||||
return func(_ *Config) error { return nil }
|
||||
}
|
||||
|
||||
@@ -9,9 +9,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
|
||||
log "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/nomad/helper"
|
||||
"github.com/hashicorp/nomad/plugins/base"
|
||||
"github.com/hashicorp/nomad/plugins/device"
|
||||
"github.com/hashicorp/nomad/plugins/shared/hclspec"
|
||||
@@ -38,10 +37,10 @@ const (
|
||||
var (
|
||||
// pluginInfo describes the plugin
|
||||
pluginInfo = &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginApiVersion: "0.0.1", // XXX This should be an array and should be consts
|
||||
PluginVersion: "0.1.0",
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
PluginVersion: "v0.1.0",
|
||||
Name: pluginName,
|
||||
}
|
||||
|
||||
// configSpec is the specification of the plugin's configuration
|
||||
@@ -109,9 +108,9 @@ func (d *FsDevice) ConfigSchema() (*hclspec.Spec, error) {
|
||||
}
|
||||
|
||||
// SetConfig is used to set the configuration of the plugin.
|
||||
func (d *FsDevice) SetConfig(data []byte, cfg *base.ClientAgentConfig) error {
|
||||
func (d *FsDevice) SetConfig(c *base.Config) error {
|
||||
var config Config
|
||||
if err := base.MsgPackDecode(data, &config); err != nil {
|
||||
if err := base.MsgPackDecode(c.PluginConfig, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -24,27 +24,30 @@ func TestDevicePlugin_PluginInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
|
||||
var (
|
||||
apiVersions = []string{"v0.1.0", "v0.2.0"}
|
||||
)
|
||||
|
||||
const (
|
||||
apiVersion = "v0.1.0"
|
||||
pluginVersion = "v0.2.1"
|
||||
pluginName = "mock_device"
|
||||
)
|
||||
|
||||
knownType := func() (*base.PluginInfoResponse, error) {
|
||||
info := &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginApiVersion: apiVersion,
|
||||
PluginVersion: pluginVersion,
|
||||
Name: pluginName,
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginApiVersions: apiVersions,
|
||||
PluginVersion: pluginVersion,
|
||||
Name: pluginName,
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
unknownType := func() (*base.PluginInfoResponse, error) {
|
||||
info := &base.PluginInfoResponse{
|
||||
Type: "bad",
|
||||
PluginApiVersion: apiVersion,
|
||||
PluginVersion: pluginVersion,
|
||||
Name: pluginName,
|
||||
Type: "bad",
|
||||
PluginApiVersions: apiVersions,
|
||||
PluginVersion: pluginVersion,
|
||||
Name: pluginName,
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
@@ -74,7 +77,7 @@ func TestDevicePlugin_PluginInfo(t *testing.T) {
|
||||
|
||||
resp, err := impl.PluginInfo()
|
||||
require.NoError(err)
|
||||
require.Equal(apiVersion, resp.PluginApiVersion)
|
||||
require.Equal(apiVersions, resp.PluginApiVersions)
|
||||
require.Equal(pluginVersion, resp.PluginVersion)
|
||||
require.Equal(pluginName, resp.Name)
|
||||
require.Equal(base.PluginTypeDevice, resp.Type)
|
||||
@@ -129,17 +132,17 @@ func TestDevicePlugin_SetConfig(t *testing.T) {
|
||||
MockPlugin: &base.MockPlugin{
|
||||
PluginInfoF: func() (*base.PluginInfoResponse, error) {
|
||||
return &base.PluginInfoResponse{
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginApiVersion: "v0.0.1",
|
||||
PluginVersion: "v0.0.1",
|
||||
Name: "mock_device",
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginApiVersions: []string{"v0.0.1"},
|
||||
PluginVersion: "v0.0.1",
|
||||
Name: "mock_device",
|
||||
}, nil
|
||||
},
|
||||
ConfigSchemaF: func() (*hclspec.Spec, error) {
|
||||
return base.TestSpec, nil
|
||||
},
|
||||
SetConfigF: func(data []byte, cfg *base.ClientAgentConfig) error {
|
||||
receivedData = data
|
||||
SetConfigF: func(cfg *base.Config) error {
|
||||
receivedData = cfg.PluginConfig
|
||||
return nil
|
||||
},
|
||||
},
|
||||
@@ -169,7 +172,7 @@ func TestDevicePlugin_SetConfig(t *testing.T) {
|
||||
})
|
||||
cdata, err := msgpack.Marshal(config, config.Type())
|
||||
require.NoError(err)
|
||||
require.NoError(impl.SetConfig(cdata, nil))
|
||||
require.NoError(impl.SetConfig(&base.Config{PluginConfig: cdata}))
|
||||
require.Equal(cdata, receivedData)
|
||||
|
||||
// Decode the value back
|
||||
|
||||
6
plugins/device/versions.go
Normal file
6
plugins/device/versions.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package device
|
||||
|
||||
const (
|
||||
// ApiVersion010 is the initial API version for the device plugins
|
||||
ApiVersion010 = "v0.1.0"
|
||||
)
|
||||
6
plugins/drivers/versions.go
Normal file
6
plugins/drivers/versions.go
Normal file
@@ -0,0 +1,6 @@
|
||||
package drivers
|
||||
|
||||
const (
|
||||
// ApiVersion010 is the initial API version for the device plugins
|
||||
ApiVersion010 = "v0.1.0"
|
||||
)
|
||||
@@ -51,10 +51,11 @@ func TestPluginLoaderWithOptions(t testing.T,
|
||||
|
||||
// Build the plugin loader
|
||||
config := &loader.PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: "",
|
||||
Configs: configs,
|
||||
InternalPlugins: internal,
|
||||
Logger: logger,
|
||||
PluginDir: "",
|
||||
Configs: configs,
|
||||
InternalPlugins: internal,
|
||||
SupportedVersions: loader.AgentSupportedApiVersions,
|
||||
}
|
||||
l, err := loader.NewPluginLoader(config)
|
||||
if err != nil {
|
||||
|
||||
@@ -120,7 +120,7 @@ func (c *Device) Run(args []string) int {
|
||||
}
|
||||
c.spec = spec
|
||||
|
||||
if err := c.setConfig(spec, config, nil); err != nil {
|
||||
if err := c.setConfig(spec, device.ApiVersion010, config, nil); err != nil {
|
||||
c.logger.Error("failed to set config", "error", err)
|
||||
return 1
|
||||
}
|
||||
@@ -188,7 +188,7 @@ func (c *Device) getSpec() (hcldec.Spec, error) {
|
||||
return schema, nil
|
||||
}
|
||||
|
||||
func (c *Device) setConfig(spec hcldec.Spec, config []byte, nmdCfg *base.ClientAgentConfig) error {
|
||||
func (c *Device) setConfig(spec hcldec.Spec, apiVersion string, config []byte, nmdCfg *base.AgentConfig) error {
|
||||
// Parse the config into hcl
|
||||
configVal, err := hclConfigToInterface(config)
|
||||
if err != nil {
|
||||
@@ -216,8 +216,14 @@ func (c *Device) setConfig(spec hcldec.Spec, config []byte, nmdCfg *base.ClientA
|
||||
return err
|
||||
}
|
||||
|
||||
req := &base.Config{
|
||||
PluginConfig: config,
|
||||
AgentConfig: nmdCfg,
|
||||
ApiVersion: apiVersion,
|
||||
}
|
||||
|
||||
c.logger.Trace("msgpack config", "config", string(cdata))
|
||||
if err := c.dev.SetConfig(cdata, nmdCfg); err != nil {
|
||||
if err := c.dev.SetConfig(req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
15
plugins/shared/loader/api_versions.go
Normal file
15
plugins/shared/loader/api_versions.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package loader
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/nomad/plugins/base"
|
||||
"github.com/hashicorp/nomad/plugins/device"
|
||||
)
|
||||
|
||||
var (
|
||||
// AgentSupportedApiVersions is the set of API versions supported by the
|
||||
// Nomad agent by plugin type.
|
||||
AgentSupportedApiVersions = map[string][]string{
|
||||
base.PluginTypeDevice: {device.ApiVersion010},
|
||||
base.PluginTypeDriver: {device.ApiVersion010},
|
||||
}
|
||||
)
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
plugin "github.com/hashicorp/go-plugin"
|
||||
@@ -130,6 +131,18 @@ func (l *PluginLoader) initInternal(plugins map[PluginID]*InternalPluginConfig,
|
||||
}
|
||||
info.version = v
|
||||
|
||||
// Detect the plugin API version to use
|
||||
av, err := l.selectApiVersion(i)
|
||||
if err != nil {
|
||||
multierror.Append(&mErr, fmt.Errorf("failed to validate API versions %v for internal plugin %s: %v", i.PluginApiVersions, k, err))
|
||||
continue
|
||||
}
|
||||
if av == "" {
|
||||
l.logger.Warn("skipping plugin because supported API versions for plugin and Nomad do not overlap", "plugin", k)
|
||||
continue
|
||||
}
|
||||
info.apiVersion = av
|
||||
|
||||
// Get the config schema
|
||||
schema, err := base.ConfigSchema()
|
||||
if err != nil {
|
||||
@@ -142,9 +155,66 @@ func (l *PluginLoader) initInternal(plugins map[PluginID]*InternalPluginConfig,
|
||||
fingerprinted[k] = info
|
||||
}
|
||||
|
||||
if err := mErr.ErrorOrNil(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return fingerprinted, nil
|
||||
}
|
||||
|
||||
// selectApiVersion takes in PluginInfo and returns the highest compatable
|
||||
// version or an error if the plugins response is malformed. If there is no
|
||||
// overlap, an empty string is returned.
|
||||
func (l *PluginLoader) selectApiVersion(i *base.PluginInfoResponse) (string, error) {
|
||||
if i == nil {
|
||||
return "", fmt.Errorf("nil plugin info given")
|
||||
}
|
||||
if len(i.PluginApiVersions) == 0 {
|
||||
return "", fmt.Errorf("plugin provided no compatible API versions")
|
||||
}
|
||||
|
||||
pluginVersions, err := convertVersions(i.PluginApiVersions)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("plugin provided invalid versions: %v", err)
|
||||
}
|
||||
|
||||
// Lookup the supported versions. These will be sorted highest to lowest
|
||||
supportedVersions, ok := l.supportedVersions[i.Type]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unsupported plugin type %q", i.Type)
|
||||
}
|
||||
|
||||
for _, sv := range supportedVersions {
|
||||
for _, pv := range pluginVersions {
|
||||
if sv.Equal(pv) {
|
||||
return pv.Original(), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// convertVersions takes a list of string versions and returns a sorted list of
|
||||
// versions from highest to lowest.
|
||||
func convertVersions(in []string) ([]*version.Version, error) {
|
||||
converted := make([]*version.Version, len(in))
|
||||
for i, v := range in {
|
||||
vv, err := version.NewVersion(v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert version %q : %v", v, err)
|
||||
}
|
||||
|
||||
converted[i] = vv
|
||||
}
|
||||
|
||||
sort.Slice(converted, func(i, j int) bool {
|
||||
return converted[i].GreaterThan(converted[j])
|
||||
})
|
||||
|
||||
return converted, nil
|
||||
}
|
||||
|
||||
// scan scans the plugin directory and retrieves potentially eligible binaries
|
||||
func (l *PluginLoader) scan() ([]os.FileInfo, error) {
|
||||
if l.pluginDir == "" {
|
||||
@@ -200,10 +270,14 @@ func (l *PluginLoader) fingerprintPlugins(plugins []os.FileInfo, configs map[str
|
||||
c := configs[name]
|
||||
info, err := l.fingerprintPlugin(p, c)
|
||||
if err != nil {
|
||||
l.logger.Error("failed to fingerprint plugin", "plugin", name)
|
||||
l.logger.Error("failed to fingerprint plugin", "plugin", name, "error", err)
|
||||
multierror.Append(&mErr, err)
|
||||
continue
|
||||
}
|
||||
if info == nil {
|
||||
// Plugin was skipped for validation reasons
|
||||
continue
|
||||
}
|
||||
|
||||
id := PluginID{
|
||||
Name: info.baseInfo.Name,
|
||||
@@ -297,6 +371,17 @@ func (l *PluginLoader) fingerprintPlugin(pluginExe os.FileInfo, config *config.P
|
||||
}
|
||||
info.version = v
|
||||
|
||||
// Detect the plugin API version to use
|
||||
av, err := l.selectApiVersion(i)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to validate API versions %v for plugin %s (%v): %v", i.PluginApiVersions, i.Name, info.exePath, err)
|
||||
}
|
||||
if av == "" {
|
||||
l.logger.Warn("skipping plugin because supported API versions for plugin and Nomad do not overlap", "plugin", i.Name, "path", info.exePath)
|
||||
return nil, nil
|
||||
}
|
||||
info.apiVersion = av
|
||||
|
||||
// Retrieve the schema
|
||||
schema, err := bplugin.ConfigSchema()
|
||||
if err != nil {
|
||||
@@ -404,12 +489,18 @@ func (l *PluginLoader) validePluginConfig(id PluginID, info *pluginInfo) error {
|
||||
}
|
||||
defer instance.Kill()
|
||||
|
||||
base, ok := instance.Plugin().(base.BasePlugin)
|
||||
b, ok := instance.Plugin().(base.BasePlugin)
|
||||
if !ok {
|
||||
return fmt.Errorf("dispensed plugin %s doesn't meet base plugin interface", id)
|
||||
}
|
||||
|
||||
if err := base.SetConfig(cdata, nil); err != nil {
|
||||
c := &base.Config{
|
||||
PluginConfig: cdata,
|
||||
AgentConfig: nil,
|
||||
ApiVersion: info.apiVersion,
|
||||
}
|
||||
|
||||
if err := b.SetConfig(c); err != nil {
|
||||
return fmt.Errorf("setting config on plugin failed: %v", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -22,11 +22,15 @@ type PluginInstance interface {
|
||||
|
||||
// Exited returns whether the plugin has exited
|
||||
Exited() bool
|
||||
|
||||
// ApiVersion returns the API version to be used with the plugin
|
||||
ApiVersion() string
|
||||
}
|
||||
|
||||
// internalPluginInstance wraps an internal plugin
|
||||
type internalPluginInstance struct {
|
||||
instance interface{}
|
||||
instance interface{}
|
||||
apiVersion string
|
||||
}
|
||||
|
||||
func (p *internalPluginInstance) Internal() bool { return true }
|
||||
@@ -34,16 +38,19 @@ func (p *internalPluginInstance) Kill()
|
||||
func (p *internalPluginInstance) ReattachConfig() (*plugin.ReattachConfig, bool) { return nil, false }
|
||||
func (p *internalPluginInstance) Plugin() interface{} { return p.instance }
|
||||
func (p *internalPluginInstance) Exited() bool { return false }
|
||||
func (p *internalPluginInstance) ApiVersion() string { return p.apiVersion }
|
||||
|
||||
// externalPluginInstance wraps an external plugin
|
||||
type externalPluginInstance struct {
|
||||
client *plugin.Client
|
||||
instance interface{}
|
||||
client *plugin.Client
|
||||
instance interface{}
|
||||
apiVersion string
|
||||
}
|
||||
|
||||
func (p *externalPluginInstance) Internal() bool { return false }
|
||||
func (p *externalPluginInstance) Plugin() interface{} { return p.instance }
|
||||
func (p *externalPluginInstance) Exited() bool { return p.client.Exited() }
|
||||
func (p *externalPluginInstance) ApiVersion() string { return p.apiVersion }
|
||||
|
||||
func (p *externalPluginInstance) ReattachConfig() (*plugin.ReattachConfig, bool) {
|
||||
return p.client.ReattachConfig(), true
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
type PluginCatalog interface {
|
||||
// Dispense returns the plugin given its name and type. This will also
|
||||
// configure the plugin
|
||||
Dispense(name, pluginType string, config *base.ClientAgentConfig, logger log.Logger) (PluginInstance, error)
|
||||
Dispense(name, pluginType string, config *base.AgentConfig, logger log.Logger) (PluginInstance, error)
|
||||
|
||||
// Reattach is used to reattach to a previously launched external plugin.
|
||||
Reattach(name, pluginType string, config *plugin.ReattachConfig) (PluginInstance, error)
|
||||
@@ -28,17 +28,10 @@ type PluginCatalog interface {
|
||||
Catalog() map[string][]*base.PluginInfoResponse
|
||||
}
|
||||
|
||||
// PluginLoader is used to retrieve plugins either externally or from internal
|
||||
// factories.
|
||||
type PluginLoader struct {
|
||||
// logger is the plugin loaders logger
|
||||
logger log.Logger
|
||||
|
||||
// pluginDir is the directory containing plugin binaries
|
||||
pluginDir string
|
||||
|
||||
// plugins maps a plugin to information required to launch it
|
||||
plugins map[PluginID]*pluginInfo
|
||||
// InternalPluginConfig is used to configure launching an internal plugin.
|
||||
type InternalPluginConfig struct {
|
||||
Config map[string]interface{}
|
||||
Factory plugins.PluginFactory
|
||||
}
|
||||
|
||||
// PluginID is a tuple identifying a plugin
|
||||
@@ -75,12 +68,25 @@ type PluginLoaderConfig struct {
|
||||
|
||||
// InternalPlugins allows registering internal plugins.
|
||||
InternalPlugins map[PluginID]*InternalPluginConfig
|
||||
|
||||
// SupportedVersions is a mapping of plugin type to the supported versions
|
||||
SupportedVersions map[string][]string
|
||||
}
|
||||
|
||||
// InternalPluginConfig is used to configure launching an internal plugin.
|
||||
type InternalPluginConfig struct {
|
||||
Config map[string]interface{}
|
||||
Factory plugins.PluginFactory
|
||||
// PluginLoader is used to retrieve plugins either externally or from internal
|
||||
// factories.
|
||||
type PluginLoader struct {
|
||||
// logger is the plugin loaders logger
|
||||
logger log.Logger
|
||||
|
||||
// supportedVersions is a mapping of plugin type to the supported versions
|
||||
supportedVersions map[string][]*version.Version
|
||||
|
||||
// pluginDir is the directory containing plugin binaries
|
||||
pluginDir string
|
||||
|
||||
// plugins maps a plugin to information required to launch it
|
||||
plugins map[PluginID]*pluginInfo
|
||||
}
|
||||
|
||||
// pluginInfo captures the necessary information to launch and configure a
|
||||
@@ -91,8 +97,9 @@ type pluginInfo struct {
|
||||
exePath string
|
||||
args []string
|
||||
|
||||
baseInfo *base.PluginInfoResponse
|
||||
version *version.Version
|
||||
baseInfo *base.PluginInfoResponse
|
||||
version *version.Version
|
||||
apiVersion string
|
||||
|
||||
configSchema *hclspec.Spec
|
||||
config map[string]interface{}
|
||||
@@ -106,11 +113,22 @@ func NewPluginLoader(config *PluginLoaderConfig) (*PluginLoader, error) {
|
||||
return nil, fmt.Errorf("invalid plugin loader configuration passed: %v", err)
|
||||
}
|
||||
|
||||
// Convert the versions
|
||||
supportedVersions := make(map[string][]*version.Version, len(config.SupportedVersions))
|
||||
for pType, versions := range config.SupportedVersions {
|
||||
converted, err := convertVersions(versions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
supportedVersions[pType] = converted
|
||||
}
|
||||
|
||||
logger := config.Logger.Named("plugin_loader").With("plugin_dir", config.PluginDir)
|
||||
l := &PluginLoader{
|
||||
logger: logger,
|
||||
pluginDir: config.PluginDir,
|
||||
plugins: make(map[PluginID]*pluginInfo),
|
||||
logger: logger,
|
||||
supportedVersions: supportedVersions,
|
||||
pluginDir: config.PluginDir,
|
||||
plugins: make(map[PluginID]*pluginInfo),
|
||||
}
|
||||
|
||||
if err := l.init(config); err != nil {
|
||||
@@ -122,7 +140,7 @@ func NewPluginLoader(config *PluginLoaderConfig) (*PluginLoader, error) {
|
||||
|
||||
// Dispense returns a plugin instance, loading it either internally or by
|
||||
// launching an external plugin.
|
||||
func (l *PluginLoader) Dispense(name, pluginType string, config *base.ClientAgentConfig, logger log.Logger) (PluginInstance, error) {
|
||||
func (l *PluginLoader) Dispense(name, pluginType string, config *base.AgentConfig, logger log.Logger) (PluginInstance, error) {
|
||||
id := PluginID{
|
||||
Name: name,
|
||||
PluginType: pluginType,
|
||||
@@ -136,26 +154,31 @@ func (l *PluginLoader) Dispense(name, pluginType string, config *base.ClientAgen
|
||||
var instance PluginInstance
|
||||
if pinfo.factory != nil {
|
||||
instance = &internalPluginInstance{
|
||||
instance: pinfo.factory(logger),
|
||||
instance: pinfo.factory(logger),
|
||||
apiVersion: pinfo.apiVersion,
|
||||
}
|
||||
} else {
|
||||
var err error
|
||||
instance, err = l.dispensePlugin(pinfo.baseInfo.Type, pinfo.exePath, pinfo.args, nil, logger)
|
||||
instance, err = l.dispensePlugin(pinfo.baseInfo.Type, pinfo.apiVersion, pinfo.exePath, pinfo.args, nil, logger)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to launch plugin: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Cast to the base type and set the config
|
||||
base, ok := instance.Plugin().(base.BasePlugin)
|
||||
b, ok := instance.Plugin().(base.BasePlugin)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("plugin %s doesn't implement base plugin interface", id)
|
||||
}
|
||||
|
||||
if len(pinfo.msgpackConfig) != 0 {
|
||||
if err := base.SetConfig(pinfo.msgpackConfig, config); err != nil {
|
||||
return nil, fmt.Errorf("setting config for plugin %s failed: %v", id, err)
|
||||
}
|
||||
c := &base.Config{
|
||||
PluginConfig: pinfo.msgpackConfig,
|
||||
AgentConfig: config,
|
||||
ApiVersion: pinfo.apiVersion,
|
||||
}
|
||||
|
||||
if err := b.SetConfig(c); err != nil {
|
||||
return nil, fmt.Errorf("setting config for plugin %s failed: %v", id, err)
|
||||
}
|
||||
|
||||
return instance, nil
|
||||
@@ -163,12 +186,12 @@ func (l *PluginLoader) Dispense(name, pluginType string, config *base.ClientAgen
|
||||
|
||||
// Reattach reattaches to a previously launched external plugin.
|
||||
func (l *PluginLoader) Reattach(name, pluginType string, config *plugin.ReattachConfig) (PluginInstance, error) {
|
||||
return l.dispensePlugin(pluginType, "", nil, config, l.logger)
|
||||
return l.dispensePlugin(pluginType, "", "", nil, config, l.logger)
|
||||
}
|
||||
|
||||
// dispensePlugin is used to launch or reattach to an external plugin.
|
||||
func (l *PluginLoader) dispensePlugin(
|
||||
pluginType, cmd string, args []string, reattach *plugin.ReattachConfig,
|
||||
pluginType, apiVersion, cmd string, args []string, reattach *plugin.ReattachConfig,
|
||||
logger log.Logger) (PluginInstance, error) {
|
||||
|
||||
var pluginCmd *exec.Cmd
|
||||
@@ -207,6 +230,31 @@ func (l *PluginLoader) dispensePlugin(
|
||||
client: client,
|
||||
instance: raw,
|
||||
}
|
||||
|
||||
if apiVersion != "" {
|
||||
instance.apiVersion = apiVersion
|
||||
} else {
|
||||
// We do not know the API version since we are reattaching, so discover
|
||||
// it
|
||||
bplugin := raw.(base.BasePlugin)
|
||||
|
||||
// Retrieve base plugin information
|
||||
i, err := bplugin.PluginInfo()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get plugin info for plugin: %v", err)
|
||||
}
|
||||
|
||||
apiVersion, err := l.selectApiVersion(i)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to validate API versions %v for plugin %s: %v", i.PluginApiVersions, i.Name, err)
|
||||
}
|
||||
if apiVersion == "" {
|
||||
return nil, fmt.Errorf("failed to reattach to plugin because supported API versions for the plugin and Nomad do not overlap")
|
||||
}
|
||||
|
||||
instance.apiVersion = apiVersion
|
||||
}
|
||||
|
||||
return instance, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,11 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
log "github.com/hashicorp/go-hclog"
|
||||
version "github.com/hashicorp/go-version"
|
||||
"github.com/hashicorp/nomad/helper/testlog"
|
||||
"github.com/hashicorp/nomad/nomad/structs/config"
|
||||
"github.com/hashicorp/nomad/plugins/base"
|
||||
@@ -16,6 +18,14 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
// supportedApiVersions is the set of api versions that the "client" can
|
||||
// support
|
||||
supportedApiVersions = map[string][]string{
|
||||
base.PluginTypeDevice: {device.ApiVersion010},
|
||||
}
|
||||
)
|
||||
|
||||
// harness is used to build a temp directory and copy our own test executable
|
||||
// into it, allowing the plugin loader to scan for plugins.
|
||||
type harness struct {
|
||||
@@ -104,18 +114,21 @@ func TestPluginLoader_External(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Args: []string{"-plugin", "-name", plugins[0],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0]},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0],
|
||||
"-api-version", device.ApiVersion010},
|
||||
},
|
||||
{
|
||||
Name: plugins[1],
|
||||
Args: []string{"-plugin", "-name", plugins[1],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[1]},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[1],
|
||||
"-api-version", device.ApiVersion010, "-api-version", "v0.2.0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -133,21 +146,155 @@ func TestPluginLoader_External(t *testing.T) {
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[0],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[0],
|
||||
PluginApiVersions: []string{"v0.1.0"},
|
||||
},
|
||||
{
|
||||
Name: plugins[1],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[1],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{"v0.1.0", "v0.2.0"},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
}
|
||||
|
||||
func TestPluginLoader_External_ApiVersions(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
|
||||
// Create two plugins
|
||||
plugins := []string{"mock-device", "mock-device-2", "mock-device-3"}
|
||||
pluginVersions := []string{"v0.0.1", "v0.0.2"}
|
||||
h := newHarness(t, plugins)
|
||||
defer h.cleanup()
|
||||
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: map[string][]string{
|
||||
base.PluginTypeDevice: {"0.2.0", "0.2.1", "0.3.0"},
|
||||
},
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
// No supporting version
|
||||
Name: plugins[0],
|
||||
Args: []string{"-plugin", "-name", plugins[0],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0],
|
||||
"-api-version", "v0.1.0"},
|
||||
},
|
||||
{
|
||||
// Pick highest matching
|
||||
Name: plugins[1],
|
||||
Args: []string{"-plugin", "-name", plugins[1],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[1],
|
||||
"-api-version", "v0.1.0",
|
||||
"-api-version", "v0.2.0",
|
||||
"-api-version", "v0.2.1",
|
||||
"-api-version", "v0.2.2",
|
||||
},
|
||||
},
|
||||
{
|
||||
// Pick highest matching
|
||||
Name: plugins[2],
|
||||
Args: []string{"-plugin", "-name", plugins[2],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[1],
|
||||
"-api-version", "v0.1.0",
|
||||
"-api-version", "v0.2.0",
|
||||
"-api-version", "v0.2.1",
|
||||
"-api-version", "v0.3.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
l, err := NewPluginLoader(lconfig)
|
||||
require.NoError(err)
|
||||
|
||||
// Get the catalog and assert we have the two plugins
|
||||
c := l.Catalog()
|
||||
require.Len(c, 1)
|
||||
require.Contains(c, base.PluginTypeDevice)
|
||||
detected := c[base.PluginTypeDevice]
|
||||
require.Len(detected, 2)
|
||||
sort.Slice(detected, func(i, j int) bool { return detected[i].Name < detected[j].Name })
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugins[1],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{"v0.1.0", "v0.2.0", "v0.2.1", "v0.2.2"},
|
||||
},
|
||||
{
|
||||
Name: plugins[2],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{"v0.1.0", "v0.2.0", "v0.2.1", "v0.3.0"},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
|
||||
// Test we chose the correct versions by dispensing and checking and then
|
||||
// reattaching and checking
|
||||
p1, err := l.Dispense(plugins[1], base.PluginTypeDevice, nil, logger)
|
||||
require.NoError(err)
|
||||
defer p1.Kill()
|
||||
require.Equal("v0.2.1", p1.ApiVersion())
|
||||
|
||||
p2, err := l.Dispense(plugins[2], base.PluginTypeDevice, nil, logger)
|
||||
require.NoError(err)
|
||||
defer p2.Kill()
|
||||
require.Equal("v0.3.0", p2.ApiVersion())
|
||||
|
||||
// Test reattach api versions
|
||||
rc1, ok := p1.ReattachConfig()
|
||||
require.True(ok)
|
||||
r1, err := l.Reattach(plugins[1], base.PluginTypeDriver, rc1)
|
||||
require.NoError(err)
|
||||
require.Equal("v0.2.1", r1.ApiVersion())
|
||||
|
||||
rc2, ok := p2.ReattachConfig()
|
||||
require.True(ok)
|
||||
r2, err := l.Reattach(plugins[2], base.PluginTypeDriver, rc2)
|
||||
require.NoError(err)
|
||||
require.Equal("v0.3.0", r2.ApiVersion())
|
||||
}
|
||||
|
||||
func TestPluginLoader_External_NoApiVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
|
||||
// Create two plugins
|
||||
plugins := []string{"mock-device"}
|
||||
pluginVersions := []string{"v0.0.1", "v0.0.2"}
|
||||
h := newHarness(t, plugins)
|
||||
defer h.cleanup()
|
||||
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Args: []string{"-plugin", "-name", plugins[0],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0]},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := NewPluginLoader(lconfig)
|
||||
require.Error(err)
|
||||
require.Contains(err.Error(), "no compatible API versions")
|
||||
}
|
||||
|
||||
func TestPluginLoader_External_Config(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
@@ -161,13 +308,14 @@ func TestPluginLoader_External_Config(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Args: []string{"-plugin", "-name", plugins[0],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0]},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0], "-api-version", device.ApiVersion010},
|
||||
Config: map[string]interface{}{
|
||||
"foo": "1",
|
||||
"bar": "2",
|
||||
@@ -176,7 +324,7 @@ func TestPluginLoader_External_Config(t *testing.T) {
|
||||
{
|
||||
Name: plugins[1],
|
||||
Args: []string{"-plugin", "-name", plugins[1],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[1]},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[1], "-api-version", device.ApiVersion010},
|
||||
Config: map[string]interface{}{
|
||||
"foo": "3",
|
||||
"bar": "4",
|
||||
@@ -198,16 +346,16 @@ func TestPluginLoader_External_Config(t *testing.T) {
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[0],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[0],
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
{
|
||||
Name: plugins[1],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[1],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
@@ -227,13 +375,14 @@ func TestPluginLoader_External_Config_Bad(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Args: []string{"-plugin", "-name", plugins[0],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0]},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0], "-api-version", device.ApiVersion010},
|
||||
Config: map[string]interface{}{
|
||||
"foo": "1",
|
||||
"bar": "2",
|
||||
@@ -261,18 +410,19 @@ func TestPluginLoader_External_VersionOverlap(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Args: []string{"-plugin", "-name", plugins[0],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0]},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0], "-api-version", device.ApiVersion010},
|
||||
},
|
||||
{
|
||||
Name: plugins[1],
|
||||
Args: []string{"-plugin", "-name", plugins[0],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[1]},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[1], "-api-version", device.ApiVersion010},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -290,10 +440,10 @@ func TestPluginLoader_External_VersionOverlap(t *testing.T) {
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
@@ -309,24 +459,26 @@ func TestPluginLoader_Internal(t *testing.T) {
|
||||
|
||||
plugins := []string{"mock-device", "mock-device-2"}
|
||||
pluginVersions := []string{"v0.0.1", "v0.0.2"}
|
||||
pluginApiVersions := []string{device.ApiVersion010}
|
||||
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
InternalPlugins: map[PluginID]*InternalPluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[0], true),
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[0], pluginApiVersions, true),
|
||||
},
|
||||
{
|
||||
Name: plugins[1],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[1], base.PluginTypeDevice, pluginVersions[1], true),
|
||||
Factory: mockFactory(plugins[1], base.PluginTypeDevice, pluginVersions[1], pluginApiVersions, true),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -344,21 +496,134 @@ func TestPluginLoader_Internal(t *testing.T) {
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[0],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[0],
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
{
|
||||
Name: plugins[1],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[1],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
}
|
||||
|
||||
func TestPluginLoader_Internal_ApiVersions(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
|
||||
// Create two plugins
|
||||
plugins := []string{"mock-device", "mock-device-2", "mock-device-3"}
|
||||
pluginVersions := []string{"v0.0.1", "v0.0.2"}
|
||||
h := newHarness(t, nil)
|
||||
defer h.cleanup()
|
||||
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: map[string][]string{
|
||||
base.PluginTypeDevice: {"0.2.0", "0.2.1", "0.3.0"},
|
||||
},
|
||||
InternalPlugins: map[PluginID]*InternalPluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[0], []string{"v0.1.0"}, true),
|
||||
},
|
||||
{
|
||||
Name: plugins[1],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[1], base.PluginTypeDevice, pluginVersions[1],
|
||||
[]string{"v0.1.0", "v0.2.0", "v0.2.1", "v0.2.2"}, true),
|
||||
},
|
||||
{
|
||||
Name: plugins[2],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[2], base.PluginTypeDevice, pluginVersions[1],
|
||||
[]string{"v0.1.0", "v0.2.0", "v0.2.1", "v0.3.0"}, true),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
l, err := NewPluginLoader(lconfig)
|
||||
require.NoError(err)
|
||||
|
||||
// Get the catalog and assert we have the two plugins
|
||||
c := l.Catalog()
|
||||
require.Len(c, 1)
|
||||
require.Contains(c, base.PluginTypeDevice)
|
||||
detected := c[base.PluginTypeDevice]
|
||||
require.Len(detected, 2)
|
||||
sort.Slice(detected, func(i, j int) bool { return detected[i].Name < detected[j].Name })
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugins[1],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{"v0.1.0", "v0.2.0", "v0.2.1", "v0.2.2"},
|
||||
},
|
||||
{
|
||||
Name: plugins[2],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{"v0.1.0", "v0.2.0", "v0.2.1", "v0.3.0"},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
|
||||
// Test we chose the correct versions by dispensing and checking and then
|
||||
// reattaching and checking
|
||||
p1, err := l.Dispense(plugins[1], base.PluginTypeDevice, nil, logger)
|
||||
require.NoError(err)
|
||||
defer p1.Kill()
|
||||
require.Equal("v0.2.1", p1.ApiVersion())
|
||||
|
||||
p2, err := l.Dispense(plugins[2], base.PluginTypeDevice, nil, logger)
|
||||
require.NoError(err)
|
||||
defer p2.Kill()
|
||||
require.Equal("v0.3.0", p2.ApiVersion())
|
||||
}
|
||||
|
||||
func TestPluginLoader_Internal_NoApiVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
|
||||
// Create two plugins
|
||||
plugins := []string{"mock-device"}
|
||||
pluginVersions := []string{"v0.0.1", "v0.0.2"}
|
||||
h := newHarness(t, nil)
|
||||
defer h.cleanup()
|
||||
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
InternalPlugins: map[PluginID]*InternalPluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[0], nil, true),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := NewPluginLoader(lconfig)
|
||||
require.Error(err)
|
||||
require.Contains(err.Error(), "no compatible API versions")
|
||||
}
|
||||
|
||||
func TestPluginLoader_Internal_Config(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
@@ -369,18 +634,20 @@ func TestPluginLoader_Internal_Config(t *testing.T) {
|
||||
|
||||
plugins := []string{"mock-device", "mock-device-2"}
|
||||
pluginVersions := []string{"v0.0.1", "v0.0.2"}
|
||||
pluginApiVersions := []string{device.ApiVersion010}
|
||||
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
InternalPlugins: map[PluginID]*InternalPluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[0], true),
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[0], pluginApiVersions, true),
|
||||
Config: map[string]interface{}{
|
||||
"foo": "1",
|
||||
"bar": "2",
|
||||
@@ -390,7 +657,7 @@ func TestPluginLoader_Internal_Config(t *testing.T) {
|
||||
Name: plugins[1],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[1], base.PluginTypeDevice, pluginVersions[1], true),
|
||||
Factory: mockFactory(plugins[1], base.PluginTypeDevice, pluginVersions[1], pluginApiVersions, true),
|
||||
Config: map[string]interface{}{
|
||||
"foo": "3",
|
||||
"bar": "4",
|
||||
@@ -412,16 +679,16 @@ func TestPluginLoader_Internal_Config(t *testing.T) {
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[0],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[0],
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
{
|
||||
Name: plugins[1],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[1],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
@@ -438,6 +705,7 @@ func TestPluginLoader_Internal_ExternalConfig(t *testing.T) {
|
||||
|
||||
plugin := "mock-device"
|
||||
pluginVersion := "v0.0.1"
|
||||
pluginApiVersions := []string{device.ApiVersion010}
|
||||
|
||||
id := PluginID{
|
||||
Name: plugin,
|
||||
@@ -451,11 +719,12 @@ func TestPluginLoader_Internal_ExternalConfig(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
InternalPlugins: map[PluginID]*InternalPluginConfig{
|
||||
id: {
|
||||
Factory: mockFactory(plugin, base.PluginTypeDevice, pluginVersion, true),
|
||||
Factory: mockFactory(plugin, base.PluginTypeDevice, pluginVersion, pluginApiVersions, true),
|
||||
Config: map[string]interface{}{
|
||||
"foo": "1",
|
||||
"bar": "2",
|
||||
@@ -482,10 +751,10 @@ func TestPluginLoader_Internal_ExternalConfig(t *testing.T) {
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugin,
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersion,
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugin,
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersion,
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
@@ -507,18 +776,20 @@ func TestPluginLoader_Internal_Config_Bad(t *testing.T) {
|
||||
|
||||
plugins := []string{"mock-device"}
|
||||
pluginVersions := []string{"v0.0.1"}
|
||||
pluginApiVersions := []string{device.ApiVersion010}
|
||||
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
InternalPlugins: map[PluginID]*InternalPluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[0], true),
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[0], pluginApiVersions, true),
|
||||
Config: map[string]interface{}{
|
||||
"foo": "1",
|
||||
"bar": "2",
|
||||
@@ -540,19 +811,22 @@ func TestPluginLoader_InternalOverrideExternal(t *testing.T) {
|
||||
// Create two plugins
|
||||
plugins := []string{"mock-device"}
|
||||
pluginVersions := []string{"v0.0.1", "v0.0.2"}
|
||||
pluginApiVersions := []string{device.ApiVersion010}
|
||||
|
||||
h := newHarness(t, plugins)
|
||||
defer h.cleanup()
|
||||
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Args: []string{"-plugin", "-name", plugins[0],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0]},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0], "-api-version", pluginApiVersions[0]},
|
||||
},
|
||||
},
|
||||
InternalPlugins: map[PluginID]*InternalPluginConfig{
|
||||
@@ -560,7 +834,7 @@ func TestPluginLoader_InternalOverrideExternal(t *testing.T) {
|
||||
Name: plugins[0],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[1], true),
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[1], pluginApiVersions, true),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -578,10 +852,10 @@ func TestPluginLoader_InternalOverrideExternal(t *testing.T) {
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
@@ -594,19 +868,22 @@ func TestPluginLoader_ExternalOverrideInternal(t *testing.T) {
|
||||
// Create two plugins
|
||||
plugins := []string{"mock-device"}
|
||||
pluginVersions := []string{"v0.0.1", "v0.0.2"}
|
||||
pluginApiVersions := []string{device.ApiVersion010}
|
||||
|
||||
h := newHarness(t, plugins)
|
||||
defer h.cleanup()
|
||||
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Args: []string{"-plugin", "-name", plugins[0],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[1]},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[1], "-api-version", pluginApiVersions[0]},
|
||||
},
|
||||
},
|
||||
InternalPlugins: map[PluginID]*InternalPluginConfig{
|
||||
@@ -614,7 +891,7 @@ func TestPluginLoader_ExternalOverrideInternal(t *testing.T) {
|
||||
Name: plugins[0],
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[0], true),
|
||||
Factory: mockFactory(plugins[0], base.PluginTypeDevice, pluginVersions[0], pluginApiVersions, true),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -632,10 +909,10 @@ func TestPluginLoader_ExternalOverrideInternal(t *testing.T) {
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[1],
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
@@ -656,13 +933,14 @@ func TestPluginLoader_Dispense_External(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugin,
|
||||
Args: []string{"-plugin", "-name", plugin,
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersion},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersion, "-api-version", device.ApiVersion010},
|
||||
Config: map[string]interface{}{
|
||||
"res_key": expKey,
|
||||
},
|
||||
@@ -694,11 +972,12 @@ func TestPluginLoader_Dispense_Internal(t *testing.T) {
|
||||
// Create two plugins
|
||||
plugin := "mock-device"
|
||||
pluginVersion := "v0.0.1"
|
||||
pluginApiVersions := []string{device.ApiVersion010}
|
||||
h := newHarness(t, nil)
|
||||
defer h.cleanup()
|
||||
|
||||
expKey := "set_config_worked"
|
||||
expNomadConfig := &base.ClientAgentConfig{
|
||||
expNomadConfig := &base.AgentConfig{
|
||||
Driver: &base.ClientDriverConfig{
|
||||
ClientMinPort: 100,
|
||||
},
|
||||
@@ -707,14 +986,15 @@ func TestPluginLoader_Dispense_Internal(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
InternalPlugins: map[PluginID]*InternalPluginConfig{
|
||||
{
|
||||
Name: plugin,
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}: {
|
||||
Factory: mockFactory(plugin, base.PluginTypeDevice, pluginVersion, true),
|
||||
Factory: mockFactory(plugin, base.PluginTypeDevice, pluginVersion, pluginApiVersions, true),
|
||||
Config: map[string]interface{}{
|
||||
"res_key": expKey,
|
||||
},
|
||||
@@ -741,6 +1021,7 @@ func TestPluginLoader_Dispense_Internal(t *testing.T) {
|
||||
mock, ok := p.Plugin().(*mockPlugin)
|
||||
require.True(ok)
|
||||
require.Exactly(expNomadConfig, mock.nomadConfig)
|
||||
require.Equal(device.ApiVersion010, mock.negotiatedApiVersion)
|
||||
}
|
||||
|
||||
func TestPluginLoader_Dispense_NoConfigSchema_External(t *testing.T) {
|
||||
@@ -758,13 +1039,14 @@ func TestPluginLoader_Dispense_NoConfigSchema_External(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugin,
|
||||
Args: []string{"-plugin", "-config-schema=false", "-name", plugin,
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersion},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersion, "-api-version", device.ApiVersion010},
|
||||
Config: map[string]interface{}{
|
||||
"res_key": expKey,
|
||||
},
|
||||
@@ -797,6 +1079,7 @@ func TestPluginLoader_Dispense_NoConfigSchema_Internal(t *testing.T) {
|
||||
// Create two plugins
|
||||
plugin := "mock-device"
|
||||
pluginVersion := "v0.0.1"
|
||||
pluginApiVersions := []string{device.ApiVersion010}
|
||||
h := newHarness(t, nil)
|
||||
defer h.cleanup()
|
||||
|
||||
@@ -809,11 +1092,12 @@ func TestPluginLoader_Dispense_NoConfigSchema_Internal(t *testing.T) {
|
||||
PluginType: base.PluginTypeDevice,
|
||||
}
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
InternalPlugins: map[PluginID]*InternalPluginConfig{
|
||||
pid: {
|
||||
Factory: mockFactory(plugin, base.PluginTypeDevice, pluginVersion, false),
|
||||
Factory: mockFactory(plugin, base.PluginTypeDevice, pluginVersion, pluginApiVersions, false),
|
||||
Config: map[string]interface{}{
|
||||
"res_key": expKey,
|
||||
},
|
||||
@@ -826,7 +1110,7 @@ func TestPluginLoader_Dispense_NoConfigSchema_Internal(t *testing.T) {
|
||||
require.Contains(err.Error(), "configuration not allowed")
|
||||
|
||||
// Remove the config and try again
|
||||
lconfig.InternalPlugins[pid].Factory = mockFactory(plugin, base.PluginTypeDevice, pluginVersion, true)
|
||||
lconfig.InternalPlugins[pid].Factory = mockFactory(plugin, base.PluginTypeDevice, pluginVersion, pluginApiVersions, true)
|
||||
l, err := NewPluginLoader(lconfig)
|
||||
require.NoError(err)
|
||||
|
||||
@@ -854,13 +1138,14 @@ func TestPluginLoader_Reattach_External(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugin,
|
||||
Args: []string{"-plugin", "-name", plugin,
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersion},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersion, "-api-version", device.ApiVersion010},
|
||||
Config: map[string]interface{}{
|
||||
"res_key": expKey,
|
||||
},
|
||||
@@ -914,8 +1199,9 @@ func TestPluginLoader_Bad_Executable(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugin,
|
||||
@@ -956,13 +1242,14 @@ func TestPluginLoader_External_SkipBadFiles(t *testing.T) {
|
||||
logger := testlog.HCLogger(t)
|
||||
logger.SetLevel(log.Trace)
|
||||
lconfig := &PluginLoaderConfig{
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
Logger: logger,
|
||||
PluginDir: h.pluginDir(),
|
||||
SupportedVersions: supportedApiVersions,
|
||||
Configs: []*config.PluginConfig{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Args: []string{"-plugin", "-name", plugins[0],
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0]},
|
||||
"-type", base.PluginTypeDevice, "-version", pluginVersions[0], "-api-version", device.ApiVersion010},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -980,11 +1267,55 @@ func TestPluginLoader_External_SkipBadFiles(t *testing.T) {
|
||||
|
||||
expected := []*base.PluginInfoResponse{
|
||||
{
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[0],
|
||||
PluginApiVersion: "v0.1.0",
|
||||
Name: plugins[0],
|
||||
Type: base.PluginTypeDevice,
|
||||
PluginVersion: pluginVersions[0],
|
||||
PluginApiVersions: []string{device.ApiVersion010},
|
||||
},
|
||||
}
|
||||
require.EqualValues(expected, detected)
|
||||
}
|
||||
|
||||
func TestPluginLoader_ConvertVersions(t *testing.T) {
|
||||
v010 := version.Must(version.NewVersion("v0.1.0"))
|
||||
v020 := version.Must(version.NewVersion("v0.2.0"))
|
||||
v021 := version.Must(version.NewVersion("v0.2.1"))
|
||||
v030 := version.Must(version.NewVersion("v0.3.0"))
|
||||
|
||||
cases := []struct {
|
||||
in []string
|
||||
out []*version.Version
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
in: []string{"v0.1.0", "0.2.0", "v0.2.1"},
|
||||
out: []*version.Version{v021, v020, v010},
|
||||
},
|
||||
{
|
||||
in: []string{"0.3.0", "v0.1.0", "0.2.0", "v0.2.1"},
|
||||
out: []*version.Version{v030, v021, v020, v010},
|
||||
},
|
||||
{
|
||||
in: []string{"foo", "v0.1.0", "0.2.0", "v0.2.1"},
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(strings.Join(c.in, ","), func(t *testing.T) {
|
||||
act, err := convertVersions(c.in)
|
||||
if err != nil {
|
||||
if c.err {
|
||||
return
|
||||
}
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
require.Len(t, act, len(c.out))
|
||||
for i, v := range act {
|
||||
if !v.Equal(c.out[i]) {
|
||||
t.Fatalf("parsed version[%d] not equal: %v != %v", i, v, c.out[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,20 +15,33 @@ import (
|
||||
"github.com/hashicorp/nomad/plugins/shared/hclspec"
|
||||
)
|
||||
|
||||
type stringSliceFlags []string
|
||||
|
||||
func (i *stringSliceFlags) String() string {
|
||||
return "my string representation"
|
||||
}
|
||||
|
||||
func (i *stringSliceFlags) Set(value string) error {
|
||||
*i = append(*i, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TestMain runs either the tests or runs a mock plugin based on the passed
|
||||
// flags
|
||||
func TestMain(m *testing.M) {
|
||||
var plugin, configSchema bool
|
||||
var name, pluginType, pluginVersion string
|
||||
var pluginApiVersions stringSliceFlags
|
||||
flag.BoolVar(&plugin, "plugin", false, "run binary as a plugin")
|
||||
flag.BoolVar(&configSchema, "config-schema", true, "return a config schema")
|
||||
flag.StringVar(&name, "name", "", "plugin name")
|
||||
flag.StringVar(&pluginType, "type", "", "plugin type")
|
||||
flag.StringVar(&pluginVersion, "version", "", "plugin version")
|
||||
flag.Var(&pluginApiVersions, "api-version", "supported plugin API version")
|
||||
flag.Parse()
|
||||
|
||||
if plugin {
|
||||
if err := pluginMain(name, pluginType, pluginVersion, configSchema); err != nil {
|
||||
if err := pluginMain(name, pluginType, pluginVersion, pluginApiVersions, configSchema); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -38,7 +51,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
// pluginMain starts a mock plugin using the passed parameters
|
||||
func pluginMain(name, pluginType, version string, config bool) error {
|
||||
func pluginMain(name, pluginType, version string, apiVersions []string, config bool) error {
|
||||
// Validate passed parameters
|
||||
if name == "" || pluginType == "" {
|
||||
return fmt.Errorf("name and plugin type must be specified")
|
||||
@@ -55,6 +68,7 @@ func pluginMain(name, pluginType, version string, config bool) error {
|
||||
name: name,
|
||||
ptype: pluginType,
|
||||
version: version,
|
||||
apiVersions: apiVersions,
|
||||
configSchema: config,
|
||||
}
|
||||
|
||||
@@ -79,12 +93,13 @@ func pluginMain(name, pluginType, version string, config bool) error {
|
||||
|
||||
// mockFactory returns a PluginFactory method which creates the mock plugin with
|
||||
// the passed parameters
|
||||
func mockFactory(name, ptype, version string, configSchema bool) func(log log.Logger) interface{} {
|
||||
func mockFactory(name, ptype, version string, apiVersions []string, configSchema bool) func(log log.Logger) interface{} {
|
||||
return func(log log.Logger) interface{} {
|
||||
return &mockPlugin{
|
||||
name: name,
|
||||
ptype: ptype,
|
||||
version: version,
|
||||
apiVersions: apiVersions,
|
||||
configSchema: configSchema,
|
||||
}
|
||||
}
|
||||
@@ -96,12 +111,18 @@ type mockPlugin struct {
|
||||
name string
|
||||
ptype string
|
||||
version string
|
||||
apiVersions []string
|
||||
configSchema bool
|
||||
|
||||
// config is built on SetConfig
|
||||
config *mockPluginConfig
|
||||
|
||||
// nomadconfig is set on SetConfig
|
||||
nomadConfig *base.ClientAgentConfig
|
||||
nomadConfig *base.AgentConfig
|
||||
|
||||
// negotiatedApiVersion is the version of the api to use and is set on
|
||||
// SetConfig
|
||||
negotiatedApiVersion string
|
||||
}
|
||||
|
||||
// mockPluginConfig is the configuration for the mock plugin
|
||||
@@ -118,10 +139,10 @@ type mockPluginConfig struct {
|
||||
// building the mock plugin
|
||||
func (m *mockPlugin) PluginInfo() (*base.PluginInfoResponse, error) {
|
||||
return &base.PluginInfoResponse{
|
||||
Type: m.ptype,
|
||||
PluginApiVersion: "v0.1.0",
|
||||
PluginVersion: m.version,
|
||||
Name: m.name,
|
||||
Type: m.ptype,
|
||||
PluginApiVersions: m.apiVersions,
|
||||
PluginVersion: m.version,
|
||||
Name: m.name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -141,14 +162,17 @@ func (m *mockPlugin) ConfigSchema() (*hclspec.Spec, error) {
|
||||
}
|
||||
|
||||
// SetConfig decodes the configuration and stores it
|
||||
func (m *mockPlugin) SetConfig(data []byte, cfg *base.ClientAgentConfig) error {
|
||||
func (m *mockPlugin) SetConfig(c *base.Config) error {
|
||||
var config mockPluginConfig
|
||||
if err := base.MsgPackDecode(data, &config); err != nil {
|
||||
return err
|
||||
if len(c.PluginConfig) != 0 {
|
||||
if err := base.MsgPackDecode(c.PluginConfig, &config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
m.config = &config
|
||||
m.nomadConfig = cfg
|
||||
m.nomadConfig = c.AgentConfig
|
||||
m.negotiatedApiVersion = c.ApiVersion
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,12 @@ import (
|
||||
|
||||
// MockCatalog provides a mock PluginCatalog to be used for testing
|
||||
type MockCatalog struct {
|
||||
DispenseF func(name, pluginType string, cfg *base.ClientAgentConfig, logger log.Logger) (PluginInstance, error)
|
||||
DispenseF func(name, pluginType string, cfg *base.AgentConfig, logger log.Logger) (PluginInstance, error)
|
||||
ReattachF func(name, pluginType string, config *plugin.ReattachConfig) (PluginInstance, error)
|
||||
CatalogF func() map[string][]*base.PluginInfoResponse
|
||||
}
|
||||
|
||||
func (m *MockCatalog) Dispense(name, pluginType string, cfg *base.ClientAgentConfig, logger log.Logger) (PluginInstance, error) {
|
||||
func (m *MockCatalog) Dispense(name, pluginType string, cfg *base.AgentConfig, logger log.Logger) (PluginInstance, error) {
|
||||
return m.DispenseF(name, pluginType, cfg, logger)
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ type MockInstance struct {
|
||||
ReattachConfigF func() (*plugin.ReattachConfig, bool)
|
||||
PluginF func() interface{}
|
||||
ExitedF func() bool
|
||||
ApiVersionF func() string
|
||||
}
|
||||
|
||||
func (m *MockInstance) Internal() bool { return m.InternalPlugin }
|
||||
@@ -43,11 +44,12 @@ func (m *MockInstance) Kill() { m.KillF
|
||||
func (m *MockInstance) ReattachConfig() (*plugin.ReattachConfig, bool) { return m.ReattachConfigF() }
|
||||
func (m *MockInstance) Plugin() interface{} { return m.PluginF() }
|
||||
func (m *MockInstance) Exited() bool { return m.ExitedF() }
|
||||
func (m *MockInstance) ApiVersion() string { return m.ApiVersionF() }
|
||||
|
||||
// MockBasicExternalPlugin returns a MockInstance that simulates an external
|
||||
// plugin returning it has been exited after kill is called. It returns the
|
||||
// passed inst as the plugin
|
||||
func MockBasicExternalPlugin(inst interface{}) *MockInstance {
|
||||
func MockBasicExternalPlugin(inst interface{}, apiVersion string) *MockInstance {
|
||||
var killedLock sync.Mutex
|
||||
killed := helper.BoolToPtr(false)
|
||||
return &MockInstance{
|
||||
@@ -79,5 +81,7 @@ func MockBasicExternalPlugin(inst interface{}) *MockInstance {
|
||||
defer killedLock.Unlock()
|
||||
return *killed
|
||||
},
|
||||
|
||||
ApiVersionF: func() string { return apiVersion },
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ func (s *SingletonLoader) Catalog() map[string][]*base.PluginInfoResponse {
|
||||
// Dispense returns the plugin given its name and type. This will also
|
||||
// configure the plugin. If there is an instance of an already running plugin,
|
||||
// this is used.
|
||||
func (s *SingletonLoader) Dispense(name, pluginType string, config *base.ClientAgentConfig, logger log.Logger) (loader.PluginInstance, error) {
|
||||
func (s *SingletonLoader) Dispense(name, pluginType string, config *base.AgentConfig, logger log.Logger) (loader.PluginInstance, error) {
|
||||
return s.getPlugin(false, name, pluginType, logger, config, nil)
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ func (s *SingletonLoader) Reattach(name, pluginType string, config *plugin.Reatt
|
||||
// getPlugin is a helper that either dispenses or reattaches to a plugin using
|
||||
// futures to ensure only a single instance is retrieved
|
||||
func (s *SingletonLoader) getPlugin(reattach bool, name, pluginType string, logger log.Logger,
|
||||
nomadConfig *base.ClientAgentConfig, config *plugin.ReattachConfig) (loader.PluginInstance, error) {
|
||||
nomadConfig *base.AgentConfig, config *plugin.ReattachConfig) (loader.PluginInstance, error) {
|
||||
|
||||
// Lock the instance map to prevent races
|
||||
s.instanceLock.Lock()
|
||||
@@ -102,7 +102,7 @@ func (s *SingletonLoader) getPlugin(reattach bool, name, pluginType string, logg
|
||||
|
||||
// dispense should be called in a go routine to not block and creates the
|
||||
// desired plugin, setting the results in the future.
|
||||
func (s *SingletonLoader) dispense(f *future, name, pluginType string, config *base.ClientAgentConfig, logger log.Logger) {
|
||||
func (s *SingletonLoader) dispense(f *future, name, pluginType string, config *base.AgentConfig, logger log.Logger) {
|
||||
i, err := s.loader.Dispense(name, pluginType, config, logger)
|
||||
f.set(i, err)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func TestSingleton_Dispense(t *testing.T) {
|
||||
|
||||
dispenseCalled := 0
|
||||
s, c := harness(t)
|
||||
c.DispenseF = func(_, _ string, _ *base.ClientAgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
c.DispenseF = func(_, _ string, _ *base.AgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
p := &base.MockPlugin{}
|
||||
i := &loader.MockInstance{
|
||||
ExitedF: func() bool { return false },
|
||||
@@ -77,7 +77,7 @@ func TestSingleton_Dispense_Exit_Dispense(t *testing.T) {
|
||||
exited := false
|
||||
dispenseCalled := 0
|
||||
s, c := harness(t)
|
||||
c.DispenseF = func(_, _ string, _ *base.ClientAgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
c.DispenseF = func(_, _ string, _ *base.AgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
p := &base.MockPlugin{}
|
||||
i := &loader.MockInstance{
|
||||
ExitedF: func() bool { return exited },
|
||||
@@ -125,7 +125,7 @@ func TestSingleton_DispenseError_Dispense(t *testing.T) {
|
||||
require := require.New(t)
|
||||
|
||||
dispenseCalled := 0
|
||||
good := func(_, _ string, _ *base.ClientAgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
good := func(_, _ string, _ *base.AgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
p := &base.MockPlugin{}
|
||||
i := &loader.MockInstance{
|
||||
ExitedF: func() bool { return false },
|
||||
@@ -135,7 +135,7 @@ func TestSingleton_DispenseError_Dispense(t *testing.T) {
|
||||
return i, nil
|
||||
}
|
||||
|
||||
bad := func(_, _ string, _ *base.ClientAgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
bad := func(_, _ string, _ *base.AgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
dispenseCalled++
|
||||
return nil, fmt.Errorf("bad")
|
||||
}
|
||||
@@ -169,7 +169,7 @@ func TestSingleton_ReattachError_Dispense(t *testing.T) {
|
||||
|
||||
dispenseCalled, reattachCalled := 0, 0
|
||||
s, c := harness(t)
|
||||
c.DispenseF = func(_, _ string, _ *base.ClientAgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
c.DispenseF = func(_, _ string, _ *base.AgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
p := &base.MockPlugin{}
|
||||
i := &loader.MockInstance{
|
||||
ExitedF: func() bool { return false },
|
||||
@@ -209,7 +209,7 @@ func TestSingleton_Reattach_Dispense(t *testing.T) {
|
||||
|
||||
dispenseCalled, reattachCalled := 0, 0
|
||||
s, c := harness(t)
|
||||
c.DispenseF = func(_, _ string, _ *base.ClientAgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
c.DispenseF = func(_, _ string, _ *base.AgentConfig, _ log.Logger) (loader.PluginInstance, error) {
|
||||
dispenseCalled++
|
||||
return nil, fmt.Errorf("bad")
|
||||
}
|
||||
|
||||
34
vendor/github.com/hashicorp/go-version/constraint.go
generated
vendored
34
vendor/github.com/hashicorp/go-version/constraint.go
generated
vendored
@@ -2,6 +2,7 @@ package version
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
@@ -113,6 +114,26 @@ func parseSingle(v string) (*Constraint, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func prereleaseCheck(v, c *Version) bool {
|
||||
switch vPre, cPre := v.Prerelease() != "", c.Prerelease() != ""; {
|
||||
case cPre && vPre:
|
||||
// A constraint with a pre-release can only match a pre-release version
|
||||
// with the same base segments.
|
||||
return reflect.DeepEqual(c.Segments64(), v.Segments64())
|
||||
|
||||
case !cPre && vPre:
|
||||
// A constraint without a pre-release can only match a version without a
|
||||
// pre-release.
|
||||
return false
|
||||
|
||||
case cPre && !vPre:
|
||||
// OK, except with the pessimistic operator
|
||||
case !cPre && !vPre:
|
||||
// OK
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Constraint functions
|
||||
//-------------------------------------------------------------------
|
||||
@@ -126,22 +147,27 @@ func constraintNotEqual(v, c *Version) bool {
|
||||
}
|
||||
|
||||
func constraintGreaterThan(v, c *Version) bool {
|
||||
return v.Compare(c) == 1
|
||||
return prereleaseCheck(v, c) && v.Compare(c) == 1
|
||||
}
|
||||
|
||||
func constraintLessThan(v, c *Version) bool {
|
||||
return v.Compare(c) == -1
|
||||
return prereleaseCheck(v, c) && v.Compare(c) == -1
|
||||
}
|
||||
|
||||
func constraintGreaterThanEqual(v, c *Version) bool {
|
||||
return v.Compare(c) >= 0
|
||||
return prereleaseCheck(v, c) && v.Compare(c) >= 0
|
||||
}
|
||||
|
||||
func constraintLessThanEqual(v, c *Version) bool {
|
||||
return v.Compare(c) <= 0
|
||||
return prereleaseCheck(v, c) && v.Compare(c) <= 0
|
||||
}
|
||||
|
||||
func constraintPessimistic(v, c *Version) bool {
|
||||
// Using a pessimistic constraint with a pre-release, restricts versions to pre-releases
|
||||
if !prereleaseCheck(v, c) || (c.Prerelease() != "" && v.Prerelease() == "") {
|
||||
return false
|
||||
}
|
||||
|
||||
// If the version being checked is naturally less than the constraint, then there
|
||||
// is no way for the version to be valid against the constraint
|
||||
if v.LessThan(c) {
|
||||
|
||||
41
vendor/github.com/hashicorp/go-version/version.go
generated
vendored
41
vendor/github.com/hashicorp/go-version/version.go
generated
vendored
@@ -15,8 +15,8 @@ var versionRegexp *regexp.Regexp
|
||||
// The raw regular expression string used for testing the validity
|
||||
// of a version.
|
||||
const VersionRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
|
||||
`(-?([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
|
||||
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
|
||||
`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-?([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
|
||||
`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
|
||||
`?`
|
||||
|
||||
// Version represents a single version.
|
||||
@@ -25,6 +25,7 @@ type Version struct {
|
||||
pre string
|
||||
segments []int64
|
||||
si int
|
||||
original string
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -59,11 +60,17 @@ func NewVersion(v string) (*Version, error) {
|
||||
segments = append(segments, 0)
|
||||
}
|
||||
|
||||
pre := matches[7]
|
||||
if pre == "" {
|
||||
pre = matches[4]
|
||||
}
|
||||
|
||||
return &Version{
|
||||
metadata: matches[7],
|
||||
pre: matches[4],
|
||||
metadata: matches[10],
|
||||
pre: pre,
|
||||
segments: segments,
|
||||
si: si,
|
||||
original: v,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -166,14 +173,16 @@ func comparePart(preSelf string, preOther string) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
var selfInt int64
|
||||
selfNumeric := true
|
||||
_, err := strconv.ParseInt(preSelf, 10, 64)
|
||||
selfInt, err := strconv.ParseInt(preSelf, 10, 64)
|
||||
if err != nil {
|
||||
selfNumeric = false
|
||||
}
|
||||
|
||||
var otherInt int64
|
||||
otherNumeric := true
|
||||
_, err = strconv.ParseInt(preOther, 10, 64)
|
||||
otherInt, err = strconv.ParseInt(preOther, 10, 64)
|
||||
if err != nil {
|
||||
otherNumeric = false
|
||||
}
|
||||
@@ -197,7 +206,9 @@ func comparePart(preSelf string, preOther string) int {
|
||||
return -1
|
||||
} else if !selfNumeric && otherNumeric {
|
||||
return 1
|
||||
} else if preSelf > preOther {
|
||||
} else if !selfNumeric && !otherNumeric && preSelf > preOther {
|
||||
return 1
|
||||
} else if selfInt > otherInt {
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -297,11 +308,19 @@ func (v *Version) Segments() []int {
|
||||
// for a version "1.2.3-beta", segments will return a slice of
|
||||
// 1, 2, 3.
|
||||
func (v *Version) Segments64() []int64 {
|
||||
return v.segments
|
||||
result := make([]int64, len(v.segments))
|
||||
copy(result, v.segments)
|
||||
return result
|
||||
}
|
||||
|
||||
// String returns the full version string included pre-release
|
||||
// and metadata information.
|
||||
//
|
||||
// This value is rebuilt according to the parsed segments and other
|
||||
// information. Therefore, ambiguities in the version string such as
|
||||
// prefixed zeroes (1.04.0 => 1.4.0), `v` prefix (v1.0.0 => 1.0.0), and
|
||||
// missing parts (1.0 => 1.0.0) will be made into a canonicalized form
|
||||
// as shown in the parenthesized examples.
|
||||
func (v *Version) String() string {
|
||||
var buf bytes.Buffer
|
||||
fmtParts := make([]string, len(v.segments))
|
||||
@@ -320,3 +339,9 @@ func (v *Version) String() string {
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// Original returns the original parsed version as-is, including any
|
||||
// potential whitespace, `v` prefix, etc.
|
||||
func (v *Version) Original() string {
|
||||
return v.original
|
||||
}
|
||||
|
||||
2
vendor/vendor.json
vendored
2
vendor/vendor.json
vendored
@@ -196,7 +196,7 @@
|
||||
{"path":"github.com/hashicorp/go-sockaddr/template","checksumSHA1":"PDp9DVLvf3KWxhs4G4DpIwauMSU=","revision":"6d291a969b86c4b633730bfc6b8b9d64c3aafed9","revisionTime":"2018-03-20T11:50:54Z"},
|
||||
{"path":"github.com/hashicorp/go-syslog","checksumSHA1":"xZ7Ban1x//6uUIU1xtrTbCYNHBc=","revision":"42a2b573b664dbf281bd48c3cc12c086b17a39ba"},
|
||||
{"path":"github.com/hashicorp/go-uuid","checksumSHA1":"mAkPa/RLuIwN53GbwIEMATexams=","revision":"64130c7a86d732268a38cb04cfbaf0cc987fda98","revisionTime":"2016-07-17T02:21:40Z"},
|
||||
{"path":"github.com/hashicorp/go-version","checksumSHA1":"tUGxc7rfX0cmhOOUDhMuAZ9rWsA=","revision":"03c5bf6be031b6dd45afec16b1cf94fc8938bc77","revisionTime":"2017-02-02T08:07:59Z"},
|
||||
{"path":"github.com/hashicorp/go-version","checksumSHA1":"r0pj5dMHCghpaQZ3f1BRGoKiSWw=","revision":"b5a281d3160aa11950a6182bd9a9dc2cb1e02d50","revisionTime":"2018-08-24T00:43:55Z"},
|
||||
{"path":"github.com/hashicorp/golang-lru","checksumSHA1":"d9PxF1XQGLMJZRct2R8qVM/eYlE=","revision":"a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4","revisionTime":"2016-02-07T21:47:19Z"},
|
||||
{"path":"github.com/hashicorp/golang-lru/simplelru","checksumSHA1":"2nOpYjx8Sn57bqlZq17yM4YJuM4=","revision":"a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4"},
|
||||
{"path":"github.com/hashicorp/hcl","checksumSHA1":"8OPDk+bKyRGJoKcS4QNw9F7dpE8=","revision":"6e968a3fcdcbab092f5307fd0d85479d5af1e4dc","revisionTime":"2016-11-01T18:00:25Z"},
|
||||
|
||||
Reference in New Issue
Block a user