mirror of https://github.com/docker/docs.git
Revise CommandLine interface to contain libmachine client and store
Signed-off-by: Nathan LeClaire <nathan.leclaire@gmail.com>
This commit is contained in:
parent
3affe5ec25
commit
19ce7b79bd
|
@ -10,8 +10,6 @@ import (
|
||||||
"github.com/docker/machine/commands"
|
"github.com/docker/machine/commands"
|
||||||
"github.com/docker/machine/commands/mcndirs"
|
"github.com/docker/machine/commands/mcndirs"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
"github.com/docker/machine/libmachine/mcnutils"
|
|
||||||
"github.com/docker/machine/libmachine/ssh"
|
|
||||||
"github.com/docker/machine/version"
|
"github.com/docker/machine/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -74,16 +72,6 @@ func main() {
|
||||||
app.Name = path.Base(os.Args[0])
|
app.Name = path.Base(os.Args[0])
|
||||||
app.Author = "Docker Machine Contributors"
|
app.Author = "Docker Machine Contributors"
|
||||||
app.Email = "https://github.com/docker/machine"
|
app.Email = "https://github.com/docker/machine"
|
||||||
app.Before = func(c *cli.Context) error {
|
|
||||||
// TODO: Need better handling of config, everything is too
|
|
||||||
// complected together right now.
|
|
||||||
if c.GlobalBool("native-ssh") {
|
|
||||||
ssh.SetDefaultClient(ssh.Native)
|
|
||||||
}
|
|
||||||
mcnutils.GithubAPIToken = c.GlobalString("github-api-token")
|
|
||||||
mcndirs.BaseDir = c.GlobalString("storage-path")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
app.Commands = commands.Commands
|
app.Commands = commands.Commands
|
||||||
app.CommandNotFound = cmdNotFound
|
app.CommandNotFound = cmdNotFound
|
||||||
|
|
|
@ -4,46 +4,33 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/docker/machine/libmachine/host"
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/persist"
|
"github.com/docker/machine/libmachine/persist"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errTooManyArguments = errors.New("Error: Too many arguments given")
|
errTooManyArguments = errors.New("Error: Too many arguments given")
|
||||||
|
errNoActiveHost = errors.New("No active host found")
|
||||||
)
|
)
|
||||||
|
|
||||||
func cmdActive(c CommandLine) error {
|
func cmdActive(c CommandLine, api libmachine.API) error {
|
||||||
if len(c.Args()) > 0 {
|
if len(c.Args()) > 0 {
|
||||||
return errTooManyArguments
|
return errTooManyArguments
|
||||||
}
|
}
|
||||||
|
|
||||||
store := getStore(c)
|
hosts, err := persist.LoadAllHosts(api)
|
||||||
|
|
||||||
host, err := getActiveHost(store)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error getting active host: %s", err)
|
return fmt.Errorf("Error getting active host: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if host != nil {
|
items := getHostListItems(hosts)
|
||||||
fmt.Println(host.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
for _, item := range items {
|
||||||
}
|
|
||||||
|
|
||||||
func getActiveHost(store persist.Store) (*host.Host, error) {
|
|
||||||
hosts, err := listHosts(store)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
hostListItems := getHostListItems(hosts)
|
|
||||||
|
|
||||||
for _, item := range hostListItems {
|
|
||||||
if item.Active {
|
if item.Active {
|
||||||
return loadHost(store, item.Name)
|
fmt.Println(item.Name)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("Active host not found")
|
return errNoActiveHost
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,13 @@ import (
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/docker/machine/commands/mcndirs"
|
"github.com/docker/machine/commands/mcndirs"
|
||||||
"github.com/docker/machine/drivers/errdriver"
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/cert"
|
"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/host"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
|
"github.com/docker/machine/libmachine/mcnutils"
|
||||||
"github.com/docker/machine/libmachine/persist"
|
"github.com/docker/machine/libmachine/persist"
|
||||||
|
"github.com/docker/machine/libmachine/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -64,26 +63,49 @@ func (c *contextCommandLine) Application() *cli.App {
|
||||||
return c.App
|
return c.App
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPluginDriver(driverName string, rawContent []byte) (drivers.Driver, error) {
|
func runAction(actionName string, c CommandLine, api libmachine.API) error {
|
||||||
d, err := rpcdriver.NewRPCClientDriver(rawContent, driverName)
|
hosts, err := persist.LoadHosts(api, c.Args())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Not being able to find a driver binary is a "known error"
|
return err
|
||||||
if _, ok := err.(localbinary.ErrPluginBinaryNotFound); ok {
|
}
|
||||||
return errdriver.NewDriver(driverName), nil
|
|
||||||
|
if len(hosts) == 0 {
|
||||||
|
return ErrNoMachineSpecified
|
||||||
|
}
|
||||||
|
|
||||||
|
if errs := runActionForeachMachine(actionName, hosts); len(errs) > 0 {
|
||||||
|
return consolidateErrs(errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, h := range hosts {
|
||||||
|
if err := api.Save(h); err != nil {
|
||||||
|
return fmt.Errorf("Error saving host to store: %s", err)
|
||||||
}
|
}
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if driverName == "virtualbox" {
|
return nil
|
||||||
return drivers.NewSerialDriver(d), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return d, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func fatalOnError(command func(commandLine CommandLine) error) func(context *cli.Context) {
|
func fatalOnError(command func(commandLine CommandLine, api libmachine.API) error) func(context *cli.Context) {
|
||||||
return func(context *cli.Context) {
|
return func(context *cli.Context) {
|
||||||
if err := command(&contextCommandLine{context}); err != nil {
|
api := libmachine.NewClient(mcndirs.GetBaseDir())
|
||||||
|
|
||||||
|
if context.GlobalBool("native-ssh") {
|
||||||
|
api.SSHClientType = ssh.Native
|
||||||
|
}
|
||||||
|
api.GithubAPIToken = context.GlobalString("github-api-token")
|
||||||
|
api.Filestore.Path = context.GlobalString("storage-path")
|
||||||
|
|
||||||
|
// TODO (nathanleclaire): These should ultimately be accessed
|
||||||
|
// through the libmachine client by the rest of the code and
|
||||||
|
// not through their respective modules. For now, however,
|
||||||
|
// they are also being set the way that they originally were
|
||||||
|
// set to preserve backwards compatibility.
|
||||||
|
mcndirs.BaseDir = api.Filestore.Path
|
||||||
|
mcnutils.GithubAPIToken = api.GithubAPIToken
|
||||||
|
ssh.SetDefaultClient(api.SSHClientType)
|
||||||
|
|
||||||
|
if err := command(&contextCommandLine{context}, api); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,88 +124,6 @@ func confirmInput(msg string) (bool, error) {
|
||||||
return confirmed, nil
|
return confirmed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStore(c CommandLine) persist.Store {
|
|
||||||
certInfo := getCertPathInfoFromContext(c)
|
|
||||||
return &persist.Filestore{
|
|
||||||
Path: c.GlobalString("storage-path"),
|
|
||||||
CaCertPath: certInfo.CaCertPath,
|
|
||||||
CaPrivateKeyPath: certInfo.CaPrivateKeyPath,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func listHosts(store persist.Store) ([]*host.Host, error) {
|
|
||||||
cliHosts := []*host.Host{}
|
|
||||||
|
|
||||||
hosts, err := store.List()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error attempting to list hosts from store: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, h := range hosts {
|
|
||||||
d, err := newPluginDriver(h.DriverName, h.RawDriver)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error attempting to invoke binary for plugin '%s': %s", h.DriverName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
h.Driver = d
|
|
||||||
|
|
||||||
cliHosts = append(cliHosts, h)
|
|
||||||
}
|
|
||||||
|
|
||||||
return cliHosts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadHost(store persist.Store, hostName string) (*host.Host, error) {
|
|
||||||
h, err := store.Load(hostName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Loading host from store failed: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
d, err := newPluginDriver(h.DriverName, h.RawDriver)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error attempting to invoke binary for plugin: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
h.Driver = d
|
|
||||||
|
|
||||||
return h, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveHost(store persist.Store, h *host.Host) error {
|
|
||||||
if err := store.Save(h); err != nil {
|
|
||||||
return fmt.Errorf("Error attempting to save host to store: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFirstArgHost(c CommandLine) (*host.Host, error) {
|
|
||||||
store := getStore(c)
|
|
||||||
hostName := c.Args().First()
|
|
||||||
|
|
||||||
h, err := loadHost(store, hostName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error trying to get host %q: %s", hostName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return h, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getHostsFromContext(c CommandLine) ([]*host.Host, error) {
|
|
||||||
store := getStore(c)
|
|
||||||
hosts := []*host.Host{}
|
|
||||||
|
|
||||||
for _, hostName := range c.Args() {
|
|
||||||
h, err := loadHost(store, hostName)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Could not load host %q: %s", hostName, err)
|
|
||||||
}
|
|
||||||
hosts = append(hosts, h)
|
|
||||||
}
|
|
||||||
|
|
||||||
return hosts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var Commands = []cli.Command{
|
var Commands = []cli.Command{
|
||||||
{
|
{
|
||||||
Name: "active",
|
Name: "active",
|
||||||
|
@ -427,52 +367,27 @@ func consolidateErrs(errs []error) error {
|
||||||
return errors.New(strings.TrimSpace(finalErr))
|
return errors.New(strings.TrimSpace(finalErr))
|
||||||
}
|
}
|
||||||
|
|
||||||
func runActionWithContext(actionName string, c CommandLine) error {
|
// Returns the cert paths. codegangsta/cli will not set the cert paths if the
|
||||||
store := getStore(c)
|
// storage-path is set to something different so we cannot use the paths in the
|
||||||
|
// global options. le sigh.
|
||||||
hosts, err := getHostsFromContext(c)
|
func getCertPathInfoFromCommandLine(c CommandLine) cert.PathInfo {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(hosts) == 0 {
|
|
||||||
return ErrNoMachineSpecified
|
|
||||||
}
|
|
||||||
|
|
||||||
if errs := runActionForeachMachine(actionName, hosts); len(errs) > 0 {
|
|
||||||
return consolidateErrs(errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, h := range hosts {
|
|
||||||
if err := saveHost(store, h); err != nil {
|
|
||||||
return fmt.Errorf("Error saving host to store: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the cert paths.
|
|
||||||
// codegangsta/cli will not set the cert paths if the storage-path is set to
|
|
||||||
// something different so we cannot use the paths in the global options. le
|
|
||||||
// sigh.
|
|
||||||
func getCertPathInfoFromContext(c CommandLine) cert.PathInfo {
|
|
||||||
caCertPath := c.GlobalString("tls-ca-cert")
|
caCertPath := c.GlobalString("tls-ca-cert")
|
||||||
|
caKeyPath := c.GlobalString("tls-ca-key")
|
||||||
|
clientCertPath := c.GlobalString("tls-client-cert")
|
||||||
|
clientKeyPath := c.GlobalString("tls-client-key")
|
||||||
|
|
||||||
if caCertPath == "" {
|
if caCertPath == "" {
|
||||||
caCertPath = filepath.Join(mcndirs.GetMachineCertDir(), "ca.pem")
|
caCertPath = filepath.Join(mcndirs.GetMachineCertDir(), "ca.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
caKeyPath := c.GlobalString("tls-ca-key")
|
|
||||||
if caKeyPath == "" {
|
if caKeyPath == "" {
|
||||||
caKeyPath = filepath.Join(mcndirs.GetMachineCertDir(), "ca-key.pem")
|
caKeyPath = filepath.Join(mcndirs.GetMachineCertDir(), "ca-key.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
clientCertPath := c.GlobalString("tls-client-cert")
|
|
||||||
if clientCertPath == "" {
|
if clientCertPath == "" {
|
||||||
clientCertPath = filepath.Join(mcndirs.GetMachineCertDir(), "cert.pem")
|
clientCertPath = filepath.Join(mcndirs.GetMachineCertDir(), "cert.pem")
|
||||||
}
|
}
|
||||||
|
|
||||||
clientKeyPath := c.GlobalString("tls-client-key")
|
|
||||||
if clientKeyPath == "" {
|
if clientKeyPath == "" {
|
||||||
clientKeyPath = filepath.Join(mcndirs.GetMachineCertDir(), "key.pem")
|
clientKeyPath = filepath.Join(mcndirs.GetMachineCertDir(), "key.pem")
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/auth"
|
"github.com/docker/machine/libmachine/auth"
|
||||||
"github.com/docker/machine/libmachine/cert"
|
"github.com/docker/machine/libmachine/cert"
|
||||||
"github.com/docker/machine/libmachine/host"
|
"github.com/docker/machine/libmachine/host"
|
||||||
|
@ -26,7 +27,7 @@ Be advised that this will trigger a Docker daemon restart which will stop runnin
|
||||||
`, e.hostURL, e.wrappedErr)
|
`, e.hostURL, e.wrappedErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdConfig(c CommandLine) error {
|
func cmdConfig(c CommandLine, api libmachine.API) error {
|
||||||
// Ensure that log messages always go to stderr when this command is
|
// Ensure that log messages always go to stderr when this command is
|
||||||
// being run (it is intended to be run in a subshell)
|
// being run (it is intended to be run in a subshell)
|
||||||
log.SetOutWriter(os.Stderr)
|
log.SetOutWriter(os.Stderr)
|
||||||
|
@ -35,7 +36,7 @@ func cmdConfig(c CommandLine) error {
|
||||||
return ErrExpectedOneMachine
|
return ErrExpectedOneMachine
|
||||||
}
|
}
|
||||||
|
|
||||||
host, err := getFirstArgHost(c)
|
host, err := api.Load(c.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import (
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
"github.com/docker/machine/libmachine/mcnerror"
|
"github.com/docker/machine/libmachine/mcnerror"
|
||||||
"github.com/docker/machine/libmachine/mcnflag"
|
"github.com/docker/machine/libmachine/mcnflag"
|
||||||
"github.com/docker/machine/libmachine/persist"
|
|
||||||
"github.com/docker/machine/libmachine/swarm"
|
"github.com/docker/machine/libmachine/swarm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -123,28 +122,19 @@ var (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func cmdCreateInner(c CommandLine) error {
|
func cmdCreateInner(c CommandLine, api libmachine.API) error {
|
||||||
if len(c.Args()) > 1 {
|
if len(c.Args()) > 1 {
|
||||||
return fmt.Errorf("Invalid command line. Found extra arguments %v", c.Args()[1:])
|
return fmt.Errorf("Invalid command line. Found extra arguments %v", c.Args()[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
name := c.Args().First()
|
name := c.Args().First()
|
||||||
driverName := c.String("driver")
|
|
||||||
certInfo := getCertPathInfoFromContext(c)
|
|
||||||
|
|
||||||
storePath := c.GlobalString("storage-path")
|
|
||||||
|
|
||||||
store := &persist.Filestore{
|
|
||||||
Path: storePath,
|
|
||||||
CaCertPath: certInfo.CaCertPath,
|
|
||||||
CaPrivateKeyPath: certInfo.CaPrivateKeyPath,
|
|
||||||
}
|
|
||||||
|
|
||||||
if name == "" {
|
if name == "" {
|
||||||
c.ShowHelp()
|
c.ShowHelp()
|
||||||
return errNoMachineName
|
return errNoMachineName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
driverName := c.String("driver")
|
||||||
|
|
||||||
validName := host.ValidateHostName(name)
|
validName := host.ValidateHostName(name)
|
||||||
if !validName {
|
if !validName {
|
||||||
return fmt.Errorf("Error creating machine: %s", mcnerror.ErrInvalidHostname)
|
return fmt.Errorf("Error creating machine: %s", mcnerror.ErrInvalidHostname)
|
||||||
|
@ -163,16 +153,18 @@ func cmdCreateInner(c CommandLine) error {
|
||||||
return fmt.Errorf("Error attempting to marshal bare driver data: %s", err)
|
return fmt.Errorf("Error attempting to marshal bare driver data: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
driver, err := newPluginDriver(driverName, bareDriverData)
|
driver, err := api.NewPluginDriver(driverName, bareDriverData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error loading driver %q: %s", driverName, err)
|
return fmt.Errorf("Error loading driver %q: %s", driverName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
h, err := store.NewHost(driver)
|
h, err := api.NewHost(driver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error getting new host: %s", err)
|
return fmt.Errorf("Error getting new host: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
certInfo := getCertPathInfoFromCommandLine(c)
|
||||||
|
|
||||||
h.HostOptions = &host.Options{
|
h.HostOptions = &host.Options{
|
||||||
AuthOptions: &auth.Options{
|
AuthOptions: &auth.Options{
|
||||||
CertDir: mcndirs.GetMachineCertDir(),
|
CertDir: mcndirs.GetMachineCertDir(),
|
||||||
|
@ -207,7 +199,7 @@ func cmdCreateInner(c CommandLine) error {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
exists, err := store.Exists(h.Name)
|
exists, err := api.Exists(h.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error checking if host exists: %s", err)
|
return fmt.Errorf("Error checking if host exists: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -227,11 +219,11 @@ func cmdCreateInner(c CommandLine) error {
|
||||||
return fmt.Errorf("Error setting machine configuration from flags provided: %s", err)
|
return fmt.Errorf("Error setting machine configuration from flags provided: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := libmachine.Create(store, h); err != nil {
|
if err := api.Create(h); err != nil {
|
||||||
return fmt.Errorf("Error creating machine: %s", err)
|
return fmt.Errorf("Error creating machine: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := saveHost(store, h); err != nil {
|
if err := api.Save(h); err != nil {
|
||||||
return fmt.Errorf("Error attempting to save store: %s", err)
|
return fmt.Errorf("Error attempting to save store: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,7 +268,7 @@ func flagHackLookup(flagName string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdCreateOuter(c CommandLine) error {
|
func cmdCreateOuter(c CommandLine, api libmachine.API) error {
|
||||||
const (
|
const (
|
||||||
flagLookupMachineName = "flag-lookup"
|
flagLookupMachineName = "flag-lookup"
|
||||||
)
|
)
|
||||||
|
@ -296,7 +288,7 @@ func cmdCreateOuter(c CommandLine) error {
|
||||||
return fmt.Errorf("Error attempting to marshal bare driver data: %s", err)
|
return fmt.Errorf("Error attempting to marshal bare driver data: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
driver, err := newPluginDriver(driverName, bareDriverData)
|
driver, err := api.NewPluginDriver(driverName, bareDriverData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error loading driver %q: %s", driverName, err)
|
return fmt.Errorf("Error loading driver %q: %s", driverName, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/docker/machine/commands/mcndirs"
|
"github.com/docker/machine/commands/mcndirs"
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,23 +36,23 @@ type ShellConfig struct {
|
||||||
NoProxyValue string
|
NoProxyValue string
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdEnv(c CommandLine) error {
|
func cmdEnv(c CommandLine, api libmachine.API) error {
|
||||||
// Ensure that log messages always go to stderr when this command is
|
// Ensure that log messages always go to stderr when this command is
|
||||||
// being run (it is intended to be run in a subshell)
|
// being run (it is intended to be run in a subshell)
|
||||||
log.SetOutWriter(os.Stderr)
|
log.SetOutWriter(os.Stderr)
|
||||||
|
|
||||||
if c.Bool("unset") {
|
if c.Bool("unset") {
|
||||||
return unset(c)
|
return unset(c, api)
|
||||||
}
|
}
|
||||||
return set(c)
|
return set(c, api)
|
||||||
}
|
}
|
||||||
|
|
||||||
func set(c CommandLine) error {
|
func set(c CommandLine, api libmachine.API) error {
|
||||||
if len(c.Args()) != 1 {
|
if len(c.Args()) != 1 {
|
||||||
return errImproperEnvArgs
|
return errImproperEnvArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
host, err := getFirstArgHost(c)
|
host, err := api.Load(c.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -118,7 +119,7 @@ func set(c CommandLine) error {
|
||||||
return executeTemplateStdout(shellCfg)
|
return executeTemplateStdout(shellCfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func unset(c CommandLine) error {
|
func unset(c CommandLine, api libmachine.API) error {
|
||||||
if len(c.Args()) != 0 {
|
if len(c.Args()) != 0 {
|
||||||
return errImproperUnsetEnvArgs
|
return errImproperUnsetEnvArgs
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
)
|
)
|
||||||
|
|
||||||
var funcMap = template.FuncMap{
|
var funcMap = template.FuncMap{
|
||||||
|
@ -18,13 +20,13 @@ var funcMap = template.FuncMap{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdInspect(c CommandLine) error {
|
func cmdInspect(c CommandLine, api libmachine.API) error {
|
||||||
if len(c.Args()) == 0 {
|
if len(c.Args()) == 0 {
|
||||||
c.ShowHelp()
|
c.ShowHelp()
|
||||||
return ErrExpectedOneMachine
|
return ErrExpectedOneMachine
|
||||||
}
|
}
|
||||||
|
|
||||||
host, err := getFirstArgHost(c)
|
host, err := api.Load(c.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
func cmdIP(c CommandLine) error {
|
import "github.com/docker/machine/libmachine"
|
||||||
return runActionWithContext("ip", c)
|
|
||||||
|
func cmdIP(c CommandLine, api libmachine.API) error {
|
||||||
|
return runAction("ip", c, api)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
func cmdKill(c CommandLine) error {
|
import "github.com/docker/machine/libmachine"
|
||||||
return runActionWithContext("kill", c)
|
|
||||||
|
func cmdKill(c CommandLine, api libmachine.API) error {
|
||||||
|
return runAction("kill", c, api)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,11 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/drivers"
|
"github.com/docker/machine/libmachine/drivers"
|
||||||
"github.com/docker/machine/libmachine/host"
|
"github.com/docker/machine/libmachine/host"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
|
"github.com/docker/machine/libmachine/persist"
|
||||||
"github.com/docker/machine/libmachine/state"
|
"github.com/docker/machine/libmachine/state"
|
||||||
"github.com/docker/machine/libmachine/swarm"
|
"github.com/docker/machine/libmachine/swarm"
|
||||||
"github.com/skarademir/naturalsort"
|
"github.com/skarademir/naturalsort"
|
||||||
|
@ -39,15 +41,14 @@ type HostListItem struct {
|
||||||
SwarmOptions *swarm.Options
|
SwarmOptions *swarm.Options
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdLs(c CommandLine) error {
|
func cmdLs(c CommandLine, api libmachine.API) error {
|
||||||
quiet := c.Bool("quiet")
|
quiet := c.Bool("quiet")
|
||||||
filters, err := parseFilters(c.StringSlice("filter"))
|
filters, err := parseFilters(c.StringSlice("filter"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
store := getStore(c)
|
hostList, err := persist.LoadAllHosts(api)
|
||||||
hostList, err := listHosts(store)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -261,15 +262,9 @@ func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) {
|
||||||
close(stateCh)
|
close(stateCh)
|
||||||
close(urlCh)
|
close(urlCh)
|
||||||
|
|
||||||
active, err := isActive(currentState, url)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("error determining if host is active for host %s: %s",
|
|
||||||
h.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
stateQueryChan <- HostListItem{
|
stateQueryChan <- HostListItem{
|
||||||
Name: h.Name,
|
Name: h.Name,
|
||||||
Active: active,
|
Active: isActive(currentState, url),
|
||||||
DriverName: h.Driver.DriverName(),
|
DriverName: h.Driver.DriverName(),
|
||||||
State: currentState,
|
State: currentState,
|
||||||
URL: url,
|
URL: url,
|
||||||
|
@ -332,14 +327,14 @@ func sortHostListItemsByName(items []HostListItem) {
|
||||||
|
|
||||||
// IsActive provides a single function for determining if a host is active
|
// IsActive provides a single function for determining if a host is active
|
||||||
// based on both the url and if the host is stopped.
|
// based on both the url and if the host is stopped.
|
||||||
func isActive(currentState state.State, url string) (bool, error) {
|
func isActive(currentState state.State, url string) bool {
|
||||||
if currentState != state.Running {
|
dockerHost := os.Getenv("DOCKER_HOST")
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: hard-coding the swarm port is a travesty...
|
// TODO: hard-coding the swarm port is a travesty...
|
||||||
dockerHost := os.Getenv("DOCKER_HOST")
|
|
||||||
deSwarmedHost := strings.Replace(dockerHost, ":3376", ":2376", 1)
|
deSwarmedHost := strings.Replace(dockerHost, ":3376", ":2376", 1)
|
||||||
|
if dockerHost == url || deSwarmedHost == url {
|
||||||
|
return currentState == state.Running
|
||||||
|
}
|
||||||
|
|
||||||
return dockerHost == url || deSwarmedHost == url, nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -467,9 +467,8 @@ func TestIsActive(t *testing.T) {
|
||||||
os.Setenv("DOCKER_HOST", c.dockerHost)
|
os.Setenv("DOCKER_HOST", c.dockerHost)
|
||||||
}
|
}
|
||||||
|
|
||||||
actual, err := isActive(c.state, "tcp://1.2.3.4:2376")
|
actual := isActive(c.state, "tcp://1.2.3.4:2376")
|
||||||
|
|
||||||
assert.Equal(t, c.expected, actual, "IsActive(%s, \"%s\") should return %v, but didn't", c.state, c.dockerHost, c.expected)
|
assert.Equal(t, c.expected, actual, "IsActive(%s, \"%s\") should return %v, but didn't", c.state, c.dockerHost, c.expected)
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func cmdRegenerateCerts(c CommandLine) error {
|
func cmdRegenerateCerts(c CommandLine, api libmachine.API) error {
|
||||||
if !c.Bool("force") {
|
if !c.Bool("force") {
|
||||||
ok, err := confirmInput("Regenerate TLS machine certs? Warning: this is irreversible.")
|
ok, err := confirmInput("Regenerate TLS machine certs? Warning: this is irreversible.")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -18,5 +19,5 @@ func cmdRegenerateCerts(c CommandLine) error {
|
||||||
|
|
||||||
log.Infof("Regenerating TLS certificates")
|
log.Infof("Regenerating TLS certificates")
|
||||||
|
|
||||||
return runActionWithContext("configureAuth", c)
|
return runAction("configureAuth", c, api)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func cmdRestart(c CommandLine) error {
|
func cmdRestart(c CommandLine, api libmachine.API) error {
|
||||||
if err := runActionWithContext("restart", c); err != nil {
|
if err := runAction("restart", c, api); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,20 +4,20 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func cmdRm(c CommandLine) error {
|
func cmdRm(c CommandLine, api libmachine.API) error {
|
||||||
if len(c.Args()) == 0 {
|
if len(c.Args()) == 0 {
|
||||||
c.ShowHelp()
|
c.ShowHelp()
|
||||||
return errors.New("You must specify a machine name")
|
return errors.New("You must specify a machine name")
|
||||||
}
|
}
|
||||||
|
|
||||||
force := c.Bool("force")
|
force := c.Bool("force")
|
||||||
store := getStore(c)
|
|
||||||
|
|
||||||
for _, hostName := range c.Args() {
|
for _, hostName := range c.Args() {
|
||||||
h, err := loadHost(store, hostName)
|
h, err := api.Load(hostName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error removing host %q: %s", hostName, err)
|
return fmt.Errorf("Error removing host %q: %s", hostName, err)
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ func cmdRm(c CommandLine) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.Remove(hostName); err != nil {
|
if err := api.Remove(hostName); err != nil {
|
||||||
log.Errorf("Error removing machine %q from store: %s", hostName, err)
|
log.Errorf("Error removing machine %q from store: %s", hostName, err)
|
||||||
} else {
|
} else {
|
||||||
log.Infof("Successfully removed %s", hostName)
|
log.Infof("Successfully removed %s", hostName)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
"github.com/docker/machine/libmachine/persist"
|
"github.com/docker/machine/libmachine/persist"
|
||||||
)
|
)
|
||||||
|
@ -44,7 +45,7 @@ type storeHostInfoLoader struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storeHostInfoLoader) load(name string) (HostInfo, error) {
|
func (s *storeHostInfoLoader) load(name string) (HostInfo, error) {
|
||||||
host, err := loadHost(s.store, name)
|
host, err := s.store.Load(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error loading host: %s", err)
|
return nil, fmt.Errorf("Error loading host: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -52,7 +53,7 @@ func (s *storeHostInfoLoader) load(name string) (HostInfo, error) {
|
||||||
return host.Driver, nil
|
return host.Driver, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdScp(c CommandLine) error {
|
func cmdScp(c CommandLine, api libmachine.API) error {
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
c.ShowHelp()
|
c.ShowHelp()
|
||||||
|
@ -62,8 +63,7 @@ func cmdScp(c CommandLine) error {
|
||||||
src := args[0]
|
src := args[0]
|
||||||
dest := args[1]
|
dest := args[1]
|
||||||
|
|
||||||
store := getStore(c)
|
hostInfoLoader := &storeHostInfoLoader{api}
|
||||||
hostInfoLoader := &storeHostInfoLoader{store}
|
|
||||||
|
|
||||||
cmd, err := getScpCmd(src, dest, c.Bool("recursive"), hostInfoLoader)
|
cmd, err := getScpCmd(src, dest, c.Bool("recursive"), hostInfoLoader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -3,10 +3,11 @@ package commands
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/state"
|
"github.com/docker/machine/libmachine/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
func cmdSSH(c CommandLine) error {
|
func cmdSSH(c CommandLine, api libmachine.API) error {
|
||||||
// Check for help flag -- Needed due to SkipFlagParsing
|
// Check for help flag -- Needed due to SkipFlagParsing
|
||||||
for _, arg := range c.Args() {
|
for _, arg := range c.Args() {
|
||||||
if arg == "-help" || arg == "--help" || arg == "-h" {
|
if arg == "-help" || arg == "--help" || arg == "-h" {
|
||||||
|
@ -20,8 +21,7 @@ func cmdSSH(c CommandLine) error {
|
||||||
return ErrExpectedOneMachine
|
return ErrExpectedOneMachine
|
||||||
}
|
}
|
||||||
|
|
||||||
store := getStore(c)
|
host, err := api.Load(name)
|
||||||
host, err := loadHost(store, name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func cmdStart(c CommandLine) error {
|
func cmdStart(c CommandLine, api libmachine.API) error {
|
||||||
if err := runActionWithContext("start", c); err != nil {
|
if err := runAction("start", c, api); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func cmdStatus(c CommandLine) error {
|
func cmdStatus(c CommandLine, api libmachine.API) error {
|
||||||
if len(c.Args()) != 1 {
|
if len(c.Args()) != 1 {
|
||||||
return ErrExpectedOneMachine
|
return ErrExpectedOneMachine
|
||||||
}
|
}
|
||||||
|
|
||||||
host, err := getFirstArgHost(c)
|
host, err := api.Load(c.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
func cmdStop(c CommandLine) error {
|
import "github.com/docker/machine/libmachine"
|
||||||
return runActionWithContext("stop", c)
|
|
||||||
|
func cmdStop(c CommandLine, api libmachine.API) error {
|
||||||
|
return runAction("stop", c, api)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
func cmdUpgrade(c CommandLine) error {
|
import "github.com/docker/machine/libmachine"
|
||||||
return runActionWithContext("upgrade", c)
|
|
||||||
|
func cmdUpgrade(c CommandLine, api libmachine.API) error {
|
||||||
|
return runAction("upgrade", c, api)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,16 @@ package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/docker/machine/libmachine"
|
||||||
)
|
)
|
||||||
|
|
||||||
func cmdURL(c CommandLine) error {
|
func cmdURL(c CommandLine, api libmachine.API) error {
|
||||||
if len(c.Args()) != 1 {
|
if len(c.Args()) != 1 {
|
||||||
return ErrExpectedOneMachine
|
return ErrExpectedOneMachine
|
||||||
}
|
}
|
||||||
|
|
||||||
host, err := getFirstArgHost(c)
|
host, err := api.Load(c.Args().First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
func cmdVersion(c CommandLine) error {
|
import "github.com/docker/machine/libmachine"
|
||||||
|
|
||||||
|
func cmdVersion(c CommandLine, api libmachine.API) error {
|
||||||
c.ShowVersion()
|
c.ShowVersion()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/machine/libmachine"
|
|
||||||
"github.com/docker/machine/libmachine/drivers"
|
"github.com/docker/machine/libmachine/drivers"
|
||||||
"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
|
"github.com/docker/machine/libmachine/drivers/plugin/localbinary"
|
||||||
"github.com/docker/machine/libmachine/drivers/rpc"
|
"github.com/docker/machine/libmachine/drivers/rpc"
|
||||||
|
"github.com/docker/machine/libmachine/log"
|
||||||
"github.com/docker/machine/libmachine/version"
|
"github.com/docker/machine/libmachine/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ Please use this plugin through the main 'docker-machine' binary.
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
libmachine.SetDebug(true)
|
log.IsDebug = true
|
||||||
|
|
||||||
rpcd := rpcdriver.NewRPCServerDriver(d)
|
rpcd := rpcdriver.NewRPCServerDriver(d)
|
||||||
rpc.Register(rpcd)
|
rpc.Register(rpcd)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
// Sample Virtualbox create independent of Machine CLI.
|
// Sample Virtualbox create independent of Machine CLI.
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
@ -11,16 +12,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
libmachine.SetDebug(true)
|
log.IsDebug = true
|
||||||
|
|
||||||
log.SetOutWriter(os.Stdout)
|
log.SetOutWriter(os.Stdout)
|
||||||
log.SetErrWriter(os.Stderr)
|
log.SetErrWriter(os.Stderr)
|
||||||
|
|
||||||
// returns the familiar store at $HOME/.docker/machine
|
client := libmachine.NewClient("/tmp/automatic")
|
||||||
store := libmachine.GetDefaultStore()
|
|
||||||
|
|
||||||
// over-ride this for now (don't want to muck with my default store)
|
|
||||||
store.Path = "/tmp/automatic"
|
|
||||||
|
|
||||||
hostName := "myfunhost"
|
hostName := "myfunhost"
|
||||||
|
|
||||||
|
@ -29,14 +25,24 @@ func main() {
|
||||||
driver.CPU = 2
|
driver.CPU = 2
|
||||||
driver.Memory = 2048
|
driver.Memory = 2048
|
||||||
|
|
||||||
h, err := store.NewHost(driver)
|
data, err := json.Marshal(driver)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginDriver, err := client.NewPluginDriver("virtualbox", data)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
h, err := client.NewHost(pluginDriver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
h.HostOptions.EngineOptions.StorageDriver = "overlay"
|
h.HostOptions.EngineOptions.StorageDriver = "overlay"
|
||||||
|
|
||||||
if err := libmachine.Create(store, h); err != nil {
|
if err := client.Create(h); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,29 +4,81 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/docker/machine/libmachine/auth"
|
||||||
"github.com/docker/machine/libmachine/cert"
|
"github.com/docker/machine/libmachine/cert"
|
||||||
"github.com/docker/machine/libmachine/drivers"
|
"github.com/docker/machine/libmachine/drivers"
|
||||||
|
"github.com/docker/machine/libmachine/engine"
|
||||||
"github.com/docker/machine/libmachine/host"
|
"github.com/docker/machine/libmachine/host"
|
||||||
"github.com/docker/machine/libmachine/log"
|
"github.com/docker/machine/libmachine/log"
|
||||||
"github.com/docker/machine/libmachine/mcnutils"
|
"github.com/docker/machine/libmachine/mcnutils"
|
||||||
"github.com/docker/machine/libmachine/persist"
|
"github.com/docker/machine/libmachine/persist"
|
||||||
"github.com/docker/machine/libmachine/provision"
|
"github.com/docker/machine/libmachine/provision"
|
||||||
|
"github.com/docker/machine/libmachine/ssh"
|
||||||
"github.com/docker/machine/libmachine/state"
|
"github.com/docker/machine/libmachine/state"
|
||||||
|
"github.com/docker/machine/libmachine/swarm"
|
||||||
|
"github.com/docker/machine/libmachine/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetDefaultStore() *persist.Filestore {
|
type API interface {
|
||||||
homeDir := mcnutils.GetHomeDir()
|
persist.Store
|
||||||
certsDir := filepath.Join(homeDir, ".docker", "machine", "certs")
|
NewPluginDriver(string, []byte) (drivers.Driver, error)
|
||||||
return &persist.Filestore{
|
NewHost(drivers.Driver) (*host.Host, error)
|
||||||
Path: homeDir,
|
Create(h *host.Host) error
|
||||||
CaCertPath: certsDir,
|
}
|
||||||
CaPrivateKeyPath: certsDir,
|
|
||||||
|
type Client struct {
|
||||||
|
*persist.PluginStore
|
||||||
|
IsDebug bool
|
||||||
|
SSHClientType ssh.ClientType
|
||||||
|
GithubAPIToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClient(storePath string) *Client {
|
||||||
|
certsDir := filepath.Join(storePath, ".docker", "machine", "certs")
|
||||||
|
return &Client{
|
||||||
|
IsDebug: false,
|
||||||
|
SSHClientType: ssh.External,
|
||||||
|
PluginStore: persist.NewPluginStore(storePath, certsDir, certsDir),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *Client) NewHost(driver drivers.Driver) (*host.Host, error) {
|
||||||
|
certDir := filepath.Join(api.Path, "certs")
|
||||||
|
|
||||||
|
hostOptions := &host.Options{
|
||||||
|
AuthOptions: &auth.Options{
|
||||||
|
CertDir: certDir,
|
||||||
|
CaCertPath: filepath.Join(certDir, "ca.pem"),
|
||||||
|
CaPrivateKeyPath: filepath.Join(certDir, "ca-key.pem"),
|
||||||
|
ClientCertPath: filepath.Join(certDir, "cert.pem"),
|
||||||
|
ClientKeyPath: filepath.Join(certDir, "key.pem"),
|
||||||
|
ServerCertPath: filepath.Join(api.GetMachinesDir(), "server.pem"),
|
||||||
|
ServerKeyPath: filepath.Join(api.GetMachinesDir(), "server-key.pem"),
|
||||||
|
},
|
||||||
|
EngineOptions: &engine.Options{
|
||||||
|
InstallURL: "https://get.docker.com",
|
||||||
|
StorageDriver: "aufs",
|
||||||
|
TLSVerify: true,
|
||||||
|
},
|
||||||
|
SwarmOptions: &swarm.Options{
|
||||||
|
Host: "tcp://0.0.0.0:3376",
|
||||||
|
Image: "swarm:latest",
|
||||||
|
Strategy: "spread",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return &host.Host{
|
||||||
|
ConfigVersion: version.ConfigVersion,
|
||||||
|
Name: driver.GetMachineName(),
|
||||||
|
Driver: driver,
|
||||||
|
DriverName: driver.DriverName(),
|
||||||
|
HostOptions: hostOptions,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Create is the wrapper method which covers all of the boilerplate around
|
// Create is the wrapper method which covers all of the boilerplate around
|
||||||
// actually creating, provisioning, and persisting an instance in the store.
|
// actually creating, provisioning, and persisting an instance in the store.
|
||||||
func Create(store persist.Store, h *host.Host) error {
|
func (api *Client) Create(h *host.Host) error {
|
||||||
if err := cert.BootstrapCertificates(h.HostOptions.AuthOptions); err != nil {
|
if err := cert.BootstrapCertificates(h.HostOptions.AuthOptions); err != nil {
|
||||||
return fmt.Errorf("Error generating certificates: %s", err)
|
return fmt.Errorf("Error generating certificates: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -37,7 +89,7 @@ func Create(store persist.Store, h *host.Host) error {
|
||||||
return fmt.Errorf("Error with pre-create check: %s", err)
|
return fmt.Errorf("Error with pre-create check: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.Save(h); err != nil {
|
if err := api.Save(h); err != nil {
|
||||||
return fmt.Errorf("Error saving host to store before attempting creation: %s", err)
|
return fmt.Errorf("Error saving host to store before attempting creation: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +99,7 @@ func Create(store persist.Store, h *host.Host) error {
|
||||||
return fmt.Errorf("Error in driver during machine creation: %s", err)
|
return fmt.Errorf("Error in driver during machine creation: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := store.Save(h); err != nil {
|
if err := api.Save(h); err != nil {
|
||||||
return fmt.Errorf("Error saving host to store after attempting creation: %s", err)
|
return fmt.Errorf("Error saving host to store after attempting creation: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +131,3 @@ func Create(store persist.Store, h *host.Host) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetDebug(val bool) {
|
|
||||||
log.IsDebug = val
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,15 +8,8 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/machine/libmachine/auth"
|
|
||||||
"github.com/docker/machine/libmachine/drivers"
|
|
||||||
"github.com/docker/machine/libmachine/drivers/rpc"
|
|
||||||
"github.com/docker/machine/libmachine/engine"
|
|
||||||
"github.com/docker/machine/libmachine/host"
|
"github.com/docker/machine/libmachine/host"
|
||||||
"github.com/docker/machine/libmachine/log"
|
|
||||||
"github.com/docker/machine/libmachine/mcnerror"
|
"github.com/docker/machine/libmachine/mcnerror"
|
||||||
"github.com/docker/machine/libmachine/swarm"
|
|
||||||
"github.com/docker/machine/libmachine/version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Filestore struct {
|
type Filestore struct {
|
||||||
|
@ -25,7 +18,15 @@ type Filestore struct {
|
||||||
CaPrivateKeyPath string
|
CaPrivateKeyPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Filestore) getMachinesDir() string {
|
func NewFilestore(path, caCertPath, caPrivateKeyPath string) *Filestore {
|
||||||
|
return &Filestore{
|
||||||
|
Path: path,
|
||||||
|
CaCertPath: caCertPath,
|
||||||
|
CaPrivateKeyPath: caPrivateKeyPath,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Filestore) GetMachinesDir() string {
|
||||||
return filepath.Join(s.Path, "machines")
|
return filepath.Join(s.Path, "machines")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,31 +35,12 @@ func (s Filestore) saveToFile(data []byte, file string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Filestore) Save(host *host.Host) error {
|
func (s Filestore) Save(host *host.Host) error {
|
||||||
if serialDriver, ok := host.Driver.(*drivers.SerialDriver); ok {
|
|
||||||
// Unwrap Driver
|
|
||||||
host.Driver = serialDriver.Driver
|
|
||||||
|
|
||||||
// Re-wrap Driver when done
|
|
||||||
defer func() {
|
|
||||||
host.Driver = serialDriver
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Does this belong here?
|
|
||||||
if rpcClientDriver, ok := host.Driver.(*rpcdriver.RPCClientDriver); ok {
|
|
||||||
data, err := rpcClientDriver.GetConfigRaw()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error getting raw config for driver: %s", err)
|
|
||||||
}
|
|
||||||
host.RawDriver = data
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := json.MarshalIndent(host, "", " ")
|
data, err := json.MarshalIndent(host, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
hostPath := filepath.Join(s.getMachinesDir(), host.Name)
|
hostPath := filepath.Join(s.GetMachinesDir(), host.Name)
|
||||||
|
|
||||||
// Ensure that the directory we want to save to exists.
|
// Ensure that the directory we want to save to exists.
|
||||||
if err := os.MkdirAll(hostPath, 0700); err != nil {
|
if err := os.MkdirAll(hostPath, 0700); err != nil {
|
||||||
|
@ -69,34 +51,29 @@ func (s Filestore) Save(host *host.Host) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Filestore) Remove(name string) error {
|
func (s Filestore) Remove(name string) error {
|
||||||
hostPath := filepath.Join(s.getMachinesDir(), name)
|
hostPath := filepath.Join(s.GetMachinesDir(), name)
|
||||||
return os.RemoveAll(hostPath)
|
return os.RemoveAll(hostPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Filestore) List() ([]*host.Host, error) {
|
func (s Filestore) List() ([]string, error) {
|
||||||
dir, err := ioutil.ReadDir(s.getMachinesDir())
|
dir, err := ioutil.ReadDir(s.GetMachinesDir())
|
||||||
if err != nil && !os.IsNotExist(err) {
|
if err != nil && !os.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts := []*host.Host{}
|
hostNames := []string{}
|
||||||
|
|
||||||
for _, file := range dir {
|
for _, file := range dir {
|
||||||
if file.IsDir() && !strings.HasPrefix(file.Name(), ".") {
|
if file.IsDir() && !strings.HasPrefix(file.Name(), ".") {
|
||||||
host, err := s.Load(file.Name())
|
hostNames = append(hostNames, file.Name())
|
||||||
if err != nil {
|
|
||||||
log.Errorf("error loading host %q: %s", file.Name(), err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
hosts = append(hosts, host)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hosts, nil
|
return hostNames, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Filestore) Exists(name string) (bool, error) {
|
func (s Filestore) Exists(name string) (bool, error) {
|
||||||
_, err := os.Stat(filepath.Join(s.getMachinesDir(), name))
|
_, err := os.Stat(filepath.Join(s.GetMachinesDir(), name))
|
||||||
|
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -108,7 +85,7 @@ func (s Filestore) Exists(name string) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Filestore) loadConfig(h *host.Host) error {
|
func (s Filestore) loadConfig(h *host.Host) error {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(s.getMachinesDir(), h.Name, "config.json"))
|
data, err := ioutil.ReadFile(filepath.Join(s.GetMachinesDir(), h.Name, "config.json"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -128,7 +105,7 @@ func (s Filestore) loadConfig(h *host.Host) error {
|
||||||
|
|
||||||
// If we end up performing a migration, we should save afterwards so we don't have to do it again on subsequent invocations.
|
// If we end up performing a migration, we should save afterwards so we don't have to do it again on subsequent invocations.
|
||||||
if migrationPerformed {
|
if migrationPerformed {
|
||||||
if err := s.saveToFile(data, filepath.Join(s.getMachinesDir(), h.Name, "config.json.bak")); err != nil {
|
if err := s.saveToFile(data, filepath.Join(s.GetMachinesDir(), h.Name, "config.json.bak")); err != nil {
|
||||||
return fmt.Errorf("Error attempting to save backup after migration: %s", err)
|
return fmt.Errorf("Error attempting to save backup after migration: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,11 +115,10 @@ func (s Filestore) loadConfig(h *host.Host) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Filestore) Load(name string) (*host.Host, error) {
|
func (s Filestore) Load(name string) (*host.Host, error) {
|
||||||
hostPath := filepath.Join(s.getMachinesDir(), name)
|
hostPath := filepath.Join(s.GetMachinesDir(), name)
|
||||||
|
|
||||||
if _, err := os.Stat(hostPath); os.IsNotExist(err) {
|
if _, err := os.Stat(hostPath); os.IsNotExist(err) {
|
||||||
return nil, mcnerror.ErrHostDoesNotExist{
|
return nil, mcnerror.ErrHostDoesNotExist{
|
||||||
|
@ -160,37 +136,3 @@ func (s Filestore) Load(name string) (*host.Host, error) {
|
||||||
|
|
||||||
return host, nil
|
return host, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Filestore) NewHost(driver drivers.Driver) (*host.Host, error) {
|
|
||||||
certDir := filepath.Join(s.Path, "certs")
|
|
||||||
|
|
||||||
hostOptions := &host.Options{
|
|
||||||
AuthOptions: &auth.Options{
|
|
||||||
CertDir: certDir,
|
|
||||||
CaCertPath: filepath.Join(certDir, "ca.pem"),
|
|
||||||
CaPrivateKeyPath: filepath.Join(certDir, "ca-key.pem"),
|
|
||||||
ClientCertPath: filepath.Join(certDir, "cert.pem"),
|
|
||||||
ClientKeyPath: filepath.Join(certDir, "key.pem"),
|
|
||||||
ServerCertPath: filepath.Join(s.getMachinesDir(), "server.pem"),
|
|
||||||
ServerKeyPath: filepath.Join(s.getMachinesDir(), "server-key.pem"),
|
|
||||||
},
|
|
||||||
EngineOptions: &engine.Options{
|
|
||||||
InstallURL: "https://get.docker.com",
|
|
||||||
StorageDriver: "aufs",
|
|
||||||
TLSVerify: true,
|
|
||||||
},
|
|
||||||
SwarmOptions: &swarm.Options{
|
|
||||||
Host: "tcp://0.0.0.0:3376",
|
|
||||||
Image: "swarm:latest",
|
|
||||||
Strategy: "spread",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return &host.Host{
|
|
||||||
ConfigVersion: version.ConfigVersion,
|
|
||||||
Name: driver.GetMachineName(),
|
|
||||||
Driver: driver,
|
|
||||||
DriverName: driver.DriverName(),
|
|
||||||
HostOptions: hostOptions,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ func TestStoreSave(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(store.getMachinesDir(), h.Name)
|
path := filepath.Join(store.GetMachinesDir(), h.Name)
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
t.Fatalf("Host path doesn't exist: %s", path)
|
t.Fatalf("Host path doesn't exist: %s", path)
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ func TestStoreRemove(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(store.getMachinesDir(), h.Name)
|
path := filepath.Join(store.GetMachinesDir(), h.Name)
|
||||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
t.Fatalf("Host path doesn't exist: %s", path)
|
t.Fatalf("Host path doesn't exist: %s", path)
|
||||||
}
|
}
|
||||||
|
@ -101,8 +101,8 @@ func TestStoreList(t *testing.T) {
|
||||||
t.Fatalf("List returned %d items, expected 1", len(hosts))
|
t.Fatalf("List returned %d items, expected 1", len(hosts))
|
||||||
}
|
}
|
||||||
|
|
||||||
if hosts[0].Name != h.Name {
|
if hosts[0] != h.Name {
|
||||||
t.Fatalf("hosts[0] name is incorrect, got: %s", hosts[0].Name)
|
t.Fatalf("hosts[0] name is incorrect, got: %s", hosts[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
package persist
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/docker/machine/drivers/errdriver"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PluginDriverFactory interface {
|
||||||
|
NewPluginDriver(string, []byte) (drivers.Driver, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type RPCPluginDriverFactory struct{}
|
||||||
|
|
||||||
|
type PluginStore struct {
|
||||||
|
*Filestore
|
||||||
|
PluginDriverFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
func (factory RPCPluginDriverFactory) 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
|
||||||
|
}
|
||||||
|
|
||||||
|
if driverName == "virtualbox" {
|
||||||
|
return drivers.NewSerialDriver(d), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPluginStore(path, caCertPath, caPrivateKeyPath string) *PluginStore {
|
||||||
|
return &PluginStore{
|
||||||
|
Filestore: NewFilestore(path, caCertPath, caPrivateKeyPath),
|
||||||
|
PluginDriverFactory: RPCPluginDriverFactory{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps PluginStore) Save(host *host.Host) error {
|
||||||
|
if serialDriver, ok := host.Driver.(*drivers.SerialDriver); ok {
|
||||||
|
// Unwrap Driver
|
||||||
|
host.Driver = serialDriver.Driver
|
||||||
|
|
||||||
|
// Re-wrap Driver when done
|
||||||
|
defer func() {
|
||||||
|
host.Driver = serialDriver
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Does this belong here?
|
||||||
|
if rpcClientDriver, ok := host.Driver.(*rpcdriver.RPCClientDriver); ok {
|
||||||
|
data, err := rpcClientDriver.GetConfigRaw()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error getting raw config for driver: %s", err)
|
||||||
|
}
|
||||||
|
host.RawDriver = data
|
||||||
|
}
|
||||||
|
|
||||||
|
return ps.Filestore.Save(host)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps PluginStore) Load(name string) (*host.Host, error) {
|
||||||
|
h, err := ps.Filestore.Load(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
d, err := ps.NewPluginDriver(h.DriverName, h.RawDriver)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
h.Driver = d
|
||||||
|
|
||||||
|
return h, nil
|
||||||
|
}
|
|
@ -1,21 +1,15 @@
|
||||||
package persist
|
package persist
|
||||||
|
|
||||||
import (
|
import "github.com/docker/machine/libmachine/host"
|
||||||
"github.com/docker/machine/libmachine/drivers"
|
|
||||||
"github.com/docker/machine/libmachine/host"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Store interface {
|
type Store interface {
|
||||||
// Exists returns whether a machine exists or not
|
// Exists returns whether a machine exists or not
|
||||||
Exists(name string) (bool, error)
|
Exists(name string) (bool, error)
|
||||||
|
|
||||||
// NewHost will initialize a new host machine
|
|
||||||
NewHost(driver drivers.Driver) (*host.Host, error)
|
|
||||||
|
|
||||||
// List returns a list of all hosts in the store
|
// List returns a list of all hosts in the store
|
||||||
List() ([]*host.Host, error)
|
List() ([]string, error)
|
||||||
|
|
||||||
// Get loads a host by name
|
// Load loads a host by name
|
||||||
Load(name string) (*host.Host, error)
|
Load(name string) (*host.Host, error)
|
||||||
|
|
||||||
// Remove removes a machine from the store
|
// Remove removes a machine from the store
|
||||||
|
@ -24,3 +18,28 @@ type Store interface {
|
||||||
// Save persists a machine in the store
|
// Save persists a machine in the store
|
||||||
Save(host *host.Host) error
|
Save(host *host.Host) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoadHosts(s Store, hostNames []string) ([]*host.Host, error) {
|
||||||
|
loadedHosts := []*host.Host{}
|
||||||
|
|
||||||
|
for _, hostName := range hostNames {
|
||||||
|
h, err := s.Load(hostName)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: (nathanleclaire) Should these be bundled up
|
||||||
|
// into one error instead of exiting?
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
loadedHosts = append(loadedHosts, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadedHosts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadAllHosts(s Store) ([]*host.Host, error) {
|
||||||
|
hostNames, err := s.List()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadHosts(s, hostNames)
|
||||||
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ load ${BASE_TEST_DIR}/helpers.bash
|
||||||
@test "none: rm non existent machine fails 'machine rm ∞'" {
|
@test "none: rm non existent machine fails 'machine rm ∞'" {
|
||||||
run machine rm ∞
|
run machine rm ∞
|
||||||
[ "$status" -eq 1 ]
|
[ "$status" -eq 1 ]
|
||||||
[[ ${lines[0]} == "Error removing host \"∞\": Loading host from store failed: Host does not exist: \"∞\"" ]]
|
[[ ${lines[0]} == "Error removing host \"∞\": Host does not exist: \"∞\"" ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "none: rm is successful 'machine rm 0'" {
|
@test "none: rm is successful 'machine rm 0'" {
|
||||||
|
|
Loading…
Reference in New Issue