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:
Nathan LeClaire
2015-11-02 22:07:54 -08:00
parent bccbe19a86
commit 9a4bc9a20d
5 changed files with 150 additions and 17 deletions

View File

@@ -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
}

View File

@@ -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
View 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}
}

View File

@@ -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 {

View File

@@ -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
}
}()