finished logs functionality and tests
parent
77919b82b0
commit
706f974751
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright 2016 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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/docker/machine/libmachine"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/minikube/pkg/minikube/cluster"
|
||||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
)
|
||||
|
||||
// logsCmd represents the logs command
|
||||
var logsCmd = &cobra.Command{
|
||||
Use: "logs",
|
||||
Short: "Gets the logs of the running localkube instance, used for debugging minikube, not user code.",
|
||||
Long: `Gets the logs of the running localkube instance, used for debugging minikube, not user code.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
api := libmachine.NewClient(constants.Minipath, constants.MakeMiniPath("certs"))
|
||||
defer api.Close()
|
||||
s, err := cluster.GetHostLogs(api)
|
||||
if err != nil {
|
||||
log.Println("Error getting machine logs:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Fprintln(os.Stdout, s)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(logsCmd)
|
||||
}
|
|
@ -243,19 +243,10 @@ func createHost(api libmachine.API, config MachineConfig) (*host.Host, error) {
|
|||
|
||||
// GetHostDockerEnv gets the necessary docker env variables to allow the use of docker through minikube's vm
|
||||
func GetHostDockerEnv(api libmachine.API) (map[string]string, error) {
|
||||
exists, err := api.Exists(constants.MachineName)
|
||||
host, err := checkIfApiExistsAndLoad(api)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("Machine does not exist")
|
||||
}
|
||||
|
||||
host, err := api.Load(constants.MachineName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ip, err := host.Driver.GetIP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -272,3 +263,32 @@ func GetHostDockerEnv(api libmachine.API) (map[string]string, error) {
|
|||
}
|
||||
return envMap, nil
|
||||
}
|
||||
|
||||
// GetHostLogs gets the localkube logs of the host VM.
|
||||
func GetHostLogs(api libmachine.API) (string, error) {
|
||||
host, err := checkIfApiExistsAndLoad(api)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s, err := host.RunSSHCommand(logsCommand)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
return s, err
|
||||
}
|
||||
|
||||
func checkIfApiExistsAndLoad(api libmachine.API) (*host.Host, error) {
|
||||
exists, err := api.Exists(constants.MachineName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("Machine does not exist for api.Exists(%s)", constants.MachineName)
|
||||
}
|
||||
|
||||
host, err := api.Load(constants.MachineName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return host, nil
|
||||
}
|
||||
|
|
|
@ -327,7 +327,7 @@ func TestSetupCerts(t *testing.T) {
|
|||
contents, _ := ioutil.ReadFile(cert)
|
||||
transferred := s.Transfers.Bytes()
|
||||
if !bytes.Contains(transferred, contents) {
|
||||
t.Fatalf("Certificate not copied. Expected transfers to contain %s. It was: %s", contents, transferred)
|
||||
t.Fatalf("Certificate not copied. Expected transfers to contain: %s. It was: %s", contents, transferred)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -361,3 +361,30 @@ func TestGetHostDockerEnv(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostGetLogs(t *testing.T) {
|
||||
api := tests.NewMockAPI()
|
||||
|
||||
s, _ := tests.NewSSHServer()
|
||||
port, err := s.Start()
|
||||
if err != nil {
|
||||
t.Fatalf("Error starting ssh server: %s", err)
|
||||
}
|
||||
|
||||
d := &tests.MockDriver{
|
||||
Port: port,
|
||||
BaseDriver: drivers.BaseDriver{
|
||||
IPAddress: "127.0.0.1",
|
||||
SSHKeyPath: "",
|
||||
},
|
||||
}
|
||||
api.Hosts[constants.MachineName] = &host.Host{Driver: d}
|
||||
|
||||
if _, err := GetHostLogs(api); err != nil {
|
||||
t.Fatalf("Error getting host logs: %s", err)
|
||||
}
|
||||
|
||||
if _, ok := s.Commands[logsCommand]; !ok {
|
||||
t.Fatalf("Expected command not run: %s", logsCommand)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,13 @@ limitations under the License.
|
|||
|
||||
package cluster
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
remoteLocalKubeErrPath = "/var/log/localkube.err"
|
||||
remoteLocalKubeOutPath = "/var/log/localkube.out"
|
||||
)
|
||||
|
||||
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 --generate-certs=false > /var/log/localkube.out 2> /var/log/localkube.err < /dev/null &
|
||||
|
@ -23,3 +30,5 @@ PATH=/usr/local/sbin:$PATH nohup sudo /usr/local/bin/localkube start --generate-
|
|||
|
||||
// Kill any running instances.
|
||||
var stopCommand = "killall localkube | true"
|
||||
|
||||
var logsCommand = fmt.Sprintf("tail -n +1 %s %s", remoteLocalKubeErrPath, remoteLocalKubeOutPath)
|
||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
|||
package sshutil
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
|
@ -49,8 +48,8 @@ func TestNewSSHClient(t *testing.T) {
|
|||
t.Fatalf("Error!")
|
||||
}
|
||||
|
||||
if !strings.Contains(s.Commands[0], cmd) {
|
||||
t.Fatalf("Expected command: %s, got %s", cmd, s.Commands[0])
|
||||
if _, ok := s.Commands[cmd]; !ok {
|
||||
t.Fatalf("Expected command: %s", cmd)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
|
@ -31,7 +32,7 @@ import (
|
|||
type SSHServer struct {
|
||||
Config *ssh.ServerConfig
|
||||
// Commands stores the raw commands executed against the server.
|
||||
Commands []string
|
||||
Commands map[string]int
|
||||
Connected bool
|
||||
Transfers *bytes.Buffer
|
||||
}
|
||||
|
@ -43,6 +44,7 @@ func NewSSHServer() (*SSHServer, error) {
|
|||
s.Config = &ssh.ServerConfig{
|
||||
NoClientAuth: true,
|
||||
}
|
||||
s.Commands = make(map[string]int)
|
||||
|
||||
private, err := rsa.GenerateKey(rand.Reader, 2014)
|
||||
if err != nil {
|
||||
|
@ -56,6 +58,10 @@ func NewSSHServer() (*SSHServer, error) {
|
|||
return s, nil
|
||||
}
|
||||
|
||||
type execRequest struct {
|
||||
Command string
|
||||
}
|
||||
|
||||
// Start starts the mock SSH Server, and returns the port it's listening on.
|
||||
func (s *SSHServer) Start() (int, error) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
|
@ -88,7 +94,14 @@ func (s *SSHServer) Start() (int, error) {
|
|||
|
||||
req := <-requests
|
||||
req.Reply(true, nil)
|
||||
s.Commands = append(s.Commands, string(req.Payload))
|
||||
|
||||
//Note: string(req.Payload) adds additional characters to start of input, execRequest used to solve this issue
|
||||
var cmd execRequest
|
||||
if err := ssh.Unmarshal(req.Payload, &cmd); err != nil {
|
||||
log.Println("Unmarshall encountered error: %s", err)
|
||||
return
|
||||
}
|
||||
s.Commands[cmd.Command] = 1
|
||||
channel.SendRequest("exit-status", false, []byte{0, 0, 0, 0})
|
||||
|
||||
// Store anything that comes in over stdin.
|
||||
|
|
Loading…
Reference in New Issue