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

Commit 1af9efa

Browse files
author
David Chung
authored
change schema of plugin launch config to better support different executors e.g. 'os' and 'docker-run' (#374)
Signed-off-by: David Chung <[email protected]>
1 parent 17f7130 commit 1af9efa

File tree

8 files changed

+84
-71
lines changed

8 files changed

+84
-71
lines changed

cmd/cli/plugin.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func pluginCommand(plugins func() discovery.Plugins) *cobra.Command {
5252
}
5353

5454
configURL := start.Flags().String("config-url", "", "URL for the startup configs")
55-
osExec := start.Flags().Bool("os", false, "True to use os plugin binaries")
55+
executor := start.Flags().String("exec", "os", "Executor to use for starting up plugins: [os | docker-run]")
5656
doWait := start.Flags().BoolP("wait", "w", false, "True to wait in the foreground; Ctrl-C to exit")
5757

5858
start.RunE = func(c *cobra.Command, args []string) error {
@@ -79,8 +79,16 @@ func pluginCommand(plugins func() discovery.Plugins) *cobra.Command {
7979

8080
monitors := []*launch.Monitor{}
8181

82-
if *osExec {
83-
exec, err := os.NewLauncher()
82+
switch *executor {
83+
case "os":
84+
exec, err := os.NewLauncher("os")
85+
if err != nil {
86+
return err
87+
}
88+
monitors = append(monitors, launch.NewMonitor(exec, parsedRules))
89+
case "docker-run":
90+
// docker-run is also implemented by the same os executor. We just search for a different key (docker-run)
91+
exec, err := os.NewLauncher("docker-run")
8492
if err != nil {
8593
return err
8694
}

examples/flavor/swarm/e2e-plugins.json

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
{
33
"Plugin" : "group-default",
44
"Launch" : {
5-
"Exec" : "os",
6-
"Properties": {
5+
"os": {
76
"Cmd" : "infrakit-group-default --poll-interval 500ms --name group-stateless --log 5 > {{env "LOG_DIR"}}/group-default-{{unixtime}}.log 2>&1 &",
87
"SamePgID" : true
98
}
@@ -13,8 +12,7 @@
1312
{
1413
"Plugin" : "instance-file",
1514
"Launch" : {
16-
"Exec" : "os",
17-
"Properties" : {
15+
"os" : {
1816
"Cmd" : "infrakit-instance-file --dir {{env "TUTORIAL_DIR"}} --log 5 > {{env "LOG_DIR"}}/instance-file-{{unixtime}}.log 2>&1",
1917
"SamePgID" : true
2018
}
@@ -24,8 +22,7 @@
2422
{
2523
"Plugin" : "instance-vagrant",
2624
"Launch" : {
27-
"Exec" : "os",
28-
"Properties" : {
25+
"os" : {
2926
"Cmd" : "infrakit-instance-vagrant --log 5 > {{env "LOG_DIR"}}/instance-vagrant-{{unixtime}}.log 2>&1",
3027
"SamePgID" : true
3128
}
@@ -35,8 +32,7 @@
3532
{
3633
"Plugin" : "flavor-vanilla",
3734
"Launch" : {
38-
"Exec" : "os",
39-
"Properties" : {
35+
"os" : {
4036
"Cmd" : "infrakit-flavor-vanilla --log 5 > {{env "LOG_DIR"}}/flavor-vanilla-{{unixtime}}.log 2>&1",
4137
"SamePgID" : true
4238
}
@@ -46,8 +42,7 @@
4642
{
4743
"Plugin" : "flavor-swarm",
4844
"Launch" : {
49-
"Exec" : "os",
50-
"Properties" : {
45+
"os" : {
5146
"Cmd" : "infrakit-flavor-swarm --host {{env "SWARM_MANAGER"}} --log 5 > {{env "LOG_DIR"}}/flavor-swarm-{{unixtime}}.log 2>&1",
5247
"SamePgID" : true
5348
}

pkg/launch/monitor.go

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,25 @@ import (
1111

1212
var errNoConfig = errors.New("no-config")
1313

14-
// ExecRule encapsulates what's required to exec a plugin
15-
type ExecRule struct {
16-
// Exec is the name of the exec to use to start the plugin
17-
Exec string
18-
// Properties is the properties for the executor
19-
Properties *types.Any
20-
}
14+
// ExecName is the name of the executor to use (e.g. 'os', 'docker-run', etc.). It's found in the config.
15+
type ExecName string
2116

2217
// Rule provides the instructions on starting the plugin
2318
type Rule struct {
2419

2520
// Plugin is the name of the plugin
2621
Plugin plugin.Name
2722

28-
// Launch is the rule for starting / launching the plugin.
29-
Launch ExecRule
23+
// Launch is the rule for starting / launching the plugin. It's a dictionary with the key being
24+
// the name of the executor and the value being the properties used by that executor.
25+
Launch map[ExecName]*types.Any
3026
}
3127

3228
// Monitor runs continuously receiving requests to start a plugin.
3329
// Monitor uses a launcher to actually start the process of the plugin.
3430
type Monitor struct {
3531
exec Exec
36-
rules map[plugin.Name]Rule
32+
rules map[plugin.Name]*types.Any
3733
startChan <-chan StartPlugin
3834
inputChan chan<- StartPlugin
3935
stop chan interface{}
@@ -42,12 +38,13 @@ type Monitor struct {
4238

4339
// NewMonitor returns a monitor that continuously watches for input
4440
// requests and launches the process for the plugin, if not already running.
41+
// The configuration to use in the config is matched to the Name() of the executor (the field Exec).
4542
func NewMonitor(l Exec, rules []Rule) *Monitor {
46-
m := map[plugin.Name]Rule{}
43+
m := map[plugin.Name]*types.Any{}
4744
// index by name of plugin
4845
for _, r := range rules {
49-
if r.Launch.Exec == l.Name() {
50-
m[r.Plugin] = r
46+
if cfg, has := r.Launch[ExecName(l.Name())]; has {
47+
m[r.Plugin] = cfg
5148
}
5249
}
5350
return &Monitor{
@@ -100,30 +97,30 @@ func (m *Monitor) Start() (chan<- StartPlugin, error) {
10097
}
10198

10299
// match first by full name of the form lookup/type -- 'specialization'
103-
r, has := m.rules[req.Plugin]
100+
properties, has := m.rules[req.Plugin]
104101
if !has {
105102
// match now by lookup only -- 'base class'
106103
alternate, _ := req.Plugin.GetLookupAndType()
107-
r, has = m.rules[plugin.Name(alternate)]
104+
properties, has = m.rules[plugin.Name(alternate)]
108105
}
109106
if !has {
110107
log.Warningln("no plugin:", req)
111-
req.reportError(r.Launch.Properties, errNoConfig)
108+
req.reportError(nil, errNoConfig)
112109
continue loop
113110
}
114111

115112
configCopy := types.AnyBytes(nil)
116-
if r.Launch.Properties != nil {
117-
*configCopy = *r.Launch.Properties
113+
if properties != nil {
114+
*configCopy = *properties
118115
}
119116

120-
block, err := m.exec.Exec(r.Plugin.String(), configCopy)
117+
block, err := m.exec.Exec(req.Plugin.String(), configCopy)
121118
if err != nil {
122119
req.reportError(configCopy, err)
123120
continue loop
124121
}
125122

126-
log.Infoln("Waiting for", r.Plugin, "to start:", configCopy.String())
123+
log.Infoln("Waiting for", req.Plugin, "to start:", configCopy.String())
127124
err = <-block
128125
if err != nil {
129126
req.reportError(configCopy, err)

pkg/launch/monitor_test.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,8 @@ func TestMonitorLoopValidRule(t *testing.T) {
6969
var receivedArgs *types.Any
7070
rule := Rule{
7171
Plugin: "hello",
72-
Launch: ExecRule{
73-
Exec: "test",
74-
Properties: types.AnyValueMust(config),
72+
Launch: map[ExecName]*types.Any{
73+
"test": types.AnyValueMust(config),
7574
},
7675
}
7776
monitor := NewMonitor(&testLauncher{
@@ -112,9 +111,8 @@ func TestMonitorLoopRuleLookupBehavior(t *testing.T) {
112111
var receivedArgs *types.Any
113112
rule := Rule{
114113
Plugin: "hello",
115-
Launch: ExecRule{
116-
Exec: "test",
117-
Properties: types.AnyValueMust(config),
114+
Launch: map[ExecName]*types.Any{
115+
"test": types.AnyValueMust(config),
118116
},
119117
}
120118
monitor := NewMonitor(&testLauncher{

pkg/launch/os/os.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ type LaunchConfig struct {
1919

2020
// NewLauncher returns a Launcher that can install and start plugins. The OS version is simple - it translates
2121
// plugin names as command names and uses os.Exec
22-
func NewLauncher() (*Launcher, error) {
22+
func NewLauncher(n string) (*Launcher, error) {
2323
return &Launcher{
24+
name: n,
2425
plugins: map[string]state{},
2526
}, nil
2627
}
@@ -31,13 +32,14 @@ type state struct {
3132

3233
// Launcher is a service that implements the launch.Exec interface for starting up os processes.
3334
type Launcher struct {
35+
name string
3436
plugins map[string]state
3537
lock sync.Mutex
3638
}
3739

3840
// Name returns the name of the launcher
3941
func (l *Launcher) Name() string {
40-
return "os"
42+
return l.name
4143
}
4244

4345
// Exec starts the os process. Returns a signal channel to block on optionally.

pkg/launch/os/os_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414

1515
func TestLaunchOSCommand(t *testing.T) {
1616

17-
launcher, err := NewLauncher()
17+
launcher, err := NewLauncher("os")
1818
require.NoError(t, err)
1919

2020
starting, err := launcher.Exec("sleepPlugin", types.AnyValueMust(&LaunchConfig{
@@ -30,7 +30,7 @@ func TestLaunchWithLog(t *testing.T) {
3030

3131
logfile := filepath.Join(os.TempDir(), fmt.Sprintf("os-test-%v", time.Now().Unix()))
3232

33-
launcher, err := NewLauncher()
33+
launcher, err := NewLauncher("os")
3434
require.NoError(t, err)
3535

3636
starting, err := launcher.Exec("echoPlugin", types.AnyValueMust(&LaunchConfig{

scripts/e2e-test-plugins.json

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,66 @@
1+
{{define "rundocker"}}docker run -d --restart always -e INFRAKIT_HOME=/infrakit -e INFRAKIT_PLUGINS_DIR=/infrakit/plugins -v ~/.infrakit:/infrakit --name {{.}} infrakit/devbundle{{end}}
12
[
23
{
3-
"Plugin" : "group-default",
4+
"Plugin" : "group-stateless",
45
"Launch" : {
5-
"Exec" : "os",
6-
"Properties": {
7-
"Cmd" : "infrakit-group-default --poll-interval 500ms --name group-stateless --log 5 > {{env "LOG_DIR"}}/group-default-{{unixtime}}.log 2>&1 &",
6+
"os": {
7+
"Cmd" : "infrakit-group-default --poll-interval 500ms --name group-stateless --log 5 > {{env "INFRAKIT_HOME"}}/logs/group-stateless.log 2>&1",
88
"SamePgID" : true
9-
}
9+
},
10+
"docker-run" : {
11+
"Cmd" : "{{template "rundocker" "group-stateless"}} infrakit-group-default --poll-interval 500ms --name group-stateless --log 5"
12+
}
1013
}
1114
}
1215
,
1316
{
1417
"Plugin" : "instance-file",
1518
"Launch" : {
16-
"Exec" : "os",
17-
"Properties" : {
18-
"Cmd" : "infrakit-instance-file --dir {{env "TUTORIAL_DIR"}} --log 5 > {{env "LOG_DIR"}}/instance-file-{{unixtime}}.log 2>&1",
19+
"os" : {
20+
"Cmd" : "infrakit-instance-file --dir {{env "INFRAKIT_HOME"}}/instance-file --log 5 > {{env "INFRAKIT_HOME"}}/logs/instance-file.log 2>&1",
1921
"SamePgID" : true
22+
},
23+
"docker-run" : {
24+
"Cmd" : "{{template "rundocker" "instance-file"}} infrakit-instance-file --dir {{env "INFRAKIT_HOME"}}/instance-file --log 5"
2025
}
2126
}
2227
}
2328
,
2429
{
2530
"Plugin" : "instance-vagrant",
2631
"Launch" : {
27-
"Exec" : "os",
28-
"Properties" : {
29-
"Cmd" : "infrakit-instance-vagrant --log 5 > {{env "LOG_DIR"}}/instance-vagrant-{{unixtime}}.log 2>&1",
32+
"os" : {
33+
"Cmd" : "infrakit-instance-vagrant --log 5 > {{env "INFRAKIT_HOME"}}/logs/instance-vagrant.log 2>&1",
3034
"SamePgID" : true
35+
},
36+
"docker-run" : {
37+
"Cmd" : "{{template "rundocker" "instance-vagrant"}} infrakit-instance-vagrant --log 5"
3138
}
3239
}
3340
}
3441
,
3542
{
3643
"Plugin" : "flavor-vanilla",
3744
"Launch" : {
38-
"Exec" : "os",
39-
"Properties" : {
40-
"Cmd" : "infrakit-flavor-vanilla --log 5 > {{env "LOG_DIR"}}/flavor-vanilla-{{unixtime}}.log 2>&1",
45+
"os" : {
46+
"Cmd" : "infrakit-flavor-vanilla --log 5 > {{env "INFRAKIT_HOME"}}/logs/flavor-vanilla.log 2>&1",
4147
"SamePgID" : true
48+
},
49+
"docker-run" : {
50+
"Cmd" : "{{template "rundocker" "flavor-vanilla"}} infrakit-flavor-vanilla --log 5"
4251
}
4352
}
4453
}
4554
,
4655
{
4756
"Plugin" : "flavor-swarm",
4857
"Launch" : {
49-
"Exec" : "os",
50-
"Properties" : {
51-
"Cmd" : "infrakit-flavor-swarm --host {{env "SWARM_MANAGER"}} --log 5 > {{env "LOG_DIR"}}/flavor-swarm-{{unixtime}}.log 2>&1",
58+
"os" : {
59+
"Cmd" : "infrakit-flavor-swarm --host {{env "SWARM_MANAGER"}} --log 5 > {{env "INFRAKIT_HOME"}}/logs/flavor-swarm.log 2>&1",
5260
"SamePgID" : true
61+
},
62+
"docker-run" : {
63+
"Cmd" : "{{template "rundocker" "flavor-swarm"}} infrakit-flavor-swarm --host {{env "SWARM_MANAGER"}} --log 5"
5364
}
5465
}
5566
}

scripts/e2e-test.sh

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,19 @@ cleanup() {
2424
trap cleanup EXIT
2525

2626
# infrakit directories
27-
plugins=~/.infrakit/plugins
27+
28+
export INFRAKIT_HOME=~/.infrakit
29+
30+
plugins=$INFRAKIT_HOME/plugins
2831
mkdir -p $plugins
2932
rm -rf $plugins/*
3033

31-
configstore=~/.infrakit/configs
34+
configstore=$INFRAKIT_HOME/configs
3235
mkdir -p $configstore
3336
rm -rf $configstore/*
3437

3538
# set the leader -- for os / file based leader detection for manager
36-
leaderfile=~/.infrakit/leader
39+
leaderfile=$INFRAKIT_HOME/leader
3740
echo group > $leaderfile
3841

3942
# start up multiple instances of manager -- typically we want multiple SETS of plugins and managers
@@ -46,19 +49,18 @@ sleep 5 # manager needs to detect leadership
4649

4750
# location of logfiles when plugins are started by the plugin cli
4851
# the config json below expects LOG_DIR as an environment variable
49-
LOG_DIR=~/.infrakit/logs
52+
LOG_DIR=$INFRAKIT_HOME/logs
5053
mkdir -p $LOG_DIR
5154

52-
# see the config josn 'e2e-test-plugins.json' for reference of environment variable TUTORIAL_DIR
53-
TUTORIAL_DIR=~/.infrakit/tutorial
54-
mkdir -p $TUTORIAL_DIR
55-
rm -rf $TUTORIAL_DIR/*
55+
# see the config josn 'e2e-test-plugins.json' for reference of environment variable
56+
INSTANCE_FILE_DIR=$INFRAKIT_HOME/instance-file
57+
mkdir -p $INSTANCE_FILE_DIR
58+
rm -rf $INSTANCE_FILE_DIR/*
5659

5760
export LOG_DIR=$LOG_DIR
58-
export TUTORIAL_DIR=$TUTORIAL_DIR
5961

6062
# note -- on exit, this won't clean up the plugins started by the cli since they will be in a separate process group
61-
infrakit plugin start --wait --config-url file:///$PWD/scripts/e2e-test-plugins.json --os group-default instance-file flavor-vanilla &
63+
infrakit plugin start --wait --config-url file:///$PWD/scripts/e2e-test-plugins.json --exec os group-stateless instance-file flavor-vanilla &
6264

6365
starterpid=$!
6466
echo "plugin start pid=$starterpid"
@@ -130,7 +132,7 @@ sleep 5
130132
expect_output_lines "10 instances should exist in group" "infrakit group describe cattle -q" "10"
131133

132134
# Terminate 3 instances.
133-
pushd $TUTORIAL_DIR
135+
pushd $INSTANCE_FILE_DIR
134136
rm $(ls | head -3)
135137
popd
136138

0 commit comments

Comments
 (0)