Skip to content

Commit 9a4bc9a

Browse files
Ensure that ls will still work when plugin cannot be found
Signed-off-by: Nathan LeClaire <nathan.leclaire@gmail.com>
1 parent bccbe19 commit 9a4bc9a

File tree

5 files changed

+150
-17
lines changed

5 files changed

+150
-17
lines changed

commands/commands.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import (
1010

1111
"github.com/docker/machine/cli"
1212
"github.com/docker/machine/commands/mcndirs"
13+
"github.com/docker/machine/drivers/errdriver"
1314
"github.com/docker/machine/libmachine/cert"
15+
"github.com/docker/machine/libmachine/drivers"
16+
"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
1417
"github.com/docker/machine/libmachine/drivers/rpc"
1518
"github.com/docker/machine/libmachine/host"
1619
"github.com/docker/machine/libmachine/log"
@@ -23,9 +26,13 @@ var (
2326
ErrExpectedOneMachine = errors.New("Error: Expected one machine name as an argument")
2427
)
2528

26-
func newPluginDriver(driverName string, rawContent []byte) (*rpcdriver.RpcClientDriver, error) {
29+
func newPluginDriver(driverName string, rawContent []byte) (drivers.Driver, error) {
2730
d, err := rpcdriver.NewRpcClientDriver(rawContent, driverName)
2831
if err != nil {
32+
// Not being able to find a driver binary is a "known error"
33+
if _, ok := err.(localbinary.ErrPluginBinaryNotFound); ok {
34+
return errdriver.NewDriver(driverName), nil
35+
}
2936
return nil, err
3037
}
3138

commands/create.go

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

1515
"github.com/docker/machine/cli"
1616
"github.com/docker/machine/commands/mcndirs"
17+
"github.com/docker/machine/drivers/errdriver"
1718
"github.com/docker/machine/libmachine"
1819
"github.com/docker/machine/libmachine/auth"
1920
"github.com/docker/machine/libmachine/drivers"
@@ -295,6 +296,10 @@ func cmdCreateOuter(c *cli.Context) error {
295296
return fmt.Errorf("Error loading driver %q: %s", driverName, err)
296297
}
297298

299+
if _, ok := driver.(*errdriver.Driver); ok {
300+
return errdriver.ErrDriverNotLoadable{driverName}
301+
}
302+
298303
// TODO: So much flag manipulation and voodoo here, it seems to be
299304
// asking for trouble.
300305
//
@@ -316,8 +321,10 @@ func cmdCreateOuter(c *cli.Context) error {
316321
}
317322
}
318323

319-
if err := driver.Close(); err != nil {
320-
return err
324+
if rpcd, ok := driver.(*rpcdriver.RpcClientDriver); ok {
325+
if err := rpcd.Close(); err != nil {
326+
return err
327+
}
321328
}
322329

323330
return c.App.Run(os.Args)

drivers/errdriver/error.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package errdriver
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/docker/machine/libmachine/drivers"
7+
"github.com/docker/machine/libmachine/mcnflag"
8+
"github.com/docker/machine/libmachine/state"
9+
)
10+
11+
type Driver struct {
12+
Name string
13+
}
14+
15+
type ErrDriverNotLoadable struct {
16+
Name string
17+
}
18+
19+
func (e ErrDriverNotLoadable) Error() string {
20+
return fmt.Sprintf("Driver %q not found. Do you have the plugin binary accessible in your PATH?", e.Name)
21+
}
22+
23+
func NewDriver(Name string) drivers.Driver {
24+
return &Driver{
25+
Name: Name,
26+
}
27+
}
28+
29+
func (d *Driver) DriverName() string {
30+
return "not-found"
31+
}
32+
33+
func (d *Driver) PreCreateCheck() error {
34+
return nil
35+
}
36+
37+
func (d *Driver) GetCreateFlags() []mcnflag.Flag {
38+
return nil
39+
}
40+
41+
func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
42+
return ErrDriverNotLoadable{d.Name}
43+
}
44+
45+
func (d *Driver) GetURL() (string, error) {
46+
return "", ErrDriverNotLoadable{d.Name}
47+
}
48+
49+
func (d *Driver) GetMachineName() string {
50+
return ""
51+
}
52+
53+
func (d *Driver) GetIP() (string, error) {
54+
return "1.2.3.4", ErrDriverNotLoadable{d.Name}
55+
}
56+
57+
func (d *Driver) GetSSHHostname() (string, error) {
58+
return "", ErrDriverNotLoadable{d.Name}
59+
}
60+
61+
func (d *Driver) GetSSHKeyPath() string {
62+
return ""
63+
}
64+
65+
func (d *Driver) GetSSHPort() (int, error) {
66+
return 0, ErrDriverNotLoadable{d.Name}
67+
}
68+
69+
func (d *Driver) GetSSHUsername() string {
70+
return ""
71+
}
72+
73+
func (d *Driver) GetState() (state.State, error) {
74+
return state.Error, ErrDriverNotLoadable{d.Name}
75+
}
76+
77+
func (d *Driver) Create() error {
78+
return ErrDriverNotLoadable{d.Name}
79+
}
80+
81+
func (d *Driver) Remove() error {
82+
return ErrDriverNotLoadable{d.Name}
83+
}
84+
85+
func (d *Driver) Start() error {
86+
return ErrDriverNotLoadable{d.Name}
87+
}
88+
89+
func (d *Driver) Stop() error {
90+
return ErrDriverNotLoadable{d.Name}
91+
}
92+
93+
func (d *Driver) Restart() error {
94+
return ErrDriverNotLoadable{d.Name}
95+
}
96+
97+
func (d *Driver) Kill() error {
98+
return ErrDriverNotLoadable{d.Name}
99+
}
100+
101+
func (d *Driver) Upgrade() error {
102+
return ErrDriverNotLoadable{d.Name}
103+
}

libmachine/drivers/plugin/localbinary/plugin.go

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,29 +73,41 @@ type LocalBinaryPlugin struct {
7373
type LocalBinaryExecutor struct {
7474
pluginStdout, pluginStderr io.ReadCloser
7575
DriverName string
76+
binaryPath string
7677
}
7778

78-
func NewLocalBinaryPlugin(driverName string) *LocalBinaryPlugin {
79+
type ErrPluginBinaryNotFound struct {
80+
driverName string
81+
}
82+
83+
func (e ErrPluginBinaryNotFound) Error() string {
84+
return fmt.Sprintf("Driver %q not found. Do you have the plugin binary accessible in your PATH?", e.driverName)
85+
}
86+
87+
func NewLocalBinaryPlugin(driverName string) (*LocalBinaryPlugin, error) {
88+
binaryPath, err := exec.LookPath(fmt.Sprintf("docker-machine-driver-%s", driverName))
89+
if err != nil {
90+
return nil, ErrPluginBinaryNotFound{driverName}
91+
}
92+
93+
log.Debugf("Found binary path at %s", binaryPath)
94+
7995
return &LocalBinaryPlugin{
8096
stopCh: make(chan bool),
8197
addrCh: make(chan string, 1),
8298
Executor: &LocalBinaryExecutor{
8399
DriverName: driverName,
100+
binaryPath: binaryPath,
84101
},
85-
}
102+
}, nil
86103
}
87104

88105
func (lbe *LocalBinaryExecutor) Start() (*bufio.Scanner, *bufio.Scanner, error) {
89-
log.Debugf("Launching plugin server for driver %s", lbe.DriverName)
90-
91-
binaryPath, err := exec.LookPath(fmt.Sprintf("docker-machine-driver-%s", lbe.DriverName))
92-
if err != nil {
93-
return nil, nil, fmt.Errorf("Driver %q not found. Do you have the plugin binary accessible in your PATH?", lbe.DriverName)
94-
}
106+
var err error
95107

96-
log.Debugf("Found binary path at %s", binaryPath)
108+
log.Debugf("Launching plugin server for driver %s", lbe.DriverName)
97109

98-
cmd := exec.Command(binaryPath)
110+
cmd := exec.Command(lbe.binaryPath)
99111

100112
lbe.pluginStdout, err = cmd.StdoutPipe()
101113
if err != nil {

libmachine/drivers/rpc/client_driver.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,20 @@ func NewInternalClient(rpcclient *rpc.Client) *InternalClient {
4545
RpcClient: rpcclient,
4646
}
4747
}
48+
4849
func NewRpcClientDriver(rawDriverData []byte, driverName string) (*RpcClientDriver, error) {
4950
mcnName := ""
5051

51-
p := localbinary.NewLocalBinaryPlugin(driverName)
52+
p, err := localbinary.NewLocalBinaryPlugin(driverName)
53+
if err != nil {
54+
return nil, err
55+
}
5256

5357
go func() {
5458
if err := p.Serve(); err != nil {
55-
// If we can't safely load the server, best to just
56-
// bail.
57-
log.Fatal(err)
59+
// TODO: Is this best approach?
60+
log.Warn(err)
61+
return
5862
}
5963
}()
6064

0 commit comments

Comments
 (0)