1package provision
2
3import (
4	"bytes"
5	"fmt"
6	"text/template"
7
8	"github.com/docker/machine/libmachine/auth"
9	"github.com/docker/machine/libmachine/drivers"
10	"github.com/docker/machine/libmachine/engine"
11	"github.com/docker/machine/libmachine/log"
12	"github.com/docker/machine/libmachine/provision/pkgaction"
13	"github.com/docker/machine/libmachine/swarm"
14	"github.com/docker/machine/libmachine/versioncmp"
15)
16
17const (
18	hostTmpl = `sudo tee /var/tmp/hostname.yml << EOF
19#cloud-config
20
21hostname: %s
22EOF
23`
24)
25
26func init() {
27	Register("CoreOS", &RegisteredProvisioner{
28		New: NewCoreOSProvisioner,
29	})
30}
31
32func NewCoreOSProvisioner(d drivers.Driver) Provisioner {
33	return &CoreOSProvisioner{
34		NewSystemdProvisioner("coreos", d),
35	}
36}
37
38type CoreOSProvisioner struct {
39	SystemdProvisioner
40}
41
42func (provisioner *CoreOSProvisioner) String() string {
43	return "coreOS"
44}
45
46func (provisioner *CoreOSProvisioner) SetHostname(hostname string) error {
47	log.Debugf("SetHostname: %s", hostname)
48
49	if _, err := provisioner.SSHCommand(fmt.Sprintf(hostTmpl, hostname)); err != nil {
50		return err
51	}
52
53	if _, err := provisioner.SSHCommand("sudo systemctl start system-cloudinit@var-tmp-hostname.yml.service"); err != nil {
54		return err
55	}
56
57	return nil
58}
59
60func (provisioner *CoreOSProvisioner) GenerateDockerOptions(dockerPort int) (*DockerOptions, error) {
61	var (
62		engineCfg bytes.Buffer
63	)
64
65	driverNameLabel := fmt.Sprintf("provider=%s", provisioner.Driver.DriverName())
66	provisioner.EngineOptions.Labels = append(provisioner.EngineOptions.Labels, driverNameLabel)
67
68	dockerVersion, err := DockerClientVersion(provisioner)
69	if err != nil {
70		return nil, err
71	}
72
73	arg := "daemon"
74	if versioncmp.GreaterThanOrEqualTo(dockerVersion, "1.12.0") {
75		arg = ""
76	}
77
78	engineConfigTmpl := `[Service]
79Environment=TMPDIR=/var/tmp
80ExecStart=
81ExecStart=/usr/lib/coreos/dockerd ` + arg + ` --host=unix:///var/run/docker.sock --host=tcp://0.0.0.0:{{.DockerPort}} --tlsverify --tlscacert {{.AuthOptions.CaCertRemotePath}} --tlscert {{.AuthOptions.ServerCertRemotePath}} --tlskey {{.AuthOptions.ServerKeyRemotePath}}{{ range .EngineOptions.Labels }} --label {{.}}{{ end }}{{ range .EngineOptions.InsecureRegistry }} --insecure-registry {{.}}{{ end }}{{ range .EngineOptions.RegistryMirror }} --registry-mirror {{.}}{{ end }}{{ range .EngineOptions.ArbitraryFlags }} --{{.}}{{ end }} \$DOCKER_OPTS \$DOCKER_OPT_BIP \$DOCKER_OPT_MTU \$DOCKER_OPT_IPMASQ
82Environment={{range .EngineOptions.Env}}{{ printf "%q" . }} {{end}}
83`
84
85	t, err := template.New("engineConfig").Parse(engineConfigTmpl)
86	if err != nil {
87		return nil, err
88	}
89
90	engineConfigContext := EngineConfigContext{
91		DockerPort:    dockerPort,
92		AuthOptions:   provisioner.AuthOptions,
93		EngineOptions: provisioner.EngineOptions,
94	}
95
96	t.Execute(&engineCfg, engineConfigContext)
97
98	return &DockerOptions{
99		EngineOptions:     engineCfg.String(),
100		EngineOptionsPath: provisioner.DaemonOptionsFile,
101	}, nil
102}
103
104func (provisioner *CoreOSProvisioner) Package(name string, action pkgaction.PackageAction) error {
105	return nil
106}
107
108func (provisioner *CoreOSProvisioner) Provision(swarmOptions swarm.Options, authOptions auth.Options, engineOptions engine.Options) error {
109	provisioner.SwarmOptions = swarmOptions
110	provisioner.AuthOptions = authOptions
111	provisioner.EngineOptions = engineOptions
112
113	if err := provisioner.SetHostname(provisioner.Driver.GetMachineName()); err != nil {
114		return err
115	}
116
117	if err := makeDockerOptionsDir(provisioner); err != nil {
118		return err
119	}
120
121	log.Debugf("Preparing certificates")
122	provisioner.AuthOptions = setRemoteAuthOptions(provisioner)
123
124	log.Debugf("Setting up certificates")
125	if err := ConfigureAuth(provisioner); err != nil {
126		return err
127	}
128
129	log.Debug("Configuring swarm")
130	err := configureSwarm(provisioner, swarmOptions, provisioner.AuthOptions)
131	return err
132}
133