Removed systemd dependency from minikube, updated none driver to reflect this

pull/1592/head
Aaron Prindle 2017-06-14 14:27:01 -07:00
parent 51cf8cf9a8
commit 6639b2d91b
7 changed files with 150 additions and 58 deletions

View File

@ -241,8 +241,10 @@ func runStart(cmd *cobra.Command, args []string) {
fmt.Println(`===================
WARNING: IT IS RECOMMENDED NOT TO RUN THE NONE DRIVER ON PERSONAL WORKSTATIONS
The 'none' driver will run an insecure kubernetes apiserver as root that may leave the host vulnerable to CSRF attacks
`)
When using the none driver, the kubectl config and credentials generated will be root owned and will appear in the root home directory.
if os.Getenv("CHANGE_MINIKUBE_NONE_USER") != "" {
fmt.Println(`When using the none driver, the kubectl config and credentials generated will be root owned and will appear in the root home directory.
You will need to move the files to the appropriate location and then set the correct permissions. An example of this is below:
sudo mv /root/.kube $HOME/.kube # this will overwrite any config you have. You may have to append the file contents manually
sudo chown -R $USER $HOME/.kube
@ -252,6 +254,12 @@ You will need to move the files to the appropriate location and then set the cor
sudo chown -R $USER $HOME/.minikube
sudo chgrp -R $USER $HOME/.minikube
This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_USER=true`)
}
if err := cmdUtil.MaybeChownDirRecursiveToMinikubeUser(constants.GetMinipath()); err != nil {
glog.Errorf("Error recursively changing ownership of directory %s: %s",
constants.GetMinipath(), err)
cmdUtil.MaybeReportErrorAndExit(err)
}
}
}

View File

@ -27,6 +27,7 @@ import (
"net/http"
"os"
"os/exec"
"os/user"
"path/filepath"
"runtime"
"strings"
@ -246,3 +247,34 @@ func KillMountProcess() error {
}
return mountProc.Kill()
}
func MaybeChownDirRecursiveToMinikubeUser(dir string) error {
if os.Getenv("CHANGE_MINIKUBE_NONE_USER") != "" && os.Getenv("SUDO_USER") != "" {
username := os.Getenv("SUDO_USER")
usr, err := user.Lookup(username)
if err != nil {
return errors.Wrap(err, "Error looking up user")
}
uid, err := strconv.Atoi(usr.Uid)
if err != nil {
return errors.Wrapf(err, "Error parsing uid for user: %s", username)
}
gid, err := strconv.Atoi(usr.Gid)
if err != nil {
return errors.Wrapf(err, "Error parsing gid for user: %s", username)
}
if err := ChownR(dir, uid, gid); err != nil {
return errors.Wrapf(err, "Error changing ownership for: %s", dir)
}
}
return nil
}
func ChownR(path string, uid, gid int) error {
return filepath.Walk(path, func(name string, info os.FileInfo, err error) error {
if err == nil {
err = os.Chown(name, uid, gid)
}
return err
})
}

View File

@ -20,7 +20,6 @@ import (
"bytes"
"io"
"os"
"os/user"
"path/filepath"
"strconv"
@ -157,29 +156,7 @@ func CopyFileLocal(f CopyableFile) error {
_, err = io.Copy(target, f)
if err != nil {
return errors.Wrap(err, "Error copying file to target location")
}
if os.Getenv("CHANGE_MINIKUBE_NONE_USER") != "" {
username := os.Getenv("SUDO_USER")
if username == "" {
return nil
}
usr, err := user.Lookup(username)
if err != nil {
return errors.Wrap(err, "Error looking up user")
}
uid, err := strconv.Atoi(usr.Uid)
if err != nil {
return errors.Wrapf(err, "Error parsing uid for user: %s", username)
}
gid, err := strconv.Atoi(usr.Gid)
if err != nil {
return errors.Wrapf(err, "Error parsing gid for user: %s", username)
}
if err := os.Chown(targetPath, uid, gid); err != nil {
return errors.Wrapf(err, "Error changing ownership for: %s", targetPath)
}
return errors.Wrap(err, "Error copying file to target location, do you have the correct permissions?")
}
return nil
}

View File

@ -153,10 +153,7 @@ func GetLocalkubeStatus(api libmachine.API) (string, error) {
if err != nil {
return "", err
}
statusCmd := localkubeStatusCommand
s, err := RunCommand(h, statusCmd, false)
s, err := RunCommand(h, localkubeStatusCommand, false)
if err != nil {
return "", err
}
@ -446,7 +443,7 @@ func GetHostLogs(api libmachine.API, follow bool) (string, error) {
s, err := RunCommand(h, logsCommand, false)
if err != nil {
return "", err
return s, err
}
return s, nil
}
@ -577,15 +574,20 @@ func EnsureMinikubeRunningOrExit(api libmachine.API, exitStatus int) {
// RunCommand executes commands for both the local and driver implementations
func RunCommand(h *host.Host, command string, sudo bool) (string, error) {
if h.Driver.DriverName() == "none" {
cmd := exec.Command("/bin/sh", "-c", command)
cmd := exec.Command("/bin/bash", "-c", command)
if sudo {
cmd = exec.Command("sudo", "/bin/sh", "-c", command)
cmd = exec.Command("sudo", "/bin/bash", "-c", command)
}
out, err := cmd.CombinedOutput()
if err != nil {
return "", err
return "", errors.Wrap(err, string(out))
}
return string(out), nil
return string(out), err
}
return h.RunSSHCommand(command)
out, err := h.RunSSHCommand(command)
if err != nil {
return "", errors.Wrap(err, string(out))
}
return string(out), err
}

View File

@ -23,13 +23,20 @@ import (
"net"
"strings"
"k8s.io/minikube/pkg/minikube/constants"
"text/template"
"k8s.io/minikube/pkg/minikube/constants"
)
// Kill any running instances.
var localkubeStartCmdTemplate = "/usr/local/bin/localkube {{.Flags}} --generate-certs=false --logtostderr=true --enable-dns=false"
var startCommandNoSystemdTemplate = `
# Run with nohup so it stays up. Redirect logs to useful places.
sudo sh -c 'PATH=/usr/local/sbin:$PATH nohup {{.LocalkubeStartCmd}} > {{.Stdout}} 2> {{.Stderr}} < /dev/null & echo $! > {{.Pidfile}} &'
`
var localkubeSystemdTmpl = `[Unit]
Description=Localkube
Documentation=https://github.com/kubernetes/minikube/tree/master/pkg/localkube
@ -47,11 +54,15 @@ ExecReload=/bin/kill -s HUP $MAINPID
WantedBy=multi-user.target
`
var startCommandTemplate = `
var startCommandTemplate = "if [[ `systemctl` =~ -\\.mount ]] &>/dev/null;" + `then
{{.StartCommandSystemd}}
sudo systemctl daemon-reload
sudo systemctl enable localkube.service
sudo systemctl restart localkube.service || true
else
sudo killall localkube || true
{{.StartCommandNoSystemd}}
fi
`
func GetStartCommand(kubernetesConfig KubernetesConfig) (string, error) {
@ -59,6 +70,10 @@ func GetStartCommand(kubernetesConfig KubernetesConfig) (string, error) {
if err != nil {
return "", err
}
startCommandNoSystemd, err := GetStartCommandNoSystemd(kubernetesConfig, localkubeStartCommand)
if err != nil {
return "", err
}
startCommandSystemd, err := GetStartCommandSystemd(kubernetesConfig, localkubeStartCommand)
if err != nil {
return "", err
@ -66,9 +81,31 @@ func GetStartCommand(kubernetesConfig KubernetesConfig) (string, error) {
t := template.Must(template.New("startCommand").Parse(startCommandTemplate))
buf := bytes.Buffer{}
data := struct {
StartCommandSystemd string
StartCommandNoSystemd string
StartCommandSystemd string
}{
StartCommandSystemd: startCommandSystemd,
StartCommandNoSystemd: startCommandNoSystemd,
StartCommandSystemd: startCommandSystemd,
}
if err := t.Execute(&buf, data); err != nil {
return "", err
}
return buf.String(), nil
}
func GetStartCommandNoSystemd(kubernetesConfig KubernetesConfig, localkubeStartCmd string) (string, error) {
t := template.Must(template.New("startCommand").Parse(startCommandNoSystemdTemplate))
buf := bytes.Buffer{}
data := struct {
LocalkubeStartCmd string
Stdout string
Stderr string
Pidfile string
}{
LocalkubeStartCmd: localkubeStartCmd,
Stdout: constants.RemoteLocalKubeOutPath,
Stderr: constants.RemoteLocalKubeErrPath,
Pidfile: constants.LocalkubePIDPath,
}
if err := t.Execute(&buf, data); err != nil {
return "", err
@ -130,6 +167,7 @@ func GenLocalkubeStartCmd(kubernetesConfig KubernetesConfig) (string, error) {
flagVals = append(flagVals, fmt.Sprintf("--extra-config=%s", e.String()))
}
flags := strings.Join(flagVals, " ")
t := template.Must(template.New("localkubeStartCmd").Parse(localkubeStartCmdTemplate))
buf := bytes.Buffer{}
data := struct {
@ -145,7 +183,12 @@ func GenLocalkubeStartCmd(kubernetesConfig KubernetesConfig) (string, error) {
return buf.String(), nil
}
const logsTemplate = "sudo journalctl {{.Flags}} -u localkube"
const logsTemplate = "if [[ `systemctl` =~ -\\.mount ]] &>/dev/null; " + `then
sudo journalctl {{.Flags}} -u localkube
else
tail -n +1 {{.Flags}} {{.RemoteLocalkubeErrPath}} {{.RemoteLocalkubeOutPath}}
fi
`
func GetLogsCommand(follow bool) (string, error) {
t, err := template.New("logsTemplate").Parse(logsTemplate)
@ -173,7 +216,16 @@ func GetLogsCommand(follow bool) (string, error) {
return buf.String(), nil
}
var localkubeStatusCommand = `sudo systemctl is-active localkube 2>&1 1>/dev/null && echo "Running" || echo "Stopped"`
var localkubeStatusCommand = fmt.Sprintf("if [[ `systemctl` =~ -\\.mount ]] &>/dev/null; "+`then
sudo systemctl is-active localkube &>/dev/null && echo "Running" || echo "Stopped"
else
if ps $(cat %s) &>/dev/null; then
echo "Running"
else
echo "Stopped"
fi
fi
`, constants.LocalkubePIDPath)
func GetMountCleanupCommand(path string) string {
return fmt.Sprintf("sudo umount %s;", path)

View File

@ -31,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/tools/clientcmd/api/latest"
cmdUtil "k8s.io/minikube/cmd/util"
cfg "k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
)
@ -166,6 +167,10 @@ func WriteConfig(config *api.Config, filename string) error {
if err := ioutil.WriteFile(filename, data, 0600); err != nil {
return errors.Wrapf(err, "Error writing file %s", filename)
}
if err := cmdUtil.MaybeChownDirRecursiveToMinikubeUser(dir); err != nil {
return errors.Wrapf(err, "Error recursively changing ownership for dir: %s", dir)
}
return nil
}

View File

@ -17,17 +17,15 @@ limitations under the License.
package none
import (
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/mcnflag"
"github.com/docker/machine/libmachine/state"
"github.com/pkg/errors"
"k8s.io/minikube/pkg/minikube/constants"
)
@ -50,10 +48,6 @@ func NewDriver(hostName, storePath string) *Driver {
// PreCreateCheck checks that VBoxManage exists and works
func (d *Driver) PreCreateCheck() error {
// check that systemd is installed as it is a requirement
if _, err := exec.LookPath("systemctl"); err != nil {
return errors.New("systemd is a requirement in order to use the none driver")
}
return nil
}
@ -96,17 +90,22 @@ func (d *Driver) GetURL() (string, error) {
}
func (d *Driver) GetState() (state.State, error) {
command := `sudo systemctl is-active localkube 2>&1 1>/dev/null && echo "Running" || echo "Stopped"`
var statuscmd = fmt.Sprintf("if [[ `systemctl` =~ -\\.mount ]] &>/dev/null; "+`then
sudo systemctl is-active localkube &>/dev/null && echo "Running" || echo "Stopped"
else
if ps $(cat %s) &>/dev/null; then
echo "Running"
else
echo "Stopped"
fi
fi
`, constants.LocalkubePIDPath)
path := filepath.Join(constants.GetMinipath(), "tmp-cmd")
ioutil.WriteFile(filepath.Join(constants.GetMinipath(), "tmp-cmd"), []byte(command), os.FileMode(0644))
defer os.Remove(path)
cmd := exec.Command("sudo", "/bin/sh", path)
out, err := cmd.CombinedOutput()
out, err := runCommand(statuscmd, true)
if err != nil {
return state.None, err
}
s := strings.TrimSpace(string(out))
s := strings.TrimSpace(out)
if state.Running.String() == s {
return state.Running, nil
} else if state.Stopped.String() == s {
@ -162,11 +161,16 @@ func (d *Driver) Start() error {
}
func (d *Driver) Stop() error {
cmd := exec.Command("sudo", "systemctl", "stop", "localkube.service")
if err := cmd.Start(); err != nil {
var stopcmd = fmt.Sprintf("if [[ `systemctl` =~ -\\.mount ]] &>/dev/null; "+`then
sudo systemctl stop localkube.service
else
sudo kill $(cat %s)
fi
`, constants.LocalkubePIDPath)
_, err := runCommand(stopcmd, true)
if err != nil {
return err
}
for {
s, err := d.GetState()
if err != nil {
@ -182,3 +186,15 @@ func (d *Driver) Stop() error {
func (d *Driver) RunSSHCommandFromDriver() error {
return fmt.Errorf("driver does not support ssh commands")
}
func runCommand(command string, sudo bool) (string, error) {
cmd := exec.Command("/bin/bash", "-c", command)
if sudo {
cmd = exec.Command("sudo", "/bin/bash", "-c", command)
}
out, err := cmd.CombinedOutput()
if err != nil {
return "", errors.Wrap(err, string(out))
}
return string(out), nil
}