Merge pull request #457 from dchen1107/minionlogs

Add support to query kubelet's logs and cadvisor's stats through apiserver by passing rawquery
This commit is contained in:
Daniel Smith
2014-07-21 16:02:44 -07:00
91 changed files with 30435 additions and 0 deletions

View File

@@ -59,6 +59,8 @@ type CadvisorInterface interface {
}
// New creates a new Kubelet.
// TODO: currently it is only called by test code.
// Need cleanup.
func New() *Kubelet {
return &Kubelet{}
}
@@ -77,6 +79,7 @@ type Kubelet struct {
HTTPCheckFrequency time.Duration
pullLock sync.Mutex
HealthChecker health.HealthChecker
LogServer http.Handler
}
type manifestUpdate struct {
@@ -94,6 +97,9 @@ const (
// RunKubelet starts background goroutines. If config_path, manifest_url, or address are empty,
// they are not watched. Never returns.
func (kl *Kubelet) RunKubelet(dockerEndpoint, configPath, manifestURL string, etcdServers []string, address string, port uint) {
if kl.LogServer == nil {
kl.LogServer = http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log/")))
}
if kl.CadvisorClient == nil {
var err error
kl.CadvisorClient, err = cadvisor.NewClient("http://127.0.0.1:5000")
@@ -814,3 +820,9 @@ func (kl *Kubelet) healthy(container api.Container, dockerContainer *docker.APIC
}
return kl.HealthChecker.HealthCheck(container)
}
// Returns logs of current machine.
func (kl *Kubelet) ServeLogs(w http.ResponseWriter, req *http.Request) {
// TODO: whitelist logs we are willing to serve
kl.LogServer.ServeHTTP(w, req)
}

View File

@@ -47,6 +47,7 @@ type kubeletInterface interface {
GetRootInfo(req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
GetMachineInfo() (*info.MachineInfo, error)
GetPodInfo(name string) (api.PodInfo, error)
ServeLogs(w http.ResponseWriter, req *http.Request)
}
func (s *Server) error(w http.ResponseWriter, err error) {
@@ -131,6 +132,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
w.Header().Add("Content-type", "application/json")
w.Write(data)
case strings.HasPrefix(u.Path, "/logs/"):
s.Kubelet.ServeLogs(w, req)
default:
s.DelegateHandler.ServeHTTP(w, req)
}

View File

@@ -23,7 +23,9 @@ import (
"io/ioutil"
"net/http"
"net/http/httptest"
"net/http/httputil"
"reflect"
"strings"
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
@@ -37,6 +39,7 @@ type fakeKubelet struct {
containerInfoFunc func(podID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
rootInfoFunc func(query *info.ContainerInfoRequest) (*info.ContainerInfo, error)
machineInfoFunc func() (*info.MachineInfo, error)
logFunc func(w http.ResponseWriter, req *http.Request)
}
func (fk *fakeKubelet) GetPodInfo(name string) (api.PodInfo, error) {
@@ -55,6 +58,10 @@ func (fk *fakeKubelet) GetMachineInfo() (*info.MachineInfo, error) {
return fk.machineInfoFunc()
}
func (fk *fakeKubelet) ServeLogs(w http.ResponseWriter, req *http.Request) {
fk.logFunc(w, req)
}
type serverTestFramework struct {
updateChan chan manifestUpdate
updateReader *channelReader
@@ -253,3 +260,31 @@ func TestMachineInfo(t *testing.T) {
t.Errorf("received wrong data: %#v", receivedInfo)
}
}
func TestServeLogs(t *testing.T) {
fw := makeServerTest()
content := string(`<pre><a href="kubelet.log">kubelet.log</a><a href="google.log">google.log</a></pre>`)
fw.fakeKubelet.logFunc = func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "text/html")
w.Write([]byte(content))
}
resp, err := http.Get(fw.testHTTPServer.URL + "/logs/")
if err != nil {
t.Fatalf("Got error GETing: %v", err)
}
defer resp.Body.Close()
body, err := httputil.DumpResponse(resp, true)
if err != nil {
// copying the response body did not work
t.Errorf("Cannot copy resp: %#v", err)
}
result := string(body)
if !strings.Contains(result, "kubelet.log") || !strings.Contains(result, "google.log") {
t.Errorf("Received wrong data: %s", result)
}
}