- 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>
186 lines
4.7 KiB
Go
186 lines
4.7 KiB
Go
package provision
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/url"
|
|
"path"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/docker/machine/libmachine/auth"
|
|
"github.com/docker/machine/libmachine/cert"
|
|
"github.com/docker/machine/libmachine/log"
|
|
"github.com/docker/machine/libmachine/mcnutils"
|
|
"github.com/docker/machine/libmachine/provision/serviceaction"
|
|
)
|
|
|
|
type DockerOptions struct {
|
|
EngineOptions string
|
|
EngineOptionsPath string
|
|
}
|
|
|
|
func installDockerGeneric(p Provisioner, baseURL string) error {
|
|
// install docker - until cloudinit we use ubuntu everywhere so we
|
|
// just install it using the docker repos
|
|
if output, err := p.SSHCommand(fmt.Sprintf("if ! type docker; then curl -sSL %s | sh -; fi", baseURL)); err != nil {
|
|
return fmt.Errorf("error installing docker: %s\n", output)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func makeDockerOptionsDir(p Provisioner) error {
|
|
dockerDir := p.GetDockerOptionsDir()
|
|
if _, err := p.SSHCommand(fmt.Sprintf("sudo mkdir -p %s", dockerDir)); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func setRemoteAuthOptions(p Provisioner) auth.AuthOptions {
|
|
dockerDir := p.GetDockerOptionsDir()
|
|
authOptions := p.GetAuthOptions()
|
|
|
|
// due to windows clients, we cannot use filepath.Join as the paths
|
|
// will be mucked on the linux hosts
|
|
authOptions.CaCertRemotePath = path.Join(dockerDir, "ca.pem")
|
|
authOptions.ServerCertRemotePath = path.Join(dockerDir, "server.pem")
|
|
authOptions.ServerKeyRemotePath = path.Join(dockerDir, "server-key.pem")
|
|
|
|
return authOptions
|
|
}
|
|
|
|
func ConfigureAuth(p Provisioner) error {
|
|
var (
|
|
err error
|
|
)
|
|
|
|
machineName := p.GetDriver().GetMachineName()
|
|
authOptions := p.GetAuthOptions()
|
|
org := machineName
|
|
bits := 2048
|
|
|
|
ip, err := p.GetDriver().GetIP()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Info("Copying certs to the local machine directory...")
|
|
|
|
if err := mcnutils.CopyFile(authOptions.CaCertPath, filepath.Join(authOptions.StorePath, "ca.pem")); err != nil {
|
|
log.Fatalf("Error copying ca.pem to machine dir: %s", err)
|
|
}
|
|
|
|
if err := mcnutils.CopyFile(authOptions.ClientCertPath, filepath.Join(authOptions.StorePath, "cert.pem")); err != nil {
|
|
log.Fatalf("Error copying cert.pem to machine dir: %s", err)
|
|
}
|
|
|
|
if err := mcnutils.CopyFile(authOptions.ClientKeyPath, filepath.Join(authOptions.StorePath, "key.pem")); err != nil {
|
|
log.Fatalf("Error copying key.pem to machine dir: %s", err)
|
|
}
|
|
|
|
log.Debugf("generating server cert: %s ca-key=%s private-key=%s org=%s",
|
|
authOptions.ServerCertPath,
|
|
authOptions.CaCertPath,
|
|
authOptions.CaPrivateKeyPath,
|
|
org,
|
|
)
|
|
|
|
// TODO: Switch to passing just authOptions to this func
|
|
// instead of all these individual fields
|
|
err = cert.GenerateCert(
|
|
[]string{ip},
|
|
authOptions.ServerCertPath,
|
|
authOptions.ServerKeyPath,
|
|
authOptions.CaCertPath,
|
|
authOptions.CaPrivateKeyPath,
|
|
org,
|
|
bits,
|
|
)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("error generating server cert: %s", err)
|
|
}
|
|
|
|
if err := p.Service("docker", serviceaction.Stop); err != nil {
|
|
return err
|
|
}
|
|
|
|
// upload certs and configure TLS auth
|
|
caCert, err := ioutil.ReadFile(authOptions.CaCertPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
serverCert, err := ioutil.ReadFile(authOptions.ServerCertPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
serverKey, err := ioutil.ReadFile(authOptions.ServerKeyPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Info("Copying certs to the remote machine...")
|
|
|
|
// printf will choke if we don't pass a format string because of the
|
|
// dashes, so that's the reason for the '%%s'
|
|
certTransferCmdFmt := "printf '%%s' '%s' | sudo tee %s"
|
|
|
|
// These ones are for Jessie and Mike <3 <3 <3
|
|
if _, err := p.SSHCommand(fmt.Sprintf(certTransferCmdFmt, string(caCert), authOptions.CaCertRemotePath)); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := p.SSHCommand(fmt.Sprintf(certTransferCmdFmt, string(serverCert), authOptions.ServerCertRemotePath)); err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := p.SSHCommand(fmt.Sprintf(certTransferCmdFmt, string(serverKey), authOptions.ServerKeyRemotePath)); err != nil {
|
|
return err
|
|
}
|
|
|
|
dockerUrl, err := p.GetDriver().GetURL()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
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
|
|
}
|
|
|
|
dkrcfg, err := p.GenerateDockerOptions(dockerPort)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Info("Setting Docker configuration on the remote daemon...")
|
|
|
|
if _, err = p.SSHCommand(fmt.Sprintf("printf %%s \"%s\" | sudo tee %s", dkrcfg.EngineOptions, dkrcfg.EngineOptionsPath)); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := p.Service("docker", serviceaction.Start); err != nil {
|
|
return err
|
|
}
|
|
|
|
// TODO: Do not hardcode daemon port, ask the driver
|
|
if err := mcnutils.WaitForDocker(ip, dockerPort); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|