Remove unneeded deps
This commit is contained in:
34
vendor/github.com/google/cadvisor/api/BUILD
generated
vendored
34
vendor/github.com/google/cadvisor/api/BUILD
generated
vendored
@@ -1,34 +0,0 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"handler.go",
|
||||
"versions.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/api",
|
||||
importpath = "github.com/google/cadvisor/api",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/events:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/http/mux:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/info/v2:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/manager:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
250
vendor/github.com/google/cadvisor/api/handler.go
generated
vendored
250
vendor/github.com/google/cadvisor/api/handler.go
generated
vendored
@@ -1,250 +0,0 @@
|
||||
// Copyright 2014 Google Inc. 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 api provides a handler for /api/
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/cadvisor/events"
|
||||
httpmux "github.com/google/cadvisor/http/mux"
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
"github.com/google/cadvisor/manager"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
apiResource = "/api/"
|
||||
)
|
||||
|
||||
func RegisterHandlers(mux httpmux.Mux, m manager.Manager) error {
|
||||
apiVersions := getApiVersions()
|
||||
supportedApiVersions := make(map[string]ApiVersion, len(apiVersions))
|
||||
for _, v := range apiVersions {
|
||||
supportedApiVersions[v.Version()] = v
|
||||
}
|
||||
|
||||
mux.HandleFunc(apiResource, func(w http.ResponseWriter, r *http.Request) {
|
||||
err := handleRequest(supportedApiVersions, m, w, r)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
}
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Captures the API version, requestType [optional], and remaining request [optional].
|
||||
var apiRegexp = regexp.MustCompile(`/api/([^/]+)/?([^/]+)?(.*)`)
|
||||
|
||||
const (
|
||||
apiVersion = iota + 1
|
||||
apiRequestType
|
||||
apiRequestArgs
|
||||
)
|
||||
|
||||
func handleRequest(supportedApiVersions map[string]ApiVersion, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
glog.V(4).Infof("Request took %s", time.Since(start))
|
||||
}()
|
||||
|
||||
request := r.URL.Path
|
||||
|
||||
const apiPrefix = "/api"
|
||||
if !strings.HasPrefix(request, apiPrefix) {
|
||||
return fmt.Errorf("incomplete API request %q", request)
|
||||
}
|
||||
|
||||
// If the request doesn't have an API version, list those.
|
||||
if request == apiPrefix || request == apiResource {
|
||||
versions := make([]string, 0, len(supportedApiVersions))
|
||||
for v := range supportedApiVersions {
|
||||
versions = append(versions, v)
|
||||
}
|
||||
sort.Strings(versions)
|
||||
http.Error(w, fmt.Sprintf("Supported API versions: %s", strings.Join(versions, ",")), http.StatusBadRequest)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify that we have all the elements we expect:
|
||||
// /<version>/<request type>[/<args...>]
|
||||
requestElements := apiRegexp.FindStringSubmatch(request)
|
||||
if len(requestElements) == 0 {
|
||||
return fmt.Errorf("malformed request %q", request)
|
||||
}
|
||||
version := requestElements[apiVersion]
|
||||
requestType := requestElements[apiRequestType]
|
||||
requestArgs := strings.Split(requestElements[apiRequestArgs], "/")
|
||||
|
||||
// Check supported versions.
|
||||
versionHandler, ok := supportedApiVersions[version]
|
||||
if !ok {
|
||||
return fmt.Errorf("unsupported API version %q", version)
|
||||
}
|
||||
|
||||
// If no request type, list possible request types.
|
||||
if requestType == "" {
|
||||
requestTypes := versionHandler.SupportedRequestTypes()
|
||||
sort.Strings(requestTypes)
|
||||
http.Error(w, fmt.Sprintf("Supported request types: %q", strings.Join(requestTypes, ",")), http.StatusBadRequest)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Trim the first empty element from the request.
|
||||
if len(requestArgs) > 0 && requestArgs[0] == "" {
|
||||
requestArgs = requestArgs[1:]
|
||||
}
|
||||
|
||||
return versionHandler.HandleRequest(requestType, requestArgs, m, w, r)
|
||||
|
||||
}
|
||||
|
||||
func writeResult(res interface{}, w http.ResponseWriter) error {
|
||||
out, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshall response %+v with error: %s", res, err)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(out)
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func streamResults(eventChannel *events.EventChannel, w http.ResponseWriter, r *http.Request, m manager.Manager) error {
|
||||
cn, ok := w.(http.CloseNotifier)
|
||||
if !ok {
|
||||
return errors.New("could not access http.CloseNotifier")
|
||||
}
|
||||
flusher, ok := w.(http.Flusher)
|
||||
if !ok {
|
||||
return errors.New("could not access http.Flusher")
|
||||
}
|
||||
|
||||
w.Header().Set("Transfer-Encoding", "chunked")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
flusher.Flush()
|
||||
|
||||
enc := json.NewEncoder(w)
|
||||
for {
|
||||
select {
|
||||
case <-cn.CloseNotify():
|
||||
m.CloseEventChannel(eventChannel.GetWatchId())
|
||||
return nil
|
||||
case ev := <-eventChannel.GetChannel():
|
||||
err := enc.Encode(ev)
|
||||
if err != nil {
|
||||
glog.Errorf("error encoding message %+v for result stream: %v", ev, err)
|
||||
}
|
||||
flusher.Flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getContainerInfoRequest(body io.ReadCloser) (*info.ContainerInfoRequest, error) {
|
||||
query := info.DefaultContainerInfoRequest()
|
||||
decoder := json.NewDecoder(body)
|
||||
err := decoder.Decode(&query)
|
||||
if err != nil && err != io.EOF {
|
||||
return nil, fmt.Errorf("unable to decode the json value: %s", err)
|
||||
}
|
||||
|
||||
return &query, nil
|
||||
}
|
||||
|
||||
// The user can set any or none of the following arguments in any order
|
||||
// with any twice defined arguments being assigned the first value.
|
||||
// If the value type for the argument is wrong the field will be assumed to be
|
||||
// unassigned
|
||||
// bools: stream, subcontainers, oom_events, creation_events, deletion_events
|
||||
// ints: max_events, start_time (unix timestamp), end_time (unix timestamp)
|
||||
// example r.URL: http://localhost:8080/api/v1.3/events?oom_events=true&stream=true
|
||||
func getEventRequest(r *http.Request) (*events.Request, bool, error) {
|
||||
query := events.NewRequest()
|
||||
stream := false
|
||||
|
||||
urlMap := r.URL.Query()
|
||||
|
||||
if val, ok := urlMap["stream"]; ok {
|
||||
newBool, err := strconv.ParseBool(val[0])
|
||||
if err == nil {
|
||||
stream = newBool
|
||||
}
|
||||
}
|
||||
if val, ok := urlMap["subcontainers"]; ok {
|
||||
newBool, err := strconv.ParseBool(val[0])
|
||||
if err == nil {
|
||||
query.IncludeSubcontainers = newBool
|
||||
}
|
||||
}
|
||||
eventTypes := map[string]info.EventType{
|
||||
"oom_events": info.EventOom,
|
||||
"oom_kill_events": info.EventOomKill,
|
||||
"creation_events": info.EventContainerCreation,
|
||||
"deletion_events": info.EventContainerDeletion,
|
||||
}
|
||||
allEventTypes := false
|
||||
if val, ok := urlMap["all_events"]; ok {
|
||||
newBool, err := strconv.ParseBool(val[0])
|
||||
if err == nil {
|
||||
allEventTypes = newBool
|
||||
}
|
||||
}
|
||||
for opt, eventType := range eventTypes {
|
||||
if allEventTypes {
|
||||
query.EventType[eventType] = true
|
||||
} else if val, ok := urlMap[opt]; ok {
|
||||
newBool, err := strconv.ParseBool(val[0])
|
||||
if err == nil {
|
||||
query.EventType[eventType] = newBool
|
||||
}
|
||||
}
|
||||
}
|
||||
if val, ok := urlMap["max_events"]; ok {
|
||||
newInt, err := strconv.Atoi(val[0])
|
||||
if err == nil {
|
||||
query.MaxEventsReturned = int(newInt)
|
||||
}
|
||||
}
|
||||
if val, ok := urlMap["start_time"]; ok {
|
||||
newTime, err := time.Parse(time.RFC3339, val[0])
|
||||
if err == nil {
|
||||
query.StartTime = newTime
|
||||
}
|
||||
}
|
||||
if val, ok := urlMap["end_time"]; ok {
|
||||
newTime, err := time.Parse(time.RFC3339, val[0])
|
||||
if err == nil {
|
||||
query.EndTime = newTime
|
||||
}
|
||||
}
|
||||
|
||||
return query, stream, nil
|
||||
}
|
||||
|
||||
func getContainerName(request []string) string {
|
||||
return path.Join("/", strings.Join(request, "/"))
|
||||
}
|
559
vendor/github.com/google/cadvisor/api/versions.go
generated
vendored
559
vendor/github.com/google/cadvisor/api/versions.go
generated
vendored
@@ -1,559 +0,0 @@
|
||||
// Copyright 2015 Google Inc. 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 api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
"github.com/google/cadvisor/info/v2"
|
||||
"github.com/google/cadvisor/manager"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
containersApi = "containers"
|
||||
subcontainersApi = "subcontainers"
|
||||
machineApi = "machine"
|
||||
machineStatsApi = "machinestats"
|
||||
dockerApi = "docker"
|
||||
summaryApi = "summary"
|
||||
statsApi = "stats"
|
||||
specApi = "spec"
|
||||
eventsApi = "events"
|
||||
storageApi = "storage"
|
||||
attributesApi = "attributes"
|
||||
versionApi = "version"
|
||||
psApi = "ps"
|
||||
customMetricsApi = "appmetrics"
|
||||
)
|
||||
|
||||
// Interface for a cAdvisor API version
|
||||
type ApiVersion interface {
|
||||
// Returns the version string.
|
||||
Version() string
|
||||
|
||||
// List of supported API endpoints.
|
||||
SupportedRequestTypes() []string
|
||||
|
||||
// Handles a request. The second argument is the parameters after /api/<version>/<endpoint>
|
||||
HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error
|
||||
}
|
||||
|
||||
// Gets all supported API versions.
|
||||
func getApiVersions() []ApiVersion {
|
||||
v1_0 := &version1_0{}
|
||||
v1_1 := newVersion1_1(v1_0)
|
||||
v1_2 := newVersion1_2(v1_1)
|
||||
v1_3 := newVersion1_3(v1_2)
|
||||
v2_0 := newVersion2_0()
|
||||
v2_1 := newVersion2_1(v2_0)
|
||||
|
||||
return []ApiVersion{v1_0, v1_1, v1_2, v1_3, v2_0, v2_1}
|
||||
|
||||
}
|
||||
|
||||
// API v1.0
|
||||
|
||||
type version1_0 struct {
|
||||
}
|
||||
|
||||
func (self *version1_0) Version() string {
|
||||
return "v1.0"
|
||||
}
|
||||
|
||||
func (self *version1_0) SupportedRequestTypes() []string {
|
||||
return []string{containersApi, machineApi}
|
||||
}
|
||||
|
||||
func (self *version1_0) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
|
||||
switch requestType {
|
||||
case machineApi:
|
||||
glog.V(4).Infof("Api - Machine")
|
||||
|
||||
// Get the MachineInfo
|
||||
machineInfo, err := m.GetMachineInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeResult(machineInfo, w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case containersApi:
|
||||
containerName := getContainerName(request)
|
||||
glog.V(4).Infof("Api - Container(%s)", containerName)
|
||||
|
||||
// Get the query request.
|
||||
query, err := getContainerInfoRequest(r.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the container.
|
||||
cont, err := m.GetContainerInfo(containerName, query)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get container %q with error: %s", containerName, err)
|
||||
}
|
||||
|
||||
// Only output the container as JSON.
|
||||
err = writeResult(cont, w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown request type %q", requestType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// API v1.1
|
||||
|
||||
type version1_1 struct {
|
||||
baseVersion *version1_0
|
||||
}
|
||||
|
||||
// v1.1 builds on v1.0.
|
||||
func newVersion1_1(v *version1_0) *version1_1 {
|
||||
return &version1_1{
|
||||
baseVersion: v,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *version1_1) Version() string {
|
||||
return "v1.1"
|
||||
}
|
||||
|
||||
func (self *version1_1) SupportedRequestTypes() []string {
|
||||
return append(self.baseVersion.SupportedRequestTypes(), subcontainersApi)
|
||||
}
|
||||
|
||||
func (self *version1_1) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
|
||||
switch requestType {
|
||||
case subcontainersApi:
|
||||
containerName := getContainerName(request)
|
||||
glog.V(4).Infof("Api - Subcontainers(%s)", containerName)
|
||||
|
||||
// Get the query request.
|
||||
query, err := getContainerInfoRequest(r.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the subcontainers.
|
||||
containers, err := m.SubcontainersInfo(containerName, query)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get subcontainers for container %q with error: %s", containerName, err)
|
||||
}
|
||||
|
||||
// Only output the containers as JSON.
|
||||
err = writeResult(containers, w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return self.baseVersion.HandleRequest(requestType, request, m, w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// API v1.2
|
||||
|
||||
type version1_2 struct {
|
||||
baseVersion *version1_1
|
||||
}
|
||||
|
||||
// v1.2 builds on v1.1.
|
||||
func newVersion1_2(v *version1_1) *version1_2 {
|
||||
return &version1_2{
|
||||
baseVersion: v,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *version1_2) Version() string {
|
||||
return "v1.2"
|
||||
}
|
||||
|
||||
func (self *version1_2) SupportedRequestTypes() []string {
|
||||
return append(self.baseVersion.SupportedRequestTypes(), dockerApi)
|
||||
}
|
||||
|
||||
func (self *version1_2) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
|
||||
switch requestType {
|
||||
case dockerApi:
|
||||
glog.V(4).Infof("Api - Docker(%v)", request)
|
||||
|
||||
// Get the query request.
|
||||
query, err := getContainerInfoRequest(r.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var containers map[string]info.ContainerInfo
|
||||
// map requests for "docker/" to "docker"
|
||||
if len(request) == 1 && len(request[0]) == 0 {
|
||||
request = request[:0]
|
||||
}
|
||||
switch len(request) {
|
||||
case 0:
|
||||
// Get all Docker containers.
|
||||
containers, err = m.AllDockerContainers(query)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get all Docker containers with error: %v", err)
|
||||
}
|
||||
case 1:
|
||||
// Get one Docker container.
|
||||
var cont info.ContainerInfo
|
||||
cont, err = m.DockerContainer(request[0], query)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get Docker container %q with error: %v", request[0], err)
|
||||
}
|
||||
containers = map[string]info.ContainerInfo{
|
||||
cont.Name: cont,
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown request for Docker container %v", request)
|
||||
}
|
||||
|
||||
// Only output the containers as JSON.
|
||||
err = writeResult(containers, w)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return self.baseVersion.HandleRequest(requestType, request, m, w, r)
|
||||
}
|
||||
}
|
||||
|
||||
// API v1.3
|
||||
|
||||
type version1_3 struct {
|
||||
baseVersion *version1_2
|
||||
}
|
||||
|
||||
// v1.3 builds on v1.2.
|
||||
func newVersion1_3(v *version1_2) *version1_3 {
|
||||
return &version1_3{
|
||||
baseVersion: v,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *version1_3) Version() string {
|
||||
return "v1.3"
|
||||
}
|
||||
|
||||
func (self *version1_3) SupportedRequestTypes() []string {
|
||||
return append(self.baseVersion.SupportedRequestTypes(), eventsApi)
|
||||
}
|
||||
|
||||
func (self *version1_3) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
|
||||
switch requestType {
|
||||
case eventsApi:
|
||||
return handleEventRequest(request, m, w, r)
|
||||
default:
|
||||
return self.baseVersion.HandleRequest(requestType, request, m, w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func handleEventRequest(request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
|
||||
query, stream, err := getEventRequest(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
query.ContainerName = path.Join("/", getContainerName(request))
|
||||
glog.V(4).Infof("Api - Events(%v)", query)
|
||||
if !stream {
|
||||
pastEvents, err := m.GetPastEvents(query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeResult(pastEvents, w)
|
||||
}
|
||||
eventChannel, err := m.WatchForEvents(query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return streamResults(eventChannel, w, r, m)
|
||||
|
||||
}
|
||||
|
||||
// API v2.0
|
||||
|
||||
type version2_0 struct {
|
||||
}
|
||||
|
||||
func newVersion2_0() *version2_0 {
|
||||
return &version2_0{}
|
||||
}
|
||||
|
||||
func (self *version2_0) Version() string {
|
||||
return "v2.0"
|
||||
}
|
||||
|
||||
func (self *version2_0) SupportedRequestTypes() []string {
|
||||
return []string{versionApi, attributesApi, eventsApi, machineApi, summaryApi, statsApi, specApi, storageApi, psApi, customMetricsApi}
|
||||
}
|
||||
|
||||
func (self *version2_0) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
|
||||
opt, err := getRequestOptions(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch requestType {
|
||||
case versionApi:
|
||||
glog.V(4).Infof("Api - Version")
|
||||
versionInfo, err := m.GetVersionInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeResult(versionInfo.CadvisorVersion, w)
|
||||
case attributesApi:
|
||||
glog.V(4).Info("Api - Attributes")
|
||||
|
||||
machineInfo, err := m.GetMachineInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
versionInfo, err := m.GetVersionInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info := v2.GetAttributes(machineInfo, versionInfo)
|
||||
return writeResult(info, w)
|
||||
case machineApi:
|
||||
glog.V(4).Info("Api - Machine")
|
||||
|
||||
// TODO(rjnagal): Move machineInfo from v1.
|
||||
machineInfo, err := m.GetMachineInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeResult(machineInfo, w)
|
||||
case summaryApi:
|
||||
containerName := getContainerName(request)
|
||||
glog.V(4).Infof("Api - Summary for container %q, options %+v", containerName, opt)
|
||||
|
||||
stats, err := m.GetDerivedStats(containerName, opt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeResult(stats, w)
|
||||
case statsApi:
|
||||
name := getContainerName(request)
|
||||
glog.V(4).Infof("Api - Stats: Looking for stats for container %q, options %+v", name, opt)
|
||||
infos, err := m.GetRequestedContainersInfo(name, opt)
|
||||
if err != nil {
|
||||
if len(infos) == 0 {
|
||||
return err
|
||||
}
|
||||
glog.Errorf("Error calling GetRequestedContainersInfo: %v", err)
|
||||
}
|
||||
contStats := make(map[string][]v2.DeprecatedContainerStats, 0)
|
||||
for name, cinfo := range infos {
|
||||
contStats[name] = v2.DeprecatedStatsFromV1(cinfo)
|
||||
}
|
||||
return writeResult(contStats, w)
|
||||
case customMetricsApi:
|
||||
containerName := getContainerName(request)
|
||||
glog.V(4).Infof("Api - Custom Metrics: Looking for metrics for container %q, options %+v", containerName, opt)
|
||||
infos, err := m.GetContainerInfoV2(containerName, opt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
contMetrics := make(map[string]map[string]map[string][]info.MetricValBasic, 0)
|
||||
for _, cinfo := range infos {
|
||||
metrics := make(map[string]map[string][]info.MetricValBasic, 0)
|
||||
for _, contStat := range cinfo.Stats {
|
||||
if len(contStat.CustomMetrics) == 0 {
|
||||
continue
|
||||
}
|
||||
for name, allLabels := range contStat.CustomMetrics {
|
||||
metricLabels := make(map[string][]info.MetricValBasic, 0)
|
||||
for _, metric := range allLabels {
|
||||
if !metric.Timestamp.IsZero() {
|
||||
metVal := info.MetricValBasic{
|
||||
Timestamp: metric.Timestamp,
|
||||
IntValue: metric.IntValue,
|
||||
FloatValue: metric.FloatValue,
|
||||
}
|
||||
labels := metrics[name]
|
||||
if labels != nil {
|
||||
values := labels[metric.Label]
|
||||
values = append(values, metVal)
|
||||
labels[metric.Label] = values
|
||||
metrics[name] = labels
|
||||
} else {
|
||||
metricLabels[metric.Label] = []info.MetricValBasic{metVal}
|
||||
metrics[name] = metricLabels
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
contMetrics[containerName] = metrics
|
||||
}
|
||||
return writeResult(contMetrics, w)
|
||||
case specApi:
|
||||
containerName := getContainerName(request)
|
||||
glog.V(4).Infof("Api - Spec for container %q, options %+v", containerName, opt)
|
||||
specs, err := m.GetContainerSpec(containerName, opt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeResult(specs, w)
|
||||
case storageApi:
|
||||
label := r.URL.Query().Get("label")
|
||||
uuid := r.URL.Query().Get("uuid")
|
||||
switch {
|
||||
case uuid != "":
|
||||
fi, err := m.GetFsInfoByFsUUID(uuid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeResult(fi, w)
|
||||
case label != "":
|
||||
// Get a specific label.
|
||||
fi, err := m.GetFsInfo(label)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeResult(fi, w)
|
||||
default:
|
||||
// Get all global filesystems info.
|
||||
fi, err := m.GetFsInfo("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeResult(fi, w)
|
||||
}
|
||||
case eventsApi:
|
||||
return handleEventRequest(request, m, w, r)
|
||||
case psApi:
|
||||
// reuse container type from request.
|
||||
// ignore recursive.
|
||||
// TODO(rjnagal): consider count to limit ps output.
|
||||
name := getContainerName(request)
|
||||
glog.V(4).Infof("Api - Spec for container %q, options %+v", name, opt)
|
||||
ps, err := m.GetProcessList(name, opt)
|
||||
if err != nil {
|
||||
return fmt.Errorf("process listing failed: %v", err)
|
||||
}
|
||||
return writeResult(ps, w)
|
||||
default:
|
||||
return fmt.Errorf("unknown request type %q", requestType)
|
||||
}
|
||||
}
|
||||
|
||||
type version2_1 struct {
|
||||
baseVersion *version2_0
|
||||
}
|
||||
|
||||
func newVersion2_1(v *version2_0) *version2_1 {
|
||||
return &version2_1{
|
||||
baseVersion: v,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *version2_1) Version() string {
|
||||
return "v2.1"
|
||||
}
|
||||
|
||||
func (self *version2_1) SupportedRequestTypes() []string {
|
||||
return append([]string{machineStatsApi}, self.baseVersion.SupportedRequestTypes()...)
|
||||
}
|
||||
|
||||
func (self *version2_1) HandleRequest(requestType string, request []string, m manager.Manager, w http.ResponseWriter, r *http.Request) error {
|
||||
// Get the query request.
|
||||
opt, err := getRequestOptions(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch requestType {
|
||||
case machineStatsApi:
|
||||
glog.V(4).Infof("Api - MachineStats(%v)", request)
|
||||
cont, err := m.GetRequestedContainersInfo("/", opt)
|
||||
if err != nil {
|
||||
if len(cont) == 0 {
|
||||
return err
|
||||
}
|
||||
glog.Errorf("Error calling GetRequestedContainersInfo: %v", err)
|
||||
}
|
||||
return writeResult(v2.MachineStatsFromV1(cont["/"]), w)
|
||||
case statsApi:
|
||||
name := getContainerName(request)
|
||||
glog.V(4).Infof("Api - Stats: Looking for stats for container %q, options %+v", name, opt)
|
||||
conts, err := m.GetRequestedContainersInfo(name, opt)
|
||||
if err != nil {
|
||||
if len(conts) == 0 {
|
||||
return err
|
||||
}
|
||||
glog.Errorf("Error calling GetRequestedContainersInfo: %v", err)
|
||||
}
|
||||
contStats := make(map[string]v2.ContainerInfo, len(conts))
|
||||
for name, cont := range conts {
|
||||
if name == "/" {
|
||||
// Root cgroup stats should be exposed as machine stats
|
||||
continue
|
||||
}
|
||||
contStats[name] = v2.ContainerInfo{
|
||||
Spec: v2.ContainerSpecFromV1(&cont.Spec, cont.Aliases, cont.Namespace),
|
||||
Stats: v2.ContainerStatsFromV1(name, &cont.Spec, cont.Stats),
|
||||
}
|
||||
}
|
||||
return writeResult(contStats, w)
|
||||
default:
|
||||
return self.baseVersion.HandleRequest(requestType, request, m, w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func getRequestOptions(r *http.Request) (v2.RequestOptions, error) {
|
||||
supportedTypes := map[string]bool{
|
||||
v2.TypeName: true,
|
||||
v2.TypeDocker: true,
|
||||
}
|
||||
// fill in the defaults.
|
||||
opt := v2.RequestOptions{
|
||||
IdType: v2.TypeName,
|
||||
Count: 64,
|
||||
Recursive: false,
|
||||
}
|
||||
idType := r.URL.Query().Get("type")
|
||||
if len(idType) != 0 {
|
||||
if !supportedTypes[idType] {
|
||||
return opt, fmt.Errorf("unknown 'type' %q", idType)
|
||||
}
|
||||
opt.IdType = idType
|
||||
}
|
||||
count := r.URL.Query().Get("count")
|
||||
if len(count) != 0 {
|
||||
n, err := strconv.ParseUint(count, 10, 32)
|
||||
if err != nil {
|
||||
return opt, fmt.Errorf("failed to parse 'count' option: %v", count)
|
||||
}
|
||||
opt.Count = int(n)
|
||||
}
|
||||
recursive := r.URL.Query().Get("recursive")
|
||||
if recursive == "true" {
|
||||
opt.Recursive = true
|
||||
}
|
||||
return opt, nil
|
||||
}
|
24
vendor/github.com/google/cadvisor/healthz/BUILD
generated
vendored
24
vendor/github.com/google/cadvisor/healthz/BUILD
generated
vendored
@@ -1,24 +0,0 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["healthz.go"],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/healthz",
|
||||
importpath = "github.com/google/cadvisor/healthz",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//vendor/github.com/google/cadvisor/http/mux:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
32
vendor/github.com/google/cadvisor/healthz/healthz.go
generated
vendored
32
vendor/github.com/google/cadvisor/healthz/healthz.go
generated
vendored
@@ -1,32 +0,0 @@
|
||||
// Copyright 2014 Google Inc. 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 healthz
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
httpmux "github.com/google/cadvisor/http/mux"
|
||||
)
|
||||
|
||||
func handleHealthz(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte("ok"))
|
||||
}
|
||||
|
||||
// Register simple HTTP /healthz handler to return "ok".
|
||||
func RegisterHandler(mux httpmux.Mux) error {
|
||||
mux.HandleFunc("/healthz", handleHealthz)
|
||||
return nil
|
||||
}
|
40
vendor/github.com/google/cadvisor/http/BUILD
generated
vendored
40
vendor/github.com/google/cadvisor/http/BUILD
generated
vendored
@@ -1,40 +0,0 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["handlers.go"],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/http",
|
||||
importpath = "github.com/google/cadvisor/http",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/abbot/go-http-auth:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/api:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/healthz:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/http/mux:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/manager:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/metrics:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/pages:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/pages/static:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/validate:go_default_library",
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus/promhttp:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//vendor/github.com/google/cadvisor/http/mux:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
112
vendor/github.com/google/cadvisor/http/handlers.go
generated
vendored
112
vendor/github.com/google/cadvisor/http/handlers.go
generated
vendored
@@ -1,112 +0,0 @@
|
||||
// Copyright 2015 Google Inc. 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 http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/google/cadvisor/api"
|
||||
"github.com/google/cadvisor/healthz"
|
||||
httpmux "github.com/google/cadvisor/http/mux"
|
||||
"github.com/google/cadvisor/manager"
|
||||
"github.com/google/cadvisor/metrics"
|
||||
"github.com/google/cadvisor/pages"
|
||||
"github.com/google/cadvisor/pages/static"
|
||||
"github.com/google/cadvisor/validate"
|
||||
|
||||
auth "github.com/abbot/go-http-auth"
|
||||
"github.com/golang/glog"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
func RegisterHandlers(mux httpmux.Mux, containerManager manager.Manager, httpAuthFile, httpAuthRealm, httpDigestFile, httpDigestRealm string) error {
|
||||
// Basic health handler.
|
||||
if err := healthz.RegisterHandler(mux); err != nil {
|
||||
return fmt.Errorf("failed to register healthz handler: %s", err)
|
||||
}
|
||||
|
||||
// Validation/Debug handler.
|
||||
mux.HandleFunc(validate.ValidatePage, func(w http.ResponseWriter, r *http.Request) {
|
||||
err := validate.HandleRequest(w, containerManager)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
})
|
||||
|
||||
// Register API handler.
|
||||
if err := api.RegisterHandlers(mux, containerManager); err != nil {
|
||||
return fmt.Errorf("failed to register API handlers: %s", err)
|
||||
}
|
||||
|
||||
// Redirect / to containers page.
|
||||
mux.Handle("/", http.RedirectHandler(pages.ContainersPage, http.StatusTemporaryRedirect))
|
||||
|
||||
var authenticated bool
|
||||
|
||||
// Setup the authenticator object
|
||||
if httpAuthFile != "" {
|
||||
glog.V(1).Infof("Using auth file %s", httpAuthFile)
|
||||
secrets := auth.HtpasswdFileProvider(httpAuthFile)
|
||||
authenticator := auth.NewBasicAuthenticator(httpAuthRealm, secrets)
|
||||
mux.HandleFunc(static.StaticResource, authenticator.Wrap(staticHandler))
|
||||
if err := pages.RegisterHandlersBasic(mux, containerManager, authenticator); err != nil {
|
||||
return fmt.Errorf("failed to register pages auth handlers: %s", err)
|
||||
}
|
||||
authenticated = true
|
||||
}
|
||||
if httpAuthFile == "" && httpDigestFile != "" {
|
||||
glog.V(1).Infof("Using digest file %s", httpDigestFile)
|
||||
secrets := auth.HtdigestFileProvider(httpDigestFile)
|
||||
authenticator := auth.NewDigestAuthenticator(httpDigestRealm, secrets)
|
||||
mux.HandleFunc(static.StaticResource, authenticator.Wrap(staticHandler))
|
||||
if err := pages.RegisterHandlersDigest(mux, containerManager, authenticator); err != nil {
|
||||
return fmt.Errorf("failed to register pages digest handlers: %s", err)
|
||||
}
|
||||
authenticated = true
|
||||
}
|
||||
|
||||
// Change handler based on authenticator initalization
|
||||
if !authenticated {
|
||||
mux.HandleFunc(static.StaticResource, staticHandlerNoAuth)
|
||||
if err := pages.RegisterHandlersBasic(mux, containerManager, nil); err != nil {
|
||||
return fmt.Errorf("failed to register pages handlers: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterPrometheusHandler creates a new PrometheusCollector and configures
|
||||
// the provided HTTP mux to handle the given Prometheus endpoint.
|
||||
func RegisterPrometheusHandler(mux httpmux.Mux, containerManager manager.Manager, prometheusEndpoint string, f metrics.ContainerLabelsFunc) {
|
||||
r := prometheus.NewRegistry()
|
||||
r.MustRegister(
|
||||
metrics.NewPrometheusCollector(containerManager, f),
|
||||
prometheus.NewGoCollector(),
|
||||
prometheus.NewProcessCollector(os.Getpid(), ""),
|
||||
)
|
||||
mux.Handle(prometheusEndpoint, promhttp.HandlerFor(r, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}))
|
||||
}
|
||||
|
||||
func staticHandlerNoAuth(w http.ResponseWriter, r *http.Request) {
|
||||
static.HandleRequest(w, r.URL)
|
||||
}
|
||||
|
||||
func staticHandler(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
|
||||
static.HandleRequest(w, r.URL)
|
||||
}
|
23
vendor/github.com/google/cadvisor/http/mux/BUILD
generated
vendored
23
vendor/github.com/google/cadvisor/http/mux/BUILD
generated
vendored
@@ -1,23 +0,0 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["mux.go"],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/http/mux",
|
||||
importpath = "github.com/google/cadvisor/http/mux",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
26
vendor/github.com/google/cadvisor/http/mux/mux.go
generated
vendored
26
vendor/github.com/google/cadvisor/http/mux/mux.go
generated
vendored
@@ -1,26 +0,0 @@
|
||||
// Copyright 2015 Google Inc. 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 mux
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Mux interface expected by cAdvisor components.
|
||||
type Mux interface {
|
||||
HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
|
||||
Handler(r *http.Request) (http.Handler, string)
|
||||
Handle(pattern string, handler http.Handler)
|
||||
}
|
39
vendor/github.com/google/cadvisor/pages/BUILD
generated
vendored
39
vendor/github.com/google/cadvisor/pages/BUILD
generated
vendored
@@ -1,39 +0,0 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"containers.go",
|
||||
"docker.go",
|
||||
"pages.go",
|
||||
"templates.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/pages",
|
||||
importpath = "github.com/google/cadvisor/pages",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/abbot/go-http-auth:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/container/docker:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/http/mux:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/info/v1:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/manager:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//vendor/github.com/google/cadvisor/pages/static:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
253
vendor/github.com/google/cadvisor/pages/containers.go
generated
vendored
253
vendor/github.com/google/cadvisor/pages/containers.go
generated
vendored
@@ -1,253 +0,0 @@
|
||||
// Copyright 2014 Google Inc. 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.
|
||||
|
||||
// Page for /containers/
|
||||
package pages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
"github.com/google/cadvisor/manager"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const ContainersPage = "/containers/"
|
||||
|
||||
// from http://golang.org/doc/effective_go.html#constants
|
||||
type ByteSize float64
|
||||
|
||||
const (
|
||||
_ = iota
|
||||
// KB - kilobyte
|
||||
KB ByteSize = 1 << (10 * iota)
|
||||
// MB - megabyte
|
||||
MB
|
||||
// GB - gigabyte
|
||||
GB
|
||||
// TB - terabyte
|
||||
TB
|
||||
// PB - petabyte
|
||||
PB
|
||||
// EB - exabyte
|
||||
EB
|
||||
// ZB - zettabyte
|
||||
ZB
|
||||
// YB - yottabyte
|
||||
YB
|
||||
)
|
||||
|
||||
func (b ByteSize) Size() string {
|
||||
for _, i := range [...]ByteSize{YB, ZB, EB, PB, TB, GB, MB, KB} {
|
||||
if b >= i {
|
||||
return fmt.Sprintf("%.2f", b/i)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("%.2f", b)
|
||||
}
|
||||
|
||||
func (b ByteSize) Unit() string {
|
||||
switch {
|
||||
case b >= YB:
|
||||
return "YB"
|
||||
case b >= ZB:
|
||||
return "ZB"
|
||||
case b >= EB:
|
||||
return "EB"
|
||||
case b >= PB:
|
||||
return "PB"
|
||||
case b >= TB:
|
||||
return "TB"
|
||||
case b >= GB:
|
||||
return "GB"
|
||||
case b >= MB:
|
||||
return "MB"
|
||||
case b >= KB:
|
||||
return "KB"
|
||||
}
|
||||
return "B"
|
||||
}
|
||||
|
||||
var funcMap = template.FuncMap{
|
||||
"printMask": printMask,
|
||||
"printCores": printCores,
|
||||
"printShares": printShares,
|
||||
"printSize": printSize,
|
||||
"printUnit": printUnit,
|
||||
}
|
||||
|
||||
func printMask(mask string, numCores int) interface{} {
|
||||
masks := make([]string, numCores)
|
||||
activeCores := getActiveCores(mask)
|
||||
for i := 0; i < numCores; i++ {
|
||||
coreClass := "inactive-cpu"
|
||||
if activeCores[i] {
|
||||
coreClass = "active-cpu"
|
||||
}
|
||||
masks[i] = fmt.Sprintf("<span class=\"%s\">%d</span>", coreClass, i)
|
||||
}
|
||||
return template.HTML(strings.Join(masks, " "))
|
||||
}
|
||||
|
||||
func getActiveCores(mask string) map[int]bool {
|
||||
activeCores := make(map[int]bool)
|
||||
for _, corebits := range strings.Split(mask, ",") {
|
||||
cores := strings.Split(corebits, "-")
|
||||
if len(cores) == 1 {
|
||||
index, err := strconv.Atoi(cores[0])
|
||||
if err != nil {
|
||||
// Ignore malformed strings.
|
||||
continue
|
||||
}
|
||||
activeCores[index] = true
|
||||
} else if len(cores) == 2 {
|
||||
start, err := strconv.Atoi(cores[0])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
end, err := strconv.Atoi(cores[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for i := start; i <= end; i++ {
|
||||
activeCores[i] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return activeCores
|
||||
}
|
||||
|
||||
func printCores(millicores *uint64) string {
|
||||
cores := float64(*millicores) / 1000
|
||||
return strconv.FormatFloat(cores, 'f', 3, 64)
|
||||
}
|
||||
|
||||
func printShares(shares *uint64) string {
|
||||
return fmt.Sprintf("%d", *shares)
|
||||
}
|
||||
|
||||
// Size after which we consider memory to be "unlimited". This is not
|
||||
// MaxInt64 due to rounding by the kernel.
|
||||
const maxMemorySize = uint64(1 << 62)
|
||||
|
||||
func printSize(bytes uint64) string {
|
||||
if bytes >= maxMemorySize {
|
||||
return "unlimited"
|
||||
}
|
||||
return ByteSize(bytes).Size()
|
||||
}
|
||||
|
||||
func printUnit(bytes uint64) string {
|
||||
if bytes >= maxMemorySize {
|
||||
return ""
|
||||
}
|
||||
return ByteSize(bytes).Unit()
|
||||
}
|
||||
|
||||
func serveContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) {
|
||||
start := time.Now()
|
||||
|
||||
// The container name is the path after the handler
|
||||
containerName := u.Path[len(ContainersPage)-1:]
|
||||
|
||||
// Get the container.
|
||||
reqParams := info.ContainerInfoRequest{
|
||||
NumStats: 60,
|
||||
}
|
||||
cont, err := m.GetContainerInfo(containerName, &reqParams)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get container %q with error: %v", containerName, err), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
displayName := getContainerDisplayName(cont.ContainerReference)
|
||||
|
||||
// Get the MachineInfo
|
||||
machineInfo, err := m.GetMachineInfo()
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get machine info: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
rootDir := getRootDir(containerName)
|
||||
|
||||
// Make a list of the parent containers and their links
|
||||
pathParts := strings.Split(string(cont.Name), "/")
|
||||
parentContainers := make([]link, 0, len(pathParts))
|
||||
parentContainers = append(parentContainers, link{
|
||||
Text: "root",
|
||||
Link: path.Join(rootDir, ContainersPage),
|
||||
})
|
||||
for i := 1; i < len(pathParts); i++ {
|
||||
// Skip empty parts.
|
||||
if pathParts[i] == "" {
|
||||
continue
|
||||
}
|
||||
parentContainers = append(parentContainers, link{
|
||||
Text: pathParts[i],
|
||||
Link: path.Join(rootDir, ContainersPage, path.Join(pathParts[1:i+1]...)),
|
||||
})
|
||||
}
|
||||
|
||||
// Build the links for the subcontainers.
|
||||
subcontainerLinks := make([]link, 0, len(cont.Subcontainers))
|
||||
for _, sub := range cont.Subcontainers {
|
||||
if !m.Exists(sub.Name) {
|
||||
continue
|
||||
}
|
||||
subcontainerLinks = append(subcontainerLinks, link{
|
||||
Text: getContainerDisplayName(sub),
|
||||
Link: path.Join(rootDir, ContainersPage, sub.Name),
|
||||
})
|
||||
}
|
||||
|
||||
data := &pageData{
|
||||
DisplayName: displayName,
|
||||
ContainerName: escapeContainerName(cont.Name),
|
||||
ParentContainers: parentContainers,
|
||||
Subcontainers: subcontainerLinks,
|
||||
Spec: cont.Spec,
|
||||
Stats: cont.Stats,
|
||||
MachineInfo: machineInfo,
|
||||
IsRoot: cont.Name == "/",
|
||||
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork || cont.Spec.HasFilesystem,
|
||||
CpuAvailable: cont.Spec.HasCpu,
|
||||
MemoryAvailable: cont.Spec.HasMemory,
|
||||
NetworkAvailable: cont.Spec.HasNetwork,
|
||||
FsAvailable: cont.Spec.HasFilesystem,
|
||||
CustomMetricsAvailable: cont.Spec.HasCustomMetrics,
|
||||
SubcontainersAvailable: len(subcontainerLinks) > 0,
|
||||
Root: rootDir,
|
||||
}
|
||||
err = pageTemplate.Execute(w, data)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to apply template: %s", err)
|
||||
}
|
||||
|
||||
glog.V(5).Infof("Request took %s", time.Since(start))
|
||||
}
|
||||
|
||||
// Build a relative path to the root of the container page.
|
||||
func getRootDir(containerName string) string {
|
||||
// The root is at: container depth
|
||||
levels := (strings.Count(containerName, "/"))
|
||||
return strings.Repeat("../", levels)
|
||||
}
|
162
vendor/github.com/google/cadvisor/pages/docker.go
generated
vendored
162
vendor/github.com/google/cadvisor/pages/docker.go
generated
vendored
@@ -1,162 +0,0 @@
|
||||
// Copyright 2014 Google Inc. 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 pages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/google/cadvisor/container/docker"
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
"github.com/google/cadvisor/manager"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const DockerPage = "/docker/"
|
||||
|
||||
func toStatusKV(status info.DockerStatus) ([]keyVal, []keyVal) {
|
||||
ds := []keyVal{
|
||||
{Key: "Driver", Value: status.Driver},
|
||||
}
|
||||
for k, v := range status.DriverStatus {
|
||||
ds = append(ds, keyVal{Key: k, Value: v})
|
||||
}
|
||||
return []keyVal{
|
||||
{Key: "Docker Version", Value: status.Version},
|
||||
{Key: "Docker API Version", Value: status.APIVersion},
|
||||
{Key: "Kernel Version", Value: status.KernelVersion},
|
||||
{Key: "OS Version", Value: status.OS},
|
||||
{Key: "Host Name", Value: status.Hostname},
|
||||
{Key: "Docker Root Directory", Value: status.RootDir},
|
||||
{Key: "Execution Driver", Value: status.ExecDriver},
|
||||
{Key: "Number of Images", Value: strconv.Itoa(status.NumImages)},
|
||||
{Key: "Number of Containers", Value: strconv.Itoa(status.NumContainers)},
|
||||
}, ds
|
||||
}
|
||||
|
||||
func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) {
|
||||
start := time.Now()
|
||||
|
||||
// The container name is the path after the handler
|
||||
containerName := u.Path[len(DockerPage)-1:]
|
||||
rootDir := getRootDir(containerName)
|
||||
|
||||
var data *pageData
|
||||
if containerName == "/" {
|
||||
// Get the containers.
|
||||
reqParams := info.ContainerInfoRequest{
|
||||
NumStats: 0,
|
||||
}
|
||||
conts, err := m.AllDockerContainers(&reqParams)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get container %q with error: %v", containerName, err), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
subcontainers := make([]link, 0, len(conts))
|
||||
for _, cont := range conts {
|
||||
subcontainers = append(subcontainers, link{
|
||||
Text: getContainerDisplayName(cont.ContainerReference),
|
||||
Link: path.Join(rootDir, DockerPage, docker.ContainerNameToDockerId(cont.ContainerReference.Name)),
|
||||
})
|
||||
}
|
||||
|
||||
// Get Docker status
|
||||
status, err := m.DockerInfo()
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get docker info: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
dockerStatus, driverStatus := toStatusKV(status)
|
||||
// Get Docker Images
|
||||
images, err := m.DockerImages()
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get docker images: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
dockerContainersText := "Docker Containers"
|
||||
data = &pageData{
|
||||
DisplayName: dockerContainersText,
|
||||
ParentContainers: []link{
|
||||
{
|
||||
Text: dockerContainersText,
|
||||
Link: path.Join(rootDir, DockerPage),
|
||||
}},
|
||||
Subcontainers: subcontainers,
|
||||
Root: rootDir,
|
||||
DockerStatus: dockerStatus,
|
||||
DockerDriverStatus: driverStatus,
|
||||
DockerImages: images,
|
||||
}
|
||||
} else {
|
||||
// Get the container.
|
||||
reqParams := info.ContainerInfoRequest{
|
||||
NumStats: 60,
|
||||
}
|
||||
cont, err := m.DockerContainer(containerName[1:], &reqParams)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get container %q with error: %v", containerName, err), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
displayName := getContainerDisplayName(cont.ContainerReference)
|
||||
|
||||
// Make a list of the parent containers and their links
|
||||
var parentContainers []link
|
||||
parentContainers = append(parentContainers, link{
|
||||
Text: "Docker Containers",
|
||||
Link: path.Join(rootDir, DockerPage),
|
||||
})
|
||||
parentContainers = append(parentContainers, link{
|
||||
Text: displayName,
|
||||
Link: path.Join(rootDir, DockerPage, docker.ContainerNameToDockerId(cont.Name)),
|
||||
})
|
||||
|
||||
// Get the MachineInfo
|
||||
machineInfo, err := m.GetMachineInfo()
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get machine info: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
data = &pageData{
|
||||
DisplayName: displayName,
|
||||
ContainerName: escapeContainerName(cont.Name),
|
||||
ParentContainers: parentContainers,
|
||||
Spec: cont.Spec,
|
||||
Stats: cont.Stats,
|
||||
MachineInfo: machineInfo,
|
||||
ResourcesAvailable: cont.Spec.HasCpu || cont.Spec.HasMemory || cont.Spec.HasNetwork,
|
||||
CpuAvailable: cont.Spec.HasCpu,
|
||||
MemoryAvailable: cont.Spec.HasMemory,
|
||||
NetworkAvailable: cont.Spec.HasNetwork,
|
||||
FsAvailable: cont.Spec.HasFilesystem,
|
||||
CustomMetricsAvailable: cont.Spec.HasCustomMetrics,
|
||||
Root: rootDir,
|
||||
}
|
||||
}
|
||||
|
||||
err := pageTemplate.Execute(w, data)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to apply template: %s", err)
|
||||
}
|
||||
|
||||
glog.V(5).Infof("Request took %s", time.Since(start))
|
||||
return
|
||||
}
|
163
vendor/github.com/google/cadvisor/pages/pages.go
generated
vendored
163
vendor/github.com/google/cadvisor/pages/pages.go
generated
vendored
@@ -1,163 +0,0 @@
|
||||
// Copyright 2014 Google Inc. 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 pages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
httpmux "github.com/google/cadvisor/http/mux"
|
||||
info "github.com/google/cadvisor/info/v1"
|
||||
"github.com/google/cadvisor/manager"
|
||||
|
||||
auth "github.com/abbot/go-http-auth"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
var pageTemplate *template.Template
|
||||
|
||||
type link struct {
|
||||
// Text to show in the link.
|
||||
Text string
|
||||
|
||||
// Web address to link to.
|
||||
Link string
|
||||
}
|
||||
|
||||
type keyVal struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
|
||||
type pageData struct {
|
||||
DisplayName string
|
||||
ContainerName string
|
||||
ParentContainers []link
|
||||
Subcontainers []link
|
||||
Spec info.ContainerSpec
|
||||
Stats []*info.ContainerStats
|
||||
MachineInfo *info.MachineInfo
|
||||
IsRoot bool
|
||||
ResourcesAvailable bool
|
||||
CpuAvailable bool
|
||||
MemoryAvailable bool
|
||||
NetworkAvailable bool
|
||||
FsAvailable bool
|
||||
CustomMetricsAvailable bool
|
||||
SubcontainersAvailable bool
|
||||
Root string
|
||||
DockerStatus []keyVal
|
||||
DockerDriverStatus []keyVal
|
||||
DockerImages []info.DockerImage
|
||||
}
|
||||
|
||||
func init() {
|
||||
containersHtmlTemplate, _ := Asset("pages/assets/html/containers.html")
|
||||
pageTemplate = template.New("containersTemplate").Funcs(funcMap)
|
||||
_, err := pageTemplate.Parse(string(containersHtmlTemplate))
|
||||
if err != nil {
|
||||
glog.Fatalf("Failed to parse template: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func containerHandlerNoAuth(containerManager manager.Manager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
serveContainersPage(containerManager, w, r.URL)
|
||||
}
|
||||
}
|
||||
|
||||
func containerHandler(containerManager manager.Manager) auth.AuthenticatedHandlerFunc {
|
||||
return func(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
|
||||
serveContainersPage(containerManager, w, r.URL)
|
||||
}
|
||||
}
|
||||
|
||||
func dockerHandlerNoAuth(containerManager manager.Manager) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
serveDockerPage(containerManager, w, r.URL)
|
||||
}
|
||||
}
|
||||
|
||||
func dockerHandler(containerManager manager.Manager) auth.AuthenticatedHandlerFunc {
|
||||
return func(w http.ResponseWriter, r *auth.AuthenticatedRequest) {
|
||||
serveDockerPage(containerManager, w, r.URL)
|
||||
}
|
||||
}
|
||||
|
||||
// Register http handlers
|
||||
func RegisterHandlersDigest(mux httpmux.Mux, containerManager manager.Manager, authenticator *auth.DigestAuth) error {
|
||||
// Register the handler for the containers page.
|
||||
if authenticator != nil {
|
||||
mux.HandleFunc(ContainersPage, authenticator.Wrap(containerHandler(containerManager)))
|
||||
mux.HandleFunc(DockerPage, authenticator.Wrap(dockerHandler(containerManager)))
|
||||
} else {
|
||||
mux.HandleFunc(ContainersPage, containerHandlerNoAuth(containerManager))
|
||||
mux.HandleFunc(DockerPage, dockerHandlerNoAuth(containerManager))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RegisterHandlersBasic(mux httpmux.Mux, containerManager manager.Manager, authenticator *auth.BasicAuth) error {
|
||||
// Register the handler for the containers and docker age.
|
||||
if authenticator != nil {
|
||||
mux.HandleFunc(ContainersPage, authenticator.Wrap(containerHandler(containerManager)))
|
||||
mux.HandleFunc(DockerPage, authenticator.Wrap(dockerHandler(containerManager)))
|
||||
} else {
|
||||
mux.HandleFunc(ContainersPage, containerHandlerNoAuth(containerManager))
|
||||
mux.HandleFunc(DockerPage, dockerHandlerNoAuth(containerManager))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getContainerDisplayName(cont info.ContainerReference) string {
|
||||
// Pick a user-added alias as display name.
|
||||
displayName := ""
|
||||
for _, alias := range cont.Aliases {
|
||||
// ignore container id as alias.
|
||||
if strings.Contains(cont.Name, alias) {
|
||||
continue
|
||||
}
|
||||
// pick shortest display name if multiple aliases are available.
|
||||
if displayName == "" || len(displayName) >= len(alias) {
|
||||
displayName = alias
|
||||
}
|
||||
}
|
||||
|
||||
if displayName == "" {
|
||||
displayName = cont.Name
|
||||
} else if len(displayName) > 50 {
|
||||
// truncate display name to fit in one line.
|
||||
displayName = displayName[:50] + "..."
|
||||
}
|
||||
|
||||
// Add the full container name to the display name.
|
||||
if displayName != cont.Name {
|
||||
displayName = fmt.Sprintf("%s (%s)", displayName, cont.Name)
|
||||
}
|
||||
|
||||
return displayName
|
||||
}
|
||||
|
||||
// Escape the non-path characters on a container name.
|
||||
func escapeContainerName(containerName string) string {
|
||||
parts := strings.Split(containerName, "/")
|
||||
for i := range parts {
|
||||
parts[i] = url.QueryEscape(parts[i])
|
||||
}
|
||||
return strings.Join(parts, "/")
|
||||
}
|
27
vendor/github.com/google/cadvisor/pages/static/BUILD
generated
vendored
27
vendor/github.com/google/cadvisor/pages/static/BUILD
generated
vendored
@@ -1,27 +0,0 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"assets.go",
|
||||
"static.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/pages/static",
|
||||
importpath = "github.com/google/cadvisor/pages/static",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//vendor/github.com/golang/glog:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
442
vendor/github.com/google/cadvisor/pages/static/assets.go
generated
vendored
442
vendor/github.com/google/cadvisor/pages/static/assets.go
generated
vendored
File diff suppressed because one or more lines are too long
77
vendor/github.com/google/cadvisor/pages/static/static.go
generated
vendored
77
vendor/github.com/google/cadvisor/pages/static/static.go
generated
vendored
@@ -1,77 +0,0 @@
|
||||
// Copyright 2014 Google Inc. 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.
|
||||
|
||||
// Handler for /static content.
|
||||
|
||||
package static
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mime"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const StaticResource = "/static/"
|
||||
|
||||
var popper, _ = Asset("pages/assets/js/popper.min.js")
|
||||
var bootstrapJs, _ = Asset("pages/assets/js/bootstrap-4.0.0-beta.2.min.js")
|
||||
var containersJs, _ = Asset("pages/assets/js/containers.js")
|
||||
var gchartsJs, _ = Asset("pages/assets/js/gcharts.js")
|
||||
var googleJsapiJs, _ = Asset("pages/assets/js/google-jsapi.js")
|
||||
var jqueryJs, _ = Asset("pages/assets/js/jquery-3.0.0.min.js")
|
||||
|
||||
var bootstrapCss, _ = Asset("pages/assets/styles/bootstrap-4.0.0-beta.2.min.css")
|
||||
var bootstrapThemeCss, _ = Asset("pages/assets/styles/bootstrap-theme-3.1.1.min.css")
|
||||
var containersCss, _ = Asset("pages/assets/styles/containers.css")
|
||||
|
||||
var staticFiles = map[string][]byte{
|
||||
"popper.min.js": popper,
|
||||
"bootstrap-4.0.0-beta.2.min.css": bootstrapCss,
|
||||
"bootstrap-4.0.0-beta.2.min.js": bootstrapJs,
|
||||
"bootstrap-theme-3.1.1.min.css": bootstrapThemeCss,
|
||||
"containers.css": containersCss,
|
||||
"containers.js": containersJs,
|
||||
"gcharts.js": gchartsJs,
|
||||
"google-jsapi.js": googleJsapiJs,
|
||||
"jquery-3.0.0.min.js": jqueryJs,
|
||||
}
|
||||
|
||||
func HandleRequest(w http.ResponseWriter, u *url.URL) {
|
||||
if len(u.Path) <= len(StaticResource) {
|
||||
http.Error(w, fmt.Sprintf("unknown static resource %q", u.Path), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Get the static content if it exists.
|
||||
resource := u.Path[len(StaticResource):]
|
||||
content, ok := staticFiles[resource]
|
||||
if !ok {
|
||||
http.Error(w, fmt.Sprintf("unknown static resource %q", u.Path), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Set Content-Type if we were able to detect it.
|
||||
contentType := mime.TypeByExtension(path.Ext(resource))
|
||||
if contentType != "" {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
}
|
||||
|
||||
if _, err := w.Write(content); err != nil {
|
||||
glog.Errorf("Failed to write response: %v", err)
|
||||
}
|
||||
}
|
256
vendor/github.com/google/cadvisor/pages/templates.go
generated
vendored
256
vendor/github.com/google/cadvisor/pages/templates.go
generated
vendored
File diff suppressed because one or more lines are too long
29
vendor/github.com/google/cadvisor/validate/BUILD
generated
vendored
29
vendor/github.com/google/cadvisor/validate/BUILD
generated
vendored
@@ -1,29 +0,0 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["validate.go"],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/google/cadvisor/validate",
|
||||
importpath = "github.com/google/cadvisor/validate",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/google/cadvisor/container/docker:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/manager:go_default_library",
|
||||
"//vendor/github.com/google/cadvisor/utils:go_default_library",
|
||||
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
324
vendor/github.com/google/cadvisor/validate/validate.go
generated
vendored
324
vendor/github.com/google/cadvisor/validate/validate.go
generated
vendored
@@ -1,324 +0,0 @@
|
||||
// Copyright 2014 Google Inc. 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.
|
||||
|
||||
// Handler for /validate content.
|
||||
// Validates cadvisor dependencies - kernel, os, docker setup.
|
||||
|
||||
package validate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/google/cadvisor/container/docker"
|
||||
"github.com/google/cadvisor/manager"
|
||||
"github.com/google/cadvisor/utils"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
)
|
||||
|
||||
const (
|
||||
ValidatePage = "/validate/"
|
||||
Supported = "[Supported, but not recommended]"
|
||||
Unsupported = "[Unsupported]"
|
||||
Recommended = "[Supported and recommended]"
|
||||
Unknown = "[Unknown]"
|
||||
VersionFormat = "%d.%d%s"
|
||||
OutputFormat = "%s: %s\n\t%s\n\n"
|
||||
)
|
||||
|
||||
func getMajorMinor(version string) (int, int, error) {
|
||||
var major, minor int
|
||||
var ign string
|
||||
n, err := fmt.Sscanf(version, VersionFormat, &major, &minor, &ign)
|
||||
if n != 3 || err != nil {
|
||||
log.Printf("Failed to parse version for %s", version)
|
||||
return -1, -1, err
|
||||
}
|
||||
return major, minor, nil
|
||||
}
|
||||
|
||||
func validateKernelVersion(version string) (string, string) {
|
||||
desc := fmt.Sprintf("Kernel version is %s. Versions >= 2.6 are supported. 3.0+ are recommended.\n", version)
|
||||
major, minor, err := getMajorMinor(version)
|
||||
if err != nil {
|
||||
desc = fmt.Sprintf("Could not parse kernel version. %s", desc)
|
||||
return Unknown, desc
|
||||
}
|
||||
|
||||
if major < 2 {
|
||||
return Unsupported, desc
|
||||
}
|
||||
|
||||
if major == 2 && minor < 6 {
|
||||
return Unsupported, desc
|
||||
}
|
||||
|
||||
if major >= 3 {
|
||||
return Recommended, desc
|
||||
}
|
||||
|
||||
return Supported, desc
|
||||
}
|
||||
|
||||
func validateDockerVersion(version string) (string, string) {
|
||||
desc := fmt.Sprintf("Docker version is %s. Versions >= 1.0 are supported. 1.2+ are recommended.\n", version)
|
||||
major, minor, err := getMajorMinor(version)
|
||||
if err != nil {
|
||||
desc = fmt.Sprintf("Could not parse docker version. %s\n\t", desc)
|
||||
return Unknown, desc
|
||||
}
|
||||
if major < 1 {
|
||||
return Unsupported, desc
|
||||
}
|
||||
|
||||
if major == 1 && minor < 2 {
|
||||
return Supported, desc
|
||||
}
|
||||
|
||||
return Recommended, desc
|
||||
}
|
||||
|
||||
func getEnabledCgroups() (map[string]int, error) {
|
||||
out, err := ioutil.ReadFile("/proc/cgroups")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cgroups := make(map[string]int)
|
||||
for i, line := range strings.Split(string(out), "\n") {
|
||||
var cgroup string
|
||||
var ign, enabled int
|
||||
if i == 0 || line == "" {
|
||||
continue
|
||||
}
|
||||
n, err := fmt.Sscanf(line, "%s %d %d %d", &cgroup, &ign, &ign, &enabled)
|
||||
if n != 4 || err != nil {
|
||||
if err == nil {
|
||||
err = fmt.Errorf("failed to parse /proc/cgroup entry %s", line)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
cgroups[cgroup] = enabled
|
||||
}
|
||||
return cgroups, nil
|
||||
}
|
||||
|
||||
func areCgroupsPresent(available map[string]int, desired []string) (bool, string) {
|
||||
for _, cgroup := range desired {
|
||||
enabled, ok := available[cgroup]
|
||||
if !ok {
|
||||
reason := fmt.Sprintf("Missing cgroup %s. Available cgroups: %v\n", cgroup, available)
|
||||
return false, reason
|
||||
}
|
||||
if enabled != 1 {
|
||||
reason := fmt.Sprintf("Cgroup %s not enabled. Available cgroups: %v\n", cgroup, available)
|
||||
return false, reason
|
||||
}
|
||||
}
|
||||
return true, ""
|
||||
}
|
||||
|
||||
func validateCpuCfsBandwidth(available_cgroups map[string]int) string {
|
||||
ok, _ := areCgroupsPresent(available_cgroups, []string{"cpu"})
|
||||
if !ok {
|
||||
return "\tCpu cfs bandwidth status unknown: cpu cgroup not enabled.\n"
|
||||
}
|
||||
mnt, err := cgroups.FindCgroupMountpoint("cpu")
|
||||
if err != nil {
|
||||
return "\tCpu cfs bandwidth status unknown: cpu cgroup not mounted.\n"
|
||||
}
|
||||
_, err = os.Stat(path.Join(mnt, "cpu.cfs_period_us"))
|
||||
if os.IsNotExist(err) {
|
||||
return "\tCpu cfs bandwidth is disabled. Recompile kernel with \"CONFIG_CFS_BANDWIDTH\" enabled.\n"
|
||||
}
|
||||
|
||||
return "\tCpu cfs bandwidth is enabled.\n"
|
||||
}
|
||||
|
||||
func validateMemoryAccounting(available_cgroups map[string]int) string {
|
||||
ok, _ := areCgroupsPresent(available_cgroups, []string{"memory"})
|
||||
if !ok {
|
||||
return "\tHierarchical memory accounting status unknown: memory cgroup not enabled.\n"
|
||||
}
|
||||
mnt, err := cgroups.FindCgroupMountpoint("memory")
|
||||
if err != nil {
|
||||
return "\tHierarchical memory accounting status unknown: memory cgroup not mounted.\n"
|
||||
}
|
||||
hier, err := ioutil.ReadFile(path.Join(mnt, "memory.use_hierarchy"))
|
||||
if err != nil {
|
||||
return "\tHierarchical memory accounting status unknown: hierarchy interface unavailable.\n"
|
||||
}
|
||||
var enabled int
|
||||
n, err := fmt.Sscanf(string(hier), "%d", &enabled)
|
||||
if err != nil || n != 1 {
|
||||
return "\tHierarchical memory accounting status unknown: hierarchy interface unreadable.\n"
|
||||
}
|
||||
if enabled == 1 {
|
||||
return "\tHierarchical memory accounting enabled. Reported memory usage includes memory used by child containers.\n"
|
||||
}
|
||||
return "\tHierarchical memory accounting disabled. Memory usage does not include usage from child containers.\n"
|
||||
|
||||
}
|
||||
|
||||
func validateCgroups() (string, string) {
|
||||
required_cgroups := []string{"cpu", "cpuacct"}
|
||||
recommended_cgroups := []string{"memory", "blkio", "cpuset", "devices", "freezer"}
|
||||
available_cgroups, err := getEnabledCgroups()
|
||||
desc := fmt.Sprintf("\tFollowing cgroups are required: %v\n\tFollowing other cgroups are recommended: %v\n", required_cgroups, recommended_cgroups)
|
||||
if err != nil {
|
||||
desc = fmt.Sprintf("Could not parse /proc/cgroups.\n%s", desc)
|
||||
return Unknown, desc
|
||||
}
|
||||
ok, out := areCgroupsPresent(available_cgroups, required_cgroups)
|
||||
if !ok {
|
||||
out += desc
|
||||
return Unsupported, out
|
||||
}
|
||||
ok, out = areCgroupsPresent(available_cgroups, recommended_cgroups)
|
||||
if !ok {
|
||||
// supported, but not recommended.
|
||||
out += desc
|
||||
return Supported, out
|
||||
}
|
||||
out = fmt.Sprintf("Available cgroups: %v\n", available_cgroups)
|
||||
out += desc
|
||||
out += validateMemoryAccounting(available_cgroups)
|
||||
out += validateCpuCfsBandwidth(available_cgroups)
|
||||
return Recommended, out
|
||||
}
|
||||
|
||||
func validateDockerInfo() (string, string) {
|
||||
info, err := docker.ValidateInfo()
|
||||
if err != nil {
|
||||
return Unsupported, fmt.Sprintf("Docker setup is invalid: %v", err)
|
||||
}
|
||||
|
||||
desc := fmt.Sprintf("Storage driver is %s.\n", info.Driver)
|
||||
return Recommended, desc
|
||||
}
|
||||
|
||||
func validateCgroupMounts() (string, string) {
|
||||
const recommendedMount = "/sys/fs/cgroup"
|
||||
desc := fmt.Sprintf("\tAny cgroup mount point that is detectible and accessible is supported. %s is recommended as a standard location.\n", recommendedMount)
|
||||
mnt, err := cgroups.FindCgroupMountpoint("cpu")
|
||||
if err != nil {
|
||||
out := "Could not locate cgroup mount point.\n"
|
||||
out += desc
|
||||
return Unknown, out
|
||||
}
|
||||
mnt = path.Dir(mnt)
|
||||
if !utils.FileExists(mnt) {
|
||||
out := fmt.Sprintf("Cgroup mount directory %s inaccessible.\n", mnt)
|
||||
out += desc
|
||||
return Unsupported, out
|
||||
}
|
||||
mounts, err := ioutil.ReadDir(mnt)
|
||||
if err != nil {
|
||||
out := fmt.Sprintf("Could not read cgroup mount directory %s.\n", mnt)
|
||||
out += desc
|
||||
return Unsupported, out
|
||||
}
|
||||
mountNames := "\tCgroup mount directories: "
|
||||
for _, mount := range mounts {
|
||||
mountNames += mount.Name() + " "
|
||||
}
|
||||
mountNames += "\n"
|
||||
out := fmt.Sprintf("Cgroups are mounted at %s.\n", mnt)
|
||||
out += mountNames
|
||||
out += desc
|
||||
info, err := ioutil.ReadFile("/proc/mounts")
|
||||
if err != nil {
|
||||
out := fmt.Sprintf("Could not read /proc/mounts.\n")
|
||||
out += desc
|
||||
return Unsupported, out
|
||||
}
|
||||
out += "\tCgroup mounts:\n"
|
||||
for _, line := range strings.Split(string(info), "\n") {
|
||||
if strings.Contains(line, " cgroup ") {
|
||||
out += "\t" + line + "\n"
|
||||
}
|
||||
}
|
||||
if mnt == recommendedMount {
|
||||
return Recommended, out
|
||||
}
|
||||
return Supported, out
|
||||
}
|
||||
|
||||
func validateIoScheduler(containerManager manager.Manager) (string, string) {
|
||||
var desc string
|
||||
mi, err := containerManager.GetMachineInfo()
|
||||
if err != nil {
|
||||
return Unknown, "Machine info not available\n\t"
|
||||
}
|
||||
cfq := false
|
||||
for _, disk := range mi.DiskMap {
|
||||
desc += fmt.Sprintf("\t Disk %q Scheduler type %q.\n", disk.Name, disk.Scheduler)
|
||||
if disk.Scheduler == "cfq" {
|
||||
cfq = true
|
||||
}
|
||||
}
|
||||
// Since we get lot of random block devices, report recommended if
|
||||
// at least one of them is on cfq. Report Supported otherwise.
|
||||
if cfq {
|
||||
desc = "At least one device supports 'cfq' I/O scheduler. Some disk stats can be reported.\n" + desc
|
||||
return Recommended, desc
|
||||
}
|
||||
desc = "None of the devices support 'cfq' I/O scheduler. No disk stats can be reported.\n" + desc
|
||||
return Supported, desc
|
||||
}
|
||||
|
||||
func HandleRequest(w http.ResponseWriter, containerManager manager.Manager) error {
|
||||
// Get cAdvisor version Info.
|
||||
versionInfo, err := containerManager.GetVersionInfo()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out := fmt.Sprintf("cAdvisor version: %s\n\n", versionInfo.CadvisorVersion)
|
||||
|
||||
// No OS is preferred or unsupported as of now.
|
||||
out += fmt.Sprintf("OS version: %s\n\n", versionInfo.ContainerOsVersion)
|
||||
|
||||
kernelValidation, desc := validateKernelVersion(versionInfo.KernelVersion)
|
||||
out += fmt.Sprintf(OutputFormat, "Kernel version", kernelValidation, desc)
|
||||
|
||||
cgroupValidation, desc := validateCgroups()
|
||||
out += fmt.Sprintf(OutputFormat, "Cgroup setup", cgroupValidation, desc)
|
||||
|
||||
mountsValidation, desc := validateCgroupMounts()
|
||||
out += fmt.Sprintf(OutputFormat, "Cgroup mount setup", mountsValidation, desc)
|
||||
|
||||
dockerValidation, desc := validateDockerVersion(versionInfo.DockerVersion)
|
||||
out += fmt.Sprintf(OutputFormat, "Docker version", dockerValidation, desc)
|
||||
|
||||
dockerInfoValidation, desc := validateDockerInfo()
|
||||
out += fmt.Sprintf(OutputFormat, "Docker driver setup", dockerInfoValidation, desc)
|
||||
|
||||
ioSchedulerValidation, desc := validateIoScheduler(containerManager)
|
||||
out += fmt.Sprintf(OutputFormat, "Block device setup", ioSchedulerValidation, desc)
|
||||
|
||||
// Output debug info.
|
||||
debugInfo := containerManager.DebugInfo()
|
||||
for category, lines := range debugInfo {
|
||||
out += fmt.Sprintf(OutputFormat, category, "", strings.Join(lines, "\n\t"))
|
||||
}
|
||||
|
||||
_, err = w.Write([]byte(out))
|
||||
return err
|
||||
}
|
Reference in New Issue
Block a user