Ensure that ls will still work when plugin cannot be found
Signed-off-by: Nathan LeClaire <nathan.leclaire@gmail.com>
This commit is contained in:
@@ -10,7 +10,10 @@ import (
|
||||
|
||||
"github.com/docker/machine/cli"
|
||||
"github.com/docker/machine/commands/mcndirs"
|
||||
"github.com/docker/machine/drivers/errdriver"
|
||||
"github.com/docker/machine/libmachine/cert"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
|
||||
"github.com/docker/machine/libmachine/drivers/rpc"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
@@ -23,9 +26,13 @@ var (
|
||||
ErrExpectedOneMachine = errors.New("Error: Expected one machine name as an argument")
|
||||
)
|
||||
|
||||
func newPluginDriver(driverName string, rawContent []byte) (*rpcdriver.RpcClientDriver, error) {
|
||||
func newPluginDriver(driverName string, rawContent []byte) (drivers.Driver, error) {
|
||||
d, err := rpcdriver.NewRpcClientDriver(rawContent, driverName)
|
||||
if err != nil {
|
||||
// Not being able to find a driver binary is a "known error"
|
||||
if _, ok := err.(localbinary.ErrPluginBinaryNotFound); ok {
|
||||
return errdriver.NewDriver(driverName), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
"github.com/docker/machine/cli"
|
||||
"github.com/docker/machine/commands/mcndirs"
|
||||
"github.com/docker/machine/drivers/errdriver"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
@@ -295,6 +296,10 @@ func cmdCreateOuter(c *cli.Context) error {
|
||||
return fmt.Errorf("Error loading driver %q: %s", driverName, err)
|
||||
}
|
||||
|
||||
if _, ok := driver.(*errdriver.Driver); ok {
|
||||
return errdriver.ErrDriverNotLoadable{driverName}
|
||||
}
|
||||
|
||||
// TODO: So much flag manipulation and voodoo here, it seems to be
|
||||
// asking for trouble.
|
||||
//
|
||||
@@ -316,8 +321,10 @@ func cmdCreateOuter(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
if err := driver.Close(); err != nil {
|
||||
return err
|
||||
if rpcd, ok := driver.(*rpcdriver.RpcClientDriver); ok {
|
||||
if err := rpcd.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return c.App.Run(os.Args)
|
||||
|
||||
103
drivers/errdriver/error.go
Normal file
103
drivers/errdriver/error.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package errdriver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/mcnflag"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
type ErrDriverNotLoadable struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (e ErrDriverNotLoadable) Error() string {
|
||||
return fmt.Sprintf("Driver %q not found. Do you have the plugin binary accessible in your PATH?", e.Name)
|
||||
}
|
||||
|
||||
func NewDriver(Name string) drivers.Driver {
|
||||
return &Driver{
|
||||
Name: Name,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) DriverName() string {
|
||||
return "not-found"
|
||||
}
|
||||
|
||||
func (d *Driver) PreCreateCheck() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetCreateFlags() []mcnflag.Flag {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
|
||||
return ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) GetURL() (string, error) {
|
||||
return "", ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) GetMachineName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (d *Driver) GetIP() (string, error) {
|
||||
return "1.2.3.4", ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
return "", ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHKeyPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHPort() (int, error) {
|
||||
return 0, ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHUsername() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (d *Driver) GetState() (state.State, error) {
|
||||
return state.Error, ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) Create() error {
|
||||
return ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) Remove() error {
|
||||
return ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) Start() error {
|
||||
return ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) Stop() error {
|
||||
return ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) Restart() error {
|
||||
return ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) Kill() error {
|
||||
return ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
|
||||
func (d *Driver) Upgrade() error {
|
||||
return ErrDriverNotLoadable{d.Name}
|
||||
}
|
||||
@@ -73,29 +73,41 @@ type LocalBinaryPlugin struct {
|
||||
type LocalBinaryExecutor struct {
|
||||
pluginStdout, pluginStderr io.ReadCloser
|
||||
DriverName string
|
||||
binaryPath string
|
||||
}
|
||||
|
||||
func NewLocalBinaryPlugin(driverName string) *LocalBinaryPlugin {
|
||||
type ErrPluginBinaryNotFound struct {
|
||||
driverName string
|
||||
}
|
||||
|
||||
func (e ErrPluginBinaryNotFound) Error() string {
|
||||
return fmt.Sprintf("Driver %q not found. Do you have the plugin binary accessible in your PATH?", e.driverName)
|
||||
}
|
||||
|
||||
func NewLocalBinaryPlugin(driverName string) (*LocalBinaryPlugin, error) {
|
||||
binaryPath, err := exec.LookPath(fmt.Sprintf("docker-machine-driver-%s", driverName))
|
||||
if err != nil {
|
||||
return nil, ErrPluginBinaryNotFound{driverName}
|
||||
}
|
||||
|
||||
log.Debugf("Found binary path at %s", binaryPath)
|
||||
|
||||
return &LocalBinaryPlugin{
|
||||
stopCh: make(chan bool),
|
||||
addrCh: make(chan string, 1),
|
||||
Executor: &LocalBinaryExecutor{
|
||||
DriverName: driverName,
|
||||
binaryPath: binaryPath,
|
||||
},
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (lbe *LocalBinaryExecutor) Start() (*bufio.Scanner, *bufio.Scanner, error) {
|
||||
var err error
|
||||
|
||||
log.Debugf("Launching plugin server for driver %s", lbe.DriverName)
|
||||
|
||||
binaryPath, err := exec.LookPath(fmt.Sprintf("docker-machine-driver-%s", lbe.DriverName))
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Driver %q not found. Do you have the plugin binary accessible in your PATH?", lbe.DriverName)
|
||||
}
|
||||
|
||||
log.Debugf("Found binary path at %s", binaryPath)
|
||||
|
||||
cmd := exec.Command(binaryPath)
|
||||
cmd := exec.Command(lbe.binaryPath)
|
||||
|
||||
lbe.pluginStdout, err = cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
|
||||
@@ -45,16 +45,20 @@ func NewInternalClient(rpcclient *rpc.Client) *InternalClient {
|
||||
RpcClient: rpcclient,
|
||||
}
|
||||
}
|
||||
|
||||
func NewRpcClientDriver(rawDriverData []byte, driverName string) (*RpcClientDriver, error) {
|
||||
mcnName := ""
|
||||
|
||||
p := localbinary.NewLocalBinaryPlugin(driverName)
|
||||
p, err := localbinary.NewLocalBinaryPlugin(driverName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := p.Serve(); err != nil {
|
||||
// If we can't safely load the server, best to just
|
||||
// bail.
|
||||
log.Fatal(err)
|
||||
// TODO: Is this best approach?
|
||||
log.Warn(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user