git subrepo clone (merge) https://github.com/kubernetes-incubator/metrics-server.git metrics-server
subrepo:
subdir: "metrics-server"
merged: "92d8412"
upstream:
origin: "https://github.com/kubernetes-incubator/metrics-server.git"
branch: "master"
commit: "92d8412"
git-subrepo:
version: "0.4.0"
origin: "???"
commit: "???"
diff --git a/metrics-server/vendor/k8s.io/apiserver/pkg/audit/request.go b/metrics-server/vendor/k8s.io/apiserver/pkg/audit/request.go
new file mode 100644
index 0000000..25d6c33
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/apiserver/pkg/audit/request.go
@@ -0,0 +1,235 @@
+/*
+Copyright 2017 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 audit
+
+import (
+ "bytes"
+ "fmt"
+ "net/http"
+ "time"
+
+ "github.com/golang/glog"
+ "github.com/pborman/uuid"
+
+ "reflect"
+
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ utilnet "k8s.io/apimachinery/pkg/util/net"
+ auditinternal "k8s.io/apiserver/pkg/apis/audit"
+ "k8s.io/apiserver/pkg/authentication/user"
+ "k8s.io/apiserver/pkg/authorization/authorizer"
+)
+
+func NewEventFromRequest(req *http.Request, level auditinternal.Level, attribs authorizer.Attributes) (*auditinternal.Event, error) {
+ ev := &auditinternal.Event{
+ RequestReceivedTimestamp: metav1.NewMicroTime(time.Now()),
+ Verb: attribs.GetVerb(),
+ RequestURI: req.URL.RequestURI(),
+ }
+
+ ev.Level = level
+
+ // prefer the id from the headers. If not available, create a new one.
+ // TODO(audit): do we want to forbid the header for non-front-proxy users?
+ ids := req.Header.Get(auditinternal.HeaderAuditID)
+ if ids != "" {
+ ev.AuditID = types.UID(ids)
+ } else {
+ ev.AuditID = types.UID(uuid.NewRandom().String())
+ }
+
+ ips := utilnet.SourceIPs(req)
+ ev.SourceIPs = make([]string, len(ips))
+ for i := range ips {
+ ev.SourceIPs[i] = ips[i].String()
+ }
+
+ if user := attribs.GetUser(); user != nil {
+ ev.User.Username = user.GetName()
+ ev.User.Extra = map[string]auditinternal.ExtraValue{}
+ for k, v := range user.GetExtra() {
+ ev.User.Extra[k] = auditinternal.ExtraValue(v)
+ }
+ ev.User.Groups = user.GetGroups()
+ ev.User.UID = user.GetUID()
+ }
+
+ if attribs.IsResourceRequest() {
+ ev.ObjectRef = &auditinternal.ObjectReference{
+ Namespace: attribs.GetNamespace(),
+ Name: attribs.GetName(),
+ Resource: attribs.GetResource(),
+ Subresource: attribs.GetSubresource(),
+ APIGroup: attribs.GetAPIGroup(),
+ APIVersion: attribs.GetAPIVersion(),
+ }
+ }
+
+ return ev, nil
+}
+
+// LogImpersonatedUser fills in the impersonated user attributes into an audit event.
+func LogImpersonatedUser(ae *auditinternal.Event, user user.Info) {
+ if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
+ return
+ }
+ ae.ImpersonatedUser = &auditinternal.UserInfo{
+ Username: user.GetName(),
+ }
+ ae.ImpersonatedUser.Groups = user.GetGroups()
+ ae.ImpersonatedUser.UID = user.GetUID()
+ ae.ImpersonatedUser.Extra = map[string]auditinternal.ExtraValue{}
+ for k, v := range user.GetExtra() {
+ ae.ImpersonatedUser.Extra[k] = auditinternal.ExtraValue(v)
+ }
+}
+
+// LogRequestObject fills in the request object into an audit event. The passed runtime.Object
+// will be converted to the given gv.
+func LogRequestObject(ae *auditinternal.Event, obj runtime.Object, gvr schema.GroupVersionResource, subresource string, s runtime.NegotiatedSerializer) {
+ if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
+ return
+ }
+
+ // complete ObjectRef
+ if ae.ObjectRef == nil {
+ ae.ObjectRef = &auditinternal.ObjectReference{}
+ }
+ if acc, ok := obj.(metav1.ObjectMetaAccessor); ok {
+ meta := acc.GetObjectMeta()
+ if len(ae.ObjectRef.Namespace) == 0 {
+ ae.ObjectRef.Namespace = meta.GetNamespace()
+ }
+ if len(ae.ObjectRef.Name) == 0 {
+ ae.ObjectRef.Name = meta.GetName()
+ }
+ if len(ae.ObjectRef.UID) == 0 {
+ ae.ObjectRef.UID = meta.GetUID()
+ }
+ if len(ae.ObjectRef.ResourceVersion) == 0 {
+ ae.ObjectRef.ResourceVersion = meta.GetResourceVersion()
+ }
+ }
+ if len(ae.ObjectRef.APIVersion) == 0 {
+ ae.ObjectRef.APIGroup = gvr.Group
+ ae.ObjectRef.APIVersion = gvr.Version
+ }
+ if len(ae.ObjectRef.Resource) == 0 {
+ ae.ObjectRef.Resource = gvr.Resource
+ }
+ if len(ae.ObjectRef.Subresource) == 0 {
+ ae.ObjectRef.Subresource = subresource
+ }
+
+ if ae.Level.Less(auditinternal.LevelRequest) {
+ return
+ }
+
+ // TODO(audit): hook into the serializer to avoid double conversion
+ var err error
+ ae.RequestObject, err = encodeObject(obj, gvr.GroupVersion(), s)
+ if err != nil {
+ // TODO(audit): add error slice to audit event struct
+ glog.Warningf("Auditing failed of %v request: %v", reflect.TypeOf(obj).Name(), err)
+ return
+ }
+}
+
+// LogRequestPatch fills in the given patch as the request object into an audit event.
+func LogRequestPatch(ae *auditinternal.Event, patch []byte) {
+ if ae == nil || ae.Level.Less(auditinternal.LevelRequest) {
+ return
+ }
+
+ ae.RequestObject = &runtime.Unknown{
+ Raw: patch,
+ ContentType: runtime.ContentTypeJSON,
+ }
+}
+
+// LogResponseObject fills in the response object into an audit event. The passed runtime.Object
+// will be converted to the given gv.
+func LogResponseObject(ae *auditinternal.Event, obj runtime.Object, gv schema.GroupVersion, s runtime.NegotiatedSerializer) {
+ if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
+ return
+ }
+ if status, ok := obj.(*metav1.Status); ok {
+ // selectively copy the bounded fields.
+ ae.ResponseStatus = &metav1.Status{
+ Status: status.Status,
+ Reason: status.Reason,
+ Code: status.Code,
+ }
+ }
+
+ if ae.Level.Less(auditinternal.LevelRequestResponse) {
+ return
+ }
+ // TODO(audit): hook into the serializer to avoid double conversion
+ var err error
+ ae.ResponseObject, err = encodeObject(obj, gv, s)
+ if err != nil {
+ glog.Warningf("Audit failed for %q response: %v", reflect.TypeOf(obj).Name(), err)
+ }
+}
+
+func encodeObject(obj runtime.Object, gv schema.GroupVersion, serializer runtime.NegotiatedSerializer) (*runtime.Unknown, error) {
+ supported := serializer.SupportedMediaTypes()
+ for i := range supported {
+ if supported[i].MediaType == "application/json" {
+ enc := serializer.EncoderForVersion(supported[i].Serializer, gv)
+ var buf bytes.Buffer
+ if err := enc.Encode(obj, &buf); err != nil {
+ return nil, fmt.Errorf("encoding failed: %v", err)
+ }
+
+ return &runtime.Unknown{
+ Raw: buf.Bytes(),
+ ContentType: runtime.ContentTypeJSON,
+ }, nil
+ }
+ }
+ return nil, fmt.Errorf("no json encoder found")
+}
+
+// LogAnnotation fills in the Annotations according to the key value pair.
+func LogAnnotation(ae *auditinternal.Event, key, value string) {
+ if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
+ return
+ }
+ if ae.Annotations == nil {
+ ae.Annotations = make(map[string]string)
+ }
+ if v, ok := ae.Annotations[key]; ok && v != value {
+ glog.Warningf("Failed to set annotations[%q] to %q for audit:%q, it has already been set to %q", key, value, ae.AuditID, ae.Annotations[key])
+ return
+ }
+ ae.Annotations[key] = value
+}
+
+// LogAnnotations fills in the Annotations according to the annotations map.
+func LogAnnotations(ae *auditinternal.Event, annotations map[string]string) {
+ if ae == nil || ae.Level.Less(auditinternal.LevelMetadata) {
+ return
+ }
+ for key, value := range annotations {
+ LogAnnotation(ae, key, value)
+ }
+}