-
Notifications
You must be signed in to change notification settings - Fork 39.6k
/
log.go
138 lines (113 loc) · 4.39 KB
/
log.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
Copyright 2014 The Kubernetes Authors.
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 rest
import (
"context"
"fmt"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
genericrest "k8s.io/apiserver/pkg/registry/generic/rest"
"k8s.io/apiserver/pkg/registry/rest"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/validation"
"k8s.io/kubernetes/pkg/kubelet/client"
"k8s.io/kubernetes/pkg/registry/core/pod"
// ensure types are installed
_ "k8s.io/kubernetes/pkg/apis/core/install"
)
// LogREST implements the log endpoint for a Pod
type LogREST struct {
KubeletConn client.ConnectionInfoGetter
Store *genericregistry.Store
}
// LogREST implements GetterWithOptions
var _ = rest.GetterWithOptions(&LogREST{})
// New creates a new Pod log options object
func (r *LogREST) New() runtime.Object {
// TODO - return a resource that represents a log
return &api.Pod{}
}
// Destroy cleans up resources on shutdown.
func (r *LogREST) Destroy() {
// Given that underlying store is shared with REST,
// we don't destroy it here explicitly.
}
// ProducesMIMETypes returns a list of the MIME types the specified HTTP verb (GET, POST, DELETE,
// PATCH) can respond with.
func (r *LogREST) ProducesMIMETypes(verb string) []string {
// Since the default list does not include "plain/text", we need to
// explicitly override ProducesMIMETypes, so that it gets added to
// the "produces" section for pods/{name}/log
return []string{
"text/plain",
}
}
// ProducesObject returns an object the specified HTTP verb respond with. It will overwrite storage object if
// it is not nil. Only the type of the return object matters, the value will be ignored.
func (r *LogREST) ProducesObject(verb string) interface{} {
return ""
}
// Get retrieves a runtime.Object that will stream the contents of the pod log
func (r *LogREST) Get(ctx context.Context, name string, opts runtime.Object) (runtime.Object, error) {
// register the metrics if the context is used. This assumes sync.Once is fast. If it's not, it could be an init block.
registerMetrics()
logOpts, ok := opts.(*api.PodLogOptions)
if !ok {
return nil, fmt.Errorf("invalid options object: %#v", opts)
}
countSkipTLSMetric(logOpts.InsecureSkipTLSVerifyBackend)
if errs := validation.ValidatePodLogOptions(logOpts); len(errs) > 0 {
return nil, errors.NewInvalid(api.Kind("PodLogOptions"), name, errs)
}
location, transport, err := pod.LogLocation(ctx, r.Store, r.KubeletConn, name, logOpts)
if err != nil {
return nil, err
}
return &genericrest.LocationStreamer{
Location: location,
Transport: transport,
ContentType: "text/plain",
Flush: logOpts.Follow,
ResponseChecker: genericrest.NewGenericHttpResponseChecker(api.Resource("pods/log"), name),
RedirectChecker: genericrest.PreventRedirects,
TLSVerificationErrorCounter: podLogsTLSFailure,
DeprecatedTLSVerificationErrorCounter: deprecatedPodLogsTLSFailure,
}, nil
}
func countSkipTLSMetric(insecureSkipTLSVerifyBackend bool) {
usageType := usageEnforce
if insecureSkipTLSVerifyBackend {
usageType = usageSkipAllowed
}
counter, err := podLogsUsage.GetMetricWithLabelValues(usageType)
if err != nil {
utilruntime.HandleError(err)
return
}
counter.Inc()
deprecatedPodLogsUsage.WithLabelValues(usageType).Inc()
}
// NewGetOptions creates a new options object
func (r *LogREST) NewGetOptions() (runtime.Object, bool, string) {
return &api.PodLogOptions{}, false, ""
}
// OverrideMetricsVerb override the GET verb to CONNECT for pod log resource
func (r *LogREST) OverrideMetricsVerb(oldVerb string) (newVerb string) {
newVerb = oldVerb
if oldVerb == "GET" {
newVerb = "CONNECT"
}
return
}