diff --git a/.gitignore b/.gitignore index 074442779d..66e405ada8 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ _testmain.go /out /.gopath + +pkg/minikube/cluster/localkubecontents.go \ No newline at end of file diff --git a/Makefile b/Makefile index 6c55509749..52ef9ae38a 100644 --- a/Makefile +++ b/Makefile @@ -54,3 +54,11 @@ docker/localkube: .PHONY: test test: gopath ./test.sh + +docker/minikube-full: docker/localkube-incremental + go-bindata -nomemcopy -o pkg/minikube/cluster/localkubecontents.go -pkg cluster ./out/localkube + make minikube + +minikube-full: localkube + go-bindata -nomemcopy -o pkg/minikube/cluster/localkubecontents.go -pkg cluster ./out/localkube + make minikube \ No newline at end of file diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index ddc12c4b05..c6920dd784 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -56,6 +56,11 @@ func runStart(cmd *cobra.Command, args []string) { LocalkubeURL: localkubeURL, } + if err := cluster.UpdateCluster(host.Driver); err != nil { + log.Println("Error updating cluster: ", err) + os.Exit(1) + } + if err := cluster.StartCluster(host, config); err != nil { log.Println("Error starting cluster: ", err) os.Exit(1) diff --git a/pkg/minikube/cluster/cluster.go b/pkg/minikube/cluster/cluster.go index 1cb1eeadcc..d969f9b69b 100644 --- a/pkg/minikube/cluster/cluster.go +++ b/pkg/minikube/cluster/cluster.go @@ -27,9 +27,11 @@ import ( "github.com/docker/machine/drivers/virtualbox" "github.com/docker/machine/libmachine" + "github.com/docker/machine/libmachine/drivers" "github.com/docker/machine/libmachine/host" "github.com/docker/machine/libmachine/state" "k8s.io/minikube/pkg/minikube/constants" + "k8s.io/minikube/pkg/minikube/sshutil" ) const ( @@ -145,7 +147,7 @@ type KubernetesConfig struct { // StartCluster starts a k8s cluster on the specified Host. func StartCluster(h sshAble, config KubernetesConfig) error { - output, err := h.RunSSHCommand(getStartCommand(config.LocalkubeURL)) + output, err := h.RunSSHCommand(getStartCommand()) log.Println(output) if err != nil { return err @@ -154,6 +156,20 @@ func StartCluster(h sshAble, config KubernetesConfig) error { return nil } +func UpdateCluster(d drivers.Driver) error { + localkube, err := Asset("out/localkube") + if err != nil { + log.Println("error loadking localkube: ", err) + return err + } + + client, err := sshutil.NewSSHClient(d) + if err != nil { + return err + } + return sshutil.Transfer(localkube, "/usr/local/bin/", "localkube", "0777", client) +} + // GetCreds gets the generated credentials required to talk to the APIServer. func GetCreds(h sshAble) error { localPath := constants.Minipath diff --git a/pkg/minikube/cluster/commands.go b/pkg/minikube/cluster/commands.go index cc705c5ff3..532eb85e43 100644 --- a/pkg/minikube/cluster/commands.go +++ b/pkg/minikube/cluster/commands.go @@ -1,17 +1,10 @@ package cluster -import "fmt" - -var startCommand = `sudo killall localkube || true -# Download and install localkube, if it doesn't exist yet. -if [ ! -e /usr/local/bin/localkube ]; then - sudo curl --compressed -L %s -o /usr/local/bin/localkube - sudo chmod a+x /usr/local/bin/localkube -fi +var startCommand = ` # Run with nohup so it stays up. Redirect logs to useful places. PATH=/usr/local/sbin:$PATH nohup sudo /usr/local/bin/localkube start > /var/log/localkube.out 2> /var/log/localkube.err < /dev/null & ` -func getStartCommand(localkubeURL string) string { - return fmt.Sprintf(startCommand, localkubeURL) +func getStartCommand() string { + return startCommand } diff --git a/pkg/minikube/sshutil/sshutil.go b/pkg/minikube/sshutil/sshutil.go index 5623b29f93..28853165eb 100644 --- a/pkg/minikube/sshutil/sshutil.go +++ b/pkg/minikube/sshutil/sshutil.go @@ -17,10 +17,10 @@ limitations under the License. package sshutil import ( - "bufio" + "bytes" "fmt" "io" - "os" + "path/filepath" "github.com/docker/machine/libmachine/drivers" machinessh "github.com/docker/machine/libmachine/ssh" @@ -31,12 +31,12 @@ import ( type SSHSession interface { Close() error StdinPipe() (io.WriteCloser, error) - Start(cmd string) error + Run(cmd string) error Wait() error } -// NewSSHSession returns an SSHSession object for running commands. -func NewSSHSession(d drivers.Driver) (SSHSession, error) { +// NewSSHClient returns an SSH client object for running commands. +func NewSSHClient(d drivers.Driver) (*ssh.Client, error) { h, err := newSSHHost(d) if err != nil { return nil, err @@ -55,37 +55,51 @@ func NewSSHSession(d drivers.Driver) (SSHSession, error) { if err != nil { return nil, err } - session, err := client.NewSession() - if err != nil { - return nil, err - } - return session, nil + return client, nil } // Transfer uses an SSH session to copy a file to the remote machine. -func Transfer(localpath, remotepath string, r SSHSession) error { - f, err := os.Open(localpath) - if err != nil { +func Transfer(data []byte, remotedir, filename string, perm string, c *ssh.Client) error { + // Delete the old file first. This makes sure permissions get reset. + deleteCmd := fmt.Sprintf("sudo rm -f %s", filepath.Join(remotedir, filename)) + if err := runCommand(c, deleteCmd); err != nil { return err } - reader := bufio.NewReader(f) - cmd := fmt.Sprintf("cat > %s", remotepath) - stdin, err := r.StdinPipe() + s, err := c.NewSession() if err != nil { return err } - if err := r.Start(cmd); err != nil { + go func() { + w, err := s.StdinPipe() + defer w.Close() + if err != nil { + return + } + header := fmt.Sprintf("C%s %d %s\n", perm, len(data), filename) + fmt.Fprint(w, header) + reader := bytes.NewReader(data) + io.Copy(w, reader) + fmt.Fprint(w, "\x00") + }() + + scpcmd := fmt.Sprintf("sudo /usr/local/bin/scp -t %s", remotedir) + if err := s.Run(scpcmd); err != nil { return err } - _, err = io.Copy(stdin, reader) - stdin.Close() + + return nil +} + +func runCommand(c *ssh.Client, cmd string) error { + s, err := c.NewSession() + defer s.Close() if err != nil { return err } - return r.Wait() + return s.Run(cmd) } type sshHost struct {