From a3e114737b30ea846a1c333ffd20610bb146e8dd Mon Sep 17 00:00:00 2001 From: Evan Hazlett Date: Wed, 21 Jan 2015 22:32:37 -0500 Subject: [PATCH] fixes #282: use port from driver URL when configuring engine Signed-off-by: Evan Hazlett --- host.go | 93 ++++++++++++++++++++++++++++++++++++---------------- host_test.go | 81 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 28 deletions(-) diff --git a/host.go b/host.go index 2475cabca0..8e7e1d6bb4 100644 --- a/host.go +++ b/host.go @@ -6,9 +6,12 @@ import ( "fmt" "io/ioutil" "net" + "net/url" "os" "path/filepath" "regexp" + "strconv" + "strings" "time" log "github.com/Sirupsen/logrus" @@ -34,6 +37,11 @@ type Host struct { storePath string } +type DockerConfig struct { + EngineConfig string + EngineConfigPath string +} + type hostConfig struct { DriverName string } @@ -220,35 +228,27 @@ func (h *Host) ConfigureAuth() error { return err } - var ( - daemonOpts string - daemonOptsCfg string - daemonCfg string - ) - - // TODO @ehazlett: template? - defaultDaemonOpts := fmt.Sprintf(`--tlsverify \ ---tlscacert=%s \ ---tlskey=%s \ ---tlscert=%s`, machineCaCertPath, machineServerKeyPath, machineServerCertPath) - - switch d.DriverName() { - case "virtualbox", "vmwarefusion", "vmwarevsphere": - daemonOpts = "-H tcp://0.0.0.0:2376" - daemonOptsCfg = filepath.Join(d.GetDockerConfigDir(), "profile") - opts := fmt.Sprintf("%s %s", defaultDaemonOpts, daemonOpts) - daemonCfg = fmt.Sprintf(`EXTRA_ARGS='%s' -CACERT=%s -SERVERCERT=%s -SERVERKEY=%s -DOCKER_TLS=no`, opts, machineCaCertPath, machineServerCertPath, machineServerKeyPath) - default: - daemonOpts = "--host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:2376" - daemonOptsCfg = "/etc/default/docker" - opts := fmt.Sprintf("%s %s", defaultDaemonOpts, daemonOpts) - daemonCfg = fmt.Sprintf("export DOCKER_OPTS='%s'", opts) + dockerUrl, err := h.Driver.GetURL() + if err != nil { + return err } - cmd, err = d.GetSSHCommand(fmt.Sprintf("echo \"%s\" | sudo tee -a %s", daemonCfg, daemonOptsCfg)) + u, err := url.Parse(dockerUrl) + if err != nil { + return err + } + dockerPort := 2376 + parts := strings.Split(u.Host, ":") + if len(parts) == 2 { + dPort, err := strconv.Atoi(parts[1]) + if err != nil { + return err + } + dockerPort = dPort + } + + cfg := h.generateDockerConfig(dockerPort, machineCaCertPath, machineServerKeyPath, machineServerCertPath) + + cmd, err = d.GetSSHCommand(fmt.Sprintf("echo \"%s\" | sudo tee -a %s", cfg.EngineConfig, cfg.EngineConfigPath)) if err != nil { return err } @@ -263,6 +263,43 @@ DOCKER_TLS=no`, opts, machineCaCertPath, machineServerCertPath, machineServerKey return nil } +func (h *Host) generateDockerConfig(dockerPort int, caCertPath string, serverKeyPath string, serverCertPath string) *DockerConfig { + d := h.Driver + var ( + daemonOpts string + daemonOptsCfg string + daemonCfg string + ) + + // TODO @ehazlett: template? + defaultDaemonOpts := fmt.Sprintf(`--tlsverify \ +--tlscacert=%s \ +--tlskey=%s \ +--tlscert=%s`, caCertPath, serverKeyPath, serverCertPath) + + switch d.DriverName() { + case "virtualbox", "vmwarefusion", "vmwarevsphere": + daemonOpts = fmt.Sprintf("-H tcp://0.0.0.0:%d", dockerPort) + daemonOptsCfg = filepath.Join(d.GetDockerConfigDir(), "profile") + opts := fmt.Sprintf("%s %s", defaultDaemonOpts, daemonOpts) + daemonCfg = fmt.Sprintf(`EXTRA_ARGS='%s' +CACERT=%s +SERVERCERT=%s +SERVERKEY=%s +DOCKER_TLS=no`, opts, caCertPath, serverKeyPath, serverCertPath) + default: + daemonOpts = fmt.Sprintf("--host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:%d", dockerPort) + daemonOptsCfg = "/etc/default/docker" + opts := fmt.Sprintf("%s %s", defaultDaemonOpts, daemonOpts) + daemonCfg = fmt.Sprintf("export DOCKER_OPTS='%s'", opts) + } + + return &DockerConfig{ + EngineConfig: daemonCfg, + EngineConfigPath: daemonOptsCfg, + } +} + func (h *Host) Create(name string) error { name, err := ValidateHostName(name) if err != nil { diff --git a/host_test.go b/host_test.go index c08d24c2e0..bc3baf7eb0 100644 --- a/host_test.go +++ b/host_test.go @@ -1,7 +1,12 @@ package main import ( + "fmt" + "regexp" + "strings" "testing" + + _ "github.com/docker/machine/drivers/none" ) func TestValidateHostnameValid(t *testing.T) { @@ -37,3 +42,79 @@ func TestValidateHostnameInvalid(t *testing.T) { } } } + +func TestMachinePort(t *testing.T) { + dockerPort := 2376 + bindUrl := fmt.Sprintf("tcp://0.0.0.0:%d", dockerPort) + flags := &DriverOptionsMock{ + Data: map[string]interface{}{ + "url": bindUrl, + }, + } + + store := NewStore("", "", "") + + _, err := store.Create("test", "none", flags) + if err != nil { + t.Fatal(err) + } + + host, err := store.Load("test") + cfg := host.generateDockerConfig(dockerPort, "", "", "") + + re := regexp.MustCompile("--host=tcp://.*:(.+)") + m := re.FindStringSubmatch(cfg.EngineConfig) + if len(m) == 0 { + t.Errorf("could not find port %d in engine config", dockerPort) + } + + b := m[0] + u := strings.Split(b, "=") + url := u[1] + url = strings.Replace(url, "'", "", -1) + if url != bindUrl { + t.Errorf("expected url %s; received %s", bindUrl, url) + } + + if err := store.Remove("test", true); err != nil { + t.Fatal(err) + } +} + +func TestMachineCustomPort(t *testing.T) { + dockerPort := 3376 + bindUrl := fmt.Sprintf("tcp://0.0.0.0:%d", dockerPort) + flags := &DriverOptionsMock{ + Data: map[string]interface{}{ + "url": bindUrl, + }, + } + + store := NewStore("", "", "") + + _, err := store.Create("test", "none", flags) + if err != nil { + t.Fatal(err) + } + + host, err := store.Load("test") + cfg := host.generateDockerConfig(dockerPort, "", "", "") + + re := regexp.MustCompile("--host=tcp://.*:(.+)") + m := re.FindStringSubmatch(cfg.EngineConfig) + if len(m) == 0 { + t.Errorf("could not find port %d in engine config", dockerPort) + } + + b := m[0] + u := strings.Split(b, "=") + url := u[1] + url = strings.Replace(url, "'", "", -1) + if url != bindUrl { + t.Errorf("expected url %s; received %s", bindUrl, url) + } + + if err := store.Remove("test", true); err != nil { + t.Fatal(err) + } +}