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

Commit 21dc4cd

Browse files
author
David Chung
authored
Plugin management utility - plugin stop (#367)
Signed-off-by: David Chung <[email protected]>
1 parent f432fa4 commit 21dc4cd

File tree

5 files changed

+112
-5
lines changed

5 files changed

+112
-5
lines changed

cmd/cli/plugin.go

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ package main
22

33
import (
44
"fmt"
5+
"io/ioutil"
6+
sys_os "os"
7+
"strconv"
58
"sync"
9+
"syscall"
610

11+
log "github.com/Sirupsen/logrus"
712
"github.com/docker/infrakit/pkg/discovery"
813
"github.com/docker/infrakit/pkg/launch"
914
"github.com/docker/infrakit/pkg/launch/os"
@@ -128,7 +133,64 @@ func pluginCommand(plugins func() discovery.Plugins) *cobra.Command {
128133
return nil
129134
}
130135

131-
cmd.AddCommand(ls, start)
136+
stop := &cobra.Command{
137+
Use: "stop",
138+
Short: "Stop named plugins. Args are a list of plugin names. This assumes plugins are local processes and not containers managed by another daemon, like Docker or runc.",
139+
}
140+
141+
stop.RunE = func(c *cobra.Command, args []string) error {
142+
143+
allPlugins, err := plugins().List()
144+
if err != nil {
145+
return err
146+
}
147+
148+
for _, n := range args {
149+
150+
p, has := allPlugins[n]
151+
if !has {
152+
log.Warningf("Plugin %s not running", n)
153+
continue
154+
}
155+
156+
if p.Protocol != "unix" {
157+
log.Warningf("Plugin is not a local process", n)
158+
continue
159+
}
160+
161+
// TODO(chungers) -- here we
162+
pidFile := p.Address + ".pid"
163+
164+
buff, err := ioutil.ReadFile(pidFile)
165+
if err != nil {
166+
log.Warningf("Cannot read PID file for %s: %s", n, pidFile)
167+
continue
168+
}
169+
170+
pid, err := strconv.Atoi(string(buff))
171+
if err != nil {
172+
log.Warningf("Cannot determine PID for %s from file: %s", n, pidFile)
173+
continue
174+
}
175+
176+
process, err := sys_os.FindProcess(pid)
177+
if err != nil {
178+
log.Warningf("Error finding process of plugin %s", n)
179+
continue
180+
}
181+
182+
log.Infoln("Stopping", n, "at PID=", pid)
183+
if err := process.Signal(syscall.SIGTERM); err == nil {
184+
process.Wait()
185+
log.Infoln("Process for", n, "exited")
186+
}
187+
188+
}
189+
190+
return nil
191+
}
192+
193+
cmd.AddCommand(ls, start, stop)
132194

133195
return cmd
134196
}

pkg/cli/serverutil.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cli
22

33
import (
4+
"fmt"
5+
"io/ioutil"
46
"os"
57
"path"
68

@@ -21,11 +23,25 @@ func RunPlugin(name string, plugin server.VersionedInterface) {
2123
dir := discovery.Dir()
2224
EnsureDirExists(dir)
2325

24-
stoppable, err := server.StartPluginAtPath(path.Join(dir, name), plugin)
26+
socketPath := path.Join(dir, name)
27+
pidPath := path.Join(dir, name+".pid")
28+
29+
stoppable, err := server.StartPluginAtPath(socketPath, plugin)
30+
if err != nil {
31+
log.Error(err)
32+
}
33+
34+
// write PID file
35+
err = ioutil.WriteFile(pidPath, []byte(fmt.Sprintf("%v", os.Getpid())), 0644)
2536
if err != nil {
2637
log.Error(err)
2738
}
39+
log.Infoln("PID file at", pidPath)
2840
if stoppable != nil {
2941
stoppable.AwaitStopped()
3042
}
43+
44+
// clean up
45+
os.Remove(pidPath)
46+
log.Infoln("Removed PID file at", pidPath)
3147
}

pkg/discovery/dir.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@ import (
1111
"github.com/docker/infrakit/pkg/plugin"
1212
)
1313

14+
type errNotUnixSocket string
15+
16+
func (e errNotUnixSocket) Error() string {
17+
return string(e)
18+
}
19+
20+
// IsErrNotUnixSocket returns true if the error is due to the file not being a valid unix socket.
21+
func IsErrNotUnixSocket(e error) bool {
22+
_, is := e.(errNotUnixSocket)
23+
return is
24+
}
25+
1426
type dirPluginDiscovery struct {
1527
dir string
1628
lock sync.Mutex
@@ -51,7 +63,7 @@ func (r *dirPluginDiscovery) dirLookup(entry os.FileInfo) (*plugin.Endpoint, err
5163
}, nil
5264
}
5365

54-
return nil, fmt.Errorf("File is not a socket: %s", entry)
66+
return nil, errNotUnixSocket(fmt.Sprintf("File is not a socket: %s", entry))
5567
}
5668

5769
// List returns a list of plugins known, keyed by the name
@@ -72,8 +84,16 @@ func (r *dirPluginDiscovery) List() (map[string]*plugin.Endpoint, error) {
7284
if !entry.IsDir() {
7385

7486
instance, err := r.dirLookup(entry)
75-
if err != nil || instance == nil {
76-
log.Warningln("Loading plugin err=", err)
87+
88+
if err != nil {
89+
if !IsErrNotUnixSocket(err) {
90+
log.Warningln("Loading plugin err=", err)
91+
}
92+
continue
93+
}
94+
95+
if instance == nil {
96+
log.Warningln("Plugin in nil=")
7797
continue
7898
}
7999

pkg/discovery/dir_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ import (
1313
"github.com/stretchr/testify/require"
1414
)
1515

16+
func TestErrNotUnixSocket(t *testing.T) {
17+
err := errNotUnixSocket("no socket!")
18+
require.Error(t, err)
19+
require.True(t, IsErrNotUnixSocket(err))
20+
}
21+
1622
func blockWhileFileExists(name string) {
1723
for {
1824
_, err := os.Stat(name)

scripts/e2e-test.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,6 @@ infrakit group destroy cattle
142142
expect_output_lines "0 instances should exist" "infrakit instance describe -q --name instance-file" "0"
143143

144144
echo 'ALL TESTS PASSED'
145+
146+
echo "Stopping plugins"
147+
infrakit plugin stop group-default instance-file flavor-vanilla

0 commit comments

Comments
 (0)