refactor provision
parent
a2f2df9f81
commit
92eeb3c10b
|
@ -36,6 +36,7 @@ import (
|
|||
"github.com/docker/machine/libmachine/host"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/persist"
|
||||
lib_provision "github.com/docker/machine/libmachine/provision"
|
||||
"github.com/docker/machine/libmachine/ssh"
|
||||
"github.com/docker/machine/libmachine/state"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
|
@ -207,10 +208,16 @@ func (api *LocalClient) Create(h *host.Host) error {
|
|||
{
|
||||
"provisioning",
|
||||
func() error {
|
||||
if driver.BareMetal(h.Driver.DriverName()) || driver.IsKIC(h.Driver.DriverName()) {
|
||||
if driver.BareMetal(h.Driver.DriverName()) {
|
||||
return nil
|
||||
}
|
||||
pv := provision.NewBuildrootProvisioner(h.Driver)
|
||||
var pv lib_provision.Provisioner
|
||||
if driver.IsKIC(h.Driver.DriverName()) {
|
||||
pv = provision.NewUbuntuProvisioner(h.Driver)
|
||||
fmt.Println("choosing ubuntu provisioner")
|
||||
} else {
|
||||
pv = provision.NewBuildrootProvisioner(h.Driver)
|
||||
}
|
||||
return pv.Provision(*h.HostOptions.SwarmOptions, *h.HostOptions.AuthOptions, *h.HostOptions.EngineOptions)
|
||||
},
|
||||
},
|
||||
|
|
|
@ -19,29 +19,18 @@ package provision
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/cert"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/engine"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/provision"
|
||||
"github.com/docker/machine/libmachine/provision/pkgaction"
|
||||
"github.com/docker/machine/libmachine/provision/serviceaction"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/command"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/sshutil"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
)
|
||||
|
||||
|
@ -50,15 +39,6 @@ type BuildrootProvisioner struct {
|
|||
provision.SystemdProvisioner
|
||||
}
|
||||
|
||||
// for escaping systemd template specifiers (e.g. '%i'), which are not supported by minikube
|
||||
var systemdSpecifierEscaper = strings.NewReplacer("%", "%%")
|
||||
|
||||
func init() {
|
||||
provision.Register("Buildroot", &provision.RegisteredProvisioner{
|
||||
New: NewBuildrootProvisioner,
|
||||
})
|
||||
}
|
||||
|
||||
// NewBuildrootProvisioner creates a new BuildrootProvisioner
|
||||
func NewBuildrootProvisioner(d drivers.Driver) provision.Provisioner {
|
||||
return &BuildrootProvisioner{
|
||||
|
@ -75,17 +55,6 @@ func (p *BuildrootProvisioner) CompatibleWithHost() bool {
|
|||
return p.OsReleaseInfo.ID == "buildroot"
|
||||
}
|
||||
|
||||
// escapeSystemdDirectives escapes special characters in the input variables used to create the
|
||||
// systemd unit file, which would otherwise be interpreted as systemd directives. An example
|
||||
// are template specifiers (e.g. '%i') which are predefined variables that get evaluated dynamically
|
||||
// (see systemd man pages for more info). This is not supported by minikube, thus needs to be escaped.
|
||||
func escapeSystemdDirectives(engineConfigContext *provision.EngineConfigContext) {
|
||||
// escape '%' in Environment option so that it does not evaluate into a template specifier
|
||||
engineConfigContext.EngineOptions.Env = util.ReplaceChars(engineConfigContext.EngineOptions.Env, systemdSpecifierEscaper)
|
||||
// input might contain whitespaces, wrap it in quotes
|
||||
engineConfigContext.EngineOptions.Env = util.ConcatStrings(engineConfigContext.EngineOptions.Env, "\"", "\"")
|
||||
}
|
||||
|
||||
// GenerateDockerOptions generates the *provision.DockerOptions for this provisioner
|
||||
func (p *BuildrootProvisioner) GenerateDockerOptions(dockerPort int) (*provision.DockerOptions, error) {
|
||||
var engineCfg bytes.Buffer
|
||||
|
@ -192,14 +161,6 @@ WantedBy=multi-user.target
|
|||
return dockerCfg, nil
|
||||
}
|
||||
|
||||
func rootFileSystemType(p *BuildrootProvisioner) (string, error) {
|
||||
fs, err := p.SSHCommand("df --output=fstype / | tail -n 1")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(fs), nil
|
||||
}
|
||||
|
||||
// Package installs a package
|
||||
func (p *BuildrootProvisioner) Package(name string, action pkgaction.PackageAction) error {
|
||||
return nil
|
||||
|
@ -235,176 +196,10 @@ func (p *BuildrootProvisioner) Provision(swarmOptions swarm.Options, authOptions
|
|||
}
|
||||
|
||||
log.Debugf("setting minikube options for container-runtime")
|
||||
if err := setContainerRuntimeOptions(p); err != nil {
|
||||
if err := setContainerRuntimeOptions(p.Driver.GetMachineName(), p); err != nil {
|
||||
log.Debugf("Error setting container-runtime options during provisioning %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setRemoteAuthOptions(p provision.Provisioner) auth.Options {
|
||||
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 setContainerRuntimeOptions(p *BuildrootProvisioner) error {
|
||||
c, err := config.Load(p.Driver.GetMachineName())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting cluster config")
|
||||
}
|
||||
|
||||
switch c.KubernetesConfig.ContainerRuntime {
|
||||
case "crio", "cri-o":
|
||||
return p.setCrioOptions()
|
||||
case "containerd":
|
||||
return nil
|
||||
default:
|
||||
_, err := p.GenerateDockerOptions(engine.DefaultPort)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func (p *BuildrootProvisioner) setCrioOptions() error {
|
||||
// pass through --insecure-registry
|
||||
var (
|
||||
crioOptsTmpl = `
|
||||
CRIO_MINIKUBE_OPTIONS='{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}'
|
||||
`
|
||||
crioOptsPath = "/etc/sysconfig/crio.minikube"
|
||||
)
|
||||
t, err := template.New("crioOpts").Parse(crioOptsTmpl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var crioOptsBuf bytes.Buffer
|
||||
if err := t.Execute(&crioOptsBuf, p); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = p.SSHCommand(fmt.Sprintf("sudo mkdir -p %s && printf %%s \"%s\" | sudo tee %s", path.Dir(crioOptsPath), crioOptsBuf.String(), crioOptsPath)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureAuth(p *BuildrootProvisioner) error {
|
||||
log.Infof("configureAuth start")
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.Infof("configureAuth took %s", time.Since(start))
|
||||
}()
|
||||
|
||||
driver := p.GetDriver()
|
||||
machineName := driver.GetMachineName()
|
||||
authOptions := p.GetAuthOptions()
|
||||
org := mcnutils.GetUsername() + "." + machineName
|
||||
bits := 2048
|
||||
|
||||
ip, err := driver.GetIP()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting ip during provisioning")
|
||||
}
|
||||
|
||||
if err := copyHostCerts(authOptions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// The Host IP is always added to the certificate's SANs list
|
||||
hosts := append(authOptions.ServerCertSANs, ip, "localhost")
|
||||
log.Debugf("generating server cert: %s ca-key=%s private-key=%s org=%s san=%s",
|
||||
authOptions.ServerCertPath,
|
||||
authOptions.CaCertPath,
|
||||
authOptions.CaPrivateKeyPath,
|
||||
org,
|
||||
hosts,
|
||||
)
|
||||
|
||||
err = cert.GenerateCert(&cert.Options{
|
||||
Hosts: hosts,
|
||||
CertFile: authOptions.ServerCertPath,
|
||||
KeyFile: authOptions.ServerKeyPath,
|
||||
CAFile: authOptions.CaCertPath,
|
||||
CAKeyFile: authOptions.CaPrivateKeyPath,
|
||||
Org: org,
|
||||
Bits: bits,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating server cert: %v", err)
|
||||
}
|
||||
|
||||
return copyRemoteCerts(authOptions, driver)
|
||||
}
|
||||
|
||||
func copyHostCerts(authOptions auth.Options) error {
|
||||
log.Infof("copyHostCerts")
|
||||
execRunner := &command.ExecRunner{}
|
||||
hostCerts := map[string]string{
|
||||
authOptions.CaCertPath: path.Join(authOptions.StorePath, "ca.pem"),
|
||||
authOptions.ClientCertPath: path.Join(authOptions.StorePath, "cert.pem"),
|
||||
authOptions.ClientKeyPath: path.Join(authOptions.StorePath, "key.pem"),
|
||||
}
|
||||
|
||||
if _, err := execRunner.RunCmd(exec.Command("mkdir", "-p", authOptions.StorePath)); err != nil {
|
||||
return err
|
||||
}
|
||||
for src, dst := range hostCerts {
|
||||
f, err := assets.NewFileAsset(src, path.Dir(dst), filepath.Base(dst), "0777")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "open cert file: %s", src)
|
||||
}
|
||||
if err := execRunner.Copy(f); err != nil {
|
||||
return errors.Wrapf(err, "transferring file: %+v", f)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyRemoteCerts(authOptions auth.Options, driver drivers.Driver) error {
|
||||
log.Infof("copyRemoteCerts")
|
||||
|
||||
remoteCerts := map[string]string{
|
||||
authOptions.CaCertPath: authOptions.CaCertRemotePath,
|
||||
authOptions.ServerCertPath: authOptions.ServerCertRemotePath,
|
||||
authOptions.ServerKeyPath: authOptions.ServerKeyRemotePath,
|
||||
}
|
||||
|
||||
sshClient, err := sshutil.NewSSHClient(driver)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "provisioning: error getting ssh client")
|
||||
}
|
||||
sshRunner := command.NewSSHRunner(sshClient)
|
||||
|
||||
dirs := []string{}
|
||||
for _, dst := range remoteCerts {
|
||||
dirs = append(dirs, path.Dir(dst))
|
||||
}
|
||||
|
||||
args := append([]string{"mkdir", "-p"}, dirs...)
|
||||
if _, err = sshRunner.RunCmd(exec.Command("sudo", args...)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for src, dst := range remoteCerts {
|
||||
f, err := assets.NewFileAsset(src, path.Dir(dst), filepath.Base(dst), "0640")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error copying %s to %s", src, dst)
|
||||
}
|
||||
if err := sshRunner.Copy(f); err != nil {
|
||||
return errors.Wrapf(err, "transferring file to machine %v", f)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
Copyright 2019 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package provision
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/cert"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/engine"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/mcnutils"
|
||||
"github.com/docker/machine/libmachine/provision"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/command"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/sshutil"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
)
|
||||
|
||||
// generic interface for minikube provisioner
|
||||
type miniProvisioner interface {
|
||||
String() string
|
||||
CompatibleWithHost() bool
|
||||
GenerateDockerOptions(int) (*provision.DockerOptions, error)
|
||||
Provision(swarmOptions swarm.Options, authOptions auth.Options, engineOptions engine.Options) error
|
||||
GetDriver() drivers.Driver
|
||||
GetAuthOptions() auth.Options
|
||||
SSHCommand(string) (string, error)
|
||||
}
|
||||
|
||||
// for escaping systemd template specifiers (e.g. '%i'), which are not supported by minikube
|
||||
var systemdSpecifierEscaper = strings.NewReplacer("%", "%%")
|
||||
|
||||
func init() {
|
||||
provision.Register("Buildroot", &provision.RegisteredProvisioner{
|
||||
New: NewBuildrootProvisioner,
|
||||
})
|
||||
provision.Register("Ubuntu", &provision.RegisteredProvisioner{
|
||||
New: NewUbuntuProvisioner,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func configureAuth(p miniProvisioner) error {
|
||||
log.Infof("configureAuth start")
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.Infof("configureAuth took %s", time.Since(start))
|
||||
}()
|
||||
|
||||
driver := p.GetDriver()
|
||||
machineName := driver.GetMachineName()
|
||||
authOptions := p.GetAuthOptions()
|
||||
org := mcnutils.GetUsername() + "." + machineName
|
||||
bits := 2048
|
||||
|
||||
ip, err := driver.GetIP()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error getting ip during provisioning")
|
||||
}
|
||||
|
||||
if err := copyHostCerts(authOptions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// The Host IP is always added to the certificate's SANs list
|
||||
hosts := append(authOptions.ServerCertSANs, ip, "localhost", "127.0.0.1")
|
||||
log.Debugf("generating server cert: %s ca-key=%s private-key=%s org=%s san=%s",
|
||||
authOptions.ServerCertPath,
|
||||
authOptions.CaCertPath,
|
||||
authOptions.CaPrivateKeyPath,
|
||||
org,
|
||||
hosts,
|
||||
)
|
||||
|
||||
err = cert.GenerateCert(&cert.Options{
|
||||
Hosts: hosts,
|
||||
CertFile: authOptions.ServerCertPath,
|
||||
KeyFile: authOptions.ServerKeyPath,
|
||||
CAFile: authOptions.CaCertPath,
|
||||
CAKeyFile: authOptions.CaPrivateKeyPath,
|
||||
Org: org,
|
||||
Bits: bits,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("error generating server cert: %v", err)
|
||||
}
|
||||
|
||||
return copyRemoteCerts(authOptions, driver)
|
||||
}
|
||||
|
||||
func copyHostCerts(authOptions auth.Options) error {
|
||||
log.Infof("copyHostCerts")
|
||||
execRunner := &command.ExecRunner{}
|
||||
hostCerts := map[string]string{
|
||||
authOptions.CaCertPath: path.Join(authOptions.StorePath, "ca.pem"),
|
||||
authOptions.ClientCertPath: path.Join(authOptions.StorePath, "cert.pem"),
|
||||
authOptions.ClientKeyPath: path.Join(authOptions.StorePath, "key.pem"),
|
||||
}
|
||||
|
||||
if _, err := execRunner.RunCmd(exec.Command("mkdir", "-p", authOptions.StorePath)); err != nil {
|
||||
return err
|
||||
}
|
||||
for src, dst := range hostCerts {
|
||||
f, err := assets.NewFileAsset(src, path.Dir(dst), filepath.Base(dst), "0777")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "open cert file: %s", src)
|
||||
}
|
||||
if err := execRunner.Copy(f); err != nil {
|
||||
return errors.Wrapf(err, "transferring file: %+v", f)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyRemoteCerts(authOptions auth.Options, driver drivers.Driver) error {
|
||||
log.Infof("copyRemoteCerts")
|
||||
|
||||
remoteCerts := map[string]string{
|
||||
authOptions.CaCertPath: authOptions.CaCertRemotePath,
|
||||
authOptions.ServerCertPath: authOptions.ServerCertRemotePath,
|
||||
authOptions.ServerKeyPath: authOptions.ServerKeyRemotePath,
|
||||
}
|
||||
|
||||
sshClient, err := sshutil.NewSSHClient(driver)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "provisioning: error getting ssh client")
|
||||
}
|
||||
sshRunner := command.NewSSHRunner(sshClient)
|
||||
|
||||
dirs := []string{}
|
||||
for _, dst := range remoteCerts {
|
||||
dirs = append(dirs, path.Dir(dst))
|
||||
}
|
||||
|
||||
args := append([]string{"mkdir", "-p"}, dirs...)
|
||||
if _, err = sshRunner.RunCmd(exec.Command("sudo", args...)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for src, dst := range remoteCerts {
|
||||
f, err := assets.NewFileAsset(src, path.Dir(dst), filepath.Base(dst), "0640")
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error copying %s to %s", src, dst)
|
||||
}
|
||||
if err := sshRunner.Copy(f); err != nil {
|
||||
return errors.Wrapf(err, "transferring file to machine %v", f)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setRemoteAuthOptions(p provision.Provisioner) auth.Options {
|
||||
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 setContainerRuntimeOptions(name string, p miniProvisioner) error {
|
||||
c, err := config.Load(name)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getting cluster config")
|
||||
}
|
||||
|
||||
switch c.KubernetesConfig.ContainerRuntime {
|
||||
case "crio", "cri-o":
|
||||
return setCrioOptions(p)
|
||||
case "containerd":
|
||||
return nil
|
||||
default:
|
||||
_, err := p.GenerateDockerOptions(engine.DefaultPort)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func setCrioOptions(p provision.SSHCommander) error {
|
||||
// pass through --insecure-registry
|
||||
var (
|
||||
crioOptsTmpl = `
|
||||
CRIO_MINIKUBE_OPTIONS='{{ range .EngineOptions.InsecureRegistry }}--insecure-registry {{.}} {{ end }}'
|
||||
`
|
||||
crioOptsPath = "/etc/sysconfig/crio.minikube"
|
||||
)
|
||||
t, err := template.New("crioOpts").Parse(crioOptsTmpl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var crioOptsBuf bytes.Buffer
|
||||
if err := t.Execute(&crioOptsBuf, p); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = p.SSHCommand(fmt.Sprintf("sudo mkdir -p %s && printf %%s \"%s\" | sudo tee %s", path.Dir(crioOptsPath), crioOptsBuf.String(), crioOptsPath)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func rootFileSystemType(p provision.SSHCommander) (string, error) {
|
||||
fs, err := p.SSHCommand("df --output=fstype / | tail -n 1")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(fs), nil
|
||||
}
|
||||
|
||||
// escapeSystemdDirectives escapes special characters in the input variables used to create the
|
||||
// systemd unit file, which would otherwise be interpreted as systemd directives. An example
|
||||
// are template specifiers (e.g. '%i') which are predefined variables that get evaluated dynamically
|
||||
// (see systemd man pages for more info). This is not supported by minikube, thus needs to be escaped.
|
||||
func escapeSystemdDirectives(engineConfigContext *provision.EngineConfigContext) {
|
||||
// escape '%' in Environment option so that it does not evaluate into a template specifier
|
||||
engineConfigContext.EngineOptions.Env = util.ReplaceChars(engineConfigContext.EngineOptions.Env, systemdSpecifierEscaper)
|
||||
// input might contain whitespaces, wrap it in quotes
|
||||
engineConfigContext.EngineOptions.Env = util.ConcatStrings(engineConfigContext.EngineOptions.Env, "\"", "\"")
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
Copyright 2019 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package provision
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/docker/machine/libmachine/auth"
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/docker/machine/libmachine/engine"
|
||||
"github.com/docker/machine/libmachine/log"
|
||||
"github.com/docker/machine/libmachine/provision"
|
||||
"github.com/docker/machine/libmachine/provision/pkgaction"
|
||||
"github.com/docker/machine/libmachine/provision/serviceaction"
|
||||
"github.com/docker/machine/libmachine/swarm"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
)
|
||||
|
||||
// UbuntuProvisioner provisions the ubuntu
|
||||
type UbuntuProvisioner struct {
|
||||
BuildrootProvisioner
|
||||
}
|
||||
|
||||
// NewUbuntuProvisioner creates a new UbuntuProvisioner
|
||||
func NewUbuntuProvisioner(d drivers.Driver) provision.Provisioner {
|
||||
return &UbuntuProvisioner{
|
||||
BuildrootProvisioner{
|
||||
provision.NewSystemdProvisioner("ubuntu", d),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *UbuntuProvisioner) String() string {
|
||||
return "ubuntu"
|
||||
}
|
||||
|
||||
// CompatibleWithHost checks if provisioner is compatible with host
|
||||
func (p *UbuntuProvisioner) CompatibleWithHost() bool {
|
||||
return p.OsReleaseInfo.ID == "ubuntu"
|
||||
}
|
||||
|
||||
// GenerateDockerOptions generates the *provision.DockerOptions for this provisioner
|
||||
func (p *UbuntuProvisioner) GenerateDockerOptions(dockerPort int) (*provision.DockerOptions, error) {
|
||||
var engineCfg bytes.Buffer
|
||||
|
||||
drvLabel := fmt.Sprintf("provider=%s", p.Driver.DriverName())
|
||||
p.EngineOptions.Labels = append(p.EngineOptions.Labels, drvLabel)
|
||||
|
||||
noPivot := true
|
||||
// Using pivot_root is not supported on fstype rootfs
|
||||
if fstype, err := rootFileSystemType(p); err == nil {
|
||||
log.Debugf("root file system type: %s", fstype)
|
||||
noPivot = fstype == "rootfs"
|
||||
}
|
||||
|
||||
engineConfigTmpl := `[Unit]
|
||||
Description=Docker Application Container Engine
|
||||
Documentation=https://docs.docker.com
|
||||
BindsTo=containerd.service
|
||||
After=network-online.target firewalld.service containerd.service
|
||||
Wants=network-online.target
|
||||
Requires=docker.socket
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
`
|
||||
if noPivot {
|
||||
log.Warn("Using fundamentally insecure --no-pivot option")
|
||||
engineConfigTmpl += `
|
||||
# DOCKER_RAMDISK disables pivot_root in Docker, using MS_MOVE instead.
|
||||
Environment=DOCKER_RAMDISK=yes
|
||||
`
|
||||
}
|
||||
engineConfigTmpl += `
|
||||
{{range .EngineOptions.Env}}Environment={{.}}
|
||||
{{end}}
|
||||
|
||||
# This file is a systemd drop-in unit that inherits from the base dockerd configuration.
|
||||
# The base configuration already specifies an 'ExecStart=...' command. The first directive
|
||||
# here is to clear out that command inherited from the base configuration. Without this,
|
||||
# the command from the base configuration and the command specified here are treated as
|
||||
# a sequence of commands, which is not the desired behavior, nor is it valid -- systemd
|
||||
# will catch this invalid input and refuse to start the service with an error like:
|
||||
# Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services.
|
||||
|
||||
# NOTE: default-ulimit=nofile is set to an arbitrary number for consistency with other
|
||||
# container runtimes. If left unlimited, it may result in OOM issues with MySQL.
|
||||
ExecStart=
|
||||
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:{{.DockerPort}} -H unix:///var/run/docker.sock --default-ulimit=nofile=1048576:1048576 --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 }}
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
|
||||
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
||||
# in the kernel. We recommend using cgroups to do container-local accounting.
|
||||
LimitNOFILE=infinity
|
||||
LimitNPROC=infinity
|
||||
LimitCORE=infinity
|
||||
|
||||
# Uncomment TasksMax if your systemd version supports it.
|
||||
# Only systemd 226 and above support this version.
|
||||
TasksMax=infinity
|
||||
TimeoutStartSec=0
|
||||
|
||||
# set delegate yes so that systemd does not reset the cgroups of docker containers
|
||||
Delegate=yes
|
||||
|
||||
# kill only the docker process, not all processes in the cgroup
|
||||
KillMode=process
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
`
|
||||
t, err := template.New("engineConfig").Parse(engineConfigTmpl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
engineConfigContext := provision.EngineConfigContext{
|
||||
DockerPort: dockerPort,
|
||||
AuthOptions: p.AuthOptions,
|
||||
EngineOptions: p.EngineOptions,
|
||||
}
|
||||
|
||||
escapeSystemdDirectives(&engineConfigContext)
|
||||
|
||||
if err := t.Execute(&engineCfg, engineConfigContext); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dockerCfg := &provision.DockerOptions{
|
||||
EngineOptions: engineCfg.String(),
|
||||
EngineOptionsPath: "/lib/systemd/system/docker.service",
|
||||
}
|
||||
|
||||
log.Info("Setting Docker configuration on the remote daemon...")
|
||||
|
||||
if _, err = p.SSHCommand(fmt.Sprintf("sudo mkdir -p %s && printf %%s \"%s\" | sudo tee %s", path.Dir(dockerCfg.EngineOptionsPath), dockerCfg.EngineOptions, dockerCfg.EngineOptionsPath)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := p.Service("docker", serviceaction.Enable); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := p.Service("docker", serviceaction.Restart); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dockerCfg, nil
|
||||
}
|
||||
|
||||
// Package installs a package
|
||||
func (p *UbuntuProvisioner) Package(name string, action pkgaction.PackageAction) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Provision does the provisioning
|
||||
func (p *UbuntuProvisioner) Provision(swarmOptions swarm.Options, authOptions auth.Options, engineOptions engine.Options) error {
|
||||
fmt.Println("************ INSISDE ******* PRVOVISION ******************")
|
||||
p.SwarmOptions = swarmOptions
|
||||
p.AuthOptions = authOptions
|
||||
p.EngineOptions = engineOptions
|
||||
|
||||
log.Infof("provisioning hostname %q", p.Driver.GetMachineName())
|
||||
if err := p.SetHostname(p.Driver.GetMachineName()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.AuthOptions = setRemoteAuthOptions(p)
|
||||
log.Debugf("set auth options %+v", p.AuthOptions)
|
||||
|
||||
log.Debugf("setting up certificates")
|
||||
configAuth := func() error {
|
||||
if err := configureAuth(p); err != nil {
|
||||
log.Warnf("configureAuth failed: %v", err)
|
||||
return &retry.RetriableError{Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
err := retry.Expo(configAuth, time.Second, 2*time.Minute)
|
||||
if err != nil {
|
||||
log.Debugf("Error configuring auth during provisioning %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("setting minikube options for container-runtime")
|
||||
if err := setContainerRuntimeOptions(p.Driver.GetMachineName(), p); err != nil {
|
||||
log.Debugf("Error setting container-runtime options during provisioning %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue