mirror of https://github.com/docker/docs.git
Make libmachine usable by outside world
- Clear out some cruft tightly coupling libmachine to filestore - Comment out drivers other than virtualbox for now - Change way too many things - Mostly, break out the code to be more modular. - Destroy all traces of "provider" in its current form. It will be brought back as something more sensible, instead of something which overlaps in function with both Host and Store. - Fix mis-managed config passthru - Remove a few instances of state stored in env vars - This should be explicitly communicated in Go-land, not through the shell. - Rename "store" module to "persist" - This is done mostly to avoid confusion about the fact that a concrete instance of a "Store" interface is oftentimes referred to as "store" in the code. - Rip out repetitive antipattern for getting store - This replaces the previous repetive idiom for getting the cert info, and consequently the store, with a much less repetitive idiom. - Also, some redundant methods in commands.go for accessing hosts have either been simplified or removed entirely. - First steps towards fixing up tests - Test progress continues - Replace unit tests with integration tests - MAKE ALL UNIT TESTS PASS YAY - Add helper test files - Don't write to disk in libmachine/host - Heh.. coverage check strikes again - Fix remove code - Move cert code around - Continued progress: simplify Driver - Fixups and make creation work with new model - Move drivers module inside of libmachine - Move ssh module inside of libmachine - Move state module to libmachine - Move utils module to libmachine - Move version module to libmachine - Move log module to libmachine - Modify some constructor methods around - Change Travis build dep structure - Boring gofmt fix - Add version module - Move NewHost to store - Update some boring cert path infos to make API easier to use - Fix up some issues around the new model - Clean up some cert path stuff - Don't use shady functions to get store path :D - Continue artifact work - Fix silly machines dir bug - Continue fixing silly path issues - Change up output of vbm a bit - Continue work to make example go - Change output a little more - Last changes needed to make create finish properly - Fix config.go to use libmachine - Cut down code duplication and make both methods work with libmachine - Add pluggable logging implementation - Return error when machine already in desired state - Update example to show log method - Fix file:// bug - Fix Swarm defaults - Remove unused TLS settings from Engine and Swarm options - Remove spurious error - Correct bug detecting if migration was performed - Fix compilation errors from tests - Fix most of remaining test issues - Fix final silly bug in tests - Remove extraneous debug code - Add -race to test command - Appease the gofmt - Appease the generate coverage - Making executive decision to remove Travis coverage check In the early days I thought this would be a good idea because it would encourage people to write tests in case they added a new module. Well, in fact it has just turned into a giant nuisance and made refactoring work like this even more difficult. - Move Get to Load - Move HostListItem code to CLI Signed-off-by: Nathan LeClaire <nathan.leclaire@gmail.com>
This commit is contained in:
parent
f2bb2e0e4e
commit
b5927f10c4
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
)
|
||||
|
||||
func cmdActive(c *cli.Context) {
|
||||
|
@ -12,22 +12,8 @@ func cmdActive(c *cli.Context) {
|
|||
log.Fatal("Error: Too many arguments given.")
|
||||
}
|
||||
|
||||
certInfo := getCertPathInfo(c)
|
||||
defaultStore, err := getDefaultStore(
|
||||
c.GlobalString("storage-path"),
|
||||
certInfo.CaCertPath,
|
||||
certInfo.CaKeyPath,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
provider, err := newProvider(defaultStore)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
host, err := provider.GetActive()
|
||||
store := getStore(c)
|
||||
host, err := getActiveHost(store)
|
||||
if err != nil {
|
||||
log.Fatalf("Error getting active host: %s", err)
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -6,13 +6,10 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/skarademir/naturalsort"
|
||||
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/commands/mcndirs"
|
||||
_ "github.com/docker/machine/drivers/amazonec2"
|
||||
_ "github.com/docker/machine/drivers/azure"
|
||||
_ "github.com/docker/machine/drivers/digitalocean"
|
||||
|
@ -28,12 +25,11 @@ import (
|
|||
_ "github.com/docker/machine/drivers/vmwarefusion"
|
||||
_ "github.com/docker/machine/drivers/vmwarevcloudair"
|
||||
_ "github.com/docker/machine/drivers/vmwarevsphere"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/cert"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/persist"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -42,34 +38,6 @@ var (
|
|||
ErrExpectedOneMachine = errors.New("Error: Expected one machine name as an argument.")
|
||||
)
|
||||
|
||||
type machineConfig struct {
|
||||
machineName string
|
||||
machineDir string
|
||||
machineUrl string
|
||||
clientKeyPath string
|
||||
serverCertPath string
|
||||
clientCertPath string
|
||||
caCertPath string
|
||||
caKeyPath string
|
||||
serverKeyPath string
|
||||
AuthOptions auth.AuthOptions
|
||||
SwarmOptions swarm.SwarmOptions
|
||||
}
|
||||
|
||||
func sortHostListItemsByName(items []libmachine.HostListItem) {
|
||||
m := make(map[string]libmachine.HostListItem, len(items))
|
||||
s := make([]string, len(items))
|
||||
for i, v := range items {
|
||||
name := strings.ToLower(v.Name)
|
||||
m[name] = v
|
||||
s[i] = name
|
||||
}
|
||||
sort.Sort(naturalsort.NaturalSort(s))
|
||||
for i, v := range s {
|
||||
items[i] = m[v]
|
||||
}
|
||||
}
|
||||
|
||||
func confirmInput(msg string) bool {
|
||||
fmt.Printf("%s (y/n): ", msg)
|
||||
var resp string
|
||||
|
@ -88,69 +56,46 @@ func confirmInput(msg string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func newProvider(store libmachine.Store) (*libmachine.Provider, error) {
|
||||
return libmachine.New(store)
|
||||
func getMachineDir(rootPath string) string {
|
||||
return filepath.Join(rootPath, "machines")
|
||||
}
|
||||
|
||||
func getDefaultStore(rootPath, caCertPath, privateKeyPath string) (libmachine.Store, error) {
|
||||
return libmachine.NewFilestore(
|
||||
rootPath,
|
||||
caCertPath,
|
||||
privateKeyPath,
|
||||
), nil
|
||||
func getStore(c *cli.Context) persist.Store {
|
||||
certInfo := getCertPathInfoFromContext(c)
|
||||
return &persist.Filestore{
|
||||
Path: c.GlobalString("storage-path"),
|
||||
CaCertPath: certInfo.CaCertPath,
|
||||
CaPrivateKeyPath: certInfo.CaPrivateKeyPath,
|
||||
}
|
||||
}
|
||||
|
||||
func setupCertificates(caCertPath, caKeyPath, clientCertPath, clientKeyPath string) error {
|
||||
org := utils.GetUsername()
|
||||
bits := 2048
|
||||
func getFirstArgHost(c *cli.Context) *host.Host {
|
||||
store := getStore(c)
|
||||
hostName := c.Args().First()
|
||||
h, err := store.Load(hostName)
|
||||
if err != nil {
|
||||
// I guess I feel OK with bailing here since if we can't get
|
||||
// the host reliably we're definitely not going to be able to
|
||||
// do anything else interesting, but also this premature exit
|
||||
// feels wrong to me. Let's revisit it later.
|
||||
log.Fatalf("Error trying to get host %q: %s", hostName, err)
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
if _, err := os.Stat(utils.GetMachineCertDir()); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err := os.MkdirAll(utils.GetMachineCertDir(), 0700); err != nil {
|
||||
log.Fatalf("Error creating machine config dir: %s", err)
|
||||
}
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
func getHostsFromContext(c *cli.Context) ([]*host.Host, error) {
|
||||
store := getStore(c)
|
||||
hosts := []*host.Host{}
|
||||
|
||||
for _, hostName := range c.Args() {
|
||||
h, err := store.Load(hostName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not load host %q: %s", hostName, err)
|
||||
}
|
||||
hosts = append(hosts, h)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(caCertPath); os.IsNotExist(err) {
|
||||
log.Infof("Creating CA: %s", caCertPath)
|
||||
|
||||
// check if the key path exists; if so, error
|
||||
if _, err := os.Stat(caKeyPath); err == nil {
|
||||
log.Fatalf("The CA key already exists. Please remove it or specify a different key/cert.")
|
||||
}
|
||||
|
||||
if err := utils.GenerateCACertificate(caCertPath, caKeyPath, org, bits); err != nil {
|
||||
log.Infof("Error generating CA certificate: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := os.Stat(clientCertPath); os.IsNotExist(err) {
|
||||
log.Infof("Creating client certificate: %s", clientCertPath)
|
||||
|
||||
if _, err := os.Stat(utils.GetMachineCertDir()); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if err := os.Mkdir(utils.GetMachineCertDir(), 0700); err != nil {
|
||||
log.Fatalf("Error creating machine client cert dir: %s", err)
|
||||
}
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// check if the key path exists; if so, error
|
||||
if _, err := os.Stat(clientKeyPath); err == nil {
|
||||
log.Fatalf("The client key already exists. Please remove it or specify a different key/cert.")
|
||||
}
|
||||
|
||||
if err := utils.GenerateCert([]string{""}, clientCertPath, clientKeyPath, caCertPath, caKeyPath, org, bits); err != nil {
|
||||
log.Fatalf("Error generating client certificate: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return hosts, nil
|
||||
}
|
||||
|
||||
var sharedCreateFlags = []cli.Flag{
|
||||
|
@ -407,9 +352,21 @@ var Commands = []cli.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func printIP(h *host.Host) func() error {
|
||||
return func() error {
|
||||
ip, err := h.Driver.GetIP()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error getting IP address: %s", err)
|
||||
}
|
||||
fmt.Println(ip)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// machineCommand maps the command name to the corresponding machine command.
|
||||
// We run commands concurrently and communicate back an error if there was one.
|
||||
func machineCommand(actionName string, host *libmachine.Host, errorChan chan<- error) {
|
||||
func machineCommand(actionName string, host *host.Host, errorChan chan<- error) {
|
||||
// TODO: These actions should have their own type.
|
||||
commands := map[string](func() error){
|
||||
"configureAuth": host.ConfigureAuth,
|
||||
"start": host.Start,
|
||||
|
@ -417,7 +374,7 @@ func machineCommand(actionName string, host *libmachine.Host, errorChan chan<- e
|
|||
"restart": host.Restart,
|
||||
"kill": host.Kill,
|
||||
"upgrade": host.Upgrade,
|
||||
"ip": host.PrintIP,
|
||||
"ip": printIP(host),
|
||||
}
|
||||
|
||||
log.Debugf("command=%s machine=%s", actionName, host.Name)
|
||||
|
@ -431,10 +388,10 @@ func machineCommand(actionName string, host *libmachine.Host, errorChan chan<- e
|
|||
}
|
||||
|
||||
// runActionForeachMachine will run the command across multiple machines
|
||||
func runActionForeachMachine(actionName string, machines []*libmachine.Host) {
|
||||
func runActionForeachMachine(actionName string, machines []*host.Host) {
|
||||
var (
|
||||
numConcurrentActions = 0
|
||||
serialMachines = []*libmachine.Host{}
|
||||
serialMachines = []*host.Host{}
|
||||
errorChan = make(chan error)
|
||||
)
|
||||
|
||||
|
@ -459,7 +416,7 @@ func runActionForeachMachine(actionName string, machines []*libmachine.Host) {
|
|||
serialChan := make(chan error)
|
||||
go machineCommand(actionName, machine, serialChan)
|
||||
if err := <-serialChan; err != nil {
|
||||
log.Error(err)
|
||||
log.Errorln(err)
|
||||
}
|
||||
close(serialChan)
|
||||
}
|
||||
|
@ -469,7 +426,7 @@ func runActionForeachMachine(actionName string, machines []*libmachine.Host) {
|
|||
// rate limit us.
|
||||
for i := 0; i < numConcurrentActions; i++ {
|
||||
if err := <-errorChan; err != nil {
|
||||
log.Error(err)
|
||||
log.Errorln(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,185 +434,59 @@ func runActionForeachMachine(actionName string, machines []*libmachine.Host) {
|
|||
}
|
||||
|
||||
func runActionWithContext(actionName string, c *cli.Context) error {
|
||||
machines, err := getHosts(c)
|
||||
store := getStore(c)
|
||||
|
||||
hosts, err := getHostsFromContext(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(machines) == 0 {
|
||||
if len(hosts) == 0 {
|
||||
log.Fatal(ErrNoMachineSpecified)
|
||||
}
|
||||
|
||||
runActionForeachMachine(actionName, machines)
|
||||
runActionForeachMachine(actionName, hosts)
|
||||
|
||||
for _, h := range hosts {
|
||||
if err := store.Save(h); err != nil {
|
||||
return fmt.Errorf("Error saving host to store: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getHosts(c *cli.Context) ([]*libmachine.Host, error) {
|
||||
machines := []*libmachine.Host{}
|
||||
for _, n := range c.Args() {
|
||||
machine, err := loadMachine(n, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
machines = append(machines, machine)
|
||||
}
|
||||
|
||||
return machines, nil
|
||||
}
|
||||
|
||||
func loadMachine(name string, c *cli.Context) (*libmachine.Host, error) {
|
||||
certInfo := getCertPathInfo(c)
|
||||
defaultStore, err := getDefaultStore(
|
||||
c.GlobalString("storage-path"),
|
||||
certInfo.CaCertPath,
|
||||
certInfo.CaKeyPath,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
provider, err := newProvider(defaultStore)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
host, err := provider.Get(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return host, nil
|
||||
}
|
||||
|
||||
func getHost(c *cli.Context) *libmachine.Host {
|
||||
name := c.Args().First()
|
||||
|
||||
defaultStore, err := getDefaultStore(
|
||||
c.GlobalString("storage-path"),
|
||||
c.GlobalString("tls-ca-cert"),
|
||||
c.GlobalString("tls-ca-key"),
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
provider, err := newProvider(defaultStore)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
host, err := provider.Get(name)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to load host: %v", err)
|
||||
}
|
||||
return host
|
||||
}
|
||||
|
||||
func getDefaultProvider(c *cli.Context) *libmachine.Provider {
|
||||
certInfo := getCertPathInfo(c)
|
||||
defaultStore, err := getDefaultStore(
|
||||
c.GlobalString("storage-path"),
|
||||
certInfo.CaCertPath,
|
||||
certInfo.CaKeyPath,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
provider, err := newProvider(defaultStore)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return provider
|
||||
}
|
||||
|
||||
func getMachineConfig(c *cli.Context) (*machineConfig, error) {
|
||||
name := c.Args().First()
|
||||
certInfo := getCertPathInfo(c)
|
||||
defaultStore, err := getDefaultStore(
|
||||
c.GlobalString("storage-path"),
|
||||
certInfo.CaCertPath,
|
||||
certInfo.CaKeyPath,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
provider, err := newProvider(defaultStore)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
m, err := provider.Get(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
machineDir := filepath.Join(utils.GetMachineDir(), m.Name)
|
||||
caCert := filepath.Join(machineDir, "ca.pem")
|
||||
caKey := filepath.Join(utils.GetMachineCertDir(), "ca-key.pem")
|
||||
clientCert := filepath.Join(machineDir, "cert.pem")
|
||||
clientKey := filepath.Join(machineDir, "key.pem")
|
||||
serverCert := filepath.Join(machineDir, "server.pem")
|
||||
serverKey := filepath.Join(machineDir, "server-key.pem")
|
||||
machineUrl, err := m.GetURL()
|
||||
if err != nil {
|
||||
if err == drivers.ErrHostIsNotRunning {
|
||||
machineUrl = ""
|
||||
} else {
|
||||
return nil, fmt.Errorf("Unexpected error getting machine url: %s", err)
|
||||
}
|
||||
}
|
||||
return &machineConfig{
|
||||
machineName: name,
|
||||
machineDir: machineDir,
|
||||
machineUrl: machineUrl,
|
||||
clientKeyPath: clientKey,
|
||||
clientCertPath: clientCert,
|
||||
serverCertPath: serverCert,
|
||||
caKeyPath: caKey,
|
||||
caCertPath: caCert,
|
||||
serverKeyPath: serverKey,
|
||||
AuthOptions: *m.HostOptions.AuthOptions,
|
||||
SwarmOptions: *m.HostOptions.SwarmOptions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getCertPaths 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 getCertPathInfo(c *cli.Context) libmachine.CertPathInfo {
|
||||
// setup cert paths
|
||||
// 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 *cli.Context) cert.CertPathInfo {
|
||||
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 == "" {
|
||||
caCertPath = filepath.Join(utils.GetMachineCertDir(), "ca.pem")
|
||||
caCertPath = filepath.Join(mcndirs.GetMachineCertDir(), "ca.pem")
|
||||
}
|
||||
|
||||
if caKeyPath == "" {
|
||||
caKeyPath = filepath.Join(utils.GetMachineCertDir(), "ca-key.pem")
|
||||
caKeyPath = filepath.Join(mcndirs.GetMachineCertDir(), "ca-key.pem")
|
||||
}
|
||||
|
||||
if clientCertPath == "" {
|
||||
clientCertPath = filepath.Join(utils.GetMachineCertDir(), "cert.pem")
|
||||
clientCertPath = filepath.Join(mcndirs.GetMachineCertDir(), "cert.pem")
|
||||
}
|
||||
|
||||
if clientKeyPath == "" {
|
||||
clientKeyPath = filepath.Join(utils.GetMachineCertDir(), "key.pem")
|
||||
clientKeyPath = filepath.Join(mcndirs.GetMachineCertDir(), "key.pem")
|
||||
}
|
||||
|
||||
return libmachine.CertPathInfo{
|
||||
CaCertPath: caCertPath,
|
||||
CaKeyPath: caKeyPath,
|
||||
ClientCertPath: clientCertPath,
|
||||
ClientKeyPath: clientKeyPath,
|
||||
return cert.CertPathInfo{
|
||||
CaCertPath: caCertPath,
|
||||
CaPrivateKeyPath: caKeyPath,
|
||||
ClientCertPath: clientCertPath,
|
||||
ClientKeyPath: clientKeyPath,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,112 +1,27 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/machine/drivers/fakedriver"
|
||||
_ "github.com/docker/machine/drivers/none"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/hosttest"
|
||||
"github.com/docker/machine/libmachine/persisttest"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
hostTestName = "test-host"
|
||||
hostTestDriverName = "none"
|
||||
hostTestCaCert = "test-cert"
|
||||
hostTestPrivateKey = "test-key"
|
||||
)
|
||||
|
||||
var (
|
||||
hostTestStorePath string
|
||||
TestStoreDir string
|
||||
)
|
||||
|
||||
func init() {
|
||||
tmpDir, err := ioutil.TempDir("", "machine-test-")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
TestStoreDir = tmpDir
|
||||
}
|
||||
|
||||
func clearHosts() error {
|
||||
return os.RemoveAll(TestStoreDir)
|
||||
}
|
||||
|
||||
func getTestStore() (libmachine.Store, error) {
|
||||
tmpDir, err := ioutil.TempDir("", "machine-test-")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
hostTestStorePath = tmpDir
|
||||
|
||||
os.Setenv("MACHINE_STORAGE_PATH", tmpDir)
|
||||
|
||||
return libmachine.NewFilestore(tmpDir, hostTestCaCert, hostTestPrivateKey), nil
|
||||
}
|
||||
|
||||
func cleanup() {
|
||||
os.RemoveAll(hostTestStorePath)
|
||||
}
|
||||
|
||||
func getTestDriverFlags() *DriverOptionsMock {
|
||||
name := hostTestName
|
||||
flags := &DriverOptionsMock{
|
||||
Data: map[string]interface{}{
|
||||
"name": name,
|
||||
"url": "unix:///var/run/docker.sock",
|
||||
"swarm": false,
|
||||
"swarm-host": "",
|
||||
"swarm-master": false,
|
||||
"swarm-discovery": "",
|
||||
},
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
type DriverOptionsMock struct {
|
||||
Data map[string]interface{}
|
||||
}
|
||||
|
||||
func (d DriverOptionsMock) String(key string) string {
|
||||
return d.Data[key].(string)
|
||||
}
|
||||
|
||||
func (d DriverOptionsMock) StringSlice(key string) []string {
|
||||
return d.Data[key].([]string)
|
||||
}
|
||||
|
||||
func (d DriverOptionsMock) Int(key string) int {
|
||||
return d.Data[key].(int)
|
||||
}
|
||||
|
||||
func (d DriverOptionsMock) Bool(key string) bool {
|
||||
return d.Data[key].(bool)
|
||||
}
|
||||
|
||||
func TestRunActionForeachMachine(t *testing.T) {
|
||||
storePath, err := ioutil.TempDir("", ".docker")
|
||||
if err != nil {
|
||||
t.Fatal("Error creating tmp dir:", err)
|
||||
}
|
||||
|
||||
// Assume a bunch of machines in randomly started or
|
||||
// stopped states.
|
||||
machines := []*libmachine.Host{
|
||||
machines := []*host.Host{
|
||||
{
|
||||
Name: "foo",
|
||||
DriverName: "fakedriver",
|
||||
Driver: &fakedriver.FakeDriver{
|
||||
MockState: state.Running,
|
||||
},
|
||||
StorePath: storePath,
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
|
@ -114,7 +29,6 @@ func TestRunActionForeachMachine(t *testing.T) {
|
|||
Driver: &fakedriver.FakeDriver{
|
||||
MockState: state.Stopped,
|
||||
},
|
||||
StorePath: storePath,
|
||||
},
|
||||
{
|
||||
Name: "baz",
|
||||
|
@ -126,7 +40,6 @@ func TestRunActionForeachMachine(t *testing.T) {
|
|||
Driver: &fakedriver.FakeDriver{
|
||||
MockState: state.Stopped,
|
||||
},
|
||||
StorePath: storePath,
|
||||
},
|
||||
{
|
||||
Name: "spam",
|
||||
|
@ -134,7 +47,6 @@ func TestRunActionForeachMachine(t *testing.T) {
|
|||
Driver: &fakedriver.FakeDriver{
|
||||
MockState: state.Running,
|
||||
},
|
||||
StorePath: storePath,
|
||||
},
|
||||
{
|
||||
Name: "eggs",
|
||||
|
@ -142,7 +54,6 @@ func TestRunActionForeachMachine(t *testing.T) {
|
|||
Driver: &fakedriver.FakeDriver{
|
||||
MockState: state.Stopped,
|
||||
},
|
||||
StorePath: storePath,
|
||||
},
|
||||
{
|
||||
Name: "ham",
|
||||
|
@ -150,7 +61,6 @@ func TestRunActionForeachMachine(t *testing.T) {
|
|||
Driver: &fakedriver.FakeDriver{
|
||||
MockState: state.Running,
|
||||
},
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -191,3 +101,29 @@ func TestRunActionForeachMachine(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintIPEmptyGivenLocalEngine(t *testing.T) {
|
||||
defer persisttest.Cleanup()
|
||||
host, _ := hosttest.GetDefaultTestHost()
|
||||
|
||||
out, w := captureStdout()
|
||||
|
||||
assert.Nil(t, printIP(host)())
|
||||
w.Close()
|
||||
|
||||
assert.Equal(t, "", strings.TrimSpace(<-out))
|
||||
}
|
||||
|
||||
func TestPrintIPPrintsGivenRemoteEngine(t *testing.T) {
|
||||
defer cleanup()
|
||||
host, _ := hosttest.GetDefaultTestHost()
|
||||
host.Driver = &fakedriver.FakeDriver{}
|
||||
|
||||
out, w := captureStdout()
|
||||
|
||||
assert.Nil(t, printIP(host)())
|
||||
|
||||
w.Close()
|
||||
|
||||
assert.Equal(t, "1.2.3.4", strings.TrimSpace(<-out))
|
||||
}
|
||||
|
|
|
@ -6,74 +6,116 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/cert"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
func cmdConfig(c *cli.Context) {
|
||||
if len(c.Args()) != 1 {
|
||||
log.Fatal(ErrExpectedOneMachine)
|
||||
}
|
||||
cfg, err := getMachineConfig(c)
|
||||
|
||||
h := getFirstArgHost(c)
|
||||
|
||||
dockerHost, authOptions, err := runConnectionBoilerplate(h, c)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
dockerHost, err := getHost(c).Driver.GetURL()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if c.Bool("swarm") {
|
||||
if !cfg.SwarmOptions.Master {
|
||||
log.Fatalf("%s is not a swarm master", cfg.machineName)
|
||||
}
|
||||
u, err := url.Parse(cfg.SwarmOptions.Host)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
parts := strings.Split(u.Host, ":")
|
||||
swarmPort := parts[1]
|
||||
|
||||
// get IP of machine to replace in case swarm host is 0.0.0.0
|
||||
mUrl, err := url.Parse(dockerHost)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
mParts := strings.Split(mUrl.Host, ":")
|
||||
machineIp := mParts[0]
|
||||
|
||||
dockerHost = fmt.Sprintf("tcp://%s:%s\n", machineIp, swarmPort)
|
||||
log.Fatalf("Error running connection boilerplate: %s", err)
|
||||
}
|
||||
|
||||
log.Debug(dockerHost)
|
||||
|
||||
u, err := url.Parse(cfg.machineUrl)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if u.Scheme != "unix" {
|
||||
// validate cert and regenerate if needed
|
||||
valid, err := utils.ValidateCertificate(
|
||||
u.Host,
|
||||
cfg.caCertPath,
|
||||
cfg.serverCertPath,
|
||||
cfg.serverKeyPath,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if !valid {
|
||||
log.Debugf("invalid certs detected; regenerating for %s", u.Host)
|
||||
|
||||
if err := runActionWithContext("configureAuth", c); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("--tlsverify --tlscacert=%q --tlscert=%q --tlskey=%q -H=%s\n",
|
||||
cfg.caCertPath, cfg.clientCertPath, cfg.clientKeyPath, dockerHost)
|
||||
fmt.Printf("--tlsverify --tlscacert=%q --tlscert=%q --tlskey=%q -H=%s",
|
||||
authOptions.CaCertPath, authOptions.ClientCertPath, authOptions.ClientKeyPath, dockerHost)
|
||||
}
|
||||
|
||||
func runConnectionBoilerplate(h *host.Host, c *cli.Context) (string, *auth.AuthOptions, error) {
|
||||
hostState, err := h.Driver.GetState()
|
||||
if err != nil {
|
||||
// TODO: This is a common operation and should have a commonly
|
||||
// defined error.
|
||||
return "", &auth.AuthOptions{}, fmt.Errorf("Error trying to get host state: %s", err)
|
||||
}
|
||||
if hostState != state.Running {
|
||||
return "", &auth.AuthOptions{}, fmt.Errorf("%s is not running. Please start it in order to use the connection settings.", h.Name)
|
||||
}
|
||||
|
||||
dockerHost, err := h.Driver.GetURL()
|
||||
if err != nil {
|
||||
return "", &auth.AuthOptions{}, fmt.Errorf("Error getting driver URL: %s", err)
|
||||
}
|
||||
|
||||
if c.Bool("swarm") {
|
||||
var err error
|
||||
dockerHost, err = parseSwarm(dockerHost, h)
|
||||
if err != nil {
|
||||
return "", &auth.AuthOptions{}, fmt.Errorf("Error parsing swarm: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
u, err := url.Parse(dockerHost)
|
||||
if err != nil {
|
||||
return "", &auth.AuthOptions{}, fmt.Errorf("Error parsing URL: %s", err)
|
||||
}
|
||||
|
||||
authOptions := h.HostOptions.AuthOptions
|
||||
|
||||
if err := checkCert(u.Host, authOptions, c); err != nil {
|
||||
return "", &auth.AuthOptions{}, fmt.Errorf("Error checking and/or regenerating the certs: %s", err)
|
||||
}
|
||||
|
||||
return dockerHost, authOptions, nil
|
||||
}
|
||||
|
||||
func checkCert(hostUrl string, authOptions *auth.AuthOptions, c *cli.Context) error {
|
||||
valid, err := cert.ValidateCertificate(
|
||||
hostUrl,
|
||||
authOptions.CaCertPath,
|
||||
authOptions.ServerCertPath,
|
||||
authOptions.ServerKeyPath,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error attempting to validate the certficate: %s", err)
|
||||
}
|
||||
|
||||
if !valid {
|
||||
log.Errorf("Invalid certs detected; regenerating for %s", hostUrl)
|
||||
|
||||
if err := runActionWithContext("configureAuth", c); err != nil {
|
||||
return fmt.Errorf("Error attempting to regenerate the certs: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: This could use a unit test.
|
||||
func parseSwarm(hostUrl string, h *host.Host) (string, error) {
|
||||
swarmOptions := h.HostOptions.SwarmOptions
|
||||
|
||||
if !swarmOptions.Master {
|
||||
return "", fmt.Errorf("Error: %s is not a swarm master. The --swarm flag is intended for use with swarm masters.", h.Name)
|
||||
}
|
||||
|
||||
u, err := url.Parse(swarmOptions.Host)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("There was an error parsing the url: %s", err)
|
||||
}
|
||||
parts := strings.Split(u.Host, ":")
|
||||
swarmPort := parts[1]
|
||||
|
||||
// get IP of machine to replace in case swarm host is 0.0.0.0
|
||||
mUrl, err := url.Parse(hostUrl)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("There was an error parsing the url: %s", err)
|
||||
}
|
||||
|
||||
mParts := strings.Split(mUrl.Host, ":")
|
||||
machineIp := mParts[0]
|
||||
|
||||
hostUrl = fmt.Sprintf("tcp://%s:%s", machineIp, swarmPort)
|
||||
|
||||
return hostUrl, nil
|
||||
}
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/engine"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
)
|
||||
|
||||
func TestCmdConfig(t *testing.T) {
|
||||
defer cleanup()
|
||||
|
||||
stdout := os.Stdout
|
||||
r, w, _ := os.Pipe()
|
||||
|
||||
os.Stdout = w
|
||||
|
||||
defer func() {
|
||||
os.Stdout = stdout
|
||||
}()
|
||||
|
||||
store, err := getTestStore()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
provider, err := libmachine.New(store)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
flags := getTestDriverFlags()
|
||||
hostOptions := &libmachine.HostOptions{
|
||||
EngineOptions: &engine.EngineOptions{},
|
||||
SwarmOptions: &swarm.SwarmOptions{
|
||||
Master: false,
|
||||
Discovery: "",
|
||||
Address: "",
|
||||
Host: "",
|
||||
},
|
||||
AuthOptions: &auth.AuthOptions{},
|
||||
}
|
||||
|
||||
host, err := provider.Create("test-a", "none", hostOptions, flags)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outStr := make(chan string)
|
||||
|
||||
go func() {
|
||||
var testOutput bytes.Buffer
|
||||
io.Copy(&testOutput, r)
|
||||
outStr <- testOutput.String()
|
||||
}()
|
||||
|
||||
set := flag.NewFlagSet("config", 0)
|
||||
set.Parse([]string{"test-a"})
|
||||
globalSet := flag.NewFlagSet("test", 0)
|
||||
globalSet.String("storage-path", store.GetPath(), "")
|
||||
|
||||
c := cli.NewContext(nil, set, globalSet)
|
||||
|
||||
cmdConfig(c)
|
||||
|
||||
w.Close()
|
||||
|
||||
out := <-outStr
|
||||
|
||||
if !strings.Contains(out, "--tlsverify") {
|
||||
t.Fatalf("Expect --tlsverify")
|
||||
}
|
||||
|
||||
testMachineDir := filepath.Join(store.GetPath(), "machines", host.Name)
|
||||
|
||||
tlscacert := fmt.Sprintf("--tlscacert=\"%s/ca.pem\"", testMachineDir)
|
||||
if !strings.Contains(out, tlscacert) {
|
||||
t.Fatalf("Expected to find %s in %s", tlscacert, out)
|
||||
}
|
||||
|
||||
tlscert := fmt.Sprintf("--tlscert=\"%s/cert.pem\"", testMachineDir)
|
||||
if !strings.Contains(out, tlscert) {
|
||||
t.Fatalf("Expected to find %s in %s", tlscert, out)
|
||||
}
|
||||
|
||||
tlskey := fmt.Sprintf("--tlskey=\"%s/key.pem\"", testMachineDir)
|
||||
if !strings.Contains(out, tlskey) {
|
||||
t.Fatalf("Expected to find %s in %s", tlskey, out)
|
||||
}
|
||||
|
||||
if !strings.Contains(out, "-H=unix:///var/run/docker.sock") {
|
||||
t.Fatalf("Expect docker host URL")
|
||||
}
|
||||
}
|
|
@ -1,31 +1,51 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/docker/machine/log"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/commands/mcndirs"
|
||||
"github.com/docker/machine/drivers/driverfactory"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/engine"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnerror"
|
||||
"github.com/docker/machine/libmachine/persist"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
"github.com/docker/machine/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDriverNotRecognized = errors.New("Driver not recognized.")
|
||||
)
|
||||
|
||||
func cmdCreate(c *cli.Context) {
|
||||
var (
|
||||
err error
|
||||
driver drivers.Driver
|
||||
)
|
||||
driver := c.String("driver")
|
||||
|
||||
driverName := c.String("driver")
|
||||
name := c.Args().First()
|
||||
certInfo := getCertPathInfoFromContext(c)
|
||||
|
||||
storePath := c.GlobalString("storage-path")
|
||||
store := &persist.Filestore{
|
||||
Path: storePath,
|
||||
CaCertPath: certInfo.CaCertPath,
|
||||
CaPrivateKeyPath: certInfo.CaPrivateKeyPath,
|
||||
}
|
||||
|
||||
// TODO: Not really a fan of "none" as the default driver...
|
||||
if driver != "none" {
|
||||
c.App.Commands, err = trimDriverFlags(driver, c.App.Commands)
|
||||
if driverName != "none" {
|
||||
var err error
|
||||
|
||||
c.App.Commands, err = trimDriverFlags(driverName, c.App.Commands)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -36,42 +56,25 @@ func cmdCreate(c *cli.Context) {
|
|||
log.Fatal("You must specify a machine name")
|
||||
}
|
||||
|
||||
validName := host.ValidateHostName(name)
|
||||
if !validName {
|
||||
log.Fatal("Error creating machine: ", mcnerror.ErrInvalidHostname)
|
||||
}
|
||||
|
||||
if err := validateSwarmDiscovery(c.String("swarm-discovery")); err != nil {
|
||||
log.Fatalf("Error parsing swarm discovery: %s", err)
|
||||
}
|
||||
|
||||
certInfo := getCertPathInfo(c)
|
||||
|
||||
if err := setupCertificates(
|
||||
certInfo.CaCertPath,
|
||||
certInfo.CaKeyPath,
|
||||
certInfo.ClientCertPath,
|
||||
certInfo.ClientKeyPath); err != nil {
|
||||
log.Fatalf("Error generating certificates: %s", err)
|
||||
}
|
||||
|
||||
defaultStore, err := getDefaultStore(
|
||||
c.GlobalString("storage-path"),
|
||||
certInfo.CaCertPath,
|
||||
certInfo.CaKeyPath,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
provider, err := newProvider(defaultStore)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
hostOptions := &libmachine.HostOptions{
|
||||
hostOptions := &host.HostOptions{
|
||||
AuthOptions: &auth.AuthOptions{
|
||||
CaCertPath: certInfo.CaCertPath,
|
||||
PrivateKeyPath: certInfo.CaKeyPath,
|
||||
ClientCertPath: certInfo.ClientCertPath,
|
||||
ClientKeyPath: certInfo.ClientKeyPath,
|
||||
ServerCertPath: filepath.Join(utils.GetMachineDir(), name, "server.pem"),
|
||||
ServerKeyPath: filepath.Join(utils.GetMachineDir(), name, "server-key.pem"),
|
||||
CertDir: mcndirs.GetMachineCertDir(),
|
||||
CaCertPath: certInfo.CaCertPath,
|
||||
CaPrivateKeyPath: certInfo.CaPrivateKeyPath,
|
||||
ClientCertPath: certInfo.ClientCertPath,
|
||||
ClientKeyPath: certInfo.ClientKeyPath,
|
||||
ServerCertPath: filepath.Join(mcndirs.GetMachineDir(), name, "server.pem"),
|
||||
ServerKeyPath: filepath.Join(mcndirs.GetMachineDir(), name, "server-key.pem"),
|
||||
StorePath: filepath.Join(mcndirs.GetMachineDir(), name),
|
||||
},
|
||||
EngineOptions: &engine.EngineOptions{
|
||||
ArbitraryFlags: c.StringSlice("engine-opt"),
|
||||
|
@ -95,13 +98,39 @@ func cmdCreate(c *cli.Context) {
|
|||
},
|
||||
}
|
||||
|
||||
_, err = provider.Create(name, driver, hostOptions, c)
|
||||
driver, err := driverfactory.NewDriver(driverName, name, storePath)
|
||||
if err != nil {
|
||||
log.Errorf("Error creating machine: %s", err)
|
||||
log.Fatal("You will want to check the provider to make sure the machine and associated resources were properly removed.")
|
||||
log.Fatalf("Error trying to get driver: %s", err)
|
||||
}
|
||||
|
||||
info := fmt.Sprintf("%s env %s", c.App.Name, name)
|
||||
h, err := store.NewHost(driver)
|
||||
if err != nil {
|
||||
log.Fatalf("Error getting new host: %s", err)
|
||||
}
|
||||
|
||||
h.HostOptions = hostOptions
|
||||
|
||||
exists, err := store.Exists(h.Name)
|
||||
if err != nil {
|
||||
log.Fatalf("Error checking if host exists: %s", err)
|
||||
}
|
||||
if exists {
|
||||
log.Fatal(mcnerror.ErrHostAlreadyExists{
|
||||
Name: h.Name,
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: This should be moved out of the driver and done in the
|
||||
// commands module.
|
||||
if err := h.Driver.SetConfigFromFlags(c); err != nil {
|
||||
log.Fatalf("Error setting machine configuration from flags provided: %s", err)
|
||||
}
|
||||
|
||||
if err := libmachine.Create(store, h); err != nil {
|
||||
log.Fatalf("Error creating machine: %s", err)
|
||||
}
|
||||
|
||||
info := fmt.Sprintf("%s env %s", os.Args[0], name)
|
||||
log.Infof("To see how to connect Docker to this machine, run: %s", info)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,11 @@ package commands
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/docker/machine/log"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -37,6 +33,14 @@ func cmdEnv(c *cli.Context) {
|
|||
if len(c.Args()) != 1 && !c.Bool("unset") {
|
||||
log.Fatal(improperEnvArgsError)
|
||||
}
|
||||
|
||||
h := getFirstArgHost(c)
|
||||
|
||||
dockerHost, authOptions, err := runConnectionBoilerplate(h, c)
|
||||
if err != nil {
|
||||
log.Fatalf("Error running connection boilerplate: %s", err)
|
||||
}
|
||||
|
||||
userShell := c.String("shell")
|
||||
if userShell == "" {
|
||||
shell, err := detectShell()
|
||||
|
@ -93,70 +97,12 @@ func cmdEnv(c *cli.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
cfg, err := getMachineConfig(c)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if cfg.machineUrl == "" {
|
||||
log.Fatalf("%s is not running. Please start this with %s start %s", cfg.machineName, c.App.Name, cfg.machineName)
|
||||
}
|
||||
|
||||
dockerHost := cfg.machineUrl
|
||||
if c.Bool("swarm") {
|
||||
if !cfg.SwarmOptions.Master {
|
||||
log.Fatalf("%s is not a swarm master", cfg.machineName)
|
||||
}
|
||||
u, err := url.Parse(cfg.SwarmOptions.Host)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
parts := strings.Split(u.Host, ":")
|
||||
swarmPort := parts[1]
|
||||
|
||||
// get IP of machine to replace in case swarm host is 0.0.0.0
|
||||
mUrl, err := url.Parse(cfg.machineUrl)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
mParts := strings.Split(mUrl.Host, ":")
|
||||
machineIp := mParts[0]
|
||||
|
||||
dockerHost = fmt.Sprintf("tcp://%s:%s", machineIp, swarmPort)
|
||||
}
|
||||
|
||||
u, err := url.Parse(cfg.machineUrl)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if u.Scheme != "unix" {
|
||||
// validate cert and regenerate if needed
|
||||
valid, err := utils.ValidateCertificate(
|
||||
u.Host,
|
||||
cfg.caCertPath,
|
||||
cfg.serverCertPath,
|
||||
cfg.serverKeyPath,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if !valid {
|
||||
log.Debugf("invalid certs detected; regenerating for %s", u.Host)
|
||||
|
||||
if err := runActionWithContext("configureAuth", c); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shellCfg = ShellConfig{
|
||||
DockerCertPath: cfg.machineDir,
|
||||
DockerCertPath: authOptions.CertDir,
|
||||
DockerHost: dockerHost,
|
||||
DockerTLSVerify: "1",
|
||||
UsageHint: usageHint,
|
||||
MachineName: cfg.machineName,
|
||||
MachineName: h.Name,
|
||||
}
|
||||
|
||||
switch userShell {
|
||||
|
|
|
@ -1,316 +0,0 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/engine"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
)
|
||||
|
||||
func TestCmdEnvBash(t *testing.T) {
|
||||
stdout := os.Stdout
|
||||
shell := os.Getenv("SHELL")
|
||||
r, w, _ := os.Pipe()
|
||||
|
||||
os.Stdout = w
|
||||
os.Setenv("MACHINE_STORAGE_PATH", TestStoreDir)
|
||||
os.Setenv("SHELL", "/bin/bash")
|
||||
|
||||
defer func() {
|
||||
os.Setenv("MACHINE_STORAGE_PATH", "")
|
||||
os.Setenv("SHELL", shell)
|
||||
os.Stdout = stdout
|
||||
}()
|
||||
|
||||
if err := clearHosts(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
flags := getTestDriverFlags()
|
||||
|
||||
store, sErr := getTestStore()
|
||||
if sErr != nil {
|
||||
t.Fatal(sErr)
|
||||
}
|
||||
|
||||
provider, err := libmachine.New(store)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostOptions := &libmachine.HostOptions{
|
||||
EngineOptions: &engine.EngineOptions{},
|
||||
SwarmOptions: &swarm.SwarmOptions{
|
||||
Master: false,
|
||||
Discovery: "",
|
||||
Address: "",
|
||||
Host: "",
|
||||
},
|
||||
AuthOptions: &auth.AuthOptions{},
|
||||
}
|
||||
|
||||
host, err := provider.Create("test-a", "none", hostOptions, flags)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
host, err = provider.Get("test-a")
|
||||
if err != nil {
|
||||
t.Fatalf("error loading host: %v", err)
|
||||
}
|
||||
|
||||
outStr := make(chan string)
|
||||
|
||||
go func() {
|
||||
var testOutput bytes.Buffer
|
||||
io.Copy(&testOutput, r)
|
||||
outStr <- testOutput.String()
|
||||
}()
|
||||
|
||||
set := flag.NewFlagSet("config", 0)
|
||||
set.Parse([]string{"test-a"})
|
||||
c := cli.NewContext(nil, set, set)
|
||||
c.App = &cli.App{
|
||||
Name: "docker-machine-test",
|
||||
}
|
||||
cmdEnv(c)
|
||||
|
||||
w.Close()
|
||||
|
||||
out := <-outStr
|
||||
|
||||
// parse the output into a map of envvar:value for easier testing below
|
||||
envvars := make(map[string]string)
|
||||
for _, e := range strings.Split(strings.TrimSpace(out), "\n") {
|
||||
if !strings.HasPrefix(e, "export ") {
|
||||
continue
|
||||
}
|
||||
kv := strings.SplitN(e, "=", 2)
|
||||
key, value := kv[0], kv[1]
|
||||
envvars[strings.Replace(key, "export ", "", 1)] = value
|
||||
}
|
||||
|
||||
testMachineDir := filepath.Join(store.GetPath(), "machines", host.Name)
|
||||
|
||||
expected := map[string]string{
|
||||
"DOCKER_TLS_VERIFY": "\"1\"",
|
||||
"DOCKER_CERT_PATH": fmt.Sprintf("\"%s\"", testMachineDir),
|
||||
"DOCKER_HOST": "\"unix:///var/run/docker.sock\"",
|
||||
"DOCKER_MACHINE_NAME": `"test-a"`,
|
||||
}
|
||||
|
||||
for k, v := range envvars {
|
||||
if v != expected[k] {
|
||||
t.Fatalf("Expected %s == <%s>, but was <%s>", k, expected[k], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCmdEnvFish(t *testing.T) {
|
||||
stdout := os.Stdout
|
||||
shell := os.Getenv("SHELL")
|
||||
r, w, _ := os.Pipe()
|
||||
|
||||
os.Stdout = w
|
||||
os.Setenv("MACHINE_STORAGE_PATH", TestStoreDir)
|
||||
os.Setenv("SHELL", "/bin/fish")
|
||||
|
||||
defer func() {
|
||||
os.Setenv("MACHINE_STORAGE_PATH", "")
|
||||
os.Setenv("SHELL", shell)
|
||||
os.Stdout = stdout
|
||||
}()
|
||||
|
||||
if err := clearHosts(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
flags := getTestDriverFlags()
|
||||
|
||||
store, err := getTestStore()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
provider, err := libmachine.New(store)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostOptions := &libmachine.HostOptions{
|
||||
EngineOptions: &engine.EngineOptions{},
|
||||
SwarmOptions: &swarm.SwarmOptions{
|
||||
Master: false,
|
||||
Discovery: "",
|
||||
Address: "",
|
||||
Host: "",
|
||||
},
|
||||
AuthOptions: &auth.AuthOptions{},
|
||||
}
|
||||
|
||||
host, err := provider.Create("test-a", "none", hostOptions, flags)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
host, err = provider.Get("test-a")
|
||||
if err != nil {
|
||||
t.Fatalf("error loading host: %v", err)
|
||||
}
|
||||
|
||||
outStr := make(chan string)
|
||||
|
||||
go func() {
|
||||
var testOutput bytes.Buffer
|
||||
io.Copy(&testOutput, r)
|
||||
outStr <- testOutput.String()
|
||||
}()
|
||||
|
||||
set := flag.NewFlagSet("config", 0)
|
||||
set.Parse([]string{"test-a"})
|
||||
c := cli.NewContext(nil, set, set)
|
||||
c.App = &cli.App{
|
||||
Name: "docker-machine-test",
|
||||
}
|
||||
cmdEnv(c)
|
||||
|
||||
w.Close()
|
||||
|
||||
out := <-outStr
|
||||
|
||||
// parse the output into a map of envvar:value for easier testing below
|
||||
envvars := make(map[string]string)
|
||||
for _, e := range strings.Split(strings.TrimSuffix(out, ";\n"), ";\n") {
|
||||
if !strings.HasPrefix(e, "set -x ") {
|
||||
continue
|
||||
}
|
||||
kv := strings.SplitN(strings.Replace(e, "set -x ", "", 1), " ", 2)
|
||||
key, value := kv[0], kv[1]
|
||||
envvars[key] = value
|
||||
}
|
||||
|
||||
testMachineDir := filepath.Join(store.GetPath(), "machines", host.Name)
|
||||
|
||||
expected := map[string]string{
|
||||
"DOCKER_TLS_VERIFY": "\"1\"",
|
||||
"DOCKER_CERT_PATH": fmt.Sprintf("\"%s\"", testMachineDir),
|
||||
"DOCKER_HOST": "\"unix:///var/run/docker.sock\"",
|
||||
"DOCKER_MACHINE_NAME": `"test-a"`,
|
||||
}
|
||||
|
||||
for k, v := range envvars {
|
||||
if v != expected[k] {
|
||||
t.Fatalf("Expected %s == <%s>, but was <%s>", k, expected[k], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCmdEnvPowerShell(t *testing.T) {
|
||||
stdout := os.Stdout
|
||||
shell := os.Getenv("SHELL")
|
||||
r, w, _ := os.Pipe()
|
||||
|
||||
os.Stdout = w
|
||||
os.Setenv("MACHINE_STORAGE_PATH", TestStoreDir)
|
||||
os.Setenv("SHELL", "")
|
||||
|
||||
defer func() {
|
||||
os.Setenv("MACHINE_STORAGE_PATH", "")
|
||||
os.Setenv("SHELL", shell)
|
||||
os.Stdout = stdout
|
||||
}()
|
||||
|
||||
if err := clearHosts(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
flags := getTestDriverFlags()
|
||||
|
||||
store, sErr := getTestStore()
|
||||
if sErr != nil {
|
||||
t.Fatal(sErr)
|
||||
}
|
||||
|
||||
provider, err := libmachine.New(store)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostOptions := &libmachine.HostOptions{
|
||||
EngineOptions: &engine.EngineOptions{},
|
||||
SwarmOptions: &swarm.SwarmOptions{
|
||||
Master: false,
|
||||
Discovery: "",
|
||||
Address: "",
|
||||
Host: "",
|
||||
},
|
||||
AuthOptions: &auth.AuthOptions{},
|
||||
}
|
||||
|
||||
host, err := provider.Create("test-a", "none", hostOptions, flags)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
host, err = provider.Get("test-a")
|
||||
if err != nil {
|
||||
t.Fatalf("error loading host: %v", err)
|
||||
}
|
||||
|
||||
outStr := make(chan string)
|
||||
|
||||
go func() {
|
||||
var testOutput bytes.Buffer
|
||||
io.Copy(&testOutput, r)
|
||||
outStr <- testOutput.String()
|
||||
}()
|
||||
|
||||
set := flag.NewFlagSet("config", 0)
|
||||
set.Parse([]string{"test-a"})
|
||||
set.String("shell", "powershell", "")
|
||||
c := cli.NewContext(nil, set, set)
|
||||
c.App = &cli.App{
|
||||
Name: "docker-machine-test",
|
||||
}
|
||||
cmdEnv(c)
|
||||
|
||||
w.Close()
|
||||
|
||||
out := <-outStr
|
||||
|
||||
// parse the output into a map of envvar:value for easier testing below
|
||||
envvars := make(map[string]string)
|
||||
for _, e := range strings.Split(strings.TrimSpace(out), "\n") {
|
||||
if !strings.HasPrefix(e, "$Env") {
|
||||
continue
|
||||
}
|
||||
kv := strings.SplitN(e, " = ", 2)
|
||||
key, value := kv[0], kv[1]
|
||||
envvars[strings.Replace(key, "$Env:", "", 1)] = value
|
||||
}
|
||||
|
||||
testMachineDir := filepath.Join(store.GetPath(), "machines", host.Name)
|
||||
|
||||
expected := map[string]string{
|
||||
"DOCKER_TLS_VERIFY": "\"1\"",
|
||||
"DOCKER_CERT_PATH": fmt.Sprintf("\"%s\"", testMachineDir),
|
||||
"DOCKER_HOST": "\"unix:///var/run/docker.sock\"",
|
||||
"DOCKER_MACHINE_NAME": `"test-a"`,
|
||||
}
|
||||
|
||||
for k, v := range envvars {
|
||||
if v != expected[k] {
|
||||
t.Fatalf("Expected %s == <%s>, but was <%s>", k, expected[k], v)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import (
|
|||
"os"
|
||||
"text/template"
|
||||
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
@ -31,7 +31,7 @@ func cmdInspect(c *cli.Context) {
|
|||
log.Fatalf("Template parsing error: %v\n", err)
|
||||
}
|
||||
|
||||
jsonHost, err := json.Marshal(getHost(c))
|
||||
jsonHost, err := json.Marshal(getFirstArgHost(c))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ func cmdInspect(c *cli.Context) {
|
|||
}
|
||||
os.Stdout.Write([]byte{'\n'})
|
||||
} else {
|
||||
prettyJSON, err := json.MarshalIndent(getHost(c), "", " ")
|
||||
prettyJSON, err := json.MarshalIndent(getFirstArgHost(c), "", " ")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/engine"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCmdInspectFormat(t *testing.T) {
|
||||
actual, host := runInspectCommand(t, []string{"test-a"})
|
||||
expected, _ := json.MarshalIndent(host, "", " ")
|
||||
assert.Equal(t, string(expected), actual)
|
||||
|
||||
actual, _ = runInspectCommand(t, []string{"--format", "{{.DriverName}}", "test-a"})
|
||||
assert.Equal(t, "none", actual)
|
||||
|
||||
actual, _ = runInspectCommand(t, []string{"--format", "{{json .DriverName}}", "test-a"})
|
||||
assert.Equal(t, "\"none\"", actual)
|
||||
|
||||
actual, _ = runInspectCommand(t, []string{"--format", "{{prettyjson .Driver}}", "test-a"})
|
||||
type ExpectedDriver struct {
|
||||
CaCertPath string
|
||||
IPAddress string
|
||||
MachineName string
|
||||
PrivateKeyPath string
|
||||
SSHPort int
|
||||
SSHUser string
|
||||
SwarmDiscovery string
|
||||
SwarmHost string
|
||||
SwarmMaster bool
|
||||
URL string
|
||||
}
|
||||
expected, err := json.MarshalIndent(&ExpectedDriver{MachineName: "test-a", URL: "unix:///var/run/docker.sock"}, "", " ")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, string(expected), actual)
|
||||
}
|
||||
|
||||
func runInspectCommand(t *testing.T, args []string) (string, *libmachine.Host) {
|
||||
stdout := os.Stdout
|
||||
stderr := os.Stderr
|
||||
shell := os.Getenv("SHELL")
|
||||
r, w, _ := os.Pipe()
|
||||
|
||||
os.Stdout = w
|
||||
os.Stderr = w
|
||||
os.Setenv("MACHINE_STORAGE_PATH", TestStoreDir)
|
||||
os.Setenv("SHELL", "/bin/bash")
|
||||
|
||||
defer func() {
|
||||
os.Setenv("MACHINE_STORAGE_PATH", "")
|
||||
os.Setenv("SHELL", shell)
|
||||
os.Stdout = stdout
|
||||
os.Stderr = stderr
|
||||
}()
|
||||
|
||||
if err := clearHosts(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
store, sErr := getTestStore()
|
||||
if sErr != nil {
|
||||
t.Fatal(sErr)
|
||||
}
|
||||
|
||||
provider, err := libmachine.New(store)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hostOptions := &libmachine.HostOptions{
|
||||
EngineOptions: &engine.EngineOptions{},
|
||||
SwarmOptions: &swarm.SwarmOptions{
|
||||
Master: false,
|
||||
Discovery: "",
|
||||
Address: "",
|
||||
Host: "",
|
||||
},
|
||||
AuthOptions: &auth.AuthOptions{},
|
||||
}
|
||||
|
||||
flags := getTestDriverFlags()
|
||||
_, err = provider.Create("test-a", "none", hostOptions, flags)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outStr := make(chan string)
|
||||
|
||||
go func() {
|
||||
var testOutput bytes.Buffer
|
||||
io.Copy(&testOutput, r)
|
||||
outStr <- testOutput.String()
|
||||
}()
|
||||
|
||||
set := flag.NewFlagSet("inspect", 0)
|
||||
set.String("format", "", "")
|
||||
set.Parse(args)
|
||||
c := cli.NewContext(nil, set, set)
|
||||
cmdInspect(c)
|
||||
|
||||
w.Close()
|
||||
|
||||
out := <-outStr
|
||||
|
||||
return strings.TrimSpace(out), getHost(c)
|
||||
}
|
|
@ -2,7 +2,7 @@ package commands
|
|||
|
||||
import (
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
)
|
||||
|
||||
func cmdIp(c *cli.Context) {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -1,7 +1,7 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
182
commands/ls.go
182
commands/ls.go
|
@ -5,12 +5,23 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/persist"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
"github.com/skarademir/naturalsort"
|
||||
)
|
||||
|
||||
var (
|
||||
stateTimeoutDuration = 10 * time.Second
|
||||
)
|
||||
|
||||
// FilterOptions -
|
||||
|
@ -21,6 +32,15 @@ type FilterOptions struct {
|
|||
Name []string
|
||||
}
|
||||
|
||||
type HostListItem struct {
|
||||
Name string
|
||||
Active bool
|
||||
DriverName string
|
||||
State state.State
|
||||
URL string
|
||||
SwarmOptions *swarm.SwarmOptions
|
||||
}
|
||||
|
||||
func cmdLs(c *cli.Context) {
|
||||
quiet := c.Bool("quiet")
|
||||
filters, err := parseFilters(c.StringSlice("filter"))
|
||||
|
@ -28,8 +48,8 @@ func cmdLs(c *cli.Context) {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
provider := getDefaultProvider(c)
|
||||
hostList, err := provider.List()
|
||||
store := getStore(c)
|
||||
hostList, err := store.List()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -61,7 +81,7 @@ func cmdLs(c *cli.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
items := libmachine.GetHostListItems(hostList)
|
||||
items := getHostListItems(hostList)
|
||||
|
||||
sortHostListItemsByName(items)
|
||||
|
||||
|
@ -111,7 +131,7 @@ func parseFilters(filters []string) (FilterOptions, error) {
|
|||
return options, nil
|
||||
}
|
||||
|
||||
func filterHosts(hosts []*libmachine.Host, filters FilterOptions) []*libmachine.Host {
|
||||
func filterHosts(hosts []*host.Host, filters FilterOptions) []*host.Host {
|
||||
if len(filters.SwarmName) == 0 &&
|
||||
len(filters.DriverName) == 0 &&
|
||||
len(filters.State) == 0 &&
|
||||
|
@ -119,7 +139,7 @@ func filterHosts(hosts []*libmachine.Host, filters FilterOptions) []*libmachine.
|
|||
return hosts
|
||||
}
|
||||
|
||||
filteredHosts := []*libmachine.Host{}
|
||||
filteredHosts := []*host.Host{}
|
||||
swarmMasters := getSwarmMasters(hosts)
|
||||
|
||||
for _, h := range hosts {
|
||||
|
@ -130,7 +150,7 @@ func filterHosts(hosts []*libmachine.Host, filters FilterOptions) []*libmachine.
|
|||
return filteredHosts
|
||||
}
|
||||
|
||||
func getSwarmMasters(hosts []*libmachine.Host) map[string]string {
|
||||
func getSwarmMasters(hosts []*host.Host) map[string]string {
|
||||
swarmMasters := make(map[string]string)
|
||||
for _, h := range hosts {
|
||||
swarmOptions := h.HostOptions.SwarmOptions
|
||||
|
@ -141,7 +161,7 @@ func getSwarmMasters(hosts []*libmachine.Host) map[string]string {
|
|||
return swarmMasters
|
||||
}
|
||||
|
||||
func filterHost(host *libmachine.Host, filters FilterOptions, swarmMasters map[string]string) bool {
|
||||
func filterHost(host *host.Host, filters FilterOptions, swarmMasters map[string]string) bool {
|
||||
swarmMatches := matchesSwarmName(host, filters.SwarmName, swarmMasters)
|
||||
driverMatches := matchesDriverName(host, filters.DriverName)
|
||||
stateMatches := matchesState(host, filters.State)
|
||||
|
@ -150,7 +170,7 @@ func filterHost(host *libmachine.Host, filters FilterOptions, swarmMasters map[s
|
|||
return swarmMatches && driverMatches && stateMatches && nameMatches
|
||||
}
|
||||
|
||||
func matchesSwarmName(host *libmachine.Host, swarmNames []string, swarmMasters map[string]string) bool {
|
||||
func matchesSwarmName(host *host.Host, swarmNames []string, swarmMasters map[string]string) bool {
|
||||
if len(swarmNames) == 0 {
|
||||
return true
|
||||
}
|
||||
|
@ -164,7 +184,7 @@ func matchesSwarmName(host *libmachine.Host, swarmNames []string, swarmMasters m
|
|||
return false
|
||||
}
|
||||
|
||||
func matchesDriverName(host *libmachine.Host, driverNames []string) bool {
|
||||
func matchesDriverName(host *host.Host, driverNames []string) bool {
|
||||
if len(driverNames) == 0 {
|
||||
return true
|
||||
}
|
||||
|
@ -176,7 +196,7 @@ func matchesDriverName(host *libmachine.Host, driverNames []string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func matchesState(host *libmachine.Host, states []string) bool {
|
||||
func matchesState(host *host.Host, states []string) bool {
|
||||
if len(states) == 0 {
|
||||
return true
|
||||
}
|
||||
|
@ -192,7 +212,7 @@ func matchesState(host *libmachine.Host, states []string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func matchesName(host *libmachine.Host, names []string) bool {
|
||||
func matchesName(host *host.Host, names []string) bool {
|
||||
if len(names) == 0 {
|
||||
return true
|
||||
}
|
||||
|
@ -207,3 +227,139 @@ func matchesName(host *libmachine.Host, names []string) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getActiveHost(store persist.Store) (*host.Host, error) {
|
||||
hosts, err := store.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hostListItems := getHostListItems(hosts)
|
||||
|
||||
for _, item := range hostListItems {
|
||||
if item.Active {
|
||||
h, err := store.Load(item.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("Active host not found")
|
||||
}
|
||||
|
||||
func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) {
|
||||
currentState, err := h.Driver.GetState()
|
||||
if err != nil {
|
||||
log.Errorf("error getting state for host %s: %s", h.Name, err)
|
||||
}
|
||||
|
||||
url, err := h.GetURL()
|
||||
if err != nil {
|
||||
if err == drivers.ErrHostIsNotRunning {
|
||||
url = ""
|
||||
} else {
|
||||
log.Errorf("error getting URL for host %s: %s", h.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
active, err := isActive(h)
|
||||
if err != nil {
|
||||
log.Errorf("error determining if host is active for host %s: %s",
|
||||
h.Name, err)
|
||||
}
|
||||
|
||||
stateQueryChan <- HostListItem{
|
||||
Name: h.Name,
|
||||
Active: active,
|
||||
DriverName: h.Driver.DriverName(),
|
||||
State: currentState,
|
||||
URL: url,
|
||||
SwarmOptions: h.HostOptions.SwarmOptions,
|
||||
}
|
||||
}
|
||||
|
||||
func getHostState(h *host.Host, hostListItemsChan chan<- HostListItem) {
|
||||
// This channel is used to communicate the properties we are querying
|
||||
// about the host in the case of a successful read.
|
||||
stateQueryChan := make(chan HostListItem)
|
||||
|
||||
go attemptGetHostState(h, stateQueryChan)
|
||||
|
||||
select {
|
||||
// If we get back useful information, great. Forward it straight to
|
||||
// the original parent channel.
|
||||
case hli := <-stateQueryChan:
|
||||
hostListItemsChan <- hli
|
||||
|
||||
// Otherwise, give up after a predetermined duration.
|
||||
case <-time.After(stateTimeoutDuration):
|
||||
hostListItemsChan <- HostListItem{
|
||||
Name: h.Name,
|
||||
DriverName: h.Driver.DriverName(),
|
||||
State: state.Timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getHostListItems(hostList []*host.Host) []HostListItem {
|
||||
hostListItems := []HostListItem{}
|
||||
hostListItemsChan := make(chan HostListItem)
|
||||
|
||||
for _, h := range hostList {
|
||||
go getHostState(h, hostListItemsChan)
|
||||
}
|
||||
|
||||
for range hostList {
|
||||
hostListItems = append(hostListItems, <-hostListItemsChan)
|
||||
}
|
||||
|
||||
close(hostListItemsChan)
|
||||
return hostListItems
|
||||
}
|
||||
|
||||
// IsActive provides a single function for determining if a host is active
|
||||
// based on both the url and if the host is stopped.
|
||||
func isActive(h *host.Host) (bool, error) {
|
||||
currentState, err := h.Driver.GetState()
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("error getting state for host %s: %s", h.Name, err)
|
||||
return false, err
|
||||
}
|
||||
|
||||
url, err := h.GetURL()
|
||||
|
||||
if err != nil {
|
||||
if err == drivers.ErrHostIsNotRunning {
|
||||
url = ""
|
||||
} else {
|
||||
log.Errorf("error getting URL for host %s: %s", h.Name, err)
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
dockerHost := os.Getenv("DOCKER_HOST")
|
||||
|
||||
notStopped := currentState != state.Stopped
|
||||
correctURL := url == dockerHost
|
||||
|
||||
isActive := notStopped && correctURL
|
||||
|
||||
return isActive, nil
|
||||
}
|
||||
|
||||
func sortHostListItemsByName(items []HostListItem) {
|
||||
m := make(map[string]HostListItem, len(items))
|
||||
s := make([]string, len(items))
|
||||
for i, v := range items {
|
||||
name := strings.ToLower(v.Name)
|
||||
m[name] = v
|
||||
s[i] = name
|
||||
}
|
||||
sort.Sort(naturalsort.NaturalSort(s))
|
||||
for i, v := range s {
|
||||
items[i] = m[v]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,32 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/machine/drivers/fakedriver"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
hostTestStorePath string
|
||||
stdout *os.File
|
||||
)
|
||||
|
||||
func init() {
|
||||
stdout = os.Stdout
|
||||
}
|
||||
|
||||
func cleanup() {
|
||||
os.Stdout = stdout
|
||||
os.RemoveAll(hostTestStorePath)
|
||||
}
|
||||
|
||||
func TestParseFiltersErrorsGivenInvalidFilter(t *testing.T) {
|
||||
_, err := parseFilters([]string{"foo=bar"})
|
||||
assert.EqualError(t, err, "Unsupported filter key 'foo'")
|
||||
|
@ -52,11 +69,11 @@ func TestParseFiltersValueWithEqual(t *testing.T) {
|
|||
|
||||
func TestFilterHostsReturnsSameGivenNoFilters(t *testing.T) {
|
||||
opts := FilterOptions{}
|
||||
hosts := []*libmachine.Host{
|
||||
hosts := []*host.Host{
|
||||
{
|
||||
Name: "testhost",
|
||||
DriverName: "fakedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
},
|
||||
}
|
||||
actual := filterHosts(hosts, opts)
|
||||
|
@ -67,7 +84,7 @@ func TestFilterHostsReturnsEmptyGivenEmptyHosts(t *testing.T) {
|
|||
opts := FilterOptions{
|
||||
SwarmName: []string{"foo"},
|
||||
}
|
||||
hosts := []*libmachine.Host{}
|
||||
hosts := []*host.Host{}
|
||||
assert.Empty(t, filterHosts(hosts, opts))
|
||||
}
|
||||
|
||||
|
@ -75,11 +92,11 @@ func TestFilterHostsReturnsEmptyGivenNonMatchingFilters(t *testing.T) {
|
|||
opts := FilterOptions{
|
||||
SwarmName: []string{"foo"},
|
||||
}
|
||||
hosts := []*libmachine.Host{
|
||||
hosts := []*host.Host{
|
||||
{
|
||||
Name: "testhost",
|
||||
DriverName: "fakedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
},
|
||||
}
|
||||
assert.Empty(t, filterHosts(hosts, opts))
|
||||
|
@ -90,28 +107,28 @@ func TestFilterHostsBySwarmName(t *testing.T) {
|
|||
SwarmName: []string{"master"},
|
||||
}
|
||||
master :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "master",
|
||||
HostOptions: &libmachine.HostOptions{
|
||||
HostOptions: &host.HostOptions{
|
||||
SwarmOptions: &swarm.SwarmOptions{Master: true, Discovery: "foo"},
|
||||
},
|
||||
}
|
||||
node1 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node1",
|
||||
HostOptions: &libmachine.HostOptions{
|
||||
HostOptions: &host.HostOptions{
|
||||
SwarmOptions: &swarm.SwarmOptions{Master: false, Discovery: "foo"},
|
||||
},
|
||||
}
|
||||
othermaster :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "othermaster",
|
||||
HostOptions: &libmachine.HostOptions{
|
||||
HostOptions: &host.HostOptions{
|
||||
SwarmOptions: &swarm.SwarmOptions{Master: true, Discovery: "bar"},
|
||||
},
|
||||
}
|
||||
hosts := []*libmachine.Host{master, node1, othermaster}
|
||||
expected := []*libmachine.Host{master, node1}
|
||||
hosts := []*host.Host{master, node1, othermaster}
|
||||
expected := []*host.Host{master, node1}
|
||||
|
||||
assert.EqualValues(t, filterHosts(hosts, opts), expected)
|
||||
}
|
||||
|
@ -121,25 +138,25 @@ func TestFilterHostsByDriverName(t *testing.T) {
|
|||
DriverName: []string{"fakedriver"},
|
||||
}
|
||||
node1 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node1",
|
||||
DriverName: "fakedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
}
|
||||
node2 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node2",
|
||||
DriverName: "virtualbox",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
}
|
||||
node3 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node3",
|
||||
DriverName: "fakedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
}
|
||||
hosts := []*libmachine.Host{node1, node2, node3}
|
||||
expected := []*libmachine.Host{node1, node3}
|
||||
hosts := []*host.Host{node1, node2, node3}
|
||||
expected := []*host.Host{node1, node3}
|
||||
|
||||
assert.EqualValues(t, filterHosts(hosts, opts), expected)
|
||||
}
|
||||
|
@ -149,28 +166,28 @@ func TestFilterHostsByState(t *testing.T) {
|
|||
State: []string{"Paused", "Saved", "Stopped"},
|
||||
}
|
||||
node1 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node1",
|
||||
DriverName: "fakedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
Driver: &fakedriver.FakeDriver{MockState: state.Paused},
|
||||
}
|
||||
node2 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node2",
|
||||
DriverName: "virtualbox",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
Driver: &fakedriver.FakeDriver{MockState: state.Stopped},
|
||||
}
|
||||
node3 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node3",
|
||||
DriverName: "fakedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
Driver: &fakedriver.FakeDriver{MockState: state.Running},
|
||||
}
|
||||
hosts := []*libmachine.Host{node1, node2, node3}
|
||||
expected := []*libmachine.Host{node1, node2}
|
||||
hosts := []*host.Host{node1, node2, node3}
|
||||
expected := []*host.Host{node1, node2}
|
||||
|
||||
assert.EqualValues(t, filterHosts(hosts, opts), expected)
|
||||
}
|
||||
|
@ -180,35 +197,35 @@ func TestFilterHostsByName(t *testing.T) {
|
|||
Name: []string{"fire", "ice", "earth", "a.?r"},
|
||||
}
|
||||
node1 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "fire",
|
||||
DriverName: "fakedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
Driver: &fakedriver.FakeDriver{MockState: state.Paused, MockName: "fire"},
|
||||
}
|
||||
node2 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "ice",
|
||||
DriverName: "adriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
Driver: &fakedriver.FakeDriver{MockState: state.Paused, MockName: "ice"},
|
||||
}
|
||||
node3 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "air",
|
||||
DriverName: "nodriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
Driver: &fakedriver.FakeDriver{MockState: state.Paused, MockName: "air"},
|
||||
}
|
||||
node4 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "water",
|
||||
DriverName: "falsedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
Driver: &fakedriver.FakeDriver{MockState: state.Paused, MockName: "water"},
|
||||
}
|
||||
hosts := []*libmachine.Host{node1, node2, node3, node4}
|
||||
expected := []*libmachine.Host{node1, node2, node3}
|
||||
hosts := []*host.Host{node1, node2, node3, node4}
|
||||
expected := []*host.Host{node1, node2, node3}
|
||||
|
||||
assert.EqualValues(t, filterHosts(hosts, opts), expected)
|
||||
}
|
||||
|
@ -219,25 +236,25 @@ func TestFilterHostsMultiFlags(t *testing.T) {
|
|||
DriverName: []string{"fakedriver", "virtualbox"},
|
||||
}
|
||||
node1 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node1",
|
||||
DriverName: "fakedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
}
|
||||
node2 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node2",
|
||||
DriverName: "virtualbox",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
}
|
||||
node3 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node3",
|
||||
DriverName: "softlayer",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
}
|
||||
hosts := []*libmachine.Host{node1, node2, node3}
|
||||
expected := []*libmachine.Host{node1, node2}
|
||||
hosts := []*host.Host{node1, node2, node3}
|
||||
expected := []*host.Host{node1, node2}
|
||||
|
||||
assert.EqualValues(t, filterHosts(hosts, opts), expected)
|
||||
}
|
||||
|
@ -248,28 +265,114 @@ func TestFilterHostsDifferentFlagsProduceAND(t *testing.T) {
|
|||
State: []string{"Running"},
|
||||
}
|
||||
node1 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node1",
|
||||
DriverName: "fakedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
Driver: &fakedriver.FakeDriver{MockState: state.Paused},
|
||||
}
|
||||
node2 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node2",
|
||||
DriverName: "virtualbox",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
Driver: &fakedriver.FakeDriver{MockState: state.Stopped},
|
||||
}
|
||||
node3 :=
|
||||
&libmachine.Host{
|
||||
&host.Host{
|
||||
Name: "node3",
|
||||
DriverName: "fakedriver",
|
||||
HostOptions: &libmachine.HostOptions{},
|
||||
HostOptions: &host.HostOptions{},
|
||||
Driver: &fakedriver.FakeDriver{MockState: state.Running},
|
||||
}
|
||||
hosts := []*libmachine.Host{node1, node2, node3}
|
||||
expected := []*libmachine.Host{}
|
||||
hosts := []*host.Host{node1, node2, node3}
|
||||
expected := []*host.Host{}
|
||||
|
||||
assert.EqualValues(t, filterHosts(hosts, opts), expected)
|
||||
}
|
||||
func captureStdout() (chan string, *os.File) {
|
||||
r, w, _ := os.Pipe()
|
||||
os.Stdout = w
|
||||
|
||||
out := make(chan string)
|
||||
|
||||
go func() {
|
||||
var testOutput bytes.Buffer
|
||||
io.Copy(&testOutput, r)
|
||||
out <- testOutput.String()
|
||||
}()
|
||||
|
||||
return out, w
|
||||
}
|
||||
|
||||
func TestGetHostListItems(t *testing.T) {
|
||||
defer cleanup()
|
||||
|
||||
hostListItemsChan := make(chan HostListItem)
|
||||
|
||||
hosts := []*host.Host{
|
||||
{
|
||||
Name: "foo",
|
||||
DriverName: "fakedriver",
|
||||
Driver: &fakedriver.FakeDriver{
|
||||
MockState: state.Running,
|
||||
},
|
||||
HostOptions: &host.HostOptions{
|
||||
SwarmOptions: &swarm.SwarmOptions{
|
||||
Master: false,
|
||||
Address: "",
|
||||
Discovery: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
DriverName: "fakedriver",
|
||||
Driver: &fakedriver.FakeDriver{
|
||||
MockState: state.Stopped,
|
||||
},
|
||||
HostOptions: &host.HostOptions{
|
||||
SwarmOptions: &swarm.SwarmOptions{
|
||||
Master: false,
|
||||
Address: "",
|
||||
Discovery: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "baz",
|
||||
DriverName: "fakedriver",
|
||||
Driver: &fakedriver.FakeDriver{
|
||||
MockState: state.Running,
|
||||
},
|
||||
HostOptions: &host.HostOptions{
|
||||
SwarmOptions: &swarm.SwarmOptions{
|
||||
Master: false,
|
||||
Address: "",
|
||||
Discovery: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
expected := map[string]state.State{
|
||||
"foo": state.Running,
|
||||
"bar": state.Stopped,
|
||||
"baz": state.Running,
|
||||
}
|
||||
|
||||
items := []HostListItem{}
|
||||
for _, host := range hosts {
|
||||
go getHostState(host, hostListItemsChan)
|
||||
}
|
||||
|
||||
for i := 0; i < len(hosts); i++ {
|
||||
items = append(items, <-hostListItemsChan)
|
||||
}
|
||||
|
||||
for _, item := range items {
|
||||
if expected[item.Name] != item.State {
|
||||
t.Fatal("Expected state did not match for item", item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package mcndirs
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
)
|
||||
|
||||
func GetBaseDir() string {
|
||||
baseDir := os.Getenv("MACHINE_STORAGE_PATH")
|
||||
if baseDir == "" {
|
||||
baseDir = filepath.Join(mcnutils.GetHomeDir(), ".docker", "machine")
|
||||
}
|
||||
return baseDir
|
||||
}
|
||||
|
||||
func GetDockerDir() string {
|
||||
return filepath.Join(mcnutils.GetHomeDir(), ".docker")
|
||||
}
|
||||
|
||||
func GetMachineDir() string {
|
||||
return filepath.Join(GetBaseDir(), "machines")
|
||||
}
|
||||
|
||||
func GetMachineCertDir() string {
|
||||
return filepath.Join(GetBaseDir(), "certs")
|
||||
}
|
||||
|
||||
func GetMachineCacheDir() string {
|
||||
return filepath.Join(GetBaseDir(), "cache")
|
||||
}
|
|
@ -1,18 +1,17 @@
|
|||
package utils
|
||||
package mcndirs
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
)
|
||||
|
||||
func TestGetBaseDir(t *testing.T) {
|
||||
// reset any override env var
|
||||
homeDir := GetHomeDir()
|
||||
homeDir := mcnutils.GetHomeDir()
|
||||
baseDir := GetBaseDir()
|
||||
|
||||
if strings.Index(baseDir, homeDir) != 0 {
|
||||
|
@ -32,7 +31,7 @@ func TestGetCustomBaseDir(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetDockerDir(t *testing.T) {
|
||||
homeDir := GetHomeDir()
|
||||
homeDir := mcnutils.GetHomeDir()
|
||||
baseDir := GetBaseDir()
|
||||
|
||||
if strings.Index(baseDir, homeDir) != 0 {
|
||||
|
@ -77,63 +76,3 @@ func TestGetMachineCertDir(t *testing.T) {
|
|||
}
|
||||
os.Setenv("MACHINE_STORAGE_PATH", "")
|
||||
}
|
||||
|
||||
func TestCopyFile(t *testing.T) {
|
||||
testStr := "test-machine"
|
||||
|
||||
srcFile, err := ioutil.TempFile("", "machine-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
srcFi, err := srcFile.Stat()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
srcFile.Write([]byte(testStr))
|
||||
srcFile.Close()
|
||||
|
||||
srcFilePath := filepath.Join(os.TempDir(), srcFi.Name())
|
||||
|
||||
destFile, err := ioutil.TempFile("", "machine-copy-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
destFi, err := destFile.Stat()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
destFile.Close()
|
||||
|
||||
destFilePath := filepath.Join(os.TempDir(), destFi.Name())
|
||||
|
||||
if err := CopyFile(srcFilePath, destFilePath); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(destFilePath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if string(data) != testStr {
|
||||
t.Fatalf("expected data \"%s\"; received \"%s\"", testStr, string(data))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUsername(t *testing.T) {
|
||||
currentUser := "unknown"
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "linux":
|
||||
currentUser = os.Getenv("USER")
|
||||
case "windows":
|
||||
currentUser = os.Getenv("USERNAME")
|
||||
}
|
||||
|
||||
username := GetUsername()
|
||||
if username != currentUser {
|
||||
t.Fatalf("expected username %s; received %s", currentUser, username)
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package commands
|
|||
|
||||
import (
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
)
|
||||
|
||||
func cmdRegenerateCerts(c *cli.Context) {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -1,7 +1,7 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -2,7 +2,7 @@ package commands
|
|||
|
||||
import (
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
)
|
||||
|
||||
func cmdRm(c *cli.Context) {
|
||||
|
@ -15,27 +15,14 @@ func cmdRm(c *cli.Context) {
|
|||
|
||||
isError := false
|
||||
|
||||
certInfo := getCertPathInfo(c)
|
||||
defaultStore, err := getDefaultStore(
|
||||
c.GlobalString("storage-path"),
|
||||
certInfo.CaCertPath,
|
||||
certInfo.CaKeyPath,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
store := getStore(c)
|
||||
|
||||
provider, err := newProvider(defaultStore)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, host := range c.Args() {
|
||||
if err := provider.Remove(host, force); err != nil {
|
||||
log.Errorf("Error removing machine %s: %s", host, err)
|
||||
for _, hostName := range c.Args() {
|
||||
if err := store.Remove(hostName, force); err != nil {
|
||||
log.Errorf("Error removing machine %s: %s", hostName, err)
|
||||
isError = true
|
||||
} else {
|
||||
log.Infof("Successfully removed %s", host)
|
||||
log.Infof("Successfully removed %s", hostName)
|
||||
}
|
||||
}
|
||||
if isError {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -8,8 +8,9 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/persist"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -26,7 +27,7 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func getInfoForScpArg(hostAndPath string, provider libmachine.Provider) (*libmachine.Host, string, []string, error) {
|
||||
func getInfoForScpArg(hostAndPath string, store persist.Store) (*host.Host, string, []string, error) {
|
||||
// TODO: What to do about colon in filepath?
|
||||
splitInfo := strings.Split(hostAndPath, ":")
|
||||
|
||||
|
@ -38,7 +39,7 @@ func getInfoForScpArg(hostAndPath string, provider libmachine.Provider) (*libmac
|
|||
// Remote path. e.g. "machinename:/usr/bin/cmatrix"
|
||||
if len(splitInfo) == 2 {
|
||||
path := splitInfo[1]
|
||||
host, err := provider.Get(splitInfo[0])
|
||||
host, err := store.Load(splitInfo[0])
|
||||
if err != nil {
|
||||
return nil, "", nil, fmt.Errorf("Error loading host: %s", err)
|
||||
}
|
||||
|
@ -52,7 +53,7 @@ func getInfoForScpArg(hostAndPath string, provider libmachine.Provider) (*libmac
|
|||
return nil, "", nil, ErrMalformedInput
|
||||
}
|
||||
|
||||
func generateLocationArg(host *libmachine.Host, path string) (string, error) {
|
||||
func generateLocationArg(host *host.Host, path string) (string, error) {
|
||||
locationPrefix := ""
|
||||
if host != nil {
|
||||
ip, err := host.Driver.GetIP()
|
||||
|
@ -64,18 +65,18 @@ func generateLocationArg(host *libmachine.Host, path string) (string, error) {
|
|||
return locationPrefix + path, nil
|
||||
}
|
||||
|
||||
func getScpCmd(src, dest string, sshArgs []string, provider libmachine.Provider) (*exec.Cmd, error) {
|
||||
func getScpCmd(src, dest string, sshArgs []string, store persist.Store) (*exec.Cmd, error) {
|
||||
cmdPath, err := exec.LookPath("scp")
|
||||
if err != nil {
|
||||
return nil, errors.New("Error: You must have a copy of the scp binary locally to use the scp feature.")
|
||||
}
|
||||
|
||||
srcHost, srcPath, srcOpts, err := getInfoForScpArg(src, provider)
|
||||
srcHost, srcPath, srcOpts, err := getInfoForScpArg(src, store)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
destHost, destPath, destOpts, err := getInfoForScpArg(dest, provider)
|
||||
destHost, destPath, destOpts, err := getInfoForScpArg(dest, store)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -129,8 +130,8 @@ func cmdScp(c *cli.Context) {
|
|||
src := args[0]
|
||||
dest := args[1]
|
||||
|
||||
provider := getDefaultProvider(c)
|
||||
cmd, err := getScpCmd(src, dest, sshArgs, *provider)
|
||||
store := getStore(c)
|
||||
cmd, err := getScpCmd(src, dest, sshArgs, store)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
|
@ -7,9 +7,9 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
type ScpFakeDriver struct {
|
||||
|
@ -18,14 +18,6 @@ type ScpFakeDriver struct {
|
|||
|
||||
type ScpFakeStore struct{}
|
||||
|
||||
func (d ScpFakeDriver) AuthorizePort(ports []*drivers.Port) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d ScpFakeDriver) DeauthorizePort(ports []*drivers.Port) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d ScpFakeDriver) DriverName() string {
|
||||
return "fake"
|
||||
}
|
||||
|
@ -114,33 +106,25 @@ func (d ScpFakeDriver) GetSSHKeyPath() string {
|
|||
return "/fake/keypath/id_rsa"
|
||||
}
|
||||
|
||||
func (d ScpFakeDriver) ResolveStorePath(file string) string {
|
||||
return "/tmp/store/machines/fake"
|
||||
}
|
||||
|
||||
func (s ScpFakeStore) Exists(name string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s ScpFakeStore) GetActive() (*libmachine.Host, error) {
|
||||
func (s ScpFakeStore) GetActive() (*host.Host, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s ScpFakeStore) GetPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s ScpFakeStore) GetCACertificatePath() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (s ScpFakeStore) GetPrivateKeyPath() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (s ScpFakeStore) List() ([]*libmachine.Host, error) {
|
||||
func (s ScpFakeStore) List() ([]*host.Host, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s ScpFakeStore) Get(name string) (*libmachine.Host, error) {
|
||||
func (s ScpFakeStore) Load(name string) (*host.Host, error) {
|
||||
if name == "myfunhost" {
|
||||
return &libmachine.Host{
|
||||
return &host.Host{
|
||||
Name: "myfunhost",
|
||||
Driver: ScpFakeDriver{},
|
||||
}, nil
|
||||
|
@ -152,15 +136,19 @@ func (s ScpFakeStore) Remove(name string, force bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s ScpFakeStore) Save(host *libmachine.Host) error {
|
||||
func (s ScpFakeStore) Save(host *host.Host) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s ScpFakeStore) NewHost(driver drivers.Driver) (*host.Host, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestGetInfoForScpArg(t *testing.T) {
|
||||
provider, _ := libmachine.New(ScpFakeStore{})
|
||||
store := ScpFakeStore{}
|
||||
|
||||
expectedPath := "/tmp/foo"
|
||||
host, path, opts, err := getInfoForScpArg("/tmp/foo", *provider)
|
||||
host, path, opts, err := getInfoForScpArg("/tmp/foo", store)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error in local getInfoForScpArg call: %s", err)
|
||||
}
|
||||
|
@ -174,7 +162,7 @@ func TestGetInfoForScpArg(t *testing.T) {
|
|||
t.Fatal("opts should be nil")
|
||||
}
|
||||
|
||||
host, path, opts, err = getInfoForScpArg("myfunhost:/home/docker/foo", *provider)
|
||||
host, path, opts, err = getInfoForScpArg("myfunhost:/home/docker/foo", store)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error in machine-based getInfoForScpArg call: %s", err)
|
||||
}
|
||||
|
@ -194,14 +182,14 @@ func TestGetInfoForScpArg(t *testing.T) {
|
|||
t.Fatalf("Expected path to be /home/docker/foo, got %s", path)
|
||||
}
|
||||
|
||||
host, path, opts, err = getInfoForScpArg("foo:bar:widget", *provider)
|
||||
host, path, opts, err = getInfoForScpArg("foo:bar:widget", store)
|
||||
if err != ErrMalformedInput {
|
||||
t.Fatalf("Didn't get back an error when we were expecting it for malformed args")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateLocationArg(t *testing.T) {
|
||||
host := libmachine.Host{
|
||||
host := host.Host{
|
||||
Driver: ScpFakeDriver{},
|
||||
}
|
||||
|
||||
|
@ -224,8 +212,6 @@ func TestGenerateLocationArg(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetScpCmd(t *testing.T) {
|
||||
provider, _ := libmachine.New(ScpFakeStore{})
|
||||
|
||||
// TODO: This is a little "integration-ey". Perhaps
|
||||
// make an ScpDispatcher (name?) interface so that the reliant
|
||||
// methods can be mocked.
|
||||
|
@ -238,8 +224,9 @@ func TestGetScpCmd(t *testing.T) {
|
|||
"root@12.34.56.78:/home/docker/foo",
|
||||
)
|
||||
expectedCmd := exec.Command("/usr/bin/scp", expectedArgs...)
|
||||
store := ScpFakeStore{}
|
||||
|
||||
cmd, err := getScpCmd("/tmp/foo", "myfunhost:/home/docker/foo", append(baseSSHArgs, "-3"), *provider)
|
||||
cmd, err := getScpCmd("/tmp/foo", "myfunhost:/home/docker/foo", append(baseSSHArgs, "-3"), store)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected err getting scp command: %s", err)
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
@ -18,22 +18,8 @@ func cmdSsh(c *cli.Context) {
|
|||
log.Fatal("Error: Please specify a machine name.")
|
||||
}
|
||||
|
||||
certInfo := getCertPathInfo(c)
|
||||
defaultStore, err := getDefaultStore(
|
||||
c.GlobalString("storage-path"),
|
||||
certInfo.CaCertPath,
|
||||
certInfo.CaKeyPath,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
provider, err := newProvider(defaultStore)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
host, err := provider.Get(name)
|
||||
store := getStore(c)
|
||||
host, err := store.Load(name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -1,7 +1,7 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -1,13 +1,13 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func cmdStatus(c *cli.Context) {
|
||||
host := getHost(c)
|
||||
host := getFirstArgHost(c)
|
||||
currentState, err := host.Driver.GetState()
|
||||
if err != nil {
|
||||
log.Errorf("error getting state for host %s: %s", host.Name, err)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -1,7 +1,7 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -1,7 +1,7 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -3,13 +3,13 @@ package commands
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
)
|
||||
|
||||
func cmdUrl(c *cli.Context) {
|
||||
url, err := getHost(c).GetURL()
|
||||
url, err := getFirstArgHost(c).GetURL()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package commands
|
|
@ -12,21 +12,26 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/drivers/amazonec2/amz"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
const (
|
||||
driverName = "amazonec2"
|
||||
ipRange = "0.0.0.0/0"
|
||||
machineSecurityGroupName = "docker-machine"
|
||||
defaultAmiId = "ami-615cb725"
|
||||
defaultRegion = "us-east-1"
|
||||
defaultInstanceType = "t2.micro"
|
||||
defaultRootSize = 16
|
||||
ipRange = "0.0.0.0/0"
|
||||
machineSecurityGroupName = "docker-machine"
|
||||
defaultZone = "a"
|
||||
defaultSecurityGroup = machineSecurityGroupName
|
||||
defaultSSHUser = "ubuntu"
|
||||
defaultSpotPrice = "0.50"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -65,7 +70,6 @@ type Driver struct {
|
|||
|
||||
func init() {
|
||||
drivers.Register(driverName, &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -75,19 +79,16 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "amazonec2-access-key",
|
||||
Usage: "AWS Access Key",
|
||||
Value: "",
|
||||
EnvVar: "AWS_ACCESS_KEY_ID",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "amazonec2-secret-key",
|
||||
Usage: "AWS Secret Key",
|
||||
Value: "",
|
||||
EnvVar: "AWS_SECRET_ACCESS_KEY",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "amazonec2-session-token",
|
||||
Usage: "AWS Session Token",
|
||||
Value: "",
|
||||
EnvVar: "AWS_SESSION_TOKEN",
|
||||
},
|
||||
cli.StringFlag{
|
||||
|
@ -104,25 +105,23 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "amazonec2-vpc-id",
|
||||
Usage: "AWS VPC id",
|
||||
Value: "",
|
||||
EnvVar: "AWS_VPC_ID",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "amazonec2-zone",
|
||||
Usage: "AWS zone for instance (i.e. a,b,c,d,e)",
|
||||
Value: "a",
|
||||
Value: defaultZone,
|
||||
EnvVar: "AWS_ZONE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "amazonec2-subnet-id",
|
||||
Usage: "AWS VPC subnet id",
|
||||
Value: "",
|
||||
EnvVar: "AWS_SUBNET_ID",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "amazonec2-security-group",
|
||||
Usage: "AWS VPC security group",
|
||||
Value: "docker-machine",
|
||||
Value: defaultSecurityGroup,
|
||||
EnvVar: "AWS_SECURITY_GROUP",
|
||||
},
|
||||
cli.StringFlag{
|
||||
|
@ -145,7 +144,7 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "amazonec2-ssh-user",
|
||||
Usage: "set the name of the ssh user",
|
||||
Value: "ubuntu",
|
||||
Value: defaultSSHUser,
|
||||
EnvVar: "AWS_SSH_USER",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
|
@ -155,7 +154,7 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "amazonec2-spot-price",
|
||||
Usage: "AWS spot instance bid price (in dollar)",
|
||||
Value: "0.50",
|
||||
Value: defaultSpotPrice,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "amazonec2-private-address-only",
|
||||
|
@ -172,13 +171,23 @@ func GetCreateFlags() []cli.Flag {
|
|||
}
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
func NewDriver(hostName, storePath string) drivers.Driver {
|
||||
id := generateId()
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{
|
||||
Id: id,
|
||||
BaseDriver: inner,
|
||||
}, nil
|
||||
Id: id,
|
||||
AMI: defaultAmiId,
|
||||
Region: defaultRegion,
|
||||
InstanceType: defaultInstanceType,
|
||||
RootSize: defaultRootSize,
|
||||
Zone: defaultZone,
|
||||
SecurityGroupName: defaultSecurityGroup,
|
||||
SpotPrice: defaultSpotPrice,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
SSHUser: defaultSSHUser,
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
|
||||
|
@ -372,7 +381,7 @@ func (d *Driver) Create() error {
|
|||
d.InstanceId = instance.InstanceId
|
||||
|
||||
log.Debug("waiting for ip address to become available")
|
||||
if err := utils.WaitFor(d.instanceIpAvailable); err != nil {
|
||||
if err := mcnutils.WaitFor(d.instanceIpAvailable); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -536,7 +545,7 @@ func (d *Driver) instanceIsRunning() bool {
|
|||
}
|
||||
|
||||
func (d *Driver) waitForInstance() error {
|
||||
if err := utils.WaitFor(d.instanceIsRunning); err != nil {
|
||||
if err := mcnutils.WaitFor(d.instanceIsRunning); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -622,7 +631,7 @@ func (d *Driver) configureSecurityGroup(groupName string) error {
|
|||
securityGroup = group
|
||||
// wait until created (dat eventual consistency)
|
||||
log.Debugf("waiting for group (%s) to become available", group.GroupId)
|
||||
if err := utils.WaitFor(d.securityGroupAvailableFunc(group.GroupId)); err != nil {
|
||||
if err := mcnutils.WaitFor(d.securityGroupAvailableFunc(group.GroupId)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,10 +98,7 @@ func getTestDriver() (*Driver, error) {
|
|||
}
|
||||
defer cleanup()
|
||||
|
||||
d, err := NewDriver(machineTestName, storePath, machineTestCaCert, machineTestPrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d := NewDriver(machineTestName, storePath)
|
||||
d.SetConfigFromFlags(getDefaultTestDriverFlags())
|
||||
drv := d.(*Driver)
|
||||
return drv, nil
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -9,8 +9,8 @@ import (
|
|||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
awsauth "github.com/smartystreets/go-aws-auth"
|
||||
)
|
||||
|
||||
|
@ -151,7 +151,7 @@ func NewEC2(auth Auth, region string) *EC2 {
|
|||
func (e *EC2) awsApiCall(v url.Values) (*http.Response, error) {
|
||||
v.Set("Version", "2014-06-15")
|
||||
log.Debug("Making AWS API call with values:")
|
||||
utils.DumpVal(v)
|
||||
mcnutils.DumpVal(v)
|
||||
client := &http.Client{}
|
||||
finalEndpoint := fmt.Sprintf("%s?%s", e.Endpoint, v.Encode())
|
||||
req, err := http.NewRequest("GET", finalEndpoint, nil)
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -1 +0,0 @@
|
|||
package amz
|
|
@ -11,11 +11,11 @@ import (
|
|||
"github.com/MSOpenTech/azure-sdk-for-go/clients/vmClient"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
|
@ -31,9 +31,17 @@ type Driver struct {
|
|||
DockerSwarmMasterPort int
|
||||
}
|
||||
|
||||
const (
|
||||
defaultDockerPort = 2376
|
||||
defaultSwarmMasterPort = 3376
|
||||
defaultLocation = "West US"
|
||||
defaultSize = "Small"
|
||||
defaultSSHPort = 22
|
||||
defaultSSHUsername = "ubuntu"
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("azure", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -45,12 +53,12 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.IntFlag{
|
||||
Name: "azure-docker-port",
|
||||
Usage: "Azure Docker port",
|
||||
Value: 2376,
|
||||
Value: defaultDockerPort,
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "azure-docker-swarm-master-port",
|
||||
Usage: "Azure Docker Swarm master port",
|
||||
Value: 3376,
|
||||
Value: defaultSwarmMasterPort,
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "AZURE_IMAGE",
|
||||
|
@ -61,7 +69,7 @@ func GetCreateFlags() []cli.Flag {
|
|||
EnvVar: "AZURE_LOCATION",
|
||||
Name: "azure-location",
|
||||
Usage: "Azure location",
|
||||
Value: "West US",
|
||||
Value: defaultLocation,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "azure-password",
|
||||
|
@ -76,12 +84,12 @@ func GetCreateFlags() []cli.Flag {
|
|||
EnvVar: "AZURE_SIZE",
|
||||
Name: "azure-size",
|
||||
Usage: "Azure size",
|
||||
Value: "Small",
|
||||
Value: defaultSize,
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "azure-ssh-port",
|
||||
Usage: "Azure SSH port",
|
||||
Value: 22,
|
||||
Value: defaultSSHPort,
|
||||
},
|
||||
|
||||
cli.StringFlag{
|
||||
|
@ -97,15 +105,25 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "azure-username",
|
||||
Usage: "Azure username",
|
||||
Value: "ubuntu",
|
||||
Value: defaultSSHUsername,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
d := &Driver{BaseDriver: inner}
|
||||
return d, nil
|
||||
func NewDriver(hostName, storePath string) drivers.Driver {
|
||||
d := &Driver{
|
||||
DockerPort: defaultDockerPort,
|
||||
DockerSwarmMasterPort: defaultSwarmMasterPort,
|
||||
Location: defaultLocation,
|
||||
Size: defaultSize,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
SSHPort: defaultSSHPort,
|
||||
SSHUser: defaultSSHUsername,
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
|
@ -368,7 +386,7 @@ func (d *Driver) Kill() error {
|
|||
}
|
||||
|
||||
func generateVMName() string {
|
||||
randomID := utils.TruncateID(utils.GenerateRandomID())
|
||||
randomID := mcnutils.TruncateID(mcnutils.GenerateRandomID())
|
||||
return fmt.Sprintf("docker-host-%s", randomID)
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package azure
|
|
@ -8,10 +8,10 @@ import (
|
|||
"code.google.com/p/goauth2/oauth"
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/digitalocean/godo"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
|
@ -28,9 +28,14 @@ type Driver struct {
|
|||
PrivateNetworking bool
|
||||
}
|
||||
|
||||
const (
|
||||
defaultImage = "ubuntu-14-04-x64"
|
||||
defaultRegion = "nyc3"
|
||||
defaultSize = "512mb"
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("digitalocean", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -54,19 +59,19 @@ func GetCreateFlags() []cli.Flag {
|
|||
EnvVar: "DIGITALOCEAN_IMAGE",
|
||||
Name: "digitalocean-image",
|
||||
Usage: "Digital Ocean Image",
|
||||
Value: "ubuntu-14-04-x64",
|
||||
Value: defaultImage,
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "DIGITALOCEAN_REGION",
|
||||
Name: "digitalocean-region",
|
||||
Usage: "Digital Ocean region",
|
||||
Value: "nyc3",
|
||||
Value: defaultRegion,
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "DIGITALOCEAN_SIZE",
|
||||
Name: "digitalocean-size",
|
||||
Usage: "Digital Ocean size",
|
||||
Value: "512mb",
|
||||
Value: defaultSize,
|
||||
},
|
||||
cli.BoolFlag{
|
||||
EnvVar: "DIGITALOCEAN_IPV6",
|
||||
|
@ -86,9 +91,16 @@ func GetCreateFlags() []cli.Flag {
|
|||
}
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{BaseDriver: inner}, nil
|
||||
func NewDriver(hostName, storePath string) *Driver {
|
||||
return &Driver{
|
||||
Image: defaultImage,
|
||||
Size: defaultSize,
|
||||
Region: defaultRegion,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package digitalocean
|
|
@ -0,0 +1,65 @@
|
|||
package driverfactory
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/machine/drivers/amazonec2"
|
||||
"github.com/docker/machine/drivers/azure"
|
||||
"github.com/docker/machine/drivers/digitalocean"
|
||||
"github.com/docker/machine/drivers/exoscale"
|
||||
"github.com/docker/machine/drivers/generic"
|
||||
"github.com/docker/machine/drivers/google"
|
||||
"github.com/docker/machine/drivers/hyperv"
|
||||
"github.com/docker/machine/drivers/none"
|
||||
"github.com/docker/machine/drivers/openstack"
|
||||
"github.com/docker/machine/drivers/rackspace"
|
||||
"github.com/docker/machine/drivers/softlayer"
|
||||
"github.com/docker/machine/drivers/virtualbox"
|
||||
"github.com/docker/machine/drivers/vmwarefusion"
|
||||
"github.com/docker/machine/drivers/vmwarevcloudair"
|
||||
"github.com/docker/machine/drivers/vmwarevsphere"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
)
|
||||
|
||||
func NewDriver(driverName, hostName, storePath string) (drivers.Driver, error) {
|
||||
var (
|
||||
driver drivers.Driver
|
||||
)
|
||||
|
||||
switch driverName {
|
||||
case "virtualbox":
|
||||
driver = virtualbox.NewDriver(hostName, storePath)
|
||||
case "digitalocean":
|
||||
driver = digitalocean.NewDriver(hostName, storePath)
|
||||
case "amazonec2":
|
||||
driver = amazonec2.NewDriver(hostName, storePath)
|
||||
case "azure":
|
||||
driver = azure.NewDriver(hostName, storePath)
|
||||
case "exoscale":
|
||||
driver = exoscale.NewDriver(hostName, storePath)
|
||||
case "generic":
|
||||
driver = generic.NewDriver(hostName, storePath)
|
||||
case "google":
|
||||
driver = google.NewDriver(hostName, storePath)
|
||||
case "hyperv":
|
||||
driver = hyperv.NewDriver(hostName, storePath)
|
||||
case "openstack":
|
||||
driver = openstack.NewDriver(hostName, storePath)
|
||||
case "rackspace":
|
||||
driver = rackspace.NewDriver(hostName, storePath)
|
||||
case "softlayer":
|
||||
driver = softlayer.NewDriver(hostName, storePath)
|
||||
case "vmwarefusion":
|
||||
driver = vmwarefusion.NewDriver(hostName, storePath)
|
||||
case "vmwarevcloudair":
|
||||
driver = vmwarevcloudair.NewDriver(hostName, storePath)
|
||||
case "vmwarevsphere":
|
||||
driver = vmwarevsphere.NewDriver(hostName, storePath)
|
||||
case "none":
|
||||
driver = none.NewDriver(hostName, storePath)
|
||||
default:
|
||||
return nil, fmt.Errorf("Driver %q not recognized", driverName)
|
||||
}
|
||||
|
||||
return driver, nil
|
||||
}
|
|
@ -9,10 +9,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/pyr/egoscale/src/egoscale"
|
||||
)
|
||||
|
||||
|
@ -31,9 +31,15 @@ type Driver struct {
|
|||
Id string
|
||||
}
|
||||
|
||||
const (
|
||||
defaultInstanceProfile = "small"
|
||||
defaultDiskSize = 50
|
||||
defaultImage = "ubuntu-14.04"
|
||||
defaultAvailabilityZone = "ch-gva-2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("exoscale", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -60,19 +66,19 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
EnvVar: "EXOSCALE_INSTANCE_PROFILE",
|
||||
Name: "exoscale-instance-profile",
|
||||
Value: "small",
|
||||
Value: defaultInstanceProfile,
|
||||
Usage: "exoscale instance profile (small, medium, large, ...)",
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "EXOSCALE_DISK_SIZE",
|
||||
Name: "exoscale-disk-size",
|
||||
Value: 50,
|
||||
Value: defaultDiskSize,
|
||||
Usage: "exoscale disk size (10, 50, 100, 200, 400)",
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "EXSOCALE_IMAGE",
|
||||
Name: "exoscale-image",
|
||||
Value: "ubuntu-14.04",
|
||||
Value: defaultImage,
|
||||
Usage: "exoscale image template",
|
||||
},
|
||||
cli.StringSliceFlag{
|
||||
|
@ -84,15 +90,23 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
EnvVar: "EXOSCALE_AVAILABILITY_ZONE",
|
||||
Name: "exoscale-availability-zone",
|
||||
Value: "ch-gva-2",
|
||||
Value: defaultAvailabilityZone,
|
||||
Usage: "exoscale availibility zone",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{BaseDriver: inner}, nil
|
||||
func NewDriver(hostName, storePath string) drivers.Driver {
|
||||
return &Driver{
|
||||
InstanceProfile: defaultInstanceProfile,
|
||||
DiskSize: defaultDiskSize,
|
||||
Image: defaultImage,
|
||||
AvailabilityZone: defaultAvailabilityZone,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
|
@ -426,7 +440,7 @@ func (d *Driver) jobIsDone(client *egoscale.Client, jobid string) (bool, error)
|
|||
|
||||
func (d *Driver) waitForJob(client *egoscale.Client, jobid string) error {
|
||||
log.Infof("Waiting for job to complete...")
|
||||
return utils.WaitForSpecificOrError(func() (bool, error) {
|
||||
return mcnutils.WaitForSpecificOrError(func() (bool, error) {
|
||||
return d.jobIsDone(client, jobid)
|
||||
}, 60, 2*time.Second)
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package exoscale
|
|
@ -1,8 +1,8 @@
|
|||
package fakedriver
|
||||
|
||||
import (
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
type FakeDriver struct {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package fakedriver
|
|
@ -8,10 +8,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
|
@ -20,12 +20,17 @@ type Driver struct {
|
|||
}
|
||||
|
||||
const (
|
||||
defaultSSHUser = "root"
|
||||
defaultSSHPort = 22
|
||||
defaultTimeout = 1 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
defaultSSHKey = filepath.Join(mcnutils.GetHomeDir(), ".ssh", "id_rsa")
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("generic", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -37,29 +42,35 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "generic-ip-address",
|
||||
Usage: "IP Address of machine",
|
||||
Value: "",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "generic-ssh-user",
|
||||
Usage: "SSH user",
|
||||
Value: "root",
|
||||
Value: defaultSSHUser,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "generic-ssh-key",
|
||||
Usage: "SSH private key path",
|
||||
Value: filepath.Join(utils.GetHomeDir(), ".ssh", "id_rsa"),
|
||||
Value: defaultSSHKey,
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "generic-ssh-port",
|
||||
Usage: "SSH port",
|
||||
Value: 22,
|
||||
Value: defaultSSHPort,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{BaseDriver: inner}, nil
|
||||
func NewDriver(hostName, storePath string) drivers.Driver {
|
||||
return &Driver{
|
||||
SSHKey: defaultSSHKey,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
SSHUser: defaultSSHUser,
|
||||
SSHPort: defaultSSHPort,
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) DriverName() string {
|
||||
|
@ -98,7 +109,7 @@ func (d *Driver) PreCreateCheck() error {
|
|||
func (d *Driver) Create() error {
|
||||
log.Infof("Importing SSH key...")
|
||||
|
||||
if err := utils.CopyFile(d.SSHKey, d.GetSSHKeyPath()); err != nil {
|
||||
if err := mcnutils.CopyFile(d.SSHKey, d.GetSSHKeyPath()); err != nil {
|
||||
return fmt.Errorf("unable to copy ssh key: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package generic
|
|
@ -12,7 +12,7 @@ import (
|
|||
"time"
|
||||
|
||||
"code.google.com/p/goauth2/oauth"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
raw "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package google
|
|
@ -8,8 +8,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
raw "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package google
|
|
@ -5,10 +5,10 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
// Driver is a struct compatible with the docker.hosts.drivers.Driver interface.
|
||||
|
@ -26,9 +26,17 @@ type Driver struct {
|
|||
Tags []string
|
||||
}
|
||||
|
||||
const (
|
||||
defaultZone = "us-central1-a"
|
||||
defaultUser = "docker-user"
|
||||
defaultMachineType = "f1-micro"
|
||||
defaultScopes = "https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/logging.write"
|
||||
defaultDiskType = "pd-standard"
|
||||
defaultDiskSize = 10
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("google", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -40,19 +48,19 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "google-zone",
|
||||
Usage: "GCE Zone",
|
||||
Value: "us-central1-a",
|
||||
Value: defaultZone,
|
||||
EnvVar: "GOOGLE_ZONE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "google-machine-type",
|
||||
Usage: "GCE Machine Type",
|
||||
Value: "f1-micro",
|
||||
Value: defaultMachineType,
|
||||
EnvVar: "GOOGLE_MACHINE_TYPE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "google-username",
|
||||
Usage: "GCE User Name",
|
||||
Value: "docker-user",
|
||||
Value: defaultUser,
|
||||
EnvVar: "GOOGLE_USERNAME",
|
||||
},
|
||||
cli.StringFlag{
|
||||
|
@ -68,19 +76,19 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "google-scopes",
|
||||
Usage: "GCE Scopes (comma-separated if multiple scopes)",
|
||||
Value: "https://www.googleapis.com/auth/devstorage.read_only,https://www.googleapis.com/auth/logging.write",
|
||||
Value: defaultScopes,
|
||||
EnvVar: "GOOGLE_SCOPES",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "google-disk-size",
|
||||
Usage: "GCE Instance Disk Size (in GB)",
|
||||
Value: 10,
|
||||
Value: defaultDiskSize,
|
||||
EnvVar: "GOOGLE_DISK_SIZE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "google-disk-type",
|
||||
Usage: "GCE Instance Disk type",
|
||||
Value: "pd-standard",
|
||||
Value: defaultDiskType,
|
||||
EnvVar: "GOOGLE_DISK_TYPE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
|
@ -102,9 +110,19 @@ func GetCreateFlags() []cli.Flag {
|
|||
}
|
||||
|
||||
// NewDriver creates a Driver with the specified storePath.
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{BaseDriver: inner}, nil
|
||||
func NewDriver(machineName string, storePath string) *Driver {
|
||||
return &Driver{
|
||||
Zone: defaultZone,
|
||||
DiskType: defaultDiskType,
|
||||
DiskSize: defaultDiskSize,
|
||||
MachineType: defaultMachineType,
|
||||
Scopes: defaultScopes,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
SSHUser: defaultUser,
|
||||
MachineName: machineName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GetSSHHostname returns hostname for use with ssh
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package google
|
|
@ -1,2 +1,472 @@
|
|||
// this is empty to allow builds on non-windows platforms
|
||||
package hyperv
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
*drivers.BaseDriver
|
||||
boot2DockerURL string
|
||||
boot2DockerLoc string
|
||||
vSwitch string
|
||||
diskImage string
|
||||
DiskSize int
|
||||
MemSize int
|
||||
}
|
||||
|
||||
const (
|
||||
defaultDiskSize = 20000
|
||||
defaultMemory = 1024
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("hyper-v", &drivers.RegisteredDriver{
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
||||
func NewDriver(hostName, storePath string) drivers.Driver {
|
||||
return &Driver{
|
||||
DiskSize: defaultDiskSize,
|
||||
MemSize: defaultMemory,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// GetCreateFlags registers the flags this driver adds to
|
||||
// "docker hosts create"
|
||||
func GetCreateFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "hyper-v-boot2docker-url",
|
||||
Usage: "Hyper-V URL of the boot2docker image. Defaults to the latest available version.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "hyper-v-boot2docker-location",
|
||||
Usage: "Hyper-V local boot2docker iso. Overrides URL.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "hyper-v-virtual-switch",
|
||||
Usage: "Hyper-V virtual switch name. Defaults to first found.",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "hyper-v-disk-size",
|
||||
Usage: "Hyper-V disk size for host in MB.",
|
||||
Value: defaultDiskSize,
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "hyper-v-memory",
|
||||
Usage: "Hyper-V memory size for host in MB.",
|
||||
Value: defaultMemory,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
|
||||
d.boot2DockerURL = flags.String("hyper-v-boot2docker-url")
|
||||
d.boot2DockerLoc = flags.String("hyper-v-boot2docker-location")
|
||||
d.vSwitch = flags.String("hyper-v-virtual-switch")
|
||||
d.DiskSize = flags.Int("hyper-v-disk-size")
|
||||
d.MemSize = flags.Int("hyper-v-memory")
|
||||
d.SwarmMaster = flags.Bool("swarm-master")
|
||||
d.SwarmHost = flags.String("swarm-host")
|
||||
d.SwarmDiscovery = flags.String("swarm-discovery")
|
||||
d.SSHUser = "docker"
|
||||
d.SSHPort = 22
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
return d.GetIP()
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHUsername() string {
|
||||
if d.SSHUser == "" {
|
||||
d.SSHUser = "docker"
|
||||
}
|
||||
|
||||
return d.SSHUser
|
||||
}
|
||||
|
||||
func (d *Driver) DriverName() string {
|
||||
return "hyper-v"
|
||||
}
|
||||
|
||||
func (d *Driver) PreCreateCheck() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetURL() (string, error) {
|
||||
ip, err := d.GetIP()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ip == "" {
|
||||
return "", nil
|
||||
}
|
||||
return fmt.Sprintf("tcp://%s:2376", ip), nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetState() (state.State, error) {
|
||||
|
||||
command := []string{
|
||||
"(",
|
||||
"Get-VM",
|
||||
"-Name", d.MachineName,
|
||||
").state"}
|
||||
stdout, err := execute(command)
|
||||
if err != nil {
|
||||
return state.None, fmt.Errorf("Failed to find the VM status")
|
||||
}
|
||||
resp := parseStdout(stdout)
|
||||
|
||||
if len(resp) < 1 {
|
||||
return state.None, nil
|
||||
}
|
||||
switch resp[0] {
|
||||
case "Running":
|
||||
return state.Running, nil
|
||||
case "Off":
|
||||
return state.Stopped, nil
|
||||
}
|
||||
return state.None, nil
|
||||
}
|
||||
|
||||
func (d *Driver) Create() error {
|
||||
err := hypervAvailable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.setMachineNameIfNotSet()
|
||||
|
||||
b2dutils := mcnutils.NewB2dUtils("", "", d.StorePath)
|
||||
if err := b2dutils.CopyIsoToMachineDir(d.boot2DockerURL, d.MachineName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Creating SSH key...")
|
||||
|
||||
if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Creating VM...")
|
||||
|
||||
virtualSwitch, err := d.chooseVirtualSwitch()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = d.generateDiskImage()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
command := []string{
|
||||
"New-VM",
|
||||
"-Name", d.MachineName,
|
||||
"-Path", fmt.Sprintf("'%s'", d.ResolveStorePath(".")),
|
||||
"-MemoryStartupBytes", fmt.Sprintf("%dMB", d.MemSize)}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
command = []string{
|
||||
"Set-VMDvdDrive",
|
||||
"-VMName", d.MachineName,
|
||||
"-Path", fmt.Sprintf("'%s'", d.ResolveStorePath("boot2docker.iso"))}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
command = []string{
|
||||
"Add-VMHardDiskDrive",
|
||||
"-VMName", d.MachineName,
|
||||
"-Path", fmt.Sprintf("'%s'", d.diskImage)}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
command = []string{
|
||||
"Connect-VMNetworkAdapter",
|
||||
"-VMName", d.MachineName,
|
||||
"-SwitchName", fmt.Sprintf("'%s'", virtualSwitch)}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Starting VM...")
|
||||
if err := d.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) chooseVirtualSwitch() (string, error) {
|
||||
if d.vSwitch != "" {
|
||||
return d.vSwitch, nil
|
||||
}
|
||||
command := []string{
|
||||
"@(Get-VMSwitch).Name"}
|
||||
stdout, err := execute(command)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
switches := parseStdout(stdout)
|
||||
if len(switches) > 0 {
|
||||
log.Infof("Using switch %s", switches[0])
|
||||
return switches[0], nil
|
||||
}
|
||||
return "", fmt.Errorf("no vswitch found")
|
||||
}
|
||||
|
||||
func (d *Driver) wait() error {
|
||||
log.Infof("Waiting for host to start...")
|
||||
for {
|
||||
ip, _ := d.GetIP()
|
||||
if ip != "" {
|
||||
break
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) Start() error {
|
||||
command := []string{
|
||||
"Start-VM",
|
||||
"-Name", d.MachineName}
|
||||
_, err := execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.wait(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.IPAddress, err = d.GetIP()
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Driver) Stop() error {
|
||||
command := []string{
|
||||
"Stop-VM",
|
||||
"-Name", d.MachineName}
|
||||
_, err := execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
s, err := d.GetState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s == state.Running {
|
||||
time.Sleep(1 * time.Second)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
d.IPAddress = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) Remove() error {
|
||||
s, err := d.GetState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s == state.Running {
|
||||
if err := d.Kill(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
command := []string{
|
||||
"Remove-VM",
|
||||
"-Name", d.MachineName,
|
||||
"-Force"}
|
||||
_, err = execute(command)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Driver) Restart() error {
|
||||
err := d.Stop()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return d.Start()
|
||||
}
|
||||
|
||||
func (d *Driver) Kill() error {
|
||||
command := []string{
|
||||
"Stop-VM",
|
||||
"-Name", d.MachineName,
|
||||
"-TurnOff"}
|
||||
_, err := execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
s, err := d.GetState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s == state.Running {
|
||||
time.Sleep(1 * time.Second)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
d.IPAddress = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) setMachineNameIfNotSet() {
|
||||
if d.MachineName == "" {
|
||||
d.MachineName = fmt.Sprintf("docker-machine-unknown")
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) GetIP() (string, error) {
|
||||
command := []string{
|
||||
"((",
|
||||
"Get-VM",
|
||||
"-Name", d.MachineName,
|
||||
").networkadapters[0]).ipaddresses[0]"}
|
||||
stdout, err := execute(command)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
resp := parseStdout(stdout)
|
||||
if len(resp) < 1 {
|
||||
return "", fmt.Errorf("IP not found")
|
||||
}
|
||||
return resp[0], nil
|
||||
}
|
||||
|
||||
func (d *Driver) publicSSHKeyPath() string {
|
||||
return d.GetSSHKeyPath() + ".pub"
|
||||
}
|
||||
|
||||
func (d *Driver) generateDiskImage() error {
|
||||
// Create a small fixed vhd, put the tar in,
|
||||
// convert to dynamic, then resize
|
||||
|
||||
d.diskImage = d.ResolveStorePath("disk.vhd")
|
||||
fixed := d.ResolveStorePath("fixed.vhd")
|
||||
log.Infof("Creating VHD")
|
||||
command := []string{
|
||||
"New-VHD",
|
||||
"-Path", fmt.Sprintf("'%s'", fixed),
|
||||
"-SizeBytes", "10MB",
|
||||
"-Fixed"}
|
||||
_, err := execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tarBuf, err := d.generateTar()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(fixed, os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
file.Seek(0, os.SEEK_SET)
|
||||
_, err = file.Write(tarBuf.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file.Close()
|
||||
|
||||
command = []string{
|
||||
"Convert-VHD",
|
||||
"-Path", fmt.Sprintf("'%s'", fixed),
|
||||
"-DestinationPath", fmt.Sprintf("'%s'", d.diskImage),
|
||||
"-VHDType", "Dynamic"}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
command = []string{
|
||||
"Resize-VHD",
|
||||
"-Path", fmt.Sprintf("'%s'", d.diskImage),
|
||||
"-SizeBytes", fmt.Sprintf("%dMB", d.DiskSize)}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Make a boot2docker VM disk image.
|
||||
// See https://github.com/boot2docker/boot2docker/blob/master/rootfs/rootfs/etc/rc.d/automount
|
||||
func (d *Driver) generateTar() (*bytes.Buffer, error) {
|
||||
magicString := "boot2docker, please format-me"
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
tw := tar.NewWriter(buf)
|
||||
|
||||
// magicString first so the automount script knows to format the disk
|
||||
file := &tar.Header{Name: magicString, Size: int64(len(magicString))}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := tw.Write([]byte(magicString)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// .ssh/key.pub => authorized_keys
|
||||
file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := tw.Write([]byte(pubKey)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := tw.Write([]byte(pubKey)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := tw.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package hyperv
|
|
@ -1,509 +0,0 @@
|
|||
package hyperv
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/utils"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
*drivers.BaseDriver
|
||||
boot2DockerURL string
|
||||
boot2DockerLoc string
|
||||
vSwitch string
|
||||
diskImage string
|
||||
diskSize int
|
||||
memSize int
|
||||
}
|
||||
|
||||
func init() {
|
||||
drivers.Register("hyper-v", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
||||
// GetCreateFlags registers the flags this driver adds to
|
||||
// "docker hosts create"
|
||||
func GetCreateFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "hyper-v-boot2docker-url",
|
||||
Usage: "Hyper-V URL of the boot2docker image. Defaults to the latest available version.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "hyper-v-boot2docker-location",
|
||||
Usage: "Hyper-V local boot2docker iso. Overrides URL.",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "hyper-v-virtual-switch",
|
||||
Usage: "Hyper-V virtual switch name. Defaults to first found.",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "hyper-v-disk-size",
|
||||
Usage: "Hyper-V disk size for host in MB.",
|
||||
Value: 20000,
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "hyper-v-memory",
|
||||
Usage: "Hyper-V memory size for host in MB.",
|
||||
Value: 1024,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
|
||||
d.boot2DockerURL = flags.String("hyper-v-boot2docker-url")
|
||||
d.boot2DockerLoc = flags.String("hyper-v-boot2docker-location")
|
||||
d.vSwitch = flags.String("hyper-v-virtual-switch")
|
||||
d.diskSize = flags.Int("hyper-v-disk-size")
|
||||
d.memSize = flags.Int("hyper-v-memory")
|
||||
d.SwarmMaster = flags.Bool("swarm-master")
|
||||
d.SwarmHost = flags.String("swarm-host")
|
||||
d.SwarmDiscovery = flags.String("swarm-discovery")
|
||||
d.SSHUser = "docker"
|
||||
d.SSHPort = 22
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{BaseDriver: inner}, nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
return d.GetIP()
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHUsername() string {
|
||||
if d.SSHUser == "" {
|
||||
d.SSHUser = "docker"
|
||||
}
|
||||
|
||||
return d.SSHUser
|
||||
}
|
||||
|
||||
func (d *Driver) DriverName() string {
|
||||
return "hyper-v"
|
||||
}
|
||||
|
||||
func (d *Driver) PreCreateCheck() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetURL() (string, error) {
|
||||
ip, err := d.GetIP()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ip == "" {
|
||||
return "", nil
|
||||
}
|
||||
return fmt.Sprintf("tcp://%s:2376", ip), nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetState() (state.State, error) {
|
||||
|
||||
command := []string{
|
||||
"(",
|
||||
"Get-VM",
|
||||
"-Name", d.MachineName,
|
||||
").state"}
|
||||
stdout, err := execute(command)
|
||||
if err != nil {
|
||||
return state.None, fmt.Errorf("Failed to find the VM status")
|
||||
}
|
||||
resp := parseStdout(stdout)
|
||||
|
||||
if len(resp) < 1 {
|
||||
return state.None, nil
|
||||
}
|
||||
switch resp[0] {
|
||||
case "Running":
|
||||
return state.Running, nil
|
||||
case "Off":
|
||||
return state.Stopped, nil
|
||||
}
|
||||
return state.None, nil
|
||||
}
|
||||
|
||||
func (d *Driver) Create() error {
|
||||
err := hypervAvailable()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.setMachineNameIfNotSet()
|
||||
|
||||
var isoURL string
|
||||
|
||||
b2dutils := utils.NewB2dUtils("", "")
|
||||
|
||||
if d.boot2DockerLoc == "" {
|
||||
if d.boot2DockerURL != "" {
|
||||
isoURL = d.boot2DockerURL
|
||||
log.Infof("Downloading boot2docker.iso from %s...", isoURL)
|
||||
if err := b2dutils.DownloadISO(d.ResolveStorePath("."), "boot2docker.iso", isoURL); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// todo: check latest release URL, download if it's new
|
||||
// until then always use "latest"
|
||||
isoURL, err = b2dutils.GetLatestBoot2DockerReleaseURL()
|
||||
if err != nil {
|
||||
log.Warnf("Unable to check for the latest release: %s", err)
|
||||
|
||||
}
|
||||
// todo: use real constant for .docker
|
||||
rootPath := filepath.Join(utils.GetDockerDir())
|
||||
imgPath := filepath.Join(rootPath, "images")
|
||||
commonIsoPath := filepath.Join(imgPath, "boot2docker.iso")
|
||||
if _, err := os.Stat(commonIsoPath); os.IsNotExist(err) {
|
||||
log.Infof("Downloading boot2docker.iso to %s...", commonIsoPath)
|
||||
// just in case boot2docker.iso has been manually deleted
|
||||
if _, err := os.Stat(imgPath); os.IsNotExist(err) {
|
||||
if err := os.Mkdir(imgPath, 0700); err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if err := b2dutils.DownloadISO(imgPath, "boot2docker.iso", isoURL); err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
isoDest := d.ResolveStorePath("boot2docker.iso")
|
||||
if err := utils.CopyFile(commonIsoPath, isoDest); err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := utils.CopyFile(d.boot2DockerLoc, d.ResolveStorePath("boot2docker.iso")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("Creating SSH key...")
|
||||
|
||||
if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Creating VM...")
|
||||
|
||||
virtualSwitch, err := d.chooseVirtualSwitch()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = d.generateDiskImage()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
command := []string{
|
||||
"New-VM",
|
||||
"-Name", d.MachineName,
|
||||
"-Path", fmt.Sprintf("'%s'", d.ResolveStorePath(".")),
|
||||
"-MemoryStartupBytes", fmt.Sprintf("%dMB", d.memSize)}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
command = []string{
|
||||
"Set-VMDvdDrive",
|
||||
"-VMName", d.MachineName,
|
||||
"-Path", fmt.Sprintf("'%s'", d.ResolveStorePath("boot2docker.iso"))}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
command = []string{
|
||||
"Add-VMHardDiskDrive",
|
||||
"-VMName", d.MachineName,
|
||||
"-Path", fmt.Sprintf("'%s'", d.diskImage)}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
command = []string{
|
||||
"Connect-VMNetworkAdapter",
|
||||
"-VMName", d.MachineName,
|
||||
"-SwitchName", fmt.Sprintf("'%s'", virtualSwitch)}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Starting VM...")
|
||||
if err := d.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) chooseVirtualSwitch() (string, error) {
|
||||
if d.vSwitch != "" {
|
||||
return d.vSwitch, nil
|
||||
}
|
||||
command := []string{
|
||||
"@(Get-VMSwitch).Name"}
|
||||
stdout, err := execute(command)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
switches := parseStdout(stdout)
|
||||
if len(switches) > 0 {
|
||||
log.Infof("Using switch %s", switches[0])
|
||||
return switches[0], nil
|
||||
}
|
||||
return "", fmt.Errorf("no vswitch found")
|
||||
}
|
||||
|
||||
func (d *Driver) wait() error {
|
||||
log.Infof("Waiting for host to start...")
|
||||
for {
|
||||
ip, _ := d.GetIP()
|
||||
if ip != "" {
|
||||
break
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) Start() error {
|
||||
command := []string{
|
||||
"Start-VM",
|
||||
"-Name", d.MachineName}
|
||||
_, err := execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.wait(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.IPAddress, err = d.GetIP()
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Driver) Stop() error {
|
||||
command := []string{
|
||||
"Stop-VM",
|
||||
"-Name", d.MachineName}
|
||||
_, err := execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
s, err := d.GetState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s == state.Running {
|
||||
time.Sleep(1 * time.Second)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
d.IPAddress = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) Remove() error {
|
||||
s, err := d.GetState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s == state.Running {
|
||||
if err := d.Kill(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
command := []string{
|
||||
"Remove-VM",
|
||||
"-Name", d.MachineName,
|
||||
"-Force"}
|
||||
_, err = execute(command)
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *Driver) Restart() error {
|
||||
err := d.Stop()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return d.Start()
|
||||
}
|
||||
|
||||
func (d *Driver) Kill() error {
|
||||
command := []string{
|
||||
"Stop-VM",
|
||||
"-Name", d.MachineName,
|
||||
"-TurnOff"}
|
||||
_, err := execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for {
|
||||
s, err := d.GetState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if s == state.Running {
|
||||
time.Sleep(1 * time.Second)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
d.IPAddress = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Driver) setMachineNameIfNotSet() {
|
||||
if d.MachineName == "" {
|
||||
d.MachineName = fmt.Sprintf("docker-machine-unknown")
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) GetIP() (string, error) {
|
||||
command := []string{
|
||||
"((",
|
||||
"Get-VM",
|
||||
"-Name", d.MachineName,
|
||||
").networkadapters[0]).ipaddresses[0]"}
|
||||
stdout, err := execute(command)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
resp := parseStdout(stdout)
|
||||
if len(resp) < 1 {
|
||||
return "", fmt.Errorf("IP not found")
|
||||
}
|
||||
return resp[0], nil
|
||||
}
|
||||
|
||||
func (d *Driver) publicSSHKeyPath() string {
|
||||
return d.GetSSHKeyPath() + ".pub"
|
||||
}
|
||||
|
||||
func (d *Driver) generateDiskImage() error {
|
||||
// Create a small fixed vhd, put the tar in,
|
||||
// convert to dynamic, then resize
|
||||
|
||||
d.diskImage = d.ResolveStorePath("disk.vhd")
|
||||
fixed := d.ResolveStorePath("fixed.vhd")
|
||||
log.Infof("Creating VHD")
|
||||
command := []string{
|
||||
"New-VHD",
|
||||
"-Path", fmt.Sprintf("'%s'", fixed),
|
||||
"-SizeBytes", "10MB",
|
||||
"-Fixed"}
|
||||
_, err := execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tarBuf, err := d.generateTar()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, err := os.OpenFile(fixed, os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
file.Seek(0, os.SEEK_SET)
|
||||
_, err = file.Write(tarBuf.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file.Close()
|
||||
|
||||
command = []string{
|
||||
"Convert-VHD",
|
||||
"-Path", fmt.Sprintf("'%s'", fixed),
|
||||
"-DestinationPath", fmt.Sprintf("'%s'", d.diskImage),
|
||||
"-VHDType", "Dynamic"}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
command = []string{
|
||||
"Resize-VHD",
|
||||
"-Path", fmt.Sprintf("'%s'", d.diskImage),
|
||||
"-SizeBytes", fmt.Sprintf("%dMB", d.diskSize)}
|
||||
_, err = execute(command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Make a boot2docker VM disk image.
|
||||
// See https://github.com/boot2docker/boot2docker/blob/master/rootfs/rootfs/etc/rc.d/automount
|
||||
func (d *Driver) generateTar() (*bytes.Buffer, error) {
|
||||
magicString := "boot2docker, please format-me"
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
tw := tar.NewWriter(buf)
|
||||
|
||||
// magicString first so the automount script knows to format the disk
|
||||
file := &tar.Header{Name: magicString, Size: int64(len(magicString))}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := tw.Write([]byte(magicString)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// .ssh/key.pub => authorized_keys
|
||||
file = &tar.Header{Name: ".ssh", Typeflag: tar.TypeDir, Mode: 0700}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pubKey, err := ioutil.ReadFile(d.publicSSHKeyPath())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file = &tar.Header{Name: ".ssh/authorized_keys", Size: int64(len(pubKey)), Mode: 0644}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := tw.Write([]byte(pubKey)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
file = &tar.Header{Name: ".ssh/authorized_keys2", Size: int64(len(pubKey)), Mode: 0644}
|
||||
if err := tw.WriteHeader(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := tw.Write([]byte(pubKey)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := tw.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf, nil
|
||||
}
|
|
@ -9,7 +9,7 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
)
|
||||
|
||||
var powershell string
|
|
@ -5,8 +5,8 @@ import (
|
|||
neturl "net/url"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
// Driver is the driver used when no driver is selected. It is used to
|
||||
|
@ -19,7 +19,6 @@ type Driver struct {
|
|||
|
||||
func init() {
|
||||
drivers.Register("none", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -34,9 +33,13 @@ func GetCreateFlags() []cli.Flag {
|
|||
}
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{inner, ""}, nil
|
||||
func NewDriver(hostName, storePath string) *Driver {
|
||||
return &Driver{
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) Create() error {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package none
|
|
@ -6,9 +6,9 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/version"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/version"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/openstack"
|
||||
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
|
||||
|
@ -136,7 +136,7 @@ func (c *GenericClient) DeleteInstance(d *Driver) error {
|
|||
}
|
||||
|
||||
func (c *GenericClient) WaitForInstanceStatus(d *Driver, status string) error {
|
||||
return utils.WaitForSpecificOrError(func() (bool, error) {
|
||||
return mcnutils.WaitForSpecificOrError(func() (bool, error) {
|
||||
current, err := servers.Get(c.Compute, d.MachineId).Extract()
|
||||
if err != nil {
|
||||
return true, err
|
||||
|
@ -437,7 +437,7 @@ func (c *GenericClient) Authenticate(d *Driver) error {
|
|||
return err
|
||||
}
|
||||
|
||||
provider.UserAgent.Prepend(fmt.Sprintf("docker-machine/v%s", version.Version))
|
||||
provider.UserAgent.Prepend(fmt.Sprintf("docker-machine/v%d", version.ApiVersion))
|
||||
|
||||
if d.Insecure {
|
||||
// Configure custom TLS settings.
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package openstack
|
|
@ -7,11 +7,11 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
|
@ -42,9 +42,14 @@ type Driver struct {
|
|||
client Client
|
||||
}
|
||||
|
||||
const (
|
||||
defaultSSHUser = "root"
|
||||
defaultSSHPort = 22
|
||||
defaultActiveTimeout = 200
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("openstack", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -158,35 +163,36 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "openstack-ssh-user",
|
||||
Usage: "OpenStack SSH user",
|
||||
Value: "root",
|
||||
Value: defaultSSHUser,
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "openstack-ssh-port",
|
||||
Usage: "OpenStack SSH port",
|
||||
Value: 22,
|
||||
Value: defaultSSHPort,
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "openstack-active-timeout",
|
||||
Usage: "OpenStack active timeout",
|
||||
Value: 200,
|
||||
Value: defaultActiveTimeout,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
log.WithFields(log.Fields{
|
||||
"machineName": machineName,
|
||||
"storePath": storePath,
|
||||
"caCert": caCert,
|
||||
"privateKey": privateKey,
|
||||
}).Debug("Instantiating OpenStack driver...")
|
||||
|
||||
return NewDerivedDriver(machineName, storePath, &GenericClient{}, caCert, privateKey)
|
||||
func NewDriver(hostName, storePath string) drivers.Driver {
|
||||
return NewDerivedDriver(hostName, storePath)
|
||||
}
|
||||
|
||||
func NewDerivedDriver(machineName string, storePath string, client Client, caCert string, privateKey string) (*Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{BaseDriver: inner, client: client}, nil
|
||||
func NewDerivedDriver(hostName, storePath string) *Driver {
|
||||
return &Driver{
|
||||
client: &GenericClient{},
|
||||
ActiveTimeout: defaultActiveTimeout,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
SSHUser: defaultSSHUser,
|
||||
SSHPort: defaultSSHPort,
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
|
@ -310,7 +316,7 @@ func (d *Driver) PreCreateCheck() error {
|
|||
}
|
||||
|
||||
func (d *Driver) Create() error {
|
||||
d.KeyPairName = fmt.Sprintf("%s-%s", d.MachineName, utils.GenerateRandomID())
|
||||
d.KeyPairName = fmt.Sprintf("%s-%s", d.MachineName, mcnutils.GenerateRandomID())
|
||||
|
||||
if err := d.resolveIds(); err != nil {
|
||||
return err
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package openstack
|
|
@ -4,8 +4,8 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/docker/machine/drivers/openstack"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/version"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/version"
|
||||
"github.com/rackspace/gophercloud"
|
||||
"github.com/rackspace/gophercloud/rackspace"
|
||||
)
|
||||
|
@ -17,7 +17,6 @@ func unsupportedOpErr(operation string) error {
|
|||
// Client is a Rackspace specialization of the generic OpenStack driver.
|
||||
type Client struct {
|
||||
openstack.GenericClient
|
||||
|
||||
driver *Driver
|
||||
}
|
||||
|
||||
|
@ -42,7 +41,7 @@ func (c *Client) Authenticate(d *openstack.Driver) error {
|
|||
return err
|
||||
}
|
||||
|
||||
provider.UserAgent.Prepend(fmt.Sprintf("docker-machine/v%s", version.Version))
|
||||
provider.UserAgent.Prepend(fmt.Sprintf("docker-machine/v%d", version.ApiVersion))
|
||||
|
||||
err = rackspace.Authenticate(provider, opts)
|
||||
if err != nil {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package rackspace
|
|
@ -4,9 +4,9 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/drivers/openstack"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
)
|
||||
|
||||
// Driver is a machine driver for Rackspace. It's a specialization of the generic OpenStack one.
|
||||
|
@ -16,9 +16,16 @@ type Driver struct {
|
|||
APIKey string
|
||||
}
|
||||
|
||||
const (
|
||||
defaultEndpointType = "publicURL"
|
||||
defaultFlavorId = "general1-1"
|
||||
defaultSSHUser = "root"
|
||||
defaultSSHPort = 22
|
||||
defaultDockerInstall = "true"
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("rackspace", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -49,7 +56,7 @@ func GetCreateFlags() []cli.Flag {
|
|||
EnvVar: "OS_ENDPOINT_TYPE",
|
||||
Name: "rackspace-endpoint-type",
|
||||
Usage: "Rackspace endpoint type (adminURL, internalURL or the default publicURL)",
|
||||
Value: "publicURL",
|
||||
Value: defaultEndpointType,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "rackspace-image-id",
|
||||
|
@ -58,45 +65,38 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "rackspace-flavor-id",
|
||||
Usage: "Rackspace flavor ID. Default: General Purpose 1GB",
|
||||
Value: "general1-1",
|
||||
Value: defaultFlavorId,
|
||||
EnvVar: "OS_FLAVOR_ID",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "rackspace-ssh-user",
|
||||
Usage: "SSH user for the newly booted machine. Set to root by default",
|
||||
Value: "root",
|
||||
Value: defaultSSHUser,
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "rackspace-ssh-port",
|
||||
Usage: "SSH port for the newly booted machine. Set to 22 by default",
|
||||
Value: 22,
|
||||
Value: defaultSSHPort,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "rackspace-docker-install",
|
||||
Usage: "Set if docker have to be installed on the machine",
|
||||
Value: "true",
|
||||
Value: defaultDockerInstall,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewDriver instantiates a Rackspace driver.
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
func NewDriver(machineName, storePath string) drivers.Driver {
|
||||
log.WithFields(log.Fields{
|
||||
"machineName": machineName,
|
||||
"storePath": storePath,
|
||||
"caCert": caCert,
|
||||
"privateKey": privateKey,
|
||||
}).Debug("Instantiating Rackspace driver.")
|
||||
|
||||
client := &Client{}
|
||||
inner, err := openstack.NewDerivedDriver(machineName, storePath, client, caCert, privateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inner := openstack.NewDerivedDriver(machineName, storePath)
|
||||
|
||||
driver := &Driver{Driver: inner}
|
||||
client.driver = driver
|
||||
return driver, nil
|
||||
return &Driver{
|
||||
Driver: inner,
|
||||
}
|
||||
}
|
||||
|
||||
// DriverName is the user-visible name of this driver.
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package rackspace
|
|
@ -8,10 +8,10 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -41,16 +41,42 @@ type deviceConfig struct {
|
|||
PrivateVLAN int
|
||||
}
|
||||
|
||||
const (
|
||||
defaultMemory = 1024
|
||||
defaultDiskSize = 0
|
||||
defaultRegion = "dal01"
|
||||
defaultCpus = 1
|
||||
defaultImage = "UBUNTU_LATEST"
|
||||
defaultPublicVLANIP = 0
|
||||
defaultPrivateVLANIP = 0
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("softlayer", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{BaseDriver: inner}, nil
|
||||
func NewDriver(hostName, storePath string) drivers.Driver {
|
||||
return &Driver{
|
||||
Client: &Client{
|
||||
Endpoint: ApiEndpoint,
|
||||
},
|
||||
deviceConfig: &deviceConfig{
|
||||
HourlyBilling: true,
|
||||
DiskSize: defaultDiskSize,
|
||||
Image: defaultImage,
|
||||
Memory: defaultMemory,
|
||||
Cpu: defaultCpus,
|
||||
Region: defaultRegion,
|
||||
PrivateVLAN: defaultPrivateVLANIP,
|
||||
PublicVLAN: defaultPublicVLANIP,
|
||||
},
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
|
@ -67,49 +93,45 @@ func GetCreateFlags() []cli.Flag {
|
|||
EnvVar: "SOFTLAYER_MEMORY",
|
||||
Name: "softlayer-memory",
|
||||
Usage: "Memory in MB for machine",
|
||||
Value: 1024,
|
||||
Value: defaultMemory,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "SOFTLAYER_DISK_SIZE",
|
||||
Name: "softlayer-disk-size",
|
||||
Usage: "Disk size for machine, a value of 0 uses the default size on softlayer",
|
||||
Value: 0,
|
||||
Value: defaultDiskSize,
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "SOFTLAYER_USER",
|
||||
Name: "softlayer-user",
|
||||
Usage: "softlayer user account name",
|
||||
Value: "",
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "SOFTLAYER_API_KEY",
|
||||
Name: "softlayer-api-key",
|
||||
Usage: "softlayer user API key",
|
||||
Value: "",
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "SOFTLAYER_REGION",
|
||||
Name: "softlayer-region",
|
||||
Usage: "softlayer region for machine",
|
||||
Value: "dal01",
|
||||
Value: defaultRegion,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "SOFTLAYER_CPU",
|
||||
Name: "softlayer-cpu",
|
||||
Usage: "number of CPU's for the machine",
|
||||
Value: 1,
|
||||
Value: defaultCpus,
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "SOFTLAYER_HOSTNAME",
|
||||
Name: "softlayer-hostname",
|
||||
Usage: "hostname for the machine - defaults to machine name",
|
||||
Value: "",
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "SOFTLAYER_DOMAIN",
|
||||
Name: "softlayer-domain",
|
||||
Usage: "domain name for machine",
|
||||
Value: "",
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "SOFTLAYER_API_ENDPOINT",
|
||||
|
@ -136,19 +158,17 @@ func GetCreateFlags() []cli.Flag {
|
|||
EnvVar: "SOFTLAYER_IMAGE",
|
||||
Name: "softlayer-image",
|
||||
Usage: "OS image for machine",
|
||||
Value: "UBUNTU_LATEST",
|
||||
Value: defaultImage,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "SOFTLAYER_PUBLIC_VLAN_ID",
|
||||
Name: "softlayer-public-vlan-id",
|
||||
Usage: "",
|
||||
Value: 0,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "SOFTLAYER_PRIVATE_VLAN_ID",
|
||||
Name: "softlayer-private-vlan-id",
|
||||
Usage: "",
|
||||
Value: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,10 +80,7 @@ func getTestDriver() (*Driver, error) {
|
|||
}
|
||||
defer cleanup()
|
||||
|
||||
d, err := NewDriver(machineTestName, storePath, machineTestCaCert, machineTestPrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
d := NewDriver(machineTestName, storePath)
|
||||
d.SetConfigFromFlags(getDefaultTestDriverFlags())
|
||||
drv := d.(*Driver)
|
||||
return drv, nil
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package softlayer
|
|
@ -11,7 +11,7 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -68,15 +68,17 @@ func vbmOut(args ...string) (string, error) {
|
|||
|
||||
func vbmOutErr(args ...string) (string, string, error) {
|
||||
cmd := exec.Command(vboxManageCmd, args...)
|
||||
log.Debugf("executing: %v %v", vboxManageCmd, strings.Join(args, " "))
|
||||
log.Debugf("COMMAND: %v %v", vboxManageCmd, strings.Join(args, " "))
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
err := cmd.Run()
|
||||
stderrStr := stderr.String()
|
||||
log.Debugf("STDOUT: %v", stdout.String())
|
||||
log.Debugf("STDERR: %v", stderrStr)
|
||||
if len(args) > 0 {
|
||||
log.Debugf("STDOUT:\n{\n%v}", stdout.String())
|
||||
log.Debugf("STDERR:\n{\n%v}", stderrStr)
|
||||
}
|
||||
if err != nil {
|
||||
if ee, ok := err.(*exec.Error); ok && ee == exec.ErrNotFound {
|
||||
err = ErrVBMNotFound
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package virtualbox
|
|
@ -19,18 +19,24 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
const (
|
||||
isoFilename = "boot2docker.iso"
|
||||
defaultHostOnlyCIDR = "192.168.99.1/24"
|
||||
defaultNictype = "82540EM"
|
||||
defaultNicpromisc = "deny"
|
||||
isoFilename = "boot2docker.iso"
|
||||
defaultCPU = 1
|
||||
defaultMemory = 1024
|
||||
defaultBoot2DockerURL = ""
|
||||
defaultBoot2DockerImportVM = ""
|
||||
defaultHostOnlyCIDR = "192.168.99.1/24"
|
||||
defaultHostOnlyNictype = "82540EM"
|
||||
defaultHostOnlyPromiscMode = "deny"
|
||||
defaultNoShare = false
|
||||
defaultDiskSize = 20000
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -52,11 +58,25 @@ type Driver struct {
|
|||
|
||||
func init() {
|
||||
drivers.Register("virtualbox", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
||||
func NewDriver(hostName, storePath string) *Driver {
|
||||
return &Driver{
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
Memory: defaultMemory,
|
||||
CPU: defaultCPU,
|
||||
DiskSize: defaultDiskSize,
|
||||
HostOnlyCIDR: defaultHostOnlyCIDR,
|
||||
HostOnlyNicType: defaultHostOnlyNictype,
|
||||
HostOnlyPromiscMode: defaultHostOnlyPromiscMode,
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterCreateFlags registers the flags this driver adds to
|
||||
// "docker hosts create"
|
||||
func GetCreateFlags() []cli.Flag {
|
||||
|
@ -65,30 +85,30 @@ func GetCreateFlags() []cli.Flag {
|
|||
EnvVar: "VIRTUALBOX_MEMORY_SIZE",
|
||||
Name: "virtualbox-memory",
|
||||
Usage: "Size of memory for host in MB",
|
||||
Value: 1024,
|
||||
Value: defaultMemory,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "VIRTUALBOX_CPU_COUNT",
|
||||
Name: "virtualbox-cpu-count",
|
||||
Usage: "number of CPUs for the machine (-1 to use the number of CPUs available)",
|
||||
Value: 1,
|
||||
Value: defaultCPU,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "VIRTUALBOX_DISK_SIZE",
|
||||
Name: "virtualbox-disk-size",
|
||||
Usage: "Size of disk for host in MB",
|
||||
Value: 20000,
|
||||
Value: defaultDiskSize,
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "VIRTUALBOX_BOOT2DOCKER_URL",
|
||||
Name: "virtualbox-boot2docker-url",
|
||||
Usage: "The URL of the boot2docker image. Defaults to the latest available version",
|
||||
Value: "",
|
||||
Value: defaultBoot2DockerURL,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "virtualbox-import-boot2docker-vm",
|
||||
Usage: "The name of a Boot2Docker VM to import",
|
||||
Value: "",
|
||||
Value: defaultBoot2DockerImportVM,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "virtualbox-hostonly-cidr",
|
||||
|
@ -99,13 +119,13 @@ func GetCreateFlags() []cli.Flag {
|
|||
cli.StringFlag{
|
||||
Name: "virtualbox-hostonly-nictype",
|
||||
Usage: "Specify the Host Only Network Adapter Type",
|
||||
Value: defaultNictype,
|
||||
Value: defaultHostOnlyNictype,
|
||||
EnvVar: "VIRTUALBOX_HOSTONLY_NIC_TYPE",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "virtualbox-hostonly-nicpromisc",
|
||||
Usage: "Specify the Host Only Network Adapter Promiscuous Mode",
|
||||
Value: defaultNicpromisc,
|
||||
Value: defaultHostOnlyPromiscMode,
|
||||
EnvVar: "VIRTUALBOX_HOSTONLY_NIC_PROMISC",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
|
@ -115,11 +135,6 @@ func GetCreateFlags() []cli.Flag {
|
|||
}
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{BaseDriver: inner}, nil
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
return "localhost", nil
|
||||
}
|
||||
|
@ -179,7 +194,7 @@ func (d *Driver) Create() error {
|
|||
return err
|
||||
}
|
||||
|
||||
b2dutils := utils.NewB2dUtils("", "")
|
||||
b2dutils := mcnutils.NewB2dUtils("", "", d.StorePath)
|
||||
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -216,8 +231,8 @@ func (d *Driver) Create() error {
|
|||
d.Memory = vmInfo.Memory
|
||||
|
||||
log.Debugf("Importing SSH key...")
|
||||
keyPath := filepath.Join(utils.GetHomeDir(), ".ssh", "id_boot2docker")
|
||||
if err := utils.CopyFile(keyPath, d.GetSSHKeyPath()); err != nil {
|
||||
keyPath := filepath.Join(mcnutils.GetHomeDir(), ".ssh", "id_boot2docker")
|
||||
if err := mcnutils.CopyFile(keyPath, d.GetSSHKeyPath()); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
@ -416,7 +431,7 @@ func (d *Driver) Start() error {
|
|||
}
|
||||
|
||||
// Bail if we don't get an IP from DHCP after a given number of seconds.
|
||||
if err := utils.WaitForSpecific(d.hostOnlyIpAvailable, 5, 4*time.Second); err != nil {
|
||||
if err := mcnutils.WaitForSpecific(d.hostOnlyIpAvailable, 5, 4*time.Second); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -510,12 +525,6 @@ func (d *Driver) GetState() (state.State, error) {
|
|||
return state.None, nil
|
||||
}
|
||||
|
||||
func (d *Driver) setMachineNameIfNotSet() {
|
||||
if d.MachineName == "" {
|
||||
d.MachineName = fmt.Sprintf("docker-machine-unknown")
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) GetIP() (string, error) {
|
||||
// DHCP is used to get the IP, so virtualbox hosts don't have IPs unless
|
||||
// they are running
|
||||
|
|
|
@ -18,11 +18,11 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
cryptossh "golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
|
@ -48,9 +48,16 @@ type Driver struct {
|
|||
ConfigDriveURL string
|
||||
}
|
||||
|
||||
const (
|
||||
defaultSSHUser = B2DUser
|
||||
defaultSSHPass = B2DPass
|
||||
defaultDiskSize = 20000
|
||||
defaultCpus = 1
|
||||
defaultMemory = 1024
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("vmwarefusion", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -73,38 +80,47 @@ func GetCreateFlags() []cli.Flag {
|
|||
EnvVar: "FUSION_CPU_COUNT",
|
||||
Name: "vmwarefusion-cpu-count",
|
||||
Usage: "number of CPUs for the machine (-1 to use the number of CPUs available)",
|
||||
Value: 1,
|
||||
Value: defaultCpus,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "FUSION_MEMORY_SIZE",
|
||||
Name: "vmwarefusion-memory-size",
|
||||
Usage: "Fusion size of memory for host VM (in MB)",
|
||||
Value: 1024,
|
||||
Value: defaultMemory,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "FUSION_DISK_SIZE",
|
||||
Name: "vmwarefusion-disk-size",
|
||||
Usage: "Fusion size of disk for host VM (in MB)",
|
||||
Value: 20000,
|
||||
Value: defaultDiskSize,
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "FUSION_SSH_USER",
|
||||
Name: "vmwarefusion-ssh-user",
|
||||
Usage: "SSH user",
|
||||
Value: B2DUser,
|
||||
Value: defaultSSHUser,
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "FUSION_SSH_PASSWORD",
|
||||
Name: "vmwarefusion-ssh-password",
|
||||
Usage: "SSH password",
|
||||
Value: B2DPass,
|
||||
Value: defaultSSHPass,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{BaseDriver: inner}, nil
|
||||
func NewDriver(hostName, storePath string) drivers.Driver {
|
||||
return &Driver{
|
||||
CPUS: defaultCpus,
|
||||
Memory: defaultMemory,
|
||||
DiskSize: defaultDiskSize,
|
||||
SSHPassword: defaultSSHPass,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
SSHUser: defaultSSHUser,
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
|
@ -129,7 +145,6 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
|
|||
d.DiskSize = flags.Int("vmwarefusion-disk-size")
|
||||
d.Boot2DockerURL = flags.String("vmwarefusion-boot2docker-url")
|
||||
d.ConfigDriveURL = flags.String("vmwarefusion-configdrive-url")
|
||||
d.ConfigDriveISO = d.ResolveStorePath(isoConfigDrive)
|
||||
d.ISO = d.ResolveStorePath(isoFilename)
|
||||
d.SwarmMaster = flags.Bool("swarm-master")
|
||||
d.SwarmHost = flags.String("swarm-host")
|
||||
|
@ -191,8 +206,7 @@ func (d *Driver) PreCreateCheck() error {
|
|||
}
|
||||
|
||||
func (d *Driver) Create() error {
|
||||
|
||||
b2dutils := utils.NewB2dUtils("", "")
|
||||
b2dutils := mcnutils.NewB2dUtils("", "", d.StorePath)
|
||||
if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
|
||||
return err
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
package vmwarefusion
|
|
@ -8,11 +8,12 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/docker/machine/log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
)
|
||||
|
||||
var (
|
|
@ -1 +0,0 @@
|
|||
package vmwarefusion
|
|
@ -1,2 +0,0 @@
|
|||
// Package vmwarefusion is empty to allow builds on non-darwin platforms
|
||||
package vmwarefusion
|
|
@ -1 +0,0 @@
|
|||
package vmwarefusion
|
|
@ -12,11 +12,11 @@ import (
|
|||
"github.com/vmware/govcloudair"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/machine/drivers"
|
||||
"github.com/docker/machine/log"
|
||||
"github.com/docker/machine/ssh"
|
||||
"github.com/docker/machine/state"
|
||||
"github.com/docker/machine/utils"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
|
@ -37,9 +37,17 @@ type Driver struct {
|
|||
VAppID string
|
||||
}
|
||||
|
||||
const (
|
||||
defaultCatalog = "Public Catalog"
|
||||
defaultCatalogItem = "Ubuntu Server 12.04 LTS (amd64 20150127)"
|
||||
defaultCpus = 1
|
||||
defaultMemory = 2048
|
||||
defaultSSHPort = 22
|
||||
defaultDockerPort = 2376
|
||||
)
|
||||
|
||||
func init() {
|
||||
drivers.Register("vmwarevcloudair", &drivers.RegisteredDriver{
|
||||
New: NewDriver,
|
||||
GetCreateFlags: GetCreateFlags,
|
||||
})
|
||||
}
|
||||
|
@ -87,13 +95,13 @@ func GetCreateFlags() []cli.Flag {
|
|||
EnvVar: "VCLOUDAIR_CATALOG",
|
||||
Name: "vmwarevcloudair-catalog",
|
||||
Usage: "vCloud Air Catalog (default is Public Catalog)",
|
||||
Value: "Public Catalog",
|
||||
Value: defaultCatalog,
|
||||
},
|
||||
cli.StringFlag{
|
||||
EnvVar: "VCLOUDAIR_CATALOGITEM",
|
||||
Name: "vmwarevcloudair-catalogitem",
|
||||
Usage: "vCloud Air Catalog Item (default is Ubuntu Precise)",
|
||||
Value: "Ubuntu Server 12.04 LTS (amd64 20150127)",
|
||||
Value: defaultCatalogItem,
|
||||
},
|
||||
|
||||
// BoolTFlag is true by default.
|
||||
|
@ -107,32 +115,42 @@ func GetCreateFlags() []cli.Flag {
|
|||
EnvVar: "VCLOUDAIR_CPU_COUNT",
|
||||
Name: "vmwarevcloudair-cpu-count",
|
||||
Usage: "vCloud Air VM Cpu Count (default 1)",
|
||||
Value: 1,
|
||||
Value: defaultCpus,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "VCLOUDAIR_MEMORY_SIZE",
|
||||
Name: "vmwarevcloudair-memory-size",
|
||||
Usage: "vCloud Air VM Memory Size in MB (default 2048)",
|
||||
Value: 2048,
|
||||
Value: defaultMemory,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "VCLOUDAIR_SSH_PORT",
|
||||
Name: "vmwarevcloudair-ssh-port",
|
||||
Usage: "vCloud Air SSH port",
|
||||
Value: 22,
|
||||
Value: defaultSSHPort,
|
||||
},
|
||||
cli.IntFlag{
|
||||
EnvVar: "VCLOUDAIR_DOCKER_PORT",
|
||||
Name: "vmwarevcloudair-docker-port",
|
||||
Usage: "vCloud Air Docker port",
|
||||
Value: 2376,
|
||||
Value: defaultDockerPort,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
||||
inner := drivers.NewBaseDriver(machineName, storePath, caCert, privateKey)
|
||||
return &Driver{BaseDriver: inner}, nil
|
||||
func NewDriver(hostName, storePath string) drivers.Driver {
|
||||
return &Driver{
|
||||
Catalog: defaultCatalog,
|
||||
CatalogItem: defaultCatalogItem,
|
||||
CPUCount: defaultCpus,
|
||||
MemorySize: defaultMemory,
|
||||
DockerPort: defaultDockerPort,
|
||||
BaseDriver: &drivers.BaseDriver{
|
||||
SSHPort: defaultSSHPort,
|
||||
MachineName: hostName,
|
||||
StorePath: storePath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Driver) GetSSHHostname() (string, error) {
|
||||
|
@ -645,7 +663,7 @@ func (d *Driver) Kill() error {
|
|||
// Helpers
|
||||
|
||||
func generateVMName() string {
|
||||
randomID := utils.TruncateID(utils.GenerateRandomID())
|
||||
randomID := mcnutils.TruncateID(mcnutils.GenerateRandomID())
|
||||
return fmt.Sprintf("docker-host-%s", randomID)
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue