Vendor: Update k8s version
Signed-off-by: Michał Żyłowski <michal.zylowski@intel.com>
This commit is contained in:
parent
dfa93414c5
commit
52baf68d50
3756 changed files with 113013 additions and 92675 deletions
109
vendor/k8s.io/kubernetes/pkg/genericapiserver/BUILD
generated
vendored
109
vendor/k8s.io/kubernetes/pkg/genericapiserver/BUILD
generated
vendored
|
@ -5,110 +5,12 @@ licenses(["notice"])
|
|||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"config.go",
|
||||
"config_selfclient.go",
|
||||
"discovery.go",
|
||||
"doc.go",
|
||||
"genericapiserver.go",
|
||||
"healthz.go",
|
||||
"hooks.go",
|
||||
"resource_config.go",
|
||||
"resource_encoding_config.go",
|
||||
"serve.go",
|
||||
"storage_factory.go",
|
||||
],
|
||||
srcs = ["doc.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/admission:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/auth/handlers:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/genericapiserver/api:go_default_library",
|
||||
"//pkg/genericapiserver/api/filters:go_default_library",
|
||||
"//pkg/genericapiserver/api/openapi:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/genericapiserver/authenticator:go_default_library",
|
||||
"//pkg/genericapiserver/authorizer:go_default_library",
|
||||
"//pkg/genericapiserver/filters:go_default_library",
|
||||
"//pkg/genericapiserver/mux:go_default_library",
|
||||
"//pkg/genericapiserver/options:go_default_library",
|
||||
"//pkg/genericapiserver/routes:go_default_library",
|
||||
"//pkg/storage/storagebackend:go_default_library",
|
||||
"//pkg/util/cert:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
"//vendor:github.com/coreos/go-systemd/daemon",
|
||||
"//vendor:github.com/emicklei/go-restful",
|
||||
"//vendor:github.com/emicklei/go-restful/swagger",
|
||||
"//vendor:github.com/go-openapi/spec",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:github.com/pborman/uuid",
|
||||
"//vendor:github.com/pkg/errors",
|
||||
"//vendor:gopkg.in/natefinch/lumberjack.v2",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apimachinery",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/openapi",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/authenticator",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/request/union",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/union",
|
||||
"//vendor:k8s.io/apiserver/pkg/healthz",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"genericapiserver_test.go",
|
||||
"resource_config_test.go",
|
||||
"serve_test.go",
|
||||
"server_run_options_test.go",
|
||||
"storage_factory_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/autoscaling:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||
"//pkg/generated/openapi:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/genericapiserver/options:go_default_library",
|
||||
"//pkg/storage/etcd/testing:go_default_library",
|
||||
"//pkg/storage/storagebackend:go_default_library",
|
||||
"//pkg/util/cert:go_default_library",
|
||||
"//pkg/util/config:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
"//vendor:github.com/go-openapi/spec",
|
||||
"//vendor:github.com/stretchr/testify/assert",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apimachinery",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
@ -122,14 +24,11 @@ filegroup(
|
|||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/genericapiserver/api:all-srcs",
|
||||
"//pkg/genericapiserver/authenticator:all-srcs",
|
||||
"//pkg/genericapiserver/authorizer:all-srcs",
|
||||
"//pkg/genericapiserver/filters:all-srcs",
|
||||
"//pkg/genericapiserver/mux:all-srcs",
|
||||
"//pkg/genericapiserver/openapi:all-srcs",
|
||||
"//pkg/genericapiserver/options:all-srcs",
|
||||
"//pkg/genericapiserver/routes:all-srcs",
|
||||
"//pkg/genericapiserver/endpoints:all-srcs",
|
||||
"//pkg/genericapiserver/registry:all-srcs",
|
||||
"//pkg/genericapiserver/server:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
|
42
vendor/k8s.io/kubernetes/pkg/genericapiserver/api/rest/types.go
generated
vendored
42
vendor/k8s.io/kubernetes/pkg/genericapiserver/api/rest/types.go
generated
vendored
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
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 (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// ObjectFunc is a function to act on a given object. An error may be returned
|
||||
// if the hook cannot be completed. An ObjectFunc may transform the provided
|
||||
// object.
|
||||
type ObjectFunc func(obj runtime.Object) error
|
||||
|
||||
// AllFuncs returns an ObjectFunc that attempts to run all of the provided functions
|
||||
// in order, returning early if there are any errors.
|
||||
func AllFuncs(fns ...ObjectFunc) ObjectFunc {
|
||||
return func(obj runtime.Object) error {
|
||||
for _, fn := range fns {
|
||||
if fn == nil {
|
||||
continue
|
||||
}
|
||||
if err := fn(obj); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
2
vendor/k8s.io/kubernetes/pkg/genericapiserver/authenticator/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/genericapiserver/authenticator/BUILD
generated
vendored
|
@ -16,7 +16,6 @@ go_library(
|
|||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/util/cert:go_default_library",
|
||||
"//plugin/pkg/auth/authenticator/token/webhook:go_default_library",
|
||||
"//vendor:github.com/go-openapi/spec",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/authenticator",
|
||||
|
@ -29,6 +28,7 @@ go_library(
|
|||
"//vendor:k8s.io/apiserver/pkg/authentication/token/tokenfile",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
"//vendor:k8s.io/client-go/kubernetes/typed/authentication/v1beta1",
|
||||
"//vendor:k8s.io/client-go/util/cert",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
2
vendor/k8s.io/kubernetes/pkg/genericapiserver/authenticator/delegating.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/genericapiserver/authenticator/delegating.go
generated
vendored
|
@ -33,7 +33,7 @@ import (
|
|||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/cert"
|
||||
"k8s.io/client-go/util/cert"
|
||||
webhooktoken "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/webhook"
|
||||
)
|
||||
|
||||
|
|
2
vendor/k8s.io/kubernetes/pkg/genericapiserver/doc.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/genericapiserver/doc.go
generated
vendored
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
// Package genericapiserver contains code to setup a generic kubernetes-like API server.
|
||||
// This does not contain any kubernetes API specific code.
|
||||
// This does not contain any Kubernetes specific API types.
|
||||
// Note that this is a work in progress. We are pulling out generic code (specifically from
|
||||
// pkg/master) here.
|
||||
// We plan to move this package into a separate repo on github once it is done.
|
||||
|
|
|
@ -8,37 +8,6 @@ load(
|
|||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"apiserver.go",
|
||||
"discovery.go",
|
||||
"doc.go",
|
||||
"groupversion.go",
|
||||
"installer.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/admission:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/genericapiserver/api/handlers:go_default_library",
|
||||
"//pkg/genericapiserver/api/handlers/responsewriters:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//vendor:github.com/emicklei/go-restful",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/conversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/errors",
|
||||
"//vendor:k8s.io/apiserver/pkg/handlers/negotiation",
|
||||
"//vendor:k8s.io/apiserver/pkg/metrics",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
|
@ -50,23 +19,23 @@ go_test(
|
|||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/admission:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/testing:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/genericapiserver/api/filters:go_default_library",
|
||||
"//pkg/genericapiserver/api/handlers:go_default_library",
|
||||
"//pkg/genericapiserver/api/handlers/responsewriters:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/genericapiserver/api/testing:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/filters:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/handlers:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/handlers/responsewriters:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/testing:go_default_library",
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//plugin/pkg/admission/admit:go_default_library",
|
||||
"//plugin/pkg/admission/deny:go_default_library",
|
||||
"//vendor:github.com/emicklei/go-restful",
|
||||
"//vendor:golang.org/x/net/websocket",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/fields",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
|
@ -76,7 +45,39 @@ go_test(
|
|||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/admission",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"apiserver.go",
|
||||
"discovery.go",
|
||||
"doc.go",
|
||||
"groupversion.go",
|
||||
"installer.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/handlers:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/handlers/responsewriters:go_default_library",
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//vendor:github.com/emicklei/go-restful",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/conversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/errors",
|
||||
"//vendor:k8s.io/apiserver/pkg/admission",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/handlers/negotiation",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/metrics",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -91,11 +92,10 @@ filegroup(
|
|||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/genericapiserver/api/filters:all-srcs",
|
||||
"//pkg/genericapiserver/api/handlers:all-srcs",
|
||||
"//pkg/genericapiserver/api/openapi:all-srcs",
|
||||
"//pkg/genericapiserver/api/rest:all-srcs",
|
||||
"//pkg/genericapiserver/api/testing:all-srcs",
|
||||
"//pkg/genericapiserver/endpoints/filters:all-srcs",
|
||||
"//pkg/genericapiserver/endpoints/handlers:all-srcs",
|
||||
"//pkg/genericapiserver/endpoints/openapi:all-srcs",
|
||||
"//pkg/genericapiserver/endpoints/testing:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -8,7 +8,6 @@ reviewers:
|
|||
- lavalamp
|
||||
- smarterclayton
|
||||
- wojtek-t
|
||||
- bgrant0607
|
||||
- deads2k
|
||||
- derekwaynecarr
|
||||
- caesarxuchao
|
|
@ -14,10 +14,10 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package endpoints
|
||||
|
||||
import (
|
||||
"k8s.io/apiserver/pkg/metrics"
|
||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||
)
|
||||
|
||||
func init() {
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package endpoints
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -36,24 +36,24 @@ import (
|
|||
|
||||
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
genericapifilters "k8s.io/kubernetes/pkg/genericapiserver/api/filters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
genericapitesting "k8s.io/kubernetes/pkg/genericapiserver/api/testing"
|
||||
genericapifilters "k8s.io/kubernetes/pkg/genericapiserver/endpoints/filters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||
genericapitesting "k8s.io/kubernetes/pkg/genericapiserver/endpoints/testing"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
"k8s.io/kubernetes/plugin/pkg/admission/admit"
|
||||
"k8s.io/kubernetes/plugin/pkg/admission/deny"
|
||||
|
||||
|
@ -118,20 +118,11 @@ func newMapper() *meta.DefaultRESTMapper {
|
|||
}
|
||||
|
||||
func addGrouplessTypes() {
|
||||
type ListOptions struct {
|
||||
Object runtime.Object
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
LabelSelector string `json:"labelSelector,omitempty"`
|
||||
FieldSelector string `json:"fieldSelector,omitempty"`
|
||||
Watch bool `json:"watch,omitempty"`
|
||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
||||
TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty"`
|
||||
}
|
||||
api.Scheme.AddKnownTypes(grouplessGroupVersion,
|
||||
&genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &ListOptions{}, &metav1.ExportOptions{},
|
||||
&v1.DeleteOptions{}, &genericapitesting.SimpleGetOptions{}, &genericapitesting.SimpleRoot{})
|
||||
&genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &metav1.ListOptions{}, &metav1.ExportOptions{},
|
||||
&metav1.DeleteOptions{}, &genericapitesting.SimpleGetOptions{}, &genericapitesting.SimpleRoot{})
|
||||
api.Scheme.AddKnownTypes(grouplessInternalGroupVersion,
|
||||
&genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &api.ListOptions{}, &metav1.ExportOptions{},
|
||||
&genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &metav1.ExportOptions{},
|
||||
&genericapitesting.SimpleGetOptions{}, &genericapitesting.SimpleRoot{})
|
||||
}
|
||||
|
||||
|
@ -146,12 +137,12 @@ func addTestTypes() {
|
|||
TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty"`
|
||||
}
|
||||
api.Scheme.AddKnownTypes(testGroupVersion,
|
||||
&genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &ListOptions{}, &metav1.ExportOptions{},
|
||||
&v1.DeleteOptions{}, &genericapitesting.SimpleGetOptions{}, &genericapitesting.SimpleRoot{},
|
||||
&genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &metav1.ExportOptions{},
|
||||
&metav1.DeleteOptions{}, &genericapitesting.SimpleGetOptions{}, &genericapitesting.SimpleRoot{},
|
||||
&SimpleXGSubresource{})
|
||||
api.Scheme.AddKnownTypes(testGroupVersion, &v1.Pod{})
|
||||
api.Scheme.AddKnownTypes(testInternalGroupVersion,
|
||||
&genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &api.ListOptions{}, &metav1.ExportOptions{},
|
||||
&genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &metav1.ExportOptions{},
|
||||
&genericapitesting.SimpleGetOptions{}, &genericapitesting.SimpleRoot{},
|
||||
&SimpleXGSubresource{})
|
||||
api.Scheme.AddKnownTypes(testInternalGroupVersion, &api.Pod{})
|
||||
|
@ -164,18 +155,9 @@ func addTestTypes() {
|
|||
}
|
||||
|
||||
func addNewTestTypes() {
|
||||
type ListOptions struct {
|
||||
Object runtime.Object
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
LabelSelector string `json:"labelSelector,omitempty"`
|
||||
FieldSelector string `json:"fieldSelector,omitempty"`
|
||||
Watch bool `json:"watch,omitempty"`
|
||||
ResourceVersion string `json:"resourceVersion,omitempty"`
|
||||
TimeoutSeconds *int64 `json:"timeoutSeconds,omitempty"`
|
||||
}
|
||||
api.Scheme.AddKnownTypes(newGroupVersion,
|
||||
&genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &ListOptions{}, &metav1.ExportOptions{},
|
||||
&api.DeleteOptions{}, &genericapitesting.SimpleGetOptions{}, &genericapitesting.SimpleRoot{},
|
||||
&genericapitesting.Simple{}, &genericapitesting.SimpleList{}, &metav1.ExportOptions{},
|
||||
&metav1.DeleteOptions{}, &genericapitesting.SimpleGetOptions{}, &genericapitesting.SimpleRoot{},
|
||||
&v1.Pod{},
|
||||
)
|
||||
metav1.AddToGroupVersion(api.Scheme, newGroupVersion)
|
||||
|
@ -314,7 +296,7 @@ func handleInternal(storage map[string]rest.Storage, admissionControl admission.
|
|||
}
|
||||
|
||||
func TestSimpleSetupRight(t *testing.T) {
|
||||
s := &genericapitesting.Simple{ObjectMeta: apiv1.ObjectMeta{Name: "aName"}}
|
||||
s := &genericapitesting.Simple{ObjectMeta: metav1.ObjectMeta{Name: "aName"}}
|
||||
wire, err := runtime.Encode(codec, s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -356,7 +338,7 @@ type SimpleRESTStorage struct {
|
|||
stream *SimpleStream
|
||||
|
||||
deleted string
|
||||
deleteOptions *api.DeleteOptions
|
||||
deleteOptions *metav1.DeleteOptions
|
||||
|
||||
actualNamespace string
|
||||
namespacePresent bool
|
||||
|
@ -394,7 +376,7 @@ func (storage *SimpleRESTStorage) Export(ctx request.Context, name string, opts
|
|||
return obj, storage.errors["export"]
|
||||
}
|
||||
|
||||
func (storage *SimpleRESTStorage) List(ctx request.Context, options *api.ListOptions) (runtime.Object, error) {
|
||||
func (storage *SimpleRESTStorage) List(ctx request.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
|
||||
storage.checkContext(ctx)
|
||||
result := &genericapitesting.SimpleList{
|
||||
Items: storage.list,
|
||||
|
@ -457,7 +439,7 @@ func (storage *SimpleRESTStorage) checkContext(ctx request.Context) {
|
|||
storage.actualNamespace, storage.namespacePresent = request.NamespaceFrom(ctx)
|
||||
}
|
||||
|
||||
func (storage *SimpleRESTStorage) Delete(ctx request.Context, id string, options *api.DeleteOptions) (runtime.Object, error) {
|
||||
func (storage *SimpleRESTStorage) Delete(ctx request.Context, id string, options *metav1.DeleteOptions) (runtime.Object, error) {
|
||||
storage.checkContext(ctx)
|
||||
storage.deleted = id
|
||||
storage.deleteOptions = options
|
||||
|
@ -467,7 +449,7 @@ func (storage *SimpleRESTStorage) Delete(ctx request.Context, id string, options
|
|||
var obj runtime.Object = &metav1.Status{Status: metav1.StatusSuccess}
|
||||
var err error
|
||||
if storage.injectedFunction != nil {
|
||||
obj, err = storage.injectedFunction(&genericapitesting.Simple{ObjectMeta: apiv1.ObjectMeta{Name: id}})
|
||||
obj, err = storage.injectedFunction(&genericapitesting.Simple{ObjectMeta: metav1.ObjectMeta{Name: id}})
|
||||
}
|
||||
return obj, err
|
||||
}
|
||||
|
@ -510,7 +492,7 @@ func (storage *SimpleRESTStorage) Update(ctx request.Context, name string, objIn
|
|||
}
|
||||
|
||||
// Implement ResourceWatcher.
|
||||
func (storage *SimpleRESTStorage) Watch(ctx request.Context, options *api.ListOptions) (watch.Interface, error) {
|
||||
func (storage *SimpleRESTStorage) Watch(ctx request.Context, options *metainternalversion.ListOptions) (watch.Interface, error) {
|
||||
storage.lock.Lock()
|
||||
defer storage.lock.Unlock()
|
||||
storage.checkContext(ctx)
|
||||
|
@ -1116,7 +1098,7 @@ func TestNonEmptyList(t *testing.T) {
|
|||
simpleStorage := SimpleRESTStorage{
|
||||
list: []genericapitesting.Simple{
|
||||
{
|
||||
ObjectMeta: apiv1.ObjectMeta{Name: "something", Namespace: "other"},
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "something", Namespace: "other"},
|
||||
Other: "foo",
|
||||
},
|
||||
},
|
||||
|
@ -1167,7 +1149,7 @@ func TestSelfLinkSkipsEmptyName(t *testing.T) {
|
|||
simpleStorage := SimpleRESTStorage{
|
||||
list: []genericapitesting.Simple{
|
||||
{
|
||||
ObjectMeta: apiv1.ObjectMeta{Namespace: "other"},
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "other"},
|
||||
Other: "foo",
|
||||
},
|
||||
},
|
||||
|
@ -1241,7 +1223,7 @@ func TestExport(t *testing.T) {
|
|||
storage := map[string]rest.Storage{}
|
||||
simpleStorage := SimpleRESTStorage{
|
||||
item: genericapitesting.Simple{
|
||||
ObjectMeta: apiv1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
ResourceVersion: "1234",
|
||||
CreationTimestamp: metav1.NewTime(time.Unix(10, 10)),
|
||||
},
|
||||
|
@ -1960,7 +1942,7 @@ func TestDeleteWithOptions(t *testing.T) {
|
|||
defer server.Close()
|
||||
|
||||
grace := int64(300)
|
||||
item := &api.DeleteOptions{
|
||||
item := &metav1.DeleteOptions{
|
||||
GracePeriodSeconds: &grace,
|
||||
}
|
||||
body, err := runtime.Encode(codec, item)
|
||||
|
@ -2001,7 +1983,7 @@ func TestDeleteWithOptionsQuery(t *testing.T) {
|
|||
defer server.Close()
|
||||
|
||||
grace := int64(300)
|
||||
item := &api.DeleteOptions{
|
||||
item := &metav1.DeleteOptions{
|
||||
GracePeriodSeconds: &grace,
|
||||
}
|
||||
|
||||
|
@ -2038,7 +2020,7 @@ func TestDeleteWithOptionsQueryAndBody(t *testing.T) {
|
|||
defer server.Close()
|
||||
|
||||
grace := int64(300)
|
||||
item := &api.DeleteOptions{
|
||||
item := &metav1.DeleteOptions{
|
||||
GracePeriodSeconds: &grace,
|
||||
}
|
||||
body, err := runtime.Encode(codec, item)
|
||||
|
@ -2104,7 +2086,7 @@ func TestLegacyDeleteIgnoresOptions(t *testing.T) {
|
|||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
item := api.NewDeleteOptions(300)
|
||||
item := metav1.NewDeleteOptions(300)
|
||||
body, err := runtime.Encode(codec, item)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
|
@ -2174,7 +2156,7 @@ func TestPatch(t *testing.T) {
|
|||
storage := map[string]rest.Storage{}
|
||||
ID := "id"
|
||||
item := &genericapitesting.Simple{
|
||||
ObjectMeta: apiv1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ID,
|
||||
Namespace: "", // update should allow the client to send an empty namespace
|
||||
UID: "uid",
|
||||
|
@ -2187,7 +2169,7 @@ func TestPatch(t *testing.T) {
|
|||
t: t,
|
||||
expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + ID,
|
||||
name: ID,
|
||||
namespace: api.NamespaceDefault,
|
||||
namespace: metav1.NamespaceDefault,
|
||||
}
|
||||
handler := handleLinker(storage, selfLinker)
|
||||
server := httptest.NewServer(handler)
|
||||
|
@ -2213,7 +2195,7 @@ func TestPatchRequiresMatchingName(t *testing.T) {
|
|||
storage := map[string]rest.Storage{}
|
||||
ID := "id"
|
||||
item := &genericapitesting.Simple{
|
||||
ObjectMeta: apiv1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ID,
|
||||
Namespace: "", // update should allow the client to send an empty namespace
|
||||
UID: "uid",
|
||||
|
@ -2247,14 +2229,14 @@ func TestUpdate(t *testing.T) {
|
|||
t: t,
|
||||
expectedSet: "/" + prefix + "/" + testGroupVersion.Group + "/" + testGroupVersion.Version + "/namespaces/default/simple/" + ID,
|
||||
name: ID,
|
||||
namespace: api.NamespaceDefault,
|
||||
namespace: metav1.NamespaceDefault,
|
||||
}
|
||||
handler := handleLinker(storage, selfLinker)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
item := &genericapitesting.Simple{
|
||||
ObjectMeta: apiv1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ID,
|
||||
Namespace: "", // update should allow the client to send an empty namespace
|
||||
},
|
||||
|
@ -2291,9 +2273,9 @@ func TestUpdateInvokesAdmissionControl(t *testing.T) {
|
|||
defer server.Close()
|
||||
|
||||
item := &genericapitesting.Simple{
|
||||
ObjectMeta: apiv1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ID,
|
||||
Namespace: api.NamespaceDefault,
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
},
|
||||
Other: "bar",
|
||||
}
|
||||
|
@ -2353,7 +2335,7 @@ func TestUpdateAllowsMissingNamespace(t *testing.T) {
|
|||
defer server.Close()
|
||||
|
||||
item := &genericapitesting.Simple{
|
||||
ObjectMeta: apiv1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ID,
|
||||
},
|
||||
Other: "bar",
|
||||
|
@ -2390,7 +2372,7 @@ func TestUpdateAllowsMismatchedNamespaceOnError(t *testing.T) {
|
|||
defer server.Close()
|
||||
|
||||
item := &genericapitesting.Simple{
|
||||
ObjectMeta: apiv1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ID,
|
||||
Namespace: "other", // does not match request
|
||||
},
|
||||
|
@ -2427,7 +2409,7 @@ func TestUpdatePreventsMismatchedNamespace(t *testing.T) {
|
|||
defer server.Close()
|
||||
|
||||
item := &genericapitesting.Simple{
|
||||
ObjectMeta: apiv1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ID,
|
||||
Namespace: "other",
|
||||
},
|
||||
|
@ -2462,9 +2444,9 @@ func TestUpdateMissing(t *testing.T) {
|
|||
defer server.Close()
|
||||
|
||||
item := &genericapitesting.Simple{
|
||||
ObjectMeta: apiv1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ID,
|
||||
Namespace: api.NamespaceDefault,
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
},
|
||||
Other: "bar",
|
||||
}
|
||||
|
@ -3083,7 +3065,7 @@ func TestWriteJSONDecodeError(t *testing.T) {
|
|||
if status.Reason != metav1.StatusReasonUnknown {
|
||||
t.Errorf("unexpected reason %#v", status)
|
||||
}
|
||||
if !strings.Contains(status.Message, "no kind is registered for the type api.UnregisteredAPIObject") {
|
||||
if !strings.Contains(status.Message, "no kind is registered for the type endpoints.UnregisteredAPIObject") {
|
||||
t.Errorf("unexpected message %#v", status)
|
||||
}
|
||||
}
|
||||
|
@ -3211,7 +3193,7 @@ func TestUpdateChecksAPIVersion(t *testing.T) {
|
|||
defer server.Close()
|
||||
client := http.Client{}
|
||||
|
||||
simple := &genericapitesting.Simple{ObjectMeta: apiv1.ObjectMeta{Name: "bar"}}
|
||||
simple := &genericapitesting.Simple{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}
|
||||
data, err := runtime.Encode(newCodec, simple)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
|
@ -3238,10 +3220,10 @@ func TestUpdateChecksAPIVersion(t *testing.T) {
|
|||
// SimpleXGSubresource is a cross group subresource, i.e. the subresource does not belong to the
|
||||
// same group as its parent resource.
|
||||
type SimpleXGSubresource struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
api.ObjectMeta `json:"metadata"`
|
||||
SubresourceInfo string `json:"subresourceInfo,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
SubresourceInfo string `json:"subresourceInfo,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
func (obj *SimpleXGSubresource) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package endpoints
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -27,9 +27,9 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/handlers/negotiation"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||
)
|
||||
|
||||
// AddApiWebService adds a service to return the supported api versions at the legacy /api.
|
18
vendor/k8s.io/kubernetes/pkg/genericapiserver/endpoints/doc.go
generated
vendored
Normal file
18
vendor/k8s.io/kubernetes/pkg/genericapiserver/endpoints/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
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 endpoints contains the generic code that provides a RESTful Kubernetes-style API service.
|
||||
package endpoints // import "k8s.io/kubernetes/pkg/genericapiserver/endpoints"
|
|
@ -8,35 +8,11 @@ load(
|
|||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"audit.go",
|
||||
"authorization.go",
|
||||
"doc.go",
|
||||
"impersonation.go",
|
||||
"requestinfo.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/authentication:go_default_library",
|
||||
"//pkg/genericapiserver/api/handlers/responsewriters:go_default_library",
|
||||
"//pkg/serviceaccount:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:github.com/pborman/uuid",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/httplog",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"audit_test.go",
|
||||
"authentication_test.go",
|
||||
"authorization_test.go",
|
||||
"impersonation_test.go",
|
||||
"requestinfo_test.go",
|
||||
|
@ -46,11 +22,40 @@ go_test(
|
|||
deps = [
|
||||
"//pkg/apis/authentication:go_default_library",
|
||||
"//pkg/apis/batch:go_default_library",
|
||||
"//pkg/genericapiserver/api/handlers/responsewriters:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/handlers/responsewriters:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/authenticator",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"audit.go",
|
||||
"authentication.go",
|
||||
"authorization.go",
|
||||
"doc.go",
|
||||
"impersonation.go",
|
||||
"requestinfo.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/authentication:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/handlers/responsewriters:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:github.com/pborman/uuid",
|
||||
"//vendor:github.com/prometheus/client_golang/prometheus",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/authenticator",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/serviceaccount",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/server/httplog",
|
||||
],
|
||||
)
|
||||
|
|
@ -30,9 +30,9 @@ import (
|
|||
"github.com/pborman/uuid"
|
||||
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||
)
|
||||
|
||||
var _ http.ResponseWriter = &auditResponseWriter{}
|
|
@ -29,7 +29,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
type simpleResponseWriter struct {
|
117
vendor/k8s.io/kubernetes/pkg/genericapiserver/endpoints/filters/authentication.go
generated
vendored
Normal file
117
vendor/k8s.io/kubernetes/pkg/genericapiserver/endpoints/filters/authentication.go
generated
vendored
Normal file
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
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 filters
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
var (
|
||||
authenticatedUserCounter = prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "authenticated_user_requests",
|
||||
Help: "Counter of authenticated requests broken out by username.",
|
||||
},
|
||||
[]string{"username"},
|
||||
)
|
||||
)
|
||||
|
||||
func init() {
|
||||
prometheus.MustRegister(authenticatedUserCounter)
|
||||
}
|
||||
|
||||
// WithAuthentication creates an http handler that tries to authenticate the given request as a user, and then
|
||||
// stores any such user found onto the provided context for the request. If authentication fails or returns an error
|
||||
// the failed handler is used. On success, "Authorization" header is removed from the request and handler
|
||||
// is invoked to serve the request.
|
||||
func WithAuthentication(handler http.Handler, mapper genericapirequest.RequestContextMapper, auth authenticator.Request, failed http.Handler) http.Handler {
|
||||
if auth == nil {
|
||||
glog.Warningf("Authentication is disabled")
|
||||
return handler
|
||||
}
|
||||
return genericapirequest.WithRequestContext(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
user, ok, err := auth.AuthenticateRequest(req)
|
||||
if err != nil || !ok {
|
||||
if err != nil {
|
||||
glog.Errorf("Unable to authenticate the request due to an error: %v", err)
|
||||
}
|
||||
failed.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
// authorization header is not required anymore in case of a successful authentication.
|
||||
req.Header.Del("Authorization")
|
||||
|
||||
if ctx, ok := mapper.Get(req); ok {
|
||||
mapper.Update(req, genericapirequest.WithUser(ctx, user))
|
||||
}
|
||||
|
||||
authenticatedUserCounter.WithLabelValues(compressUsername(user.GetName())).Inc()
|
||||
|
||||
handler.ServeHTTP(w, req)
|
||||
}),
|
||||
mapper,
|
||||
)
|
||||
}
|
||||
|
||||
func Unauthorized(supportsBasicAuth bool) http.HandlerFunc {
|
||||
if supportsBasicAuth {
|
||||
return unauthorizedBasicAuth
|
||||
}
|
||||
return unauthorized
|
||||
}
|
||||
|
||||
// unauthorizedBasicAuth serves an unauthorized message to clients.
|
||||
func unauthorizedBasicAuth(w http.ResponseWriter, req *http.Request) {
|
||||
w.Header().Set("WWW-Authenticate", `Basic realm="kubernetes-master"`)
|
||||
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
// unauthorized serves an unauthorized message to clients.
|
||||
func unauthorized(w http.ResponseWriter, req *http.Request) {
|
||||
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
||||
}
|
||||
|
||||
// compressUsername maps all possible usernames onto a small set of categories
|
||||
// of usernames. This is done both to limit the cardinality of the
|
||||
// authorized_user_requests metric, and to avoid pushing actual usernames in the
|
||||
// metric.
|
||||
func compressUsername(username string) string {
|
||||
switch {
|
||||
// Known internal identities.
|
||||
case username == "admin" ||
|
||||
username == "client" ||
|
||||
username == "kube_proxy" ||
|
||||
username == "kubelet" ||
|
||||
username == "system:serviceaccount:kube-system:default":
|
||||
return username
|
||||
// Probably an email address.
|
||||
case strings.Contains(username, "@"):
|
||||
return "email_id"
|
||||
// Anything else (custom service accounts, custom external identities, etc.)
|
||||
default:
|
||||
return "other"
|
||||
}
|
||||
}
|
126
vendor/k8s.io/kubernetes/pkg/genericapiserver/endpoints/filters/authentication_test.go
generated
vendored
Normal file
126
vendor/k8s.io/kubernetes/pkg/genericapiserver/endpoints/filters/authentication_test.go
generated
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
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 filters
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
func TestAuthenticateRequest(t *testing.T) {
|
||||
success := make(chan struct{})
|
||||
contextMapper := genericapirequest.NewRequestContextMapper()
|
||||
auth := WithAuthentication(
|
||||
http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) {
|
||||
ctx, ok := contextMapper.Get(req)
|
||||
if ctx == nil || !ok {
|
||||
t.Errorf("no context stored on contextMapper: %#v", contextMapper)
|
||||
}
|
||||
user, ok := genericapirequest.UserFrom(ctx)
|
||||
if user == nil || !ok {
|
||||
t.Errorf("no user stored in context: %#v", ctx)
|
||||
}
|
||||
if req.Header.Get("Authorization") != "" {
|
||||
t.Errorf("Authorization header should be removed from request on success: %#v", req)
|
||||
}
|
||||
close(success)
|
||||
}),
|
||||
contextMapper,
|
||||
authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) {
|
||||
if req.Header.Get("Authorization") == "Something" {
|
||||
return &user.DefaultInfo{Name: "user"}, true, nil
|
||||
}
|
||||
return nil, false, errors.New("Authorization header is missing.")
|
||||
}),
|
||||
http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {
|
||||
t.Errorf("unexpected call to failed")
|
||||
}),
|
||||
)
|
||||
|
||||
auth.ServeHTTP(httptest.NewRecorder(), &http.Request{Header: map[string][]string{"Authorization": {"Something"}}})
|
||||
|
||||
<-success
|
||||
empty, err := genericapirequest.IsEmpty(contextMapper)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !empty {
|
||||
t.Fatalf("contextMapper should have no stored requests: %v", contextMapper)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthenticateRequestFailed(t *testing.T) {
|
||||
failed := make(chan struct{})
|
||||
contextMapper := genericapirequest.NewRequestContextMapper()
|
||||
auth := WithAuthentication(
|
||||
http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) {
|
||||
t.Errorf("unexpected call to handler")
|
||||
}),
|
||||
contextMapper,
|
||||
authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) {
|
||||
return nil, false, nil
|
||||
}),
|
||||
http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {
|
||||
close(failed)
|
||||
}),
|
||||
)
|
||||
|
||||
auth.ServeHTTP(httptest.NewRecorder(), &http.Request{})
|
||||
|
||||
<-failed
|
||||
empty, err := genericapirequest.IsEmpty(contextMapper)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !empty {
|
||||
t.Fatalf("contextMapper should have no stored requests: %v", contextMapper)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthenticateRequestError(t *testing.T) {
|
||||
failed := make(chan struct{})
|
||||
contextMapper := genericapirequest.NewRequestContextMapper()
|
||||
auth := WithAuthentication(
|
||||
http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) {
|
||||
t.Errorf("unexpected call to handler")
|
||||
}),
|
||||
contextMapper,
|
||||
authenticator.RequestFunc(func(req *http.Request) (user.Info, bool, error) {
|
||||
return nil, false, errors.New("failure")
|
||||
}),
|
||||
http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {
|
||||
close(failed)
|
||||
}),
|
||||
)
|
||||
|
||||
auth.ServeHTTP(httptest.NewRecorder(), &http.Request{})
|
||||
|
||||
<-failed
|
||||
empty, err := genericapirequest.IsEmpty(contextMapper)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !empty {
|
||||
t.Fatalf("contextMapper should have no stored requests: %v", contextMapper)
|
||||
}
|
||||
}
|
|
@ -23,8 +23,8 @@ import (
|
|||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||
)
|
||||
|
||||
// WithAuthorizationCheck passes all authorized requests on to handler, and returns a forbidden error otherwise.
|
|
@ -24,9 +24,9 @@ import (
|
|||
"testing"
|
||||
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||
)
|
||||
|
||||
func TestGetAuthorizerAttributes(t *testing.T) {
|
|
@ -15,5 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
// Package filters contains all the http handler chain filters which
|
||||
// _are_ api related.
|
||||
package filters // import "k8s.io/kubernetes/pkg/genericapiserver/api/filters"
|
||||
// _are_ api related, i.e. which are prerequisite for the API services
|
||||
// to work (in contrast to the filters in the server package which are
|
||||
// not part of the API contract).
|
||||
package filters // import "k8s.io/kubernetes/pkg/genericapiserver/endpoints/filters"
|
|
@ -24,14 +24,14 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apiserver/pkg/authentication/serviceaccount"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/httplog"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/server/httplog"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||
)
|
||||
|
||||
// WithImpersonation is a filter that will inspect and check requests that attempt to change the user.Info for their requests
|
|
@ -26,7 +26,7 @@ import (
|
|||
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
|
||||
)
|
||||
|
|
@ -21,8 +21,8 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||
)
|
||||
|
||||
// WithRequestInfo attaches a RequestInfo to the context.
|
|
@ -18,7 +18,7 @@ package filters
|
|||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
func newTestRequestInfoResolver() *request.RequestInfoFactory {
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package endpoints
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -29,10 +29,10 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/admission"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
)
|
||||
|
||||
// APIGroupVersion is a helper for exposing rest.Storage objects as http.Handlers via go-restful
|
||||
|
@ -49,10 +49,14 @@ type APIGroupVersion struct {
|
|||
GroupVersion schema.GroupVersion
|
||||
|
||||
// OptionsExternalVersion controls the Kubernetes APIVersion used for common objects in the apiserver
|
||||
// schema like api.Status, api.DeleteOptions, and api.ListOptions. Other implementors may
|
||||
// schema like api.Status, api.DeleteOptions, and metav1.ListOptions. Other implementors may
|
||||
// define a version "v1beta1" but want to use the Kubernetes "v1" internal objects. If
|
||||
// empty, defaults to GroupVersion.
|
||||
OptionsExternalVersion *schema.GroupVersion
|
||||
// MetaGroupVersion defaults to "meta.k8s.io/v1" and is the scheme group version used to decode
|
||||
// common API implementations like ListOptions. Future changes will allow this to vary by group
|
||||
// version (for when the inevitable meta/v2 group emerges).
|
||||
MetaGroupVersion *schema.GroupVersion
|
||||
|
||||
Mapper meta.RESTMapper
|
||||
|
|
@ -17,7 +17,7 @@ go_test(
|
|||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//pkg/util/strategicpatch:go_default_library",
|
||||
"//vendor:github.com/emicklei/go-restful",
|
||||
"//vendor:github.com/evanphx/json-patch",
|
||||
|
@ -27,7 +27,7 @@ go_test(
|
|||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/diff",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -36,17 +36,16 @@ go_library(
|
|||
srcs = [
|
||||
"discovery.go",
|
||||
"doc.go",
|
||||
"patch.go",
|
||||
"proxy.go",
|
||||
"rest.go",
|
||||
"watch.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/admission:go_default_library",
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/genericapiserver/api/handlers/responsewriters:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/handlers/responsewriters:go_default_library",
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//pkg/util:go_default_library",
|
||||
"//pkg/util/httpstream:go_default_library",
|
||||
"//pkg/util/proxy:go_default_library",
|
||||
|
@ -57,17 +56,21 @@ go_library(
|
|||
"//vendor:golang.org/x/net/websocket",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/fields",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer/streaming",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
"//vendor:k8s.io/apiserver/pkg/handlers/negotiation",
|
||||
"//vendor:k8s.io/apiserver/pkg/httplog",
|
||||
"//vendor:k8s.io/apiserver/pkg/metrics",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/admission",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/handlers/negotiation",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/metrics",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/server/httplog",
|
||||
"//vendor:k8s.io/apiserver/pkg/util/wsstream",
|
||||
],
|
||||
)
|
||||
|
@ -83,7 +86,7 @@ filegroup(
|
|||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/genericapiserver/api/handlers/responsewriters:all-srcs",
|
||||
"//pkg/genericapiserver/endpoints/handlers/responsewriters:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -22,7 +22,7 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
)
|
|
@ -15,4 +15,4 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
// Package handlers contains HTTP handlers to implement the apiserver APIs.
|
||||
package handlers // import "k8s.io/kubernetes/pkg/genericapiserver/api/handlers"
|
||||
package handlers // import "k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers"
|
131
vendor/k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/patch.go
generated
vendored
Normal file
131
vendor/k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/patch.go
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
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 handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/util/strategicpatch"
|
||||
|
||||
"github.com/evanphx/json-patch"
|
||||
)
|
||||
|
||||
// patchObjectJSON patches the <originalObject> with <patchJS> and stores
|
||||
// the result in <objToUpdate>.
|
||||
// Currently it also returns the original and patched objects serialized to
|
||||
// JSONs (this may not be needed once we can apply patches at the
|
||||
// map[string]interface{} level).
|
||||
func patchObjectJSON(
|
||||
patchType types.PatchType,
|
||||
codec runtime.Codec,
|
||||
originalObject runtime.Object,
|
||||
patchJS []byte,
|
||||
objToUpdate runtime.Object,
|
||||
versionedObj runtime.Object,
|
||||
) (originalObjJS []byte, patchedObjJS []byte, retErr error) {
|
||||
js, err := runtime.Encode(codec, originalObject)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
originalObjJS = js
|
||||
|
||||
switch patchType {
|
||||
case types.JSONPatchType:
|
||||
patchObj, err := jsonpatch.DecodePatch(patchJS)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if patchedObjJS, err = patchObj.Apply(originalObjJS); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
case types.MergePatchType:
|
||||
if patchedObjJS, err = jsonpatch.MergePatch(originalObjJS, patchJS); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
case types.StrategicMergePatchType:
|
||||
if patchedObjJS, err = strategicpatch.StrategicMergePatch(originalObjJS, patchJS, versionedObj); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
default:
|
||||
// only here as a safety net - go-restful filters content-type
|
||||
return nil, nil, fmt.Errorf("unknown Content-Type header for patch: %v", patchType)
|
||||
}
|
||||
if err := runtime.DecodeInto(codec, patchedObjJS, objToUpdate); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// strategicPatchObject applies a strategic merge patch of <patchJS> to
|
||||
// <originalObject> and stores the result in <objToUpdate>.
|
||||
// It additionally returns the map[string]interface{} representation of the
|
||||
// <originalObject> and <patchJS>.
|
||||
func strategicPatchObject(
|
||||
codec runtime.Codec,
|
||||
originalObject runtime.Object,
|
||||
patchJS []byte,
|
||||
objToUpdate runtime.Object,
|
||||
versionedObj runtime.Object,
|
||||
) (originalObjMap map[string]interface{}, patchMap map[string]interface{}, retErr error) {
|
||||
// TODO: This should be one-step conversion that doesn't require
|
||||
// json marshaling and unmarshaling once #39017 is fixed.
|
||||
data, err := runtime.Encode(codec, originalObject)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
originalObjMap = make(map[string]interface{})
|
||||
if err := json.Unmarshal(data, &originalObjMap); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
patchMap = make(map[string]interface{})
|
||||
if err := json.Unmarshal(patchJS, &patchMap); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := applyPatchToObject(codec, originalObjMap, patchMap, objToUpdate, versionedObj); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// applyPatchToObject applies a strategic merge patch of <patchMap> to
|
||||
// <originalMap> and stores the result in <objToUpdate>, though it operates
|
||||
// on versioned map[string]interface{} representations.
|
||||
func applyPatchToObject(
|
||||
codec runtime.Codec,
|
||||
originalMap map[string]interface{},
|
||||
patchMap map[string]interface{},
|
||||
objToUpdate runtime.Object,
|
||||
versionedObj runtime.Object,
|
||||
) error {
|
||||
patchedObjMap, err := strategicpatch.StrategicMergeMapPatch(originalMap, patchMap, versionedObj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: This should be one-step conversion that doesn't require
|
||||
// json marshaling and unmarshaling once #39017 is fixed.
|
||||
data, err := json.Marshal(patchedObjMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return runtime.DecodeInto(codec, data, objToUpdate)
|
||||
}
|
|
@ -31,12 +31,12 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apiserver/pkg/httplog"
|
||||
"k8s.io/apiserver/pkg/metrics"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/server/httplog"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
"k8s.io/kubernetes/pkg/util/httpstream"
|
||||
proxyutil "k8s.io/kubernetes/pkg/util/proxy"
|
||||
|
|
@ -31,14 +31,14 @@ go_library(
|
|||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//pkg/storage:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/runtime",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/handlers/negotiation",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/handlers/negotiation",
|
||||
"//vendor:k8s.io/apiserver/pkg/util/flushwriter",
|
||||
"//vendor:k8s.io/apiserver/pkg/util/wsstream",
|
||||
],
|
|
@ -15,4 +15,4 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
// Package responsewriters containers helpers to write responses in HTTP handlers.
|
||||
package responsewriters // import "k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
package responsewriters // import "k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
|
@ -52,7 +52,7 @@ func apiStatus(err error) *metav1.Status {
|
|||
status := http.StatusInternalServerError
|
||||
switch {
|
||||
//TODO: replace me with NewConflictErr
|
||||
case storage.IsTestFailed(err):
|
||||
case storage.IsConflict(err):
|
||||
status = http.StatusConflict
|
||||
}
|
||||
// Log errors that were not converted to an error status
|
|
@ -26,10 +26,10 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apiserver/pkg/handlers/negotiation"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||
"k8s.io/apiserver/pkg/util/flushwriter"
|
||||
"k8s.io/apiserver/pkg/util/wsstream"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
)
|
||||
|
||||
// WriteObject renders a returned runtime.Object to the response as a stream or an encoded object. If the object
|
|
@ -29,22 +29,22 @@ import (
|
|||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apiserver/pkg/handlers/negotiation"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/admission"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers/responsewriters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers/responsewriters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
"k8s.io/kubernetes/pkg/util"
|
||||
"k8s.io/kubernetes/pkg/util/strategicpatch"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/evanphx/json-patch"
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
|
@ -87,6 +87,8 @@ type RequestScope struct {
|
|||
Resource schema.GroupVersionResource
|
||||
Kind schema.GroupVersionKind
|
||||
Subresource string
|
||||
|
||||
MetaGroupVersion schema.GroupVersion
|
||||
}
|
||||
|
||||
func (scope *RequestScope) err(err error, w http.ResponseWriter, req *http.Request) {
|
||||
|
@ -264,8 +266,8 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch
|
|||
ctx := scope.ContextFunc(req)
|
||||
ctx = request.WithNamespace(ctx, namespace)
|
||||
|
||||
opts := api.ListOptions{}
|
||||
if err := scope.ParameterCodec.DecodeParameters(req.Request.URL.Query(), scope.Kind.GroupVersion(), &opts); err != nil {
|
||||
opts := metainternalversion.ListOptions{}
|
||||
if err := metainternalversion.ParameterCodec.DecodeParameters(req.Request.URL.Query(), scope.MetaGroupVersion, &opts); err != nil {
|
||||
scope.err(err, res.ResponseWriter, req.Request)
|
||||
return
|
||||
}
|
||||
|
@ -302,6 +304,7 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch
|
|||
}
|
||||
|
||||
if (opts.Watch || forceWatch) && rw != nil {
|
||||
glog.Infof("Started to log from %v for %v", ctx, req.Request.URL.RequestURI())
|
||||
watcher, err := rw.Watch(ctx, &opts)
|
||||
if err != nil {
|
||||
scope.err(err, res.ResponseWriter, req.Request)
|
||||
|
@ -488,7 +491,7 @@ func PatchResource(r rest.Patcher, scope RequestScope, admit admission.Interface
|
|||
if idx := strings.Index(contentType, ";"); idx > 0 {
|
||||
contentType = contentType[:idx]
|
||||
}
|
||||
patchType := api.PatchType(contentType)
|
||||
patchType := types.PatchType(contentType)
|
||||
|
||||
patchJS, err := readBody(req.Request)
|
||||
if err != nil {
|
||||
|
@ -542,7 +545,7 @@ func patchResource(
|
|||
versionedObj runtime.Object,
|
||||
patcher rest.Patcher,
|
||||
name string,
|
||||
patchType api.PatchType,
|
||||
patchType types.PatchType,
|
||||
patchJS []byte,
|
||||
namer ScopeNamer,
|
||||
copier runtime.ObjectCopier,
|
||||
|
@ -555,6 +558,8 @@ func patchResource(
|
|||
var (
|
||||
originalObjJS []byte
|
||||
originalPatchedObjJS []byte
|
||||
originalObjMap map[string]interface{}
|
||||
originalPatchMap map[string]interface{}
|
||||
lastConflictErr error
|
||||
)
|
||||
|
||||
|
@ -569,25 +574,30 @@ func patchResource(
|
|||
}
|
||||
|
||||
switch {
|
||||
case len(originalObjJS) == 0 || len(originalPatchedObjJS) == 0:
|
||||
case originalObjJS == nil && originalObjMap == nil:
|
||||
// first time through,
|
||||
// 1. apply the patch
|
||||
// 2. save the originalJS and patchedJS to detect whether there were conflicting changes on retries
|
||||
if js, err := runtime.Encode(codec, currentObject); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
originalObjJS = js
|
||||
}
|
||||
|
||||
if js, err := getPatchedJS(patchType, originalObjJS, patchJS, versionedObj); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
originalPatchedObjJS = js
|
||||
}
|
||||
// 2. save the original and patched to detect whether there were conflicting changes on retries
|
||||
|
||||
objToUpdate := patcher.New()
|
||||
if err := runtime.DecodeInto(codec, originalPatchedObjJS, objToUpdate); err != nil {
|
||||
return nil, err
|
||||
|
||||
// For performance reasons, in case of strategicpatch, we avoid json
|
||||
// marshaling and unmarshaling and operate just on map[string]interface{}.
|
||||
// In case of other patch types, we still have to operate on JSON
|
||||
// representations.
|
||||
switch patchType {
|
||||
case types.JSONPatchType, types.MergePatchType:
|
||||
originalJS, patchedJS, err := patchObjectJSON(patchType, codec, currentObject, patchJS, objToUpdate, versionedObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
originalObjJS, originalPatchedObjJS = originalJS, patchedJS
|
||||
case types.StrategicMergePatchType:
|
||||
originalMap, patchMap, err := strategicPatchObject(codec, currentObject, patchJS, objToUpdate, versionedObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
originalObjMap, originalPatchMap = originalMap, patchMap
|
||||
}
|
||||
if err := checkName(objToUpdate, name, namespace, namer); err != nil {
|
||||
return nil, err
|
||||
|
@ -602,33 +612,62 @@ func patchResource(
|
|||
// 2. build a strategic merge patch from originalJS and the currentJS
|
||||
// 3. ensure no conflicts between the two patches
|
||||
// 4. apply the #1 patch to the currentJS object
|
||||
currentObjectJS, err := runtime.Encode(codec, currentObject)
|
||||
|
||||
// TODO: This should be one-step conversion that doesn't require
|
||||
// json marshaling and unmarshaling once #39017 is fixed.
|
||||
data, err := runtime.Encode(codec, currentObject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currentPatch, err := strategicpatch.CreateStrategicMergePatch(originalObjJS, currentObjectJS, versionedObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
originalPatch, err := strategicpatch.CreateStrategicMergePatch(originalObjJS, originalPatchedObjJS, versionedObj)
|
||||
if err != nil {
|
||||
currentObjMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal(data, ¤tObjMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
diff1 := make(map[string]interface{})
|
||||
if err := json.Unmarshal(originalPatch, &diff1); err != nil {
|
||||
return nil, err
|
||||
var currentPatchMap map[string]interface{}
|
||||
if originalObjMap != nil {
|
||||
var err error
|
||||
currentPatchMap, err = strategicpatch.CreateTwoWayMergeMapPatch(originalObjMap, currentObjMap, versionedObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if originalPatchMap == nil {
|
||||
// Compute original patch, if we already didn't do this in previous retries.
|
||||
originalPatch, err := strategicpatch.CreateTwoWayMergePatch(originalObjJS, originalPatchedObjJS, versionedObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
originalPatchMap = make(map[string]interface{})
|
||||
if err := json.Unmarshal(originalPatch, &originalPatchMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Compute current patch.
|
||||
currentObjJS, err := runtime.Encode(codec, currentObject)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currentPatch, err := strategicpatch.CreateTwoWayMergePatch(originalObjJS, currentObjJS, versionedObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currentPatchMap = make(map[string]interface{})
|
||||
if err := json.Unmarshal(currentPatch, ¤tPatchMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
diff2 := make(map[string]interface{})
|
||||
if err := json.Unmarshal(currentPatch, &diff2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hasConflicts, err := strategicpatch.HasConflicts(diff1, diff2)
|
||||
|
||||
hasConflicts, err := strategicpatch.HasConflicts(originalPatchMap, currentPatchMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if hasConflicts {
|
||||
glog.V(4).Infof("patchResource failed for resource %s, because there is a meaningful conflict.\n diff1=%v\n, diff2=%v\n", name, diff1, diff2)
|
||||
if glog.V(4) {
|
||||
diff1, _ := json.Marshal(currentPatchMap)
|
||||
diff2, _ := json.Marshal(originalPatchMap)
|
||||
glog.Infof("patchResource failed for resource %s, because there is a meaningful conflict.\n diff1=%v\n, diff2=%v\n", name, diff1, diff2)
|
||||
}
|
||||
// Return the last conflict error we got if we have one
|
||||
if lastConflictErr != nil {
|
||||
return nil, lastConflictErr
|
||||
|
@ -637,14 +676,11 @@ func patchResource(
|
|||
return nil, errors.NewConflict(resource.GroupResource(), name, nil)
|
||||
}
|
||||
|
||||
newlyPatchedObjJS, err := getPatchedJS(api.StrategicMergePatchType, currentObjectJS, originalPatch, versionedObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objToUpdate := patcher.New()
|
||||
if err := runtime.DecodeInto(codec, newlyPatchedObjJS, objToUpdate); err != nil {
|
||||
if err := applyPatchToObject(codec, currentObjMap, originalPatchMap, objToUpdate, versionedObj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return objToUpdate, nil
|
||||
}
|
||||
}
|
||||
|
@ -774,7 +810,7 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco
|
|||
ctx := scope.ContextFunc(req)
|
||||
ctx = request.WithNamespace(ctx, namespace)
|
||||
|
||||
options := &api.DeleteOptions{}
|
||||
options := &metav1.DeleteOptions{}
|
||||
if allowsOptions {
|
||||
body, err := readBody(req.Request)
|
||||
if err != nil {
|
||||
|
@ -878,8 +914,8 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco
|
|||
}
|
||||
}
|
||||
|
||||
listOptions := api.ListOptions{}
|
||||
if err := scope.ParameterCodec.DecodeParameters(req.Request.URL.Query(), scope.Kind.GroupVersion(), &listOptions); err != nil {
|
||||
listOptions := metainternalversion.ListOptions{}
|
||||
if err := metainternalversion.ParameterCodec.DecodeParameters(req.Request.URL.Query(), scope.MetaGroupVersion, &listOptions); err != nil {
|
||||
scope.err(err, res.ResponseWriter, req.Request)
|
||||
return
|
||||
}
|
||||
|
@ -898,7 +934,7 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope RequestSco
|
|||
}
|
||||
}
|
||||
|
||||
options := &api.DeleteOptions{}
|
||||
options := &metav1.DeleteOptions{}
|
||||
if checkBody {
|
||||
body, err := readBody(req.Request)
|
||||
if err != nil {
|
||||
|
@ -1078,24 +1114,6 @@ func setListSelfLink(obj runtime.Object, req *restful.Request, namer ScopeNamer)
|
|||
return count, err
|
||||
}
|
||||
|
||||
func getPatchedJS(patchType api.PatchType, originalJS, patchJS []byte, obj runtime.Object) ([]byte, error) {
|
||||
switch patchType {
|
||||
case api.JSONPatchType:
|
||||
patchObj, err := jsonpatch.DecodePatch(patchJS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return patchObj.Apply(originalJS)
|
||||
case api.MergePatchType:
|
||||
return jsonpatch.MergePatch(originalJS, patchJS)
|
||||
case api.StrategicMergePatchType:
|
||||
return strategicpatch.StrategicMergePatchData(originalJS, patchJS, obj)
|
||||
default:
|
||||
// only here as a safety net - go-restful filters content-type
|
||||
return nil, fmt.Errorf("unknown Content-Type header for patch: %v", patchType)
|
||||
}
|
||||
}
|
||||
|
||||
func summarizeData(data []byte, maxLength int) string {
|
||||
switch {
|
||||
case len(data) == 0:
|
|
@ -32,11 +32,11 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
"k8s.io/kubernetes/pkg/util/strategicpatch"
|
||||
)
|
||||
|
||||
|
@ -55,16 +55,27 @@ type TestPatchSubType struct {
|
|||
func (obj *testPatchType) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
|
||||
|
||||
func TestPatchAnonymousField(t *testing.T) {
|
||||
originalJS := `{"kind":"testPatchType","theField":"my-value"}`
|
||||
patch := `{"theField": "changed!"}`
|
||||
expectedJS := `{"kind":"testPatchType","theField":"changed!"}`
|
||||
testGV := schema.GroupVersion{Group: "", Version: "v"}
|
||||
api.Scheme.AddKnownTypes(testGV, &testPatchType{})
|
||||
codec := api.Codecs.LegacyCodec(testGV)
|
||||
|
||||
actualBytes, err := getPatchedJS(api.StrategicMergePatchType, []byte(originalJS), []byte(patch), &testPatchType{})
|
||||
original := &testPatchType{
|
||||
TypeMeta: metav1.TypeMeta{Kind: "testPatchType", APIVersion: "v"},
|
||||
TestPatchSubType: TestPatchSubType{StringField: "my-value"},
|
||||
}
|
||||
patch := `{"theField": "changed!"}`
|
||||
expected := &testPatchType{
|
||||
TypeMeta: metav1.TypeMeta{Kind: "testPatchType", APIVersion: "v"},
|
||||
TestPatchSubType: TestPatchSubType{StringField: "changed!"},
|
||||
}
|
||||
|
||||
actual := &testPatchType{}
|
||||
_, _, err := strategicPatchObject(codec, original, []byte(patch), actual, &testPatchType{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if string(actualBytes) != expectedJS {
|
||||
t.Errorf("expected %v, got %v", expectedJS, string(actualBytes))
|
||||
if !api.Semantic.DeepEqual(actual, expected) {
|
||||
t.Errorf("expected %#v, got %#v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,9 +202,9 @@ func (tc *patchTestCase) Run(t *testing.T) {
|
|||
resource := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
|
||||
versionedObj := &v1.Pod{}
|
||||
|
||||
for _, patchType := range []api.PatchType{api.JSONPatchType, api.MergePatchType, api.StrategicMergePatchType} {
|
||||
for _, patchType := range []types.PatchType{types.JSONPatchType, types.MergePatchType, types.StrategicMergePatchType} {
|
||||
// TODO SUPPORT THIS!
|
||||
if patchType == api.JSONPatchType {
|
||||
if patchType == types.JSONPatchType {
|
||||
continue
|
||||
}
|
||||
t.Logf("Working with patchType %v", patchType)
|
||||
|
@ -211,17 +222,17 @@ func (tc *patchTestCase) Run(t *testing.T) {
|
|||
|
||||
patch := []byte{}
|
||||
switch patchType {
|
||||
case api.JSONPatchType:
|
||||
case types.JSONPatchType:
|
||||
continue
|
||||
|
||||
case api.StrategicMergePatchType:
|
||||
patch, err = strategicpatch.CreateStrategicMergePatch(originalObjJS, changedJS, versionedObj)
|
||||
case types.StrategicMergePatchType:
|
||||
patch, err = strategicpatch.CreateTwoWayMergePatch(originalObjJS, changedJS, versionedObj)
|
||||
if err != nil {
|
||||
t.Errorf("%s: unexpected error: %v", tc.name, err)
|
||||
return
|
||||
}
|
||||
|
||||
case api.MergePatchType:
|
||||
case types.MergePatchType:
|
||||
patch, err = jsonpatch.CreateMergePatch(originalObjJS, changedJS)
|
||||
if err != nil {
|
||||
t.Errorf("%s: unexpected error: %v", tc.name, err)
|
||||
|
@ -460,7 +471,7 @@ func TestHasUID(t *testing.T) {
|
|||
{obj: &api.Pod{}, hasUID: false},
|
||||
{obj: nil, hasUID: false},
|
||||
{obj: runtime.Object(nil), hasUID: false},
|
||||
{obj: &api.Pod{ObjectMeta: api.ObjectMeta{UID: types.UID("A")}}, hasUID: true},
|
||||
{obj: &api.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("A")}}, hasUID: true},
|
||||
}
|
||||
for i, tc := range testcases {
|
||||
actual, err := hasUID(tc.obj)
|
|
@ -29,8 +29,8 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/apiserver/pkg/handlers/negotiation"
|
||||
"k8s.io/apiserver/pkg/httplog"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||
"k8s.io/apiserver/pkg/server/httplog"
|
||||
"k8s.io/apiserver/pkg/util/wsstream"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package endpoints
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -34,13 +34,13 @@ import (
|
|||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/handlers/negotiation"
|
||||
"k8s.io/apiserver/pkg/metrics"
|
||||
"k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||
"k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
)
|
||||
|
@ -521,6 +521,11 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
Resource: a.group.GroupVersion.WithResource(resource),
|
||||
Subresource: subresource,
|
||||
Kind: fqKindToRegister,
|
||||
|
||||
MetaGroupVersion: metav1.SchemeGroupVersion,
|
||||
}
|
||||
if a.group.MetaGroupVersion != nil {
|
||||
reqScope.MetaGroupVersion = *a.group.MetaGroupVersion
|
||||
}
|
||||
for _, action := range actions {
|
||||
versionedObject := storageMeta.ProducesObject(action.Verb)
|
||||
|
@ -638,7 +643,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
|||
route := ws.PATCH(action.Path).To(handler).
|
||||
Doc(doc).
|
||||
Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")).
|
||||
Consumes(string(api.JSONPatchType), string(api.MergePatchType), string(api.StrategicMergePatchType)).
|
||||
Consumes(string(types.JSONPatchType), string(types.MergePatchType), string(types.StrategicMergePatchType)).
|
||||
Operation("patch"+namespaced+kind+strings.Title(subresource)+operationSuffix).
|
||||
Produces(append(storageMeta.ProducesMIMETypes(action.Verb), mediaTypes...)...).
|
||||
Returns(http.StatusOK, "OK", versionedObject).
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package endpoints
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -43,7 +43,7 @@ func TestScopeNamingGenerateLink(t *testing.T) {
|
|||
true,
|
||||
}
|
||||
service := &api.Service{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
Namespace: "other",
|
||||
},
|
||||
|
@ -82,8 +82,6 @@ func TestIsVowel(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGetArticleForNoun(t *testing.T) {
|
||||
type args struct {
|
||||
}
|
||||
tests := []struct {
|
||||
noun string
|
||||
padding string
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package endpoints
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -36,7 +36,7 @@ import (
|
|||
|
||||
"golang.org/x/net/websocket"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
)
|
||||
|
||||
func TestProxyRequestContentLengthAndTransferEncoding(t *testing.T) {
|
|
@ -15,7 +15,6 @@ go_library(
|
|||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//vendor:github.com/ugorji/go/codec",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
|
@ -26,8 +26,7 @@ import (
|
|||
"fmt"
|
||||
codec1978 "github.com/ugorji/go/codec"
|
||||
pkg1_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
pkg3_types "k8s.io/apimachinery/pkg/types"
|
||||
pkg2_v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
pkg2_types "k8s.io/apimachinery/pkg/types"
|
||||
"reflect"
|
||||
"runtime"
|
||||
time "time"
|
||||
|
@ -64,10 +63,9 @@ func init() {
|
|||
}
|
||||
if false { // reference the types, but skip this branch at build/run time
|
||||
var v0 pkg1_v1.TypeMeta
|
||||
var v1 pkg3_types.UID
|
||||
var v2 pkg2_v1.ObjectMeta
|
||||
var v3 time.Time
|
||||
_, _, _, _ = v0, v1, v2, v3
|
||||
var v1 pkg2_types.UID
|
||||
var v2 time.Time
|
||||
_, _, _ = v0, v1, v2
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,13 +156,25 @@ func (x *Simple) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
if yyr2 || yy2arr2 {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
yy10 := &x.ObjectMeta
|
||||
yy10.CodecEncodeSelf(e)
|
||||
yym11 := z.EncBinary()
|
||||
_ = yym11
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.EncExt(yy10) {
|
||||
} else {
|
||||
z.EncFallback(yy10)
|
||||
}
|
||||
} else {
|
||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
||||
r.EncodeString(codecSelferC_UTF81234, string("metadata"))
|
||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
||||
yy12 := &x.ObjectMeta
|
||||
yy12.CodecEncodeSelf(e)
|
||||
yym13 := z.EncBinary()
|
||||
_ = yym13
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.EncExt(yy12) {
|
||||
} else {
|
||||
z.EncFallback(yy12)
|
||||
}
|
||||
}
|
||||
if yyr2 || yy2arr2 {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
|
@ -311,33 +321,39 @@ func (x *Simple) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
|||
}
|
||||
case "metadata":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.ObjectMeta = pkg2_v1.ObjectMeta{}
|
||||
x.ObjectMeta = pkg1_v1.ObjectMeta{}
|
||||
} else {
|
||||
yyv8 := &x.ObjectMeta
|
||||
yyv8.CodecDecodeSelf(d)
|
||||
yym9 := z.DecBinary()
|
||||
_ = yym9
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.DecExt(yyv8) {
|
||||
} else {
|
||||
z.DecFallback(yyv8, false)
|
||||
}
|
||||
}
|
||||
case "other":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Other = ""
|
||||
} else {
|
||||
yyv9 := &x.Other
|
||||
yym10 := z.DecBinary()
|
||||
_ = yym10
|
||||
yyv10 := &x.Other
|
||||
yym11 := z.DecBinary()
|
||||
_ = yym11
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv9)) = r.DecodeString()
|
||||
*((*string)(yyv10)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
case "labels":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Labels = nil
|
||||
} else {
|
||||
yyv11 := &x.Labels
|
||||
yym12 := z.DecBinary()
|
||||
_ = yym12
|
||||
yyv12 := &x.Labels
|
||||
yym13 := z.DecBinary()
|
||||
_ = yym13
|
||||
if false {
|
||||
} else {
|
||||
z.F.DecMapStringStringX(yyv11, false, d)
|
||||
z.F.DecMapStringStringX(yyv12, false, d)
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
@ -351,16 +367,16 @@ func (x *Simple) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
var yyj13 int
|
||||
var yyb13 bool
|
||||
var yyhl13 bool = l >= 0
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
var yyj14 int
|
||||
var yyb14 bool
|
||||
var yyhl14 bool = l >= 0
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -368,21 +384,21 @@ func (x *Simple) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
if r.TryDecodeAsNil() {
|
||||
x.Kind = ""
|
||||
} else {
|
||||
yyv14 := &x.Kind
|
||||
yym15 := z.DecBinary()
|
||||
_ = yym15
|
||||
yyv15 := &x.Kind
|
||||
yym16 := z.DecBinary()
|
||||
_ = yym16
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv14)) = r.DecodeString()
|
||||
*((*string)(yyv15)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -390,38 +406,44 @@ func (x *Simple) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
if r.TryDecodeAsNil() {
|
||||
x.APIVersion = ""
|
||||
} else {
|
||||
yyv16 := &x.APIVersion
|
||||
yym17 := z.DecBinary()
|
||||
_ = yym17
|
||||
yyv17 := &x.APIVersion
|
||||
yym18 := z.DecBinary()
|
||||
_ = yym18
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv16)) = r.DecodeString()
|
||||
*((*string)(yyv17)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.ObjectMeta = pkg2_v1.ObjectMeta{}
|
||||
x.ObjectMeta = pkg1_v1.ObjectMeta{}
|
||||
} else {
|
||||
yyv18 := &x.ObjectMeta
|
||||
yyv18.CodecDecodeSelf(d)
|
||||
yyv19 := &x.ObjectMeta
|
||||
yym20 := z.DecBinary()
|
||||
_ = yym20
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.DecExt(yyv19) {
|
||||
} else {
|
||||
z.DecFallback(yyv19, false)
|
||||
}
|
||||
}
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -429,21 +451,21 @@ func (x *Simple) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
if r.TryDecodeAsNil() {
|
||||
x.Other = ""
|
||||
} else {
|
||||
yyv19 := &x.Other
|
||||
yym20 := z.DecBinary()
|
||||
_ = yym20
|
||||
yyv21 := &x.Other
|
||||
yym22 := z.DecBinary()
|
||||
_ = yym22
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv19)) = r.DecodeString()
|
||||
*((*string)(yyv21)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -451,26 +473,26 @@ func (x *Simple) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
if r.TryDecodeAsNil() {
|
||||
x.Labels = nil
|
||||
} else {
|
||||
yyv21 := &x.Labels
|
||||
yym22 := z.DecBinary()
|
||||
_ = yym22
|
||||
yyv23 := &x.Labels
|
||||
yym24 := z.DecBinary()
|
||||
_ = yym24
|
||||
if false {
|
||||
} else {
|
||||
z.F.DecMapStringStringX(yyv21, false, d)
|
||||
z.F.DecMapStringStringX(yyv23, false, d)
|
||||
}
|
||||
}
|
||||
for {
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
break
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
z.DecStructFieldNotFound(yyj13-1, "")
|
||||
z.DecStructFieldNotFound(yyj14-1, "")
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
}
|
||||
|
@ -562,13 +584,25 @@ func (x *SimpleRoot) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
if yyr2 || yy2arr2 {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
yy10 := &x.ObjectMeta
|
||||
yy10.CodecEncodeSelf(e)
|
||||
yym11 := z.EncBinary()
|
||||
_ = yym11
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.EncExt(yy10) {
|
||||
} else {
|
||||
z.EncFallback(yy10)
|
||||
}
|
||||
} else {
|
||||
z.EncSendContainerState(codecSelfer_containerMapKey1234)
|
||||
r.EncodeString(codecSelferC_UTF81234, string("metadata"))
|
||||
z.EncSendContainerState(codecSelfer_containerMapValue1234)
|
||||
yy12 := &x.ObjectMeta
|
||||
yy12.CodecEncodeSelf(e)
|
||||
yym13 := z.EncBinary()
|
||||
_ = yym13
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.EncExt(yy12) {
|
||||
} else {
|
||||
z.EncFallback(yy12)
|
||||
}
|
||||
}
|
||||
if yyr2 || yy2arr2 {
|
||||
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
|
@ -715,33 +749,39 @@ func (x *SimpleRoot) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
|||
}
|
||||
case "metadata":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.ObjectMeta = pkg2_v1.ObjectMeta{}
|
||||
x.ObjectMeta = pkg1_v1.ObjectMeta{}
|
||||
} else {
|
||||
yyv8 := &x.ObjectMeta
|
||||
yyv8.CodecDecodeSelf(d)
|
||||
yym9 := z.DecBinary()
|
||||
_ = yym9
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.DecExt(yyv8) {
|
||||
} else {
|
||||
z.DecFallback(yyv8, false)
|
||||
}
|
||||
}
|
||||
case "other":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Other = ""
|
||||
} else {
|
||||
yyv9 := &x.Other
|
||||
yym10 := z.DecBinary()
|
||||
_ = yym10
|
||||
yyv10 := &x.Other
|
||||
yym11 := z.DecBinary()
|
||||
_ = yym11
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv9)) = r.DecodeString()
|
||||
*((*string)(yyv10)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
case "labels":
|
||||
if r.TryDecodeAsNil() {
|
||||
x.Labels = nil
|
||||
} else {
|
||||
yyv11 := &x.Labels
|
||||
yym12 := z.DecBinary()
|
||||
_ = yym12
|
||||
yyv12 := &x.Labels
|
||||
yym13 := z.DecBinary()
|
||||
_ = yym13
|
||||
if false {
|
||||
} else {
|
||||
z.F.DecMapStringStringX(yyv11, false, d)
|
||||
z.F.DecMapStringStringX(yyv12, false, d)
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
@ -755,16 +795,16 @@ func (x *SimpleRoot) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
var h codecSelfer1234
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
var yyj13 int
|
||||
var yyb13 bool
|
||||
var yyhl13 bool = l >= 0
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
var yyj14 int
|
||||
var yyb14 bool
|
||||
var yyhl14 bool = l >= 0
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -772,21 +812,21 @@ func (x *SimpleRoot) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
if r.TryDecodeAsNil() {
|
||||
x.Kind = ""
|
||||
} else {
|
||||
yyv14 := &x.Kind
|
||||
yym15 := z.DecBinary()
|
||||
_ = yym15
|
||||
yyv15 := &x.Kind
|
||||
yym16 := z.DecBinary()
|
||||
_ = yym16
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv14)) = r.DecodeString()
|
||||
*((*string)(yyv15)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -794,38 +834,44 @@ func (x *SimpleRoot) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
if r.TryDecodeAsNil() {
|
||||
x.APIVersion = ""
|
||||
} else {
|
||||
yyv16 := &x.APIVersion
|
||||
yym17 := z.DecBinary()
|
||||
_ = yym17
|
||||
yyv17 := &x.APIVersion
|
||||
yym18 := z.DecBinary()
|
||||
_ = yym18
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv16)) = r.DecodeString()
|
||||
*((*string)(yyv17)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
if r.TryDecodeAsNil() {
|
||||
x.ObjectMeta = pkg2_v1.ObjectMeta{}
|
||||
x.ObjectMeta = pkg1_v1.ObjectMeta{}
|
||||
} else {
|
||||
yyv18 := &x.ObjectMeta
|
||||
yyv18.CodecDecodeSelf(d)
|
||||
yyv19 := &x.ObjectMeta
|
||||
yym20 := z.DecBinary()
|
||||
_ = yym20
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.DecExt(yyv19) {
|
||||
} else {
|
||||
z.DecFallback(yyv19, false)
|
||||
}
|
||||
}
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -833,21 +879,21 @@ func (x *SimpleRoot) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
if r.TryDecodeAsNil() {
|
||||
x.Other = ""
|
||||
} else {
|
||||
yyv19 := &x.Other
|
||||
yym20 := z.DecBinary()
|
||||
_ = yym20
|
||||
yyv21 := &x.Other
|
||||
yym22 := z.DecBinary()
|
||||
_ = yym22
|
||||
if false {
|
||||
} else {
|
||||
*((*string)(yyv19)) = r.DecodeString()
|
||||
*((*string)(yyv21)) = r.DecodeString()
|
||||
}
|
||||
}
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
return
|
||||
}
|
||||
|
@ -855,26 +901,26 @@ func (x *SimpleRoot) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
if r.TryDecodeAsNil() {
|
||||
x.Labels = nil
|
||||
} else {
|
||||
yyv21 := &x.Labels
|
||||
yym22 := z.DecBinary()
|
||||
_ = yym22
|
||||
yyv23 := &x.Labels
|
||||
yym24 := z.DecBinary()
|
||||
_ = yym24
|
||||
if false {
|
||||
} else {
|
||||
z.F.DecMapStringStringX(yyv21, false, d)
|
||||
z.F.DecMapStringStringX(yyv23, false, d)
|
||||
}
|
||||
}
|
||||
for {
|
||||
yyj13++
|
||||
if yyhl13 {
|
||||
yyb13 = yyj13 > l
|
||||
yyj14++
|
||||
if yyhl14 {
|
||||
yyb14 = yyj14 > l
|
||||
} else {
|
||||
yyb13 = r.CheckBreak()
|
||||
yyb14 = r.CheckBreak()
|
||||
}
|
||||
if yyb13 {
|
||||
if yyb14 {
|
||||
break
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
|
||||
z.DecStructFieldNotFound(yyj13-1, "")
|
||||
z.DecStructFieldNotFound(yyj14-1, "")
|
||||
}
|
||||
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
|
||||
}
|
|
@ -19,12 +19,11 @@ package testing
|
|||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
type Simple struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
apiv1.ObjectMeta `json:"metadata"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
// +optional
|
||||
Other string `json:"other,omitempty"`
|
||||
// +optional
|
||||
|
@ -34,8 +33,8 @@ type Simple struct {
|
|||
func (obj *Simple) GetObjectKind() schema.ObjectKind { return &obj.TypeMeta }
|
||||
|
||||
type SimpleRoot struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
apiv1.ObjectMeta `json:"metadata"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
// +optional
|
||||
Other string `json:"other,omitempty"`
|
||||
// +optional
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package endpoints
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
@ -31,6 +31,7 @@ import (
|
|||
|
||||
"golang.org/x/net/websocket"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
|
||||
|
@ -38,11 +39,9 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/handlers"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
apitesting "k8s.io/kubernetes/pkg/genericapiserver/api/testing"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/endpoints/handlers"
|
||||
apitesting "k8s.io/kubernetes/pkg/genericapiserver/endpoints/testing"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
)
|
||||
|
||||
// watchJSON defines the expected JSON wire equivalent of watch.Event
|
||||
|
@ -68,18 +67,18 @@ var watchTestTable = []struct {
|
|||
t watch.EventType
|
||||
obj runtime.Object
|
||||
}{
|
||||
{watch.Added, &apitesting.Simple{ObjectMeta: apiv1.ObjectMeta{Name: "foo"}}},
|
||||
{watch.Modified, &apitesting.Simple{ObjectMeta: apiv1.ObjectMeta{Name: "bar"}}},
|
||||
{watch.Deleted, &apitesting.Simple{ObjectMeta: apiv1.ObjectMeta{Name: "bar"}}},
|
||||
{watch.Added, &apitesting.Simple{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}},
|
||||
{watch.Modified, &apitesting.Simple{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}},
|
||||
{watch.Deleted, &apitesting.Simple{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}},
|
||||
}
|
||||
|
||||
var podWatchTestTable = []struct {
|
||||
t watch.EventType
|
||||
obj runtime.Object
|
||||
}{
|
||||
{watch.Added, roundTripOrDie(codec, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}})},
|
||||
{watch.Modified, roundTripOrDie(codec, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}})},
|
||||
{watch.Deleted, roundTripOrDie(codec, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "bar"}})},
|
||||
{watch.Added, roundTripOrDie(codec, &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})},
|
||||
{watch.Modified, roundTripOrDie(codec, &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}})},
|
||||
{watch.Deleted, roundTripOrDie(codec, &api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}})},
|
||||
}
|
||||
|
||||
func TestWatchWebsocket(t *testing.T) {
|
||||
|
@ -422,28 +421,28 @@ func TestWatchParamParsing(t *testing.T) {
|
|||
resourceVersion: "1234",
|
||||
labelSelector: "",
|
||||
fieldSelector: "",
|
||||
namespace: api.NamespaceAll,
|
||||
namespace: metav1.NamespaceAll,
|
||||
}, {
|
||||
path: rootPath,
|
||||
rawQuery: "resourceVersion=314159&fieldSelector=Host%3D&labelSelector=name%3Dfoo",
|
||||
resourceVersion: "314159",
|
||||
labelSelector: "name=foo",
|
||||
fieldSelector: "Host=",
|
||||
namespace: api.NamespaceAll,
|
||||
namespace: metav1.NamespaceAll,
|
||||
}, {
|
||||
path: rootPath,
|
||||
rawQuery: "fieldSelector=id%3dfoo&resourceVersion=1492",
|
||||
resourceVersion: "1492",
|
||||
labelSelector: "",
|
||||
fieldSelector: "id=foo",
|
||||
namespace: api.NamespaceAll,
|
||||
namespace: metav1.NamespaceAll,
|
||||
}, {
|
||||
path: rootPath,
|
||||
rawQuery: "",
|
||||
resourceVersion: "",
|
||||
labelSelector: "",
|
||||
fieldSelector: "",
|
||||
namespace: api.NamespaceAll,
|
||||
namespace: metav1.NamespaceAll,
|
||||
},
|
||||
{
|
||||
path: namespacedPath,
|
0
vendor/k8s.io/kubernetes/pkg/genericapiserver/openapi/common/.readonly
generated
vendored
0
vendor/k8s.io/kubernetes/pkg/genericapiserver/openapi/common/.readonly
generated
vendored
143
vendor/k8s.io/kubernetes/pkg/genericapiserver/openapi/common/common.go
generated
vendored
143
vendor/k8s.io/kubernetes/pkg/genericapiserver/openapi/common/common.go
generated
vendored
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 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 common
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// OpenAPIDefinition describes single type. Normally these definitions are auto-generated using gen-openapi.
|
||||
type OpenAPIDefinition struct {
|
||||
Schema spec.Schema
|
||||
Dependencies []string
|
||||
}
|
||||
|
||||
// OpenAPIDefinitions is collection of all definitions.
|
||||
type OpenAPIDefinitions map[string]OpenAPIDefinition
|
||||
|
||||
// OpenAPIDefinitionGetter gets openAPI definitions for a given type. If a type implements this interface,
|
||||
// the definition returned by it will be used, otherwise the auto-generated definitions will be used. See
|
||||
// GetOpenAPITypeFormat for more information about trade-offs of using this interface or GetOpenAPITypeFormat method when
|
||||
// possible.
|
||||
type OpenAPIDefinitionGetter interface {
|
||||
OpenAPIDefinition() *OpenAPIDefinition
|
||||
}
|
||||
|
||||
// Config is set of configuration for openAPI spec generation.
|
||||
type Config struct {
|
||||
// List of supported protocols such as https, http, etc.
|
||||
ProtocolList []string
|
||||
|
||||
// Info is general information about the API.
|
||||
Info *spec.Info
|
||||
|
||||
// DefaultResponse will be used if an operation does not have any responses listed. It
|
||||
// will show up as ... "responses" : {"default" : $DefaultResponse} in the spec.
|
||||
DefaultResponse *spec.Response
|
||||
|
||||
// CommonResponses will be added as a response to all operation specs. This is a good place to add common
|
||||
// responses such as authorization failed.
|
||||
CommonResponses map[int]spec.Response
|
||||
|
||||
// List of webservice's path prefixes to ignore
|
||||
IgnorePrefixes []string
|
||||
|
||||
// OpenAPIDefinitions should provide definition for all models used by routes. Failure to provide this map
|
||||
// or any of the models will result in spec generation failure.
|
||||
Definitions *OpenAPIDefinitions
|
||||
|
||||
// GetOperationIDAndTags returns operation id and tags for a restful route. It is an optional function to customize operation IDs.
|
||||
GetOperationIDAndTags func(servePath string, r *restful.Route) (string, []string, error)
|
||||
|
||||
// SecurityDefinitions is list of all security definitions for OpenAPI service. If this is not nil, the user of config
|
||||
// is responsible to provide DefaultSecurity and (maybe) add unauthorized response to CommonResponses.
|
||||
SecurityDefinitions *spec.SecurityDefinitions
|
||||
|
||||
// DefaultSecurity for all operations. This will pass as spec.SwaggerProps.Security to OpenAPI.
|
||||
// For most cases, this will be list of acceptable definitions in SecurityDefinitions.
|
||||
DefaultSecurity []map[string][]string
|
||||
}
|
||||
|
||||
// This function is a reference for converting go (or any custom type) to a simple open API type,format pair. There are
|
||||
// two ways to customize spec for a type. If you add it here, a type will be converted to a simple type and the type
|
||||
// comment (the comment that is added before type definition) will be lost. The spec will still have the property
|
||||
// comment. The second way is to implement OpenAPIDefinitionGetter interface. That function can customize the spec (so
|
||||
// the spec does not need to be simple type,format) or can even return a simple type,format (e.g. IntOrString). For simple
|
||||
// type formats, the benefit of adding OpenAPIDefinitionGetter interface is to keep both type and property documentation.
|
||||
// Example:
|
||||
// type Sample struct {
|
||||
// ...
|
||||
// // port of the server
|
||||
// port IntOrString
|
||||
// ...
|
||||
// }
|
||||
// // IntOrString documentation...
|
||||
// type IntOrString { ... }
|
||||
//
|
||||
// Adding IntOrString to this function:
|
||||
// "port" : {
|
||||
// format: "string",
|
||||
// type: "int-or-string",
|
||||
// Description: "port of the server"
|
||||
// }
|
||||
//
|
||||
// Implement OpenAPIDefinitionGetter for IntOrString:
|
||||
//
|
||||
// "port" : {
|
||||
// $Ref: "#/definitions/IntOrString"
|
||||
// Description: "port of the server"
|
||||
// }
|
||||
// ...
|
||||
// definitions:
|
||||
// {
|
||||
// "IntOrString": {
|
||||
// format: "string",
|
||||
// type: "int-or-string",
|
||||
// Description: "IntOrString documentation..." // new
|
||||
// }
|
||||
// }
|
||||
//
|
||||
func GetOpenAPITypeFormat(typeName string) (string, string) {
|
||||
schemaTypeFormatMap := map[string][]string{
|
||||
"uint": {"integer", "int32"},
|
||||
"uint8": {"integer", "byte"},
|
||||
"uint16": {"integer", "int32"},
|
||||
"uint32": {"integer", "int64"},
|
||||
"uint64": {"integer", "int64"},
|
||||
"int": {"integer", "int32"},
|
||||
"int8": {"integer", "byte"},
|
||||
"int16": {"integer", "int32"},
|
||||
"int32": {"integer", "int32"},
|
||||
"int64": {"integer", "int64"},
|
||||
"byte": {"integer", "byte"},
|
||||
"float64": {"number", "double"},
|
||||
"float32": {"number", "float"},
|
||||
"bool": {"boolean", ""},
|
||||
"time.Time": {"string", "date-time"},
|
||||
"string": {"string", ""},
|
||||
"integer": {"integer", ""},
|
||||
"number": {"number", ""},
|
||||
"boolean": {"boolean", ""},
|
||||
"[]byte": {"string", "byte"}, // base64 encoded characters
|
||||
}
|
||||
mapped, ok := schemaTypeFormatMap[typeName]
|
||||
if !ok {
|
||||
return "", ""
|
||||
}
|
||||
return mapped[0], mapped[1]
|
||||
}
|
|
@ -9,15 +9,8 @@ load(
|
|||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"common.go",
|
||||
"doc.go",
|
||||
],
|
||||
srcs = ["doc.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//vendor:github.com/emicklei/go-restful",
|
||||
"//vendor:github.com/go-openapi/spec",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
@ -29,6 +22,10 @@ filegroup(
|
|||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/genericapiserver/registry/generic:all-srcs",
|
||||
"//pkg/genericapiserver/registry/rest:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -14,5 +14,5 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package api contains the code that provides a rest.ful api service.
|
||||
package api // import "k8s.io/kubernetes/pkg/genericapiserver/api"
|
||||
// Package registry contains the generic implementation of the storage and system logic.
|
||||
package registry // import "k8s.io/kubernetes/pkg/genericapiserver/registry"
|
46
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/BUILD
generated
vendored
Normal file
46
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"matcher.go",
|
||||
"options.go",
|
||||
"storage_decorator.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/storage:go_default_library",
|
||||
"//pkg/storage/storagebackend:go_default_library",
|
||||
"//pkg/storage/storagebackend/factory:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/fields",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/genericapiserver/registry/generic/registry:all-srcs",
|
||||
"//pkg/genericapiserver/registry/generic/rest:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
35
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/OWNERS
generated
vendored
Executable file
35
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/OWNERS
generated
vendored
Executable file
|
@ -0,0 +1,35 @@
|
|||
reviewers:
|
||||
- thockin
|
||||
- lavalamp
|
||||
- smarterclayton
|
||||
- wojtek-t
|
||||
- deads2k
|
||||
- yujuhong
|
||||
- derekwaynecarr
|
||||
- caesarxuchao
|
||||
- mikedanese
|
||||
- liggitt
|
||||
- nikhiljindal
|
||||
- bprashanth
|
||||
- gmarek
|
||||
- davidopp
|
||||
- saad-ali
|
||||
- janetkuo
|
||||
- pwittrock
|
||||
- roberthbailey
|
||||
- ncdc
|
||||
- eparis
|
||||
- timothysc
|
||||
- jlowdermilk
|
||||
- piosz
|
||||
- dims
|
||||
- hongchaodeng
|
||||
- krousey
|
||||
- markturansky
|
||||
- fgrzadkowski
|
||||
- xiang90
|
||||
- resouer
|
||||
- mqliang
|
||||
- feihujiang
|
||||
- sdminonne
|
||||
- goltermann
|
19
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 generic provides a generic object store interface and a
|
||||
// generic label/field matching type.
|
||||
package generic // import "k8s.io/kubernetes/pkg/genericapiserver/registry/generic"
|
52
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/matcher.go
generated
vendored
Normal file
52
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/matcher.go
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
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 generic
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
)
|
||||
|
||||
// ObjectMetaFieldsSet returns a fields that represent the ObjectMeta.
|
||||
func ObjectMetaFieldsSet(objectMeta *metav1.ObjectMeta, hasNamespaceField bool) fields.Set {
|
||||
if !hasNamespaceField {
|
||||
return fields.Set{
|
||||
"metadata.name": objectMeta.Name,
|
||||
}
|
||||
}
|
||||
return fields.Set{
|
||||
"metadata.name": objectMeta.Name,
|
||||
"metadata.namespace": objectMeta.Namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// AdObjectMetaField add fields that represent the ObjectMeta to source.
|
||||
func AddObjectMetaFieldsSet(source fields.Set, objectMeta *metav1.ObjectMeta, hasNamespaceField bool) fields.Set {
|
||||
source["metadata.name"] = objectMeta.Name
|
||||
if hasNamespaceField {
|
||||
source["metadata.namespace"] = objectMeta.Namespace
|
||||
}
|
||||
return source
|
||||
}
|
||||
|
||||
// MergeFieldsSets merges a fields'set from fragment into the source.
|
||||
func MergeFieldsSets(source fields.Set, fragment fields.Set) fields.Set {
|
||||
for k, value := range fragment {
|
||||
source[k] = value
|
||||
}
|
||||
return source
|
||||
}
|
49
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/options.go
generated
vendored
Normal file
49
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/options.go
generated
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright 2016 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 generic
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/kubernetes/pkg/storage"
|
||||
"k8s.io/kubernetes/pkg/storage/storagebackend"
|
||||
)
|
||||
|
||||
// RESTOptions is set of configuration options to generic registries.
|
||||
type RESTOptions struct {
|
||||
StorageConfig *storagebackend.Config
|
||||
Decorator StorageDecorator
|
||||
|
||||
EnableGarbageCollection bool
|
||||
DeleteCollectionWorkers int
|
||||
ResourcePrefix string
|
||||
}
|
||||
|
||||
// Implement RESTOptionsGetter so that RESTOptions can directly be used when available (i.e. tests)
|
||||
func (opts RESTOptions) GetRESTOptions(schema.GroupResource) (RESTOptions, error) {
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
type RESTOptionsGetter interface {
|
||||
GetRESTOptions(resource schema.GroupResource) (RESTOptions, error)
|
||||
}
|
||||
|
||||
// StoreOptions is set of configuration options used to complete generic registries.
|
||||
type StoreOptions struct {
|
||||
RESTOptions RESTOptionsGetter
|
||||
TriggerFunc storage.TriggerPublisherFunc
|
||||
AttrFunc storage.AttrFunc
|
||||
}
|
94
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/BUILD
generated
vendored
Normal file
94
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"decorated_watcher.go",
|
||||
"doc.go",
|
||||
"storage_factory.go",
|
||||
"store.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/errors/storage:go_default_library",
|
||||
"//pkg/api/validation/path:go_default_library",
|
||||
"//pkg/genericapiserver/registry/generic:go_default_library",
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//pkg/registry/cachesize:go_default_library",
|
||||
"//pkg/storage:go_default_library",
|
||||
"//pkg/storage/etcd:go_default_library",
|
||||
"//pkg/storage/storagebackend:go_default_library",
|
||||
"//pkg/storage/storagebackend/factory:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:golang.org/x/net/context",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/fields",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"decorated_watcher_test.go",
|
||||
"store_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/genericapiserver/registry/generic:go_default_library",
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//pkg/registry/core/pod:go_default_library",
|
||||
"//pkg/storage:go_default_library",
|
||||
"//pkg/storage/etcd:go_default_library",
|
||||
"//pkg/storage/etcd/testing:go_default_library",
|
||||
"//pkg/storage/storagebackend/factory:go_default_library",
|
||||
"//pkg/storage/testing:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/fields",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/selection",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/storage/names",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
97
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/decorated_watcher.go
generated
vendored
Normal file
97
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/decorated_watcher.go
generated
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
Copyright 2016 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 registry
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
type decoratedWatcher struct {
|
||||
w watch.Interface
|
||||
decorator ObjectFunc
|
||||
cancel context.CancelFunc
|
||||
resultCh chan watch.Event
|
||||
}
|
||||
|
||||
func newDecoratedWatcher(w watch.Interface, decorator ObjectFunc) *decoratedWatcher {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
d := &decoratedWatcher{
|
||||
w: w,
|
||||
decorator: decorator,
|
||||
cancel: cancel,
|
||||
resultCh: make(chan watch.Event),
|
||||
}
|
||||
go d.run(ctx)
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *decoratedWatcher) run(ctx context.Context) {
|
||||
var recv, send watch.Event
|
||||
for {
|
||||
select {
|
||||
case recv = <-d.w.ResultChan():
|
||||
switch recv.Type {
|
||||
case watch.Added, watch.Modified, watch.Deleted:
|
||||
err := d.decorator(recv.Object)
|
||||
if err != nil {
|
||||
send = makeStatusErrorEvent(err)
|
||||
break
|
||||
}
|
||||
send = recv
|
||||
case watch.Error:
|
||||
send = recv
|
||||
}
|
||||
select {
|
||||
case d.resultCh <- send:
|
||||
if send.Type == watch.Error {
|
||||
d.cancel()
|
||||
}
|
||||
case <-ctx.Done():
|
||||
}
|
||||
case <-ctx.Done():
|
||||
d.w.Stop()
|
||||
close(d.resultCh)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *decoratedWatcher) Stop() {
|
||||
d.cancel()
|
||||
}
|
||||
|
||||
func (d *decoratedWatcher) ResultChan() <-chan watch.Event {
|
||||
return d.resultCh
|
||||
}
|
||||
|
||||
func makeStatusErrorEvent(err error) watch.Event {
|
||||
status := &metav1.Status{
|
||||
Status: metav1.StatusFailure,
|
||||
Message: err.Error(),
|
||||
Code: http.StatusInternalServerError,
|
||||
Reason: metav1.StatusReasonInternalError,
|
||||
}
|
||||
return watch.Event{
|
||||
Type: watch.Error,
|
||||
Object: status,
|
||||
}
|
||||
}
|
75
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/decorated_watcher_test.go
generated
vendored
Normal file
75
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/decorated_watcher_test.go
generated
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
Copyright 2016 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 registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func TestDecoratedWatcher(t *testing.T) {
|
||||
w := watch.NewFake()
|
||||
decorator := func(obj runtime.Object) error {
|
||||
pod := obj.(*api.Pod)
|
||||
pod.Annotations = map[string]string{"decorated": "true"}
|
||||
return nil
|
||||
}
|
||||
dw := newDecoratedWatcher(w, decorator)
|
||||
defer dw.Stop()
|
||||
|
||||
go w.Add(&api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})
|
||||
select {
|
||||
case e := <-dw.ResultChan():
|
||||
pod, ok := e.Object.(*api.Pod)
|
||||
if !ok {
|
||||
t.Errorf("Should received object of type *api.Pod, get type (%T)", e.Object)
|
||||
return
|
||||
}
|
||||
if pod.Annotations["decorated"] != "true" {
|
||||
t.Errorf("pod.Annotations[\"decorated\"], want=%s, get=%s", "true", pod.Labels["decorated"])
|
||||
}
|
||||
case <-time.After(wait.ForeverTestTimeout):
|
||||
t.Errorf("timeout after %v", wait.ForeverTestTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecoratedWatcherError(t *testing.T) {
|
||||
w := watch.NewFake()
|
||||
expErr := fmt.Errorf("expected error")
|
||||
decorator := func(obj runtime.Object) error {
|
||||
return expErr
|
||||
}
|
||||
dw := newDecoratedWatcher(w, decorator)
|
||||
defer dw.Stop()
|
||||
|
||||
go w.Add(&api.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})
|
||||
select {
|
||||
case e := <-dw.ResultChan():
|
||||
if e.Type != watch.Error {
|
||||
t.Errorf("event type want=%v, get=%v", watch.Error, e.Type)
|
||||
}
|
||||
case <-time.After(wait.ForeverTestTimeout):
|
||||
t.Errorf("timeout after %v", wait.ForeverTestTimeout)
|
||||
}
|
||||
}
|
19
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 etcd has a generic implementation of a registry that
|
||||
// stores things in etcd.
|
||||
package registry // import "k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry"
|
63
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/storage_factory.go
generated
vendored
Normal file
63
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/storage_factory.go
generated
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
Copyright 2015 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 registry
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/generic"
|
||||
"k8s.io/kubernetes/pkg/storage"
|
||||
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
|
||||
"k8s.io/kubernetes/pkg/storage/storagebackend"
|
||||
"k8s.io/kubernetes/pkg/storage/storagebackend/factory"
|
||||
)
|
||||
|
||||
var _ generic.StorageDecorator = StorageWithCacher
|
||||
|
||||
// Creates a cacher based given storageConfig.
|
||||
func StorageWithCacher(
|
||||
storageConfig *storagebackend.Config,
|
||||
capacity int,
|
||||
objectType runtime.Object,
|
||||
resourcePrefix string,
|
||||
keyFunc func(obj runtime.Object) (string, error),
|
||||
newListFunc func() runtime.Object,
|
||||
getAttrsFunc storage.AttrFunc,
|
||||
triggerFunc storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) {
|
||||
|
||||
s, d := generic.NewRawStorage(storageConfig)
|
||||
// TODO: we would change this later to make storage always have cacher and hide low level KV layer inside.
|
||||
// Currently it has two layers of same storage interface -- cacher and low level kv.
|
||||
cacherConfig := storage.CacherConfig{
|
||||
CacheCapacity: capacity,
|
||||
Storage: s,
|
||||
Versioner: etcdstorage.APIObjectVersioner{},
|
||||
Type: objectType,
|
||||
ResourcePrefix: resourcePrefix,
|
||||
KeyFunc: keyFunc,
|
||||
NewListFunc: newListFunc,
|
||||
GetAttrsFunc: getAttrsFunc,
|
||||
TriggerPublisherFunc: triggerFunc,
|
||||
Codec: storageConfig.Codec,
|
||||
}
|
||||
cacher := storage.NewCacherFromConfig(cacherConfig)
|
||||
destroyFunc := func() {
|
||||
cacher.Stop()
|
||||
d()
|
||||
}
|
||||
|
||||
return cacher, destroyFunc
|
||||
}
|
1131
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/store.go
generated
vendored
Normal file
1131
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/store.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
1302
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/store_test.go
generated
vendored
Normal file
1302
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/registry/store_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
67
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/BUILD
generated
vendored
Normal file
67
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"proxy.go",
|
||||
"response_checker.go",
|
||||
"streamer.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//pkg/util/config:go_default_library",
|
||||
"//pkg/util/httpstream:go_default_library",
|
||||
"//pkg/util/proxy:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:github.com/mxk/go-flowrate/flowrate",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/runtime",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"proxy_test.go",
|
||||
"response_checker_test.go",
|
||||
"streamer_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/util/config:go_default_library",
|
||||
"//pkg/util/httpstream:go_default_library",
|
||||
"//pkg/util/proxy:go_default_library",
|
||||
"//vendor:github.com/stretchr/testify/assert",
|
||||
"//vendor:github.com/stretchr/testify/require",
|
||||
"//vendor:golang.org/x/net/websocket",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
19
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 has generic implementations of resources used for
|
||||
// REST responses
|
||||
package rest // import "k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest"
|
371
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/proxy.go
generated
vendored
Normal file
371
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/proxy.go
generated
vendored
Normal file
|
@ -0,0 +1,371 @@
|
|||
/*
|
||||
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 (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
utilconfig "k8s.io/kubernetes/pkg/util/config"
|
||||
"k8s.io/kubernetes/pkg/util/httpstream"
|
||||
"k8s.io/kubernetes/pkg/util/proxy"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/mxk/go-flowrate/flowrate"
|
||||
)
|
||||
|
||||
// UpgradeAwareProxyHandler is a handler for proxy requests that may require an upgrade
|
||||
type UpgradeAwareProxyHandler struct {
|
||||
UpgradeRequired bool
|
||||
Location *url.URL
|
||||
// Transport provides an optional round tripper to use to proxy. If nil, the default proxy transport is used
|
||||
Transport http.RoundTripper
|
||||
// WrapTransport indicates whether the provided Transport should be wrapped with default proxy transport behavior (URL rewriting, X-Forwarded-* header setting)
|
||||
WrapTransport bool
|
||||
// InterceptRedirects determines whether the proxy should sniff backend responses for redirects,
|
||||
// following them as necessary.
|
||||
InterceptRedirects bool
|
||||
FlushInterval time.Duration
|
||||
MaxBytesPerSec int64
|
||||
Responder ErrorResponder
|
||||
}
|
||||
|
||||
const defaultFlushInterval = 200 * time.Millisecond
|
||||
|
||||
// ErrorResponder abstracts error reporting to the proxy handler to remove the need to hardcode a particular
|
||||
// error format.
|
||||
type ErrorResponder interface {
|
||||
Error(err error)
|
||||
}
|
||||
|
||||
// NewUpgradeAwareProxyHandler creates a new proxy handler with a default flush interval. Responder is required for returning
|
||||
// errors to the caller.
|
||||
func NewUpgradeAwareProxyHandler(location *url.URL, transport http.RoundTripper, wrapTransport, upgradeRequired bool, responder ErrorResponder) *UpgradeAwareProxyHandler {
|
||||
return &UpgradeAwareProxyHandler{
|
||||
Location: location,
|
||||
Transport: transport,
|
||||
WrapTransport: wrapTransport,
|
||||
UpgradeRequired: upgradeRequired,
|
||||
FlushInterval: defaultFlushInterval,
|
||||
Responder: responder,
|
||||
}
|
||||
}
|
||||
|
||||
// ServeHTTP handles the proxy request
|
||||
func (h *UpgradeAwareProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
if len(h.Location.Scheme) == 0 {
|
||||
h.Location.Scheme = "http"
|
||||
}
|
||||
if h.tryUpgrade(w, req) {
|
||||
return
|
||||
}
|
||||
if h.UpgradeRequired {
|
||||
h.Responder.Error(errors.NewBadRequest("Upgrade request required"))
|
||||
return
|
||||
}
|
||||
|
||||
loc := *h.Location
|
||||
loc.RawQuery = req.URL.RawQuery
|
||||
|
||||
// If original request URL ended in '/', append a '/' at the end of the
|
||||
// of the proxy URL
|
||||
if !strings.HasSuffix(loc.Path, "/") && strings.HasSuffix(req.URL.Path, "/") {
|
||||
loc.Path += "/"
|
||||
}
|
||||
|
||||
// From pkg/genericapiserver/endpoints/handlers/proxy.go#ServeHTTP:
|
||||
// Redirect requests with an empty path to a location that ends with a '/'
|
||||
// This is essentially a hack for http://issue.k8s.io/4958.
|
||||
// Note: Keep this code after tryUpgrade to not break that flow.
|
||||
if len(loc.Path) == 0 {
|
||||
var queryPart string
|
||||
if len(req.URL.RawQuery) > 0 {
|
||||
queryPart = "?" + req.URL.RawQuery
|
||||
}
|
||||
w.Header().Set("Location", req.URL.Path+"/"+queryPart)
|
||||
w.WriteHeader(http.StatusMovedPermanently)
|
||||
return
|
||||
}
|
||||
|
||||
if h.Transport == nil || h.WrapTransport {
|
||||
h.Transport = h.defaultProxyTransport(req.URL, h.Transport)
|
||||
}
|
||||
|
||||
newReq, err := http.NewRequest(req.Method, loc.String(), req.Body)
|
||||
if err != nil {
|
||||
h.Responder.Error(err)
|
||||
return
|
||||
}
|
||||
newReq.Header = req.Header
|
||||
newReq.ContentLength = req.ContentLength
|
||||
// Copy the TransferEncoding is for future-proofing. Currently Go only supports "chunked" and
|
||||
// it can determine the TransferEncoding based on ContentLength and the Body.
|
||||
newReq.TransferEncoding = req.TransferEncoding
|
||||
|
||||
proxy := httputil.NewSingleHostReverseProxy(&url.URL{Scheme: h.Location.Scheme, Host: h.Location.Host})
|
||||
proxy.Transport = h.Transport
|
||||
proxy.FlushInterval = h.FlushInterval
|
||||
proxy.ServeHTTP(w, newReq)
|
||||
}
|
||||
|
||||
// tryUpgrade returns true if the request was handled.
|
||||
func (h *UpgradeAwareProxyHandler) tryUpgrade(w http.ResponseWriter, req *http.Request) bool {
|
||||
if !httpstream.IsUpgradeRequest(req) {
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
backendConn net.Conn
|
||||
rawResponse []byte
|
||||
err error
|
||||
)
|
||||
if h.InterceptRedirects && utilconfig.DefaultFeatureGate.StreamingProxyRedirects() {
|
||||
backendConn, rawResponse, err = h.connectBackendWithRedirects(req)
|
||||
} else {
|
||||
backendConn, err = h.connectBackend(req.Method, h.Location, req.Header, req.Body)
|
||||
}
|
||||
if err != nil {
|
||||
h.Responder.Error(err)
|
||||
return true
|
||||
}
|
||||
defer backendConn.Close()
|
||||
|
||||
// Once the connection is hijacked, the ErrorResponder will no longer work, so
|
||||
// hijacking should be the last step in the upgrade.
|
||||
requestHijacker, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
h.Responder.Error(fmt.Errorf("request connection cannot be hijacked: %T", w))
|
||||
return true
|
||||
}
|
||||
requestHijackedConn, _, err := requestHijacker.Hijack()
|
||||
if err != nil {
|
||||
h.Responder.Error(fmt.Errorf("error hijacking request connection: %v", err))
|
||||
return true
|
||||
}
|
||||
defer requestHijackedConn.Close()
|
||||
|
||||
// Forward raw response bytes back to client.
|
||||
if len(rawResponse) > 0 {
|
||||
if _, err = requestHijackedConn.Write(rawResponse); err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("Error proxying response from backend to client: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
// Proxy the connection.
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
|
||||
go func() {
|
||||
var writer io.WriteCloser
|
||||
if h.MaxBytesPerSec > 0 {
|
||||
writer = flowrate.NewWriter(backendConn, h.MaxBytesPerSec)
|
||||
} else {
|
||||
writer = backendConn
|
||||
}
|
||||
_, err := io.Copy(writer, requestHijackedConn)
|
||||
if err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
|
||||
glog.Errorf("Error proxying data from client to backend: %v", err)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
var reader io.ReadCloser
|
||||
if h.MaxBytesPerSec > 0 {
|
||||
reader = flowrate.NewReader(backendConn, h.MaxBytesPerSec)
|
||||
} else {
|
||||
reader = backendConn
|
||||
}
|
||||
_, err := io.Copy(requestHijackedConn, reader)
|
||||
if err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
|
||||
glog.Errorf("Error proxying data from backend to client: %v", err)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
return true
|
||||
}
|
||||
|
||||
// connectBackend dials the backend at location and forwards a copy of the client request.
|
||||
func (h *UpgradeAwareProxyHandler) connectBackend(method string, location *url.URL, header http.Header, body io.Reader) (conn net.Conn, err error) {
|
||||
defer func() {
|
||||
if err != nil && conn != nil {
|
||||
conn.Close()
|
||||
conn = nil
|
||||
}
|
||||
}()
|
||||
|
||||
beReq, err := http.NewRequest(method, location.String(), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
beReq.Header = header
|
||||
|
||||
conn, err = proxy.DialURL(location, h.Transport)
|
||||
if err != nil {
|
||||
return conn, fmt.Errorf("error dialing backend: %v", err)
|
||||
}
|
||||
|
||||
if err = beReq.Write(conn); err != nil {
|
||||
return conn, fmt.Errorf("error sending request: %v", err)
|
||||
}
|
||||
|
||||
return conn, err
|
||||
}
|
||||
|
||||
// connectBackendWithRedirects dials the backend and forwards a copy of the client request. If the
|
||||
// client responds with a redirect, it is followed. The raw response bytes are returned, and should
|
||||
// be forwarded back to the client.
|
||||
func (h *UpgradeAwareProxyHandler) connectBackendWithRedirects(req *http.Request) (net.Conn, []byte, error) {
|
||||
const (
|
||||
maxRedirects = 10
|
||||
maxResponseSize = 4096
|
||||
)
|
||||
var (
|
||||
initialReq = req
|
||||
rawResponse = bytes.NewBuffer(make([]byte, 0, 256))
|
||||
location = h.Location
|
||||
intermediateConn net.Conn
|
||||
err error
|
||||
)
|
||||
defer func() {
|
||||
if intermediateConn != nil {
|
||||
intermediateConn.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
redirectLoop:
|
||||
for redirects := 0; ; redirects++ {
|
||||
if redirects > maxRedirects {
|
||||
return nil, nil, fmt.Errorf("too many redirects (%d)", redirects)
|
||||
}
|
||||
|
||||
if redirects == 0 {
|
||||
intermediateConn, err = h.connectBackend(req.Method, location, req.Header, req.Body)
|
||||
} else {
|
||||
// Redirected requests switch to "GET" according to the HTTP spec:
|
||||
// https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3
|
||||
intermediateConn, err = h.connectBackend("GET", location, initialReq.Header, nil)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Peek at the backend response.
|
||||
rawResponse.Reset()
|
||||
respReader := bufio.NewReader(io.TeeReader(
|
||||
io.LimitReader(intermediateConn, maxResponseSize), // Don't read more than maxResponseSize bytes.
|
||||
rawResponse)) // Save the raw response.
|
||||
resp, err := http.ReadResponse(respReader, req)
|
||||
if err != nil {
|
||||
// Unable to read the backend response; let the client handle it.
|
||||
glog.Warningf("Error reading backend response: %v", err)
|
||||
break redirectLoop
|
||||
}
|
||||
resp.Body.Close() // Unused.
|
||||
|
||||
switch resp.StatusCode {
|
||||
case http.StatusFound:
|
||||
// Redirect, continue.
|
||||
default:
|
||||
// Don't redirect.
|
||||
break redirectLoop
|
||||
}
|
||||
|
||||
// Reset the connection.
|
||||
intermediateConn.Close()
|
||||
intermediateConn = nil
|
||||
|
||||
// Prepare to follow the redirect.
|
||||
redirectStr := resp.Header.Get("Location")
|
||||
if redirectStr == "" {
|
||||
return nil, nil, fmt.Errorf("%d response missing Location header", resp.StatusCode)
|
||||
}
|
||||
location, err = h.Location.Parse(redirectStr)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("malformed Location header: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
backendConn := intermediateConn
|
||||
intermediateConn = nil // Don't close the connection when we return it.
|
||||
return backendConn, rawResponse.Bytes(), nil
|
||||
}
|
||||
|
||||
func (h *UpgradeAwareProxyHandler) defaultProxyTransport(url *url.URL, internalTransport http.RoundTripper) http.RoundTripper {
|
||||
scheme := url.Scheme
|
||||
host := url.Host
|
||||
suffix := h.Location.Path
|
||||
if strings.HasSuffix(url.Path, "/") && !strings.HasSuffix(suffix, "/") {
|
||||
suffix += "/"
|
||||
}
|
||||
pathPrepend := strings.TrimSuffix(url.Path, suffix)
|
||||
rewritingTransport := &proxy.Transport{
|
||||
Scheme: scheme,
|
||||
Host: host,
|
||||
PathPrepend: pathPrepend,
|
||||
RoundTripper: internalTransport,
|
||||
}
|
||||
return &corsRemovingTransport{
|
||||
RoundTripper: rewritingTransport,
|
||||
}
|
||||
}
|
||||
|
||||
// corsRemovingTransport is a wrapper for an internal transport. It removes CORS headers
|
||||
// from the internal response.
|
||||
// Implements pkg/util/net.RoundTripperWrapper
|
||||
type corsRemovingTransport struct {
|
||||
http.RoundTripper
|
||||
}
|
||||
|
||||
var _ = utilnet.RoundTripperWrapper(&corsRemovingTransport{})
|
||||
|
||||
func (rt *corsRemovingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
resp, err := rt.RoundTripper.RoundTrip(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
removeCORSHeaders(resp)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (rt *corsRemovingTransport) WrappedRoundTripper() http.RoundTripper {
|
||||
return rt.RoundTripper
|
||||
}
|
||||
|
||||
// removeCORSHeaders strip CORS headers sent from the backend
|
||||
// This should be called on all responses before returning
|
||||
func removeCORSHeaders(resp *http.Response) {
|
||||
resp.Header.Del("Access-Control-Allow-Credentials")
|
||||
resp.Header.Del("Access-Control-Allow-Headers")
|
||||
resp.Header.Del("Access-Control-Allow-Methods")
|
||||
resp.Header.Del("Access-Control-Allow-Origin")
|
||||
}
|
816
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/proxy_test.go
generated
vendored
Normal file
816
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/proxy_test.go
generated
vendored
Normal file
|
@ -0,0 +1,816 @@
|
|||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"golang.org/x/net/websocket"
|
||||
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
utilconfig "k8s.io/kubernetes/pkg/util/config"
|
||||
"k8s.io/kubernetes/pkg/util/httpstream"
|
||||
"k8s.io/kubernetes/pkg/util/proxy"
|
||||
)
|
||||
|
||||
const fakeStatusCode = 567
|
||||
|
||||
type fakeResponder struct {
|
||||
t *testing.T
|
||||
called bool
|
||||
err error
|
||||
// called chan error
|
||||
w http.ResponseWriter
|
||||
}
|
||||
|
||||
func (r *fakeResponder) Error(err error) {
|
||||
if r.called {
|
||||
r.t.Errorf("Error responder called again!\nprevious error: %v\nnew error: %v", r.err, err)
|
||||
}
|
||||
|
||||
if r.w != nil {
|
||||
r.w.WriteHeader(fakeStatusCode)
|
||||
_, writeErr := r.w.Write([]byte(err.Error()))
|
||||
assert.NoError(r.t, writeErr)
|
||||
} else {
|
||||
r.t.Logf("No ResponseWriter set")
|
||||
}
|
||||
|
||||
r.called = true
|
||||
r.err = err
|
||||
}
|
||||
|
||||
type fakeConn struct {
|
||||
err error // The error to return when io is performed over the connection.
|
||||
}
|
||||
|
||||
func (f *fakeConn) Read([]byte) (int, error) { return 0, f.err }
|
||||
func (f *fakeConn) Write([]byte) (int, error) { return 0, f.err }
|
||||
func (f *fakeConn) Close() error { return nil }
|
||||
func (fakeConn) LocalAddr() net.Addr { return nil }
|
||||
func (fakeConn) RemoteAddr() net.Addr { return nil }
|
||||
func (fakeConn) SetDeadline(t time.Time) error { return nil }
|
||||
func (fakeConn) SetReadDeadline(t time.Time) error { return nil }
|
||||
func (fakeConn) SetWriteDeadline(t time.Time) error { return nil }
|
||||
|
||||
type SimpleBackendHandler struct {
|
||||
requestURL url.URL
|
||||
requestHeader http.Header
|
||||
requestBody []byte
|
||||
requestMethod string
|
||||
responseBody string
|
||||
responseHeader map[string]string
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
func (s *SimpleBackendHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
s.requestURL = *req.URL
|
||||
s.requestHeader = req.Header
|
||||
s.requestMethod = req.Method
|
||||
var err error
|
||||
s.requestBody, err = ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
s.t.Errorf("Unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if s.responseHeader != nil {
|
||||
for k, v := range s.responseHeader {
|
||||
w.Header().Add(k, v)
|
||||
}
|
||||
}
|
||||
w.Write([]byte(s.responseBody))
|
||||
}
|
||||
|
||||
func validateParameters(t *testing.T, name string, actual url.Values, expected map[string]string) {
|
||||
for k, v := range expected {
|
||||
actualValue, ok := actual[k]
|
||||
if !ok {
|
||||
t.Errorf("%s: Expected parameter %s not received", name, k)
|
||||
continue
|
||||
}
|
||||
if actualValue[0] != v {
|
||||
t.Errorf("%s: Parameter %s values don't match. Actual: %#v, Expected: %s",
|
||||
name, k, actualValue, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func validateHeaders(t *testing.T, name string, actual http.Header, expected map[string]string, notExpected []string) {
|
||||
for k, v := range expected {
|
||||
actualValue, ok := actual[k]
|
||||
if !ok {
|
||||
t.Errorf("%s: Expected header %s not received", name, k)
|
||||
continue
|
||||
}
|
||||
if actualValue[0] != v {
|
||||
t.Errorf("%s: Header %s values don't match. Actual: %s, Expected: %s",
|
||||
name, k, actualValue, v)
|
||||
}
|
||||
}
|
||||
if notExpected == nil {
|
||||
return
|
||||
}
|
||||
for _, h := range notExpected {
|
||||
if _, present := actual[h]; present {
|
||||
t.Errorf("%s: unexpected header: %s", name, h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestServeHTTP(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
method string
|
||||
requestPath string
|
||||
expectedPath string
|
||||
requestBody string
|
||||
requestParams map[string]string
|
||||
requestHeader map[string]string
|
||||
responseHeader map[string]string
|
||||
expectedRespHeader map[string]string
|
||||
notExpectedRespHeader []string
|
||||
upgradeRequired bool
|
||||
expectError func(err error) bool
|
||||
}{
|
||||
{
|
||||
name: "root path, simple get",
|
||||
method: "GET",
|
||||
requestPath: "/",
|
||||
expectedPath: "/",
|
||||
},
|
||||
{
|
||||
name: "no upgrade header sent",
|
||||
method: "GET",
|
||||
requestPath: "/",
|
||||
upgradeRequired: true,
|
||||
expectError: func(err error) bool {
|
||||
return err != nil && strings.Contains(err.Error(), "Upgrade request required")
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "simple path, get",
|
||||
method: "GET",
|
||||
requestPath: "/path/to/test",
|
||||
expectedPath: "/path/to/test",
|
||||
},
|
||||
{
|
||||
name: "request params",
|
||||
method: "POST",
|
||||
requestPath: "/some/path/",
|
||||
expectedPath: "/some/path/",
|
||||
requestParams: map[string]string{"param1": "value/1", "param2": "value%2"},
|
||||
requestBody: "test request body",
|
||||
},
|
||||
{
|
||||
name: "request headers",
|
||||
method: "PUT",
|
||||
requestPath: "/some/path",
|
||||
expectedPath: "/some/path",
|
||||
requestHeader: map[string]string{"Header1": "value1", "Header2": "value2"},
|
||||
},
|
||||
{
|
||||
name: "empty path - slash should be added",
|
||||
method: "GET",
|
||||
requestPath: "",
|
||||
expectedPath: "/",
|
||||
},
|
||||
{
|
||||
name: "remove CORS headers",
|
||||
method: "GET",
|
||||
requestPath: "/some/path",
|
||||
expectedPath: "/some/path",
|
||||
responseHeader: map[string]string{
|
||||
"Header1": "value1",
|
||||
"Access-Control-Allow-Origin": "some.server",
|
||||
"Access-Control-Allow-Methods": "GET"},
|
||||
expectedRespHeader: map[string]string{
|
||||
"Header1": "value1",
|
||||
},
|
||||
notExpectedRespHeader: []string{
|
||||
"Access-Control-Allow-Origin",
|
||||
"Access-Control-Allow-Methods",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
func() {
|
||||
backendResponse := "<html><head></head><body><a href=\"/test/path\">Hello</a></body></html>"
|
||||
backendResponseHeader := test.responseHeader
|
||||
// Test a simple header if not specified in the test
|
||||
if backendResponseHeader == nil && test.expectedRespHeader == nil {
|
||||
backendResponseHeader = map[string]string{"Content-Type": "text/html"}
|
||||
test.expectedRespHeader = map[string]string{"Content-Type": "text/html"}
|
||||
}
|
||||
backendHandler := &SimpleBackendHandler{
|
||||
responseBody: backendResponse,
|
||||
responseHeader: backendResponseHeader,
|
||||
}
|
||||
backendServer := httptest.NewServer(backendHandler)
|
||||
defer backendServer.Close()
|
||||
|
||||
responder := &fakeResponder{t: t}
|
||||
backendURL, _ := url.Parse(backendServer.URL)
|
||||
backendURL.Path = test.requestPath
|
||||
proxyHandler := &UpgradeAwareProxyHandler{
|
||||
Location: backendURL,
|
||||
Responder: responder,
|
||||
UpgradeRequired: test.upgradeRequired,
|
||||
}
|
||||
proxyServer := httptest.NewServer(proxyHandler)
|
||||
defer proxyServer.Close()
|
||||
proxyURL, _ := url.Parse(proxyServer.URL)
|
||||
proxyURL.Path = test.requestPath
|
||||
paramValues := url.Values{}
|
||||
for k, v := range test.requestParams {
|
||||
paramValues[k] = []string{v}
|
||||
}
|
||||
proxyURL.RawQuery = paramValues.Encode()
|
||||
var requestBody io.Reader
|
||||
if test.requestBody != "" {
|
||||
requestBody = bytes.NewBufferString(test.requestBody)
|
||||
}
|
||||
req, err := http.NewRequest(test.method, proxyURL.String(), requestBody)
|
||||
if test.requestHeader != nil {
|
||||
header := http.Header{}
|
||||
for k, v := range test.requestHeader {
|
||||
header.Add(k, v)
|
||||
}
|
||||
req.Header = header
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("Error creating client request: %v", err)
|
||||
}
|
||||
client := &http.Client{}
|
||||
res, err := client.Do(req)
|
||||
if err != nil {
|
||||
t.Errorf("Error from proxy request: %v", err)
|
||||
}
|
||||
|
||||
if test.expectError != nil {
|
||||
if !responder.called {
|
||||
t.Errorf("%d: responder was not invoked", i)
|
||||
return
|
||||
}
|
||||
if !test.expectError(responder.err) {
|
||||
t.Errorf("%d: unexpected error: %v", i, responder.err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Validate backend request
|
||||
// Method
|
||||
if backendHandler.requestMethod != test.method {
|
||||
t.Errorf("Unexpected request method: %s. Expected: %s",
|
||||
backendHandler.requestMethod, test.method)
|
||||
}
|
||||
|
||||
// Body
|
||||
if string(backendHandler.requestBody) != test.requestBody {
|
||||
t.Errorf("Unexpected request body: %s. Expected: %s",
|
||||
string(backendHandler.requestBody), test.requestBody)
|
||||
}
|
||||
|
||||
// Path
|
||||
if backendHandler.requestURL.Path != test.expectedPath {
|
||||
t.Errorf("Unexpected request path: %s", backendHandler.requestURL.Path)
|
||||
}
|
||||
// Parameters
|
||||
validateParameters(t, test.name, backendHandler.requestURL.Query(), test.requestParams)
|
||||
|
||||
// Headers
|
||||
validateHeaders(t, test.name+" backend request", backendHandler.requestHeader,
|
||||
test.requestHeader, nil)
|
||||
|
||||
// Validate proxy response
|
||||
|
||||
// Response Headers
|
||||
validateHeaders(t, test.name+" backend headers", res.Header, test.expectedRespHeader, test.notExpectedRespHeader)
|
||||
|
||||
// Validate Body
|
||||
responseBody, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error reading response body: %v", err)
|
||||
}
|
||||
if rb := string(responseBody); rb != backendResponse {
|
||||
t.Errorf("Did not get expected response body: %s. Expected: %s", rb, backendResponse)
|
||||
}
|
||||
|
||||
// Error
|
||||
if responder.called {
|
||||
t.Errorf("Unexpected proxy handler error: %v", responder.err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxyUpgrade(t *testing.T) {
|
||||
|
||||
localhostPool := x509.NewCertPool()
|
||||
if !localhostPool.AppendCertsFromPEM(localhostCert) {
|
||||
t.Errorf("error setting up localhostCert pool")
|
||||
}
|
||||
|
||||
testcases := map[string]struct {
|
||||
ServerFunc func(http.Handler) *httptest.Server
|
||||
ProxyTransport http.RoundTripper
|
||||
}{
|
||||
"http": {
|
||||
ServerFunc: httptest.NewServer,
|
||||
ProxyTransport: nil,
|
||||
},
|
||||
"https (invalid hostname + InsecureSkipVerify)": {
|
||||
ServerFunc: func(h http.Handler) *httptest.Server {
|
||||
cert, err := tls.X509KeyPair(exampleCert, exampleKey)
|
||||
if err != nil {
|
||||
t.Errorf("https (invalid hostname): proxy_test: %v", err)
|
||||
}
|
||||
ts := httptest.NewUnstartedServer(h)
|
||||
ts.TLS = &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
}
|
||||
ts.StartTLS()
|
||||
return ts
|
||||
},
|
||||
ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}),
|
||||
},
|
||||
"https (valid hostname + RootCAs)": {
|
||||
ServerFunc: func(h http.Handler) *httptest.Server {
|
||||
cert, err := tls.X509KeyPair(localhostCert, localhostKey)
|
||||
if err != nil {
|
||||
t.Errorf("https (valid hostname): proxy_test: %v", err)
|
||||
}
|
||||
ts := httptest.NewUnstartedServer(h)
|
||||
ts.TLS = &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
}
|
||||
ts.StartTLS()
|
||||
return ts
|
||||
},
|
||||
ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{TLSClientConfig: &tls.Config{RootCAs: localhostPool}}),
|
||||
},
|
||||
"https (valid hostname + RootCAs + custom dialer)": {
|
||||
ServerFunc: func(h http.Handler) *httptest.Server {
|
||||
cert, err := tls.X509KeyPair(localhostCert, localhostKey)
|
||||
if err != nil {
|
||||
t.Errorf("https (valid hostname): proxy_test: %v", err)
|
||||
}
|
||||
ts := httptest.NewUnstartedServer(h)
|
||||
ts.TLS = &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
}
|
||||
ts.StartTLS()
|
||||
return ts
|
||||
},
|
||||
ProxyTransport: utilnet.SetTransportDefaults(&http.Transport{Dial: net.Dial, TLSClientConfig: &tls.Config{RootCAs: localhostPool}}),
|
||||
},
|
||||
}
|
||||
|
||||
// Enable StreamingProxyRedirects for test.
|
||||
utilconfig.DefaultFeatureGate.Set("StreamingProxyRedirects=true")
|
||||
|
||||
for k, tc := range testcases {
|
||||
for _, redirect := range []bool{false, true} {
|
||||
tcName := k
|
||||
backendPath := "/hello"
|
||||
if redirect {
|
||||
tcName += " with redirect"
|
||||
backendPath = "/redirect"
|
||||
}
|
||||
func() { // Cleanup after each test case.
|
||||
backend := http.NewServeMux()
|
||||
backend.Handle("/hello", websocket.Handler(func(ws *websocket.Conn) {
|
||||
defer ws.Close()
|
||||
body := make([]byte, 5)
|
||||
ws.Read(body)
|
||||
ws.Write([]byte("hello " + string(body)))
|
||||
}))
|
||||
backend.Handle("/redirect", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/hello", http.StatusFound)
|
||||
}))
|
||||
backendServer := tc.ServerFunc(backend)
|
||||
defer backendServer.Close()
|
||||
|
||||
serverURL, _ := url.Parse(backendServer.URL)
|
||||
serverURL.Path = backendPath
|
||||
proxyHandler := &UpgradeAwareProxyHandler{
|
||||
Location: serverURL,
|
||||
Transport: tc.ProxyTransport,
|
||||
InterceptRedirects: redirect,
|
||||
}
|
||||
proxy := httptest.NewServer(proxyHandler)
|
||||
defer proxy.Close()
|
||||
|
||||
ws, err := websocket.Dial("ws://"+proxy.Listener.Addr().String()+"/some/path", "", "http://127.0.0.1/")
|
||||
if err != nil {
|
||||
t.Fatalf("%s: websocket dial err: %s", tcName, err)
|
||||
}
|
||||
defer ws.Close()
|
||||
|
||||
if _, err := ws.Write([]byte("world")); err != nil {
|
||||
t.Fatalf("%s: write err: %s", tcName, err)
|
||||
}
|
||||
|
||||
response := make([]byte, 20)
|
||||
n, err := ws.Read(response)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: read err: %s", tcName, err)
|
||||
}
|
||||
if e, a := "hello world", string(response[0:n]); e != a {
|
||||
t.Fatalf("%s: expected '%#v', got '%#v'", tcName, e, a)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxyUpgradeErrorResponse(t *testing.T) {
|
||||
var (
|
||||
responder *fakeResponder
|
||||
expectedErr = errors.New("EXPECTED")
|
||||
)
|
||||
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
transport := http.DefaultTransport.(*http.Transport)
|
||||
transport.Dial = func(network, addr string) (net.Conn, error) {
|
||||
return &fakeConn{err: expectedErr}, nil
|
||||
}
|
||||
responder = &fakeResponder{t: t, w: w}
|
||||
proxyHandler := &UpgradeAwareProxyHandler{
|
||||
Location: &url.URL{
|
||||
Host: "fake-backend",
|
||||
},
|
||||
UpgradeRequired: true,
|
||||
Responder: responder,
|
||||
Transport: transport,
|
||||
}
|
||||
proxyHandler.ServeHTTP(w, r)
|
||||
}))
|
||||
defer proxy.Close()
|
||||
|
||||
// Send request to proxy server.
|
||||
req, err := http.NewRequest("POST", "http://"+proxy.Listener.Addr().String()+"/some/path", nil)
|
||||
require.NoError(t, err)
|
||||
req.Header.Set(httpstream.HeaderConnection, httpstream.HeaderUpgrade)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Expect error response.
|
||||
assert.True(t, responder.called)
|
||||
assert.Equal(t, fakeStatusCode, resp.StatusCode)
|
||||
msg, err := ioutil.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, string(msg), expectedErr.Error())
|
||||
}
|
||||
|
||||
func TestDefaultProxyTransport(t *testing.T) {
|
||||
tests := []struct {
|
||||
name,
|
||||
url,
|
||||
location,
|
||||
expectedScheme,
|
||||
expectedHost,
|
||||
expectedPathPrepend string
|
||||
}{
|
||||
{
|
||||
name: "simple path",
|
||||
url: "http://test.server:8080/a/test/location",
|
||||
location: "http://localhost/location",
|
||||
expectedScheme: "http",
|
||||
expectedHost: "test.server:8080",
|
||||
expectedPathPrepend: "/a/test",
|
||||
},
|
||||
{
|
||||
name: "empty path",
|
||||
url: "http://test.server:8080/a/test/",
|
||||
location: "http://localhost",
|
||||
expectedScheme: "http",
|
||||
expectedHost: "test.server:8080",
|
||||
expectedPathPrepend: "/a/test",
|
||||
},
|
||||
{
|
||||
name: "location ending in slash",
|
||||
url: "http://test.server:8080/a/test/",
|
||||
location: "http://localhost/",
|
||||
expectedScheme: "http",
|
||||
expectedHost: "test.server:8080",
|
||||
expectedPathPrepend: "/a/test",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
locURL, _ := url.Parse(test.location)
|
||||
URL, _ := url.Parse(test.url)
|
||||
h := UpgradeAwareProxyHandler{
|
||||
Location: locURL,
|
||||
}
|
||||
result := h.defaultProxyTransport(URL, nil)
|
||||
transport := result.(*corsRemovingTransport).RoundTripper.(*proxy.Transport)
|
||||
if transport.Scheme != test.expectedScheme {
|
||||
t.Errorf("%s: unexpected scheme. Actual: %s, Expected: %s", test.name, transport.Scheme, test.expectedScheme)
|
||||
}
|
||||
if transport.Host != test.expectedHost {
|
||||
t.Errorf("%s: unexpected host. Actual: %s, Expected: %s", test.name, transport.Host, test.expectedHost)
|
||||
}
|
||||
if transport.PathPrepend != test.expectedPathPrepend {
|
||||
t.Errorf("%s: unexpected path prepend. Actual: %s, Expected: %s", test.name, transport.PathPrepend, test.expectedPathPrepend)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestProxyRequestContentLengthAndTransferEncoding(t *testing.T) {
|
||||
chunk := func(data []byte) []byte {
|
||||
out := &bytes.Buffer{}
|
||||
chunker := httputil.NewChunkedWriter(out)
|
||||
for _, b := range data {
|
||||
if _, err := chunker.Write([]byte{b}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
chunker.Close()
|
||||
out.Write([]byte("\r\n"))
|
||||
return out.Bytes()
|
||||
}
|
||||
|
||||
zip := func(data []byte) []byte {
|
||||
out := &bytes.Buffer{}
|
||||
zipper := gzip.NewWriter(out)
|
||||
if _, err := zipper.Write(data); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
zipper.Close()
|
||||
return out.Bytes()
|
||||
}
|
||||
|
||||
sampleData := []byte("abcde")
|
||||
|
||||
table := map[string]struct {
|
||||
reqHeaders http.Header
|
||||
reqBody []byte
|
||||
|
||||
expectedHeaders http.Header
|
||||
expectedBody []byte
|
||||
}{
|
||||
"content-length": {
|
||||
reqHeaders: http.Header{
|
||||
"Content-Length": []string{"5"},
|
||||
},
|
||||
reqBody: sampleData,
|
||||
|
||||
expectedHeaders: http.Header{
|
||||
"Content-Length": []string{"5"},
|
||||
"Content-Encoding": nil, // none set
|
||||
"Transfer-Encoding": nil, // none set
|
||||
},
|
||||
expectedBody: sampleData,
|
||||
},
|
||||
|
||||
"content-length + identity transfer-encoding": {
|
||||
reqHeaders: http.Header{
|
||||
"Content-Length": []string{"5"},
|
||||
"Transfer-Encoding": []string{"identity"},
|
||||
},
|
||||
reqBody: sampleData,
|
||||
|
||||
expectedHeaders: http.Header{
|
||||
"Content-Length": []string{"5"},
|
||||
"Content-Encoding": nil, // none set
|
||||
"Transfer-Encoding": nil, // gets removed
|
||||
},
|
||||
expectedBody: sampleData,
|
||||
},
|
||||
|
||||
"content-length + gzip content-encoding": {
|
||||
reqHeaders: http.Header{
|
||||
"Content-Length": []string{strconv.Itoa(len(zip(sampleData)))},
|
||||
"Content-Encoding": []string{"gzip"},
|
||||
},
|
||||
reqBody: zip(sampleData),
|
||||
|
||||
expectedHeaders: http.Header{
|
||||
"Content-Length": []string{strconv.Itoa(len(zip(sampleData)))},
|
||||
"Content-Encoding": []string{"gzip"},
|
||||
"Transfer-Encoding": nil, // none set
|
||||
},
|
||||
expectedBody: zip(sampleData),
|
||||
},
|
||||
|
||||
"chunked transfer-encoding": {
|
||||
reqHeaders: http.Header{
|
||||
"Transfer-Encoding": []string{"chunked"},
|
||||
},
|
||||
reqBody: chunk(sampleData),
|
||||
|
||||
expectedHeaders: http.Header{
|
||||
"Content-Length": nil, // none set
|
||||
"Content-Encoding": nil, // none set
|
||||
"Transfer-Encoding": nil, // Transfer-Encoding gets removed
|
||||
},
|
||||
expectedBody: sampleData, // sample data is unchunked
|
||||
},
|
||||
|
||||
"chunked transfer-encoding + gzip content-encoding": {
|
||||
reqHeaders: http.Header{
|
||||
"Content-Encoding": []string{"gzip"},
|
||||
"Transfer-Encoding": []string{"chunked"},
|
||||
},
|
||||
reqBody: chunk(zip(sampleData)),
|
||||
|
||||
expectedHeaders: http.Header{
|
||||
"Content-Length": nil, // none set
|
||||
"Content-Encoding": []string{"gzip"},
|
||||
"Transfer-Encoding": nil, // gets removed
|
||||
},
|
||||
expectedBody: zip(sampleData), // sample data is unchunked, but content-encoding is preserved
|
||||
},
|
||||
|
||||
// "Transfer-Encoding: gzip" is not supported by go
|
||||
// See http/transfer.go#fixTransferEncoding (https://golang.org/src/net/http/transfer.go#L427)
|
||||
// Once it is supported, this test case should succeed
|
||||
//
|
||||
// "gzip+chunked transfer-encoding": {
|
||||
// reqHeaders: http.Header{
|
||||
// "Transfer-Encoding": []string{"chunked,gzip"},
|
||||
// },
|
||||
// reqBody: chunk(zip(sampleData)),
|
||||
//
|
||||
// expectedHeaders: http.Header{
|
||||
// "Content-Length": nil, // no content-length headers
|
||||
// "Transfer-Encoding": nil, // Transfer-Encoding gets removed
|
||||
// },
|
||||
// expectedBody: sampleData,
|
||||
// },
|
||||
}
|
||||
|
||||
successfulResponse := "backend passed tests"
|
||||
for k, item := range table {
|
||||
// Start the downstream server
|
||||
downstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
// Verify headers
|
||||
for header, v := range item.expectedHeaders {
|
||||
if !reflect.DeepEqual(v, req.Header[header]) {
|
||||
t.Errorf("%s: Expected headers for %s to be %v, got %v", k, header, v, req.Header[header])
|
||||
}
|
||||
}
|
||||
|
||||
// Read body
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
t.Errorf("%s: unexpected error %v", k, err)
|
||||
}
|
||||
req.Body.Close()
|
||||
|
||||
// Verify length
|
||||
if req.ContentLength > 0 && req.ContentLength != int64(len(body)) {
|
||||
t.Errorf("%s: ContentLength was %d, len(data) was %d", k, req.ContentLength, len(body))
|
||||
}
|
||||
|
||||
// Verify content
|
||||
if !bytes.Equal(item.expectedBody, body) {
|
||||
t.Errorf("%s: Expected %q, got %q", k, string(item.expectedBody), string(body))
|
||||
}
|
||||
|
||||
// Write successful response
|
||||
w.Write([]byte(successfulResponse))
|
||||
}))
|
||||
defer downstreamServer.Close()
|
||||
|
||||
responder := &fakeResponder{t: t}
|
||||
backendURL, _ := url.Parse(downstreamServer.URL)
|
||||
proxyHandler := &UpgradeAwareProxyHandler{
|
||||
Location: backendURL,
|
||||
Responder: responder,
|
||||
UpgradeRequired: false,
|
||||
}
|
||||
proxyServer := httptest.NewServer(proxyHandler)
|
||||
defer proxyServer.Close()
|
||||
|
||||
// Dial the proxy server
|
||||
conn, err := net.Dial(proxyServer.Listener.Addr().Network(), proxyServer.Listener.Addr().String())
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
continue
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Add standard http 1.1 headers
|
||||
if item.reqHeaders == nil {
|
||||
item.reqHeaders = http.Header{}
|
||||
}
|
||||
item.reqHeaders.Add("Connection", "close")
|
||||
item.reqHeaders.Add("Host", proxyServer.Listener.Addr().String())
|
||||
|
||||
// Write the request headers
|
||||
if _, err := fmt.Fprint(conn, "POST / HTTP/1.1\r\n"); err != nil {
|
||||
t.Fatalf("%s unexpected error %v", k, err)
|
||||
}
|
||||
for header, values := range item.reqHeaders {
|
||||
for _, value := range values {
|
||||
if _, err := fmt.Fprintf(conn, "%s: %s\r\n", header, value); err != nil {
|
||||
t.Fatalf("%s: unexpected error %v", k, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Header separator
|
||||
if _, err := fmt.Fprint(conn, "\r\n"); err != nil {
|
||||
t.Fatalf("%s: unexpected error %v", k, err)
|
||||
}
|
||||
// Body
|
||||
if _, err := conn.Write(item.reqBody); err != nil {
|
||||
t.Fatalf("%s: unexpected error %v", k, err)
|
||||
}
|
||||
|
||||
// Read response
|
||||
response, err := ioutil.ReadAll(conn)
|
||||
if err != nil {
|
||||
t.Errorf("%s: unexpected error %v", k, err)
|
||||
continue
|
||||
}
|
||||
if !strings.HasSuffix(string(response), successfulResponse) {
|
||||
t.Errorf("%s: Did not get successful response: %s", k, string(response))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exampleCert was generated from crypto/tls/generate_cert.go with the following command:
|
||||
// go run generate_cert.go --rsa-bits 512 --host example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
|
||||
var exampleCert = []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIBcjCCAR6gAwIBAgIQBOUTYowZaENkZi0faI9DgTALBgkqhkiG9w0BAQswEjEQ
|
||||
MA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2MDAw
|
||||
MFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCZ
|
||||
xfR3sgeHBraGFfF/24tTn4PRVAHOf2UOOxSQRs+aYjNqimFqf/SRIblQgeXdBJDR
|
||||
gVK5F1Js2zwlehw0bHxRAgMBAAGjUDBOMA4GA1UdDwEB/wQEAwIApDATBgNVHSUE
|
||||
DDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBYGA1UdEQQPMA2CC2V4YW1w
|
||||
bGUuY29tMAsGCSqGSIb3DQEBCwNBAI/mfBB8dm33IpUl+acSyWfL6gX5Wc0FFyVj
|
||||
dKeesE1XBuPX1My/rzU6Oy/YwX7LOL4FaeNUS6bbL4axSLPKYSs=
|
||||
-----END CERTIFICATE-----`)
|
||||
|
||||
var exampleKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIBOgIBAAJBAJnF9HeyB4cGtoYV8X/bi1Ofg9FUAc5/ZQ47FJBGz5piM2qKYWp/
|
||||
9JEhuVCB5d0EkNGBUrkXUmzbPCV6HDRsfFECAwEAAQJBAJLH9yPuButniACTn5L5
|
||||
IJQw1mWQt6zBw9eCo41YWkA0866EgjC53aPZaRjXMp0uNJGdIsys2V5rCOOLWN2C
|
||||
ODECIQDICHsi8QQQ9wpuJy8X5l8MAfxHL+DIqI84wQTeVM91FQIhAMTME8A18/7h
|
||||
1Ad6drdnxAkuC0tX6Sx0LDozrmen+HFNAiAlcEDrt0RVkIcpOrg7tuhPLQf0oudl
|
||||
Zvb3Xlj069awSQIgcT15E/43w2+RASifzVNhQ2MCTr1sSA8lL+xzK+REmnUCIBhQ
|
||||
j4139pf8Re1J50zBxS/JlQfgDQi9sO9pYeiHIxNs
|
||||
-----END RSA PRIVATE KEY-----`)
|
||||
|
||||
// localhostCert was generated from crypto/tls/generate_cert.go with the following command:
|
||||
// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
|
||||
var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
|
||||
bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
|
||||
bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
|
||||
IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
|
||||
AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
|
||||
EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
|
||||
AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
|
||||
Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
|
||||
-----END CERTIFICATE-----`)
|
||||
|
||||
// localhostKey is the private key for localhostCert.
|
||||
var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
|
||||
0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
|
||||
NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
|
||||
AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
|
||||
MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
|
||||
EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
|
||||
1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
|
||||
-----END RSA PRIVATE KEY-----`)
|
71
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/response_checker.go
generated
vendored
Normal file
71
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/response_checker.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// Check the http error status from a location URL.
|
||||
// And convert an error into a structured API object.
|
||||
// Finally ensure we close the body before returning the error
|
||||
type HttpResponseChecker interface {
|
||||
Check(resp *http.Response) error
|
||||
}
|
||||
|
||||
// Max length read from the response body of a location which returns error status
|
||||
const (
|
||||
maxReadLength = 50000
|
||||
)
|
||||
|
||||
// A generic http response checker to transform the error.
|
||||
type GenericHttpResponseChecker struct {
|
||||
QualifiedResource schema.GroupResource
|
||||
Name string
|
||||
}
|
||||
|
||||
func (checker GenericHttpResponseChecker) Check(resp *http.Response) error {
|
||||
if resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent {
|
||||
defer resp.Body.Close()
|
||||
bodyBytes, err := ioutil.ReadAll(io.LimitReader(resp.Body, maxReadLength))
|
||||
if err != nil {
|
||||
return errors.NewInternalError(err)
|
||||
}
|
||||
bodyText := string(bodyBytes)
|
||||
|
||||
switch {
|
||||
case resp.StatusCode == http.StatusInternalServerError:
|
||||
return errors.NewInternalError(fmt.Errorf("%s", bodyText))
|
||||
case resp.StatusCode == http.StatusBadRequest:
|
||||
return errors.NewBadRequest(bodyText)
|
||||
case resp.StatusCode == http.StatusNotFound:
|
||||
return errors.NewGenericServerResponse(resp.StatusCode, "", checker.QualifiedResource, checker.Name, bodyText, 0, false)
|
||||
}
|
||||
return errors.NewGenericServerResponse(resp.StatusCode, "", checker.QualifiedResource, checker.Name, bodyText, 0, false)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewGenericHttpResponseChecker(qualifiedResource schema.GroupResource, name string) GenericHttpResponseChecker {
|
||||
return GenericHttpResponseChecker{QualifiedResource: qualifiedResource, Name: name}
|
||||
}
|
95
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/response_checker_test.go
generated
vendored
Normal file
95
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/response_checker_test.go
generated
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func TestGenericHttpResponseChecker(t *testing.T) {
|
||||
responseChecker := NewGenericHttpResponseChecker(api.Resource("pods"), "foo")
|
||||
tests := []struct {
|
||||
resp *http.Response
|
||||
expectError bool
|
||||
expected error
|
||||
name string
|
||||
}{
|
||||
{
|
||||
resp: &http.Response{
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("Success")),
|
||||
StatusCode: http.StatusOK,
|
||||
},
|
||||
expectError: false,
|
||||
name: "ok",
|
||||
},
|
||||
{
|
||||
resp: &http.Response{
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("Invalid request.")),
|
||||
StatusCode: http.StatusBadRequest,
|
||||
},
|
||||
expectError: true,
|
||||
expected: errors.NewBadRequest("Invalid request."),
|
||||
name: "bad request",
|
||||
},
|
||||
{
|
||||
resp: &http.Response{
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString("Pod does not exist.")),
|
||||
StatusCode: http.StatusInternalServerError,
|
||||
},
|
||||
expectError: true,
|
||||
expected: errors.NewInternalError(fmt.Errorf("%s", "Pod does not exist.")),
|
||||
name: "internal server error",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
err := responseChecker.Check(test.resp)
|
||||
if test.expectError && err == nil {
|
||||
t.Error("unexpected non-error")
|
||||
}
|
||||
if !test.expectError && err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if test.expectError && !reflect.DeepEqual(err, test.expected) {
|
||||
t.Errorf("expected: %s, saw: %s", test.expected, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenericHttpResponseCheckerLimitReader(t *testing.T) {
|
||||
responseChecker := NewGenericHttpResponseChecker(api.Resource("pods"), "foo")
|
||||
excessedString := strings.Repeat("a", (maxReadLength + 10000))
|
||||
resp := &http.Response{
|
||||
Body: ioutil.NopCloser(bytes.NewBufferString(excessedString)),
|
||||
StatusCode: http.StatusBadRequest,
|
||||
}
|
||||
err := responseChecker.Check(resp)
|
||||
if err == nil {
|
||||
t.Error("unexpected non-error")
|
||||
}
|
||||
if len(err.Error()) != maxReadLength {
|
||||
t.Errorf("expected lenth of error message: %d, saw: %d", maxReadLength, len(err.Error()))
|
||||
}
|
||||
}
|
79
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/streamer.go
generated
vendored
Normal file
79
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/streamer.go
generated
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
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 (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
)
|
||||
|
||||
// LocationStreamer is a resource that streams the contents of a particular
|
||||
// location URL
|
||||
type LocationStreamer struct {
|
||||
Location *url.URL
|
||||
Transport http.RoundTripper
|
||||
ContentType string
|
||||
Flush bool
|
||||
ResponseChecker HttpResponseChecker
|
||||
}
|
||||
|
||||
// a LocationStreamer must implement a rest.ResourceStreamer
|
||||
var _ rest.ResourceStreamer = &LocationStreamer{}
|
||||
|
||||
func (obj *LocationStreamer) GetObjectKind() schema.ObjectKind {
|
||||
return schema.EmptyObjectKind
|
||||
}
|
||||
|
||||
// InputStream returns a stream with the contents of the URL location. If no location is provided,
|
||||
// a null stream is returned.
|
||||
func (s *LocationStreamer) InputStream(apiVersion, acceptHeader string) (stream io.ReadCloser, flush bool, contentType string, err error) {
|
||||
if s.Location == nil {
|
||||
// If no location was provided, return a null stream
|
||||
return nil, false, "", nil
|
||||
}
|
||||
transport := s.Transport
|
||||
if transport == nil {
|
||||
transport = http.DefaultTransport
|
||||
}
|
||||
client := &http.Client{Transport: transport}
|
||||
resp, err := client.Get(s.Location.String())
|
||||
if err != nil {
|
||||
return nil, false, "", err
|
||||
}
|
||||
|
||||
if s.ResponseChecker != nil {
|
||||
if err = s.ResponseChecker.Check(resp); err != nil {
|
||||
return nil, false, "", err
|
||||
}
|
||||
}
|
||||
|
||||
contentType = s.ContentType
|
||||
if len(contentType) == 0 {
|
||||
contentType = resp.Header.Get("Content-Type")
|
||||
if len(contentType) > 0 {
|
||||
contentType = strings.TrimSpace(strings.SplitN(contentType, ";", 2)[0])
|
||||
}
|
||||
}
|
||||
flush = s.Flush
|
||||
stream = resp.Body
|
||||
return
|
||||
}
|
148
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/streamer_test.go
generated
vendored
Normal file
148
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/rest/streamer_test.go
generated
vendored
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
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 (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
func TestInputStreamReader(t *testing.T) {
|
||||
resultString := "Test output"
|
||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
w.Write([]byte(resultString))
|
||||
}))
|
||||
defer s.Close()
|
||||
u, err := url.Parse(s.URL)
|
||||
if err != nil {
|
||||
t.Errorf("Error parsing server URL: %v", err)
|
||||
return
|
||||
}
|
||||
streamer := &LocationStreamer{
|
||||
Location: u,
|
||||
}
|
||||
readCloser, _, _, err := streamer.InputStream("", "")
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when getting stream: %v", err)
|
||||
return
|
||||
}
|
||||
defer readCloser.Close()
|
||||
result, err := ioutil.ReadAll(readCloser)
|
||||
if string(result) != resultString {
|
||||
t.Errorf("Stream content does not match. Got: %s. Expected: %s.", string(result), resultString)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInputStreamNullLocation(t *testing.T) {
|
||||
streamer := &LocationStreamer{
|
||||
Location: nil,
|
||||
}
|
||||
readCloser, _, _, err := streamer.InputStream("", "")
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when getting stream with null location: %v", err)
|
||||
}
|
||||
if readCloser != nil {
|
||||
t.Errorf("Expected stream to be nil. Got: %#v", readCloser)
|
||||
}
|
||||
}
|
||||
|
||||
type testTransport struct {
|
||||
body string
|
||||
err error
|
||||
}
|
||||
|
||||
func (tt *testTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
r := bufio.NewReader(bytes.NewBufferString(tt.body))
|
||||
return http.ReadResponse(r, req)
|
||||
}
|
||||
|
||||
func fakeTransport(mime, message string) http.RoundTripper {
|
||||
content := fmt.Sprintf("HTTP/1.1 200 OK\nContent-Type: %s\n\n%s", mime, message)
|
||||
return &testTransport{body: content}
|
||||
}
|
||||
|
||||
func TestInputStreamContentType(t *testing.T) {
|
||||
location, _ := url.Parse("http://www.example.com")
|
||||
streamer := &LocationStreamer{
|
||||
Location: location,
|
||||
Transport: fakeTransport("application/json", "hello world"),
|
||||
}
|
||||
readCloser, _, contentType, err := streamer.InputStream("", "")
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when getting stream: %v", err)
|
||||
return
|
||||
}
|
||||
defer readCloser.Close()
|
||||
if contentType != "application/json" {
|
||||
t.Errorf("Unexpected content type. Got: %s. Expected: application/json", contentType)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInputStreamTransport(t *testing.T) {
|
||||
message := "hello world"
|
||||
location, _ := url.Parse("http://www.example.com")
|
||||
streamer := &LocationStreamer{
|
||||
Location: location,
|
||||
Transport: fakeTransport("text/plain", message),
|
||||
}
|
||||
readCloser, _, _, err := streamer.InputStream("", "")
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error when getting stream: %v", err)
|
||||
return
|
||||
}
|
||||
defer readCloser.Close()
|
||||
result, err := ioutil.ReadAll(readCloser)
|
||||
if string(result) != message {
|
||||
t.Errorf("Stream content does not match. Got: %s. Expected: %s.", string(result), message)
|
||||
}
|
||||
}
|
||||
|
||||
func fakeInternalServerErrorTransport(mime, message string) http.RoundTripper {
|
||||
content := fmt.Sprintf("HTTP/1.1 500 \"Internal Server Error\"\nContent-Type: %s\n\n%s", mime, message)
|
||||
return &testTransport{body: content}
|
||||
}
|
||||
|
||||
func TestInputStreamInternalServerErrorTransport(t *testing.T) {
|
||||
message := "Pod is in PodPending"
|
||||
location, _ := url.Parse("http://www.example.com")
|
||||
streamer := &LocationStreamer{
|
||||
Location: location,
|
||||
Transport: fakeInternalServerErrorTransport("text/plain", message),
|
||||
ResponseChecker: NewGenericHttpResponseChecker(api.Resource(""), ""),
|
||||
}
|
||||
expectedError := errors.NewInternalError(fmt.Errorf("%s", message))
|
||||
|
||||
_, _, _, err := streamer.InputStream("", "")
|
||||
if err == nil {
|
||||
t.Errorf("unexpected non-error")
|
||||
return
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(err, expectedError) {
|
||||
t.Errorf("StreamInternalServerError does not match. Got: %s. Expected: %s.", err, expectedError)
|
||||
}
|
||||
}
|
62
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/storage_decorator.go
generated
vendored
Normal file
62
vendor/k8s.io/kubernetes/pkg/genericapiserver/registry/generic/storage_decorator.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright 2015 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 generic
|
||||
|
||||
import (
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/storage"
|
||||
"k8s.io/kubernetes/pkg/storage/storagebackend"
|
||||
"k8s.io/kubernetes/pkg/storage/storagebackend/factory"
|
||||
)
|
||||
|
||||
// StorageDecorator is a function signature for producing a storage.Interface
|
||||
// and an associated DestroyFunc from given parameters.
|
||||
type StorageDecorator func(
|
||||
config *storagebackend.Config,
|
||||
capacity int,
|
||||
objectType runtime.Object,
|
||||
resourcePrefix string,
|
||||
keyFunc func(obj runtime.Object) (string, error),
|
||||
newListFunc func() runtime.Object,
|
||||
getAttrsFunc storage.AttrFunc,
|
||||
trigger storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc)
|
||||
|
||||
// UndecoratedStorage returns the given a new storage from the given config
|
||||
// without any decoration.
|
||||
func UndecoratedStorage(
|
||||
config *storagebackend.Config,
|
||||
capacity int,
|
||||
objectType runtime.Object,
|
||||
resourcePrefix string,
|
||||
keyFunc func(obj runtime.Object) (string, error),
|
||||
newListFunc func() runtime.Object,
|
||||
getAttrsFunc storage.AttrFunc,
|
||||
trigger storage.TriggerPublisherFunc) (storage.Interface, factory.DestroyFunc) {
|
||||
return NewRawStorage(config)
|
||||
}
|
||||
|
||||
// NewRawStorage creates the low level kv storage. This is a work-around for current
|
||||
// two layer of same storage interface.
|
||||
// TODO: Once cacher is enabled on all registries (event registry is special), we will remove this method.
|
||||
func NewRawStorage(config *storagebackend.Config) (storage.Interface, factory.DestroyFunc) {
|
||||
s, d, err := factory.Create(*config)
|
||||
if err != nil {
|
||||
glog.Fatalf("Unable to create storage backend: config (%v), err (%v)", config, err)
|
||||
}
|
||||
return s, d
|
||||
}
|
|
@ -17,7 +17,6 @@ go_library(
|
|||
"export.go",
|
||||
"meta.go",
|
||||
"rest.go",
|
||||
"types.go",
|
||||
"update.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
|
@ -28,12 +27,13 @@ go_library(
|
|||
"//pkg/util/uuid:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/storage/names",
|
||||
],
|
||||
)
|
||||
|
@ -49,7 +49,7 @@ filegroup(
|
|||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/genericapiserver/api/rest/resttest:all-srcs",
|
||||
"//pkg/genericapiserver/registry/rest/resttest:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
@ -62,6 +62,7 @@ go_test(
|
|||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/util/uuid:go_default_library",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
],
|
||||
)
|
|
@ -18,12 +18,12 @@ package rest
|
|||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/validation/genericvalidation"
|
||||
"k8s.io/kubernetes/pkg/api/validation/path"
|
||||
)
|
||||
|
@ -33,7 +33,7 @@ import (
|
|||
// API conventions.
|
||||
type RESTCreateStrategy interface {
|
||||
runtime.ObjectTyper
|
||||
// The name generate is used when the standard GenerateName field is set.
|
||||
// The name generator is used when the standard GenerateName field is set.
|
||||
// The NameGenerator will be invoked prior to validation.
|
||||
names.NameGenerator
|
||||
|
||||
|
@ -44,11 +44,16 @@ type RESTCreateStrategy interface {
|
|||
// sort order-insensitive list fields, etc. This should not remove fields
|
||||
// whose presence would be considered a validation error.
|
||||
PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object)
|
||||
// Validate is invoked after default fields in the object have been filled in before
|
||||
// the object is persisted. This method should not mutate the object.
|
||||
// Validate returns an ErrorList with validation errors or nil. Validate
|
||||
// is invoked after default fields in the object have been filled in
|
||||
// before the object is persisted. This method should not mutate the
|
||||
// object.
|
||||
Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList
|
||||
// Canonicalize is invoked after validation has succeeded but before the
|
||||
// object has been persisted. This method may mutate the object.
|
||||
// Canonicalize allows an object to be mutated into a canonical form. This
|
||||
// ensures that code that operates on these objects can rely on the common
|
||||
// form for things like comparison. Canonicalize is invoked after
|
||||
// validation has succeeded but before the object has been persisted.
|
||||
// This method may mutate the object.
|
||||
Canonicalize(obj runtime.Object)
|
||||
}
|
||||
|
||||
|
@ -66,7 +71,7 @@ func BeforeCreate(strategy RESTCreateStrategy, ctx genericapirequest.Context, ob
|
|||
return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
|
||||
}
|
||||
} else {
|
||||
objectMeta.Namespace = api.NamespaceNone
|
||||
objectMeta.Namespace = metav1.NamespaceNone
|
||||
}
|
||||
objectMeta.DeletionTimestamp = nil
|
||||
objectMeta.DeletionGracePeriodSeconds = nil
|
||||
|
@ -115,8 +120,8 @@ func CheckGeneratedNameError(strategy RESTCreateStrategy, err error, obj runtime
|
|||
}
|
||||
|
||||
// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error.
|
||||
func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (*api.ObjectMeta, schema.GroupVersionKind, error) {
|
||||
objectMeta, err := api.ObjectMetaFor(obj)
|
||||
func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (*metav1.ObjectMeta, schema.GroupVersionKind, error) {
|
||||
objectMeta, err := metav1.ObjectMetaFor(obj)
|
||||
if err != nil {
|
||||
return nil, schema.GroupVersionKind{}, errors.NewInternalError(err)
|
||||
}
|
|
@ -24,8 +24,7 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
// RESTDeleteStrategy defines deletion behavior on an object that follows Kubernetes
|
||||
|
@ -53,7 +52,7 @@ type GarbageCollectionDeleteStrategy interface {
|
|||
type RESTGracefulDeleteStrategy interface {
|
||||
// CheckGracefulDelete should return true if the object can be gracefully deleted and set
|
||||
// any default values on the DeleteOptions.
|
||||
CheckGracefulDelete(ctx genericapirequest.Context, obj runtime.Object, options *api.DeleteOptions) bool
|
||||
CheckGracefulDelete(ctx genericapirequest.Context, obj runtime.Object, options *metav1.DeleteOptions) bool
|
||||
}
|
||||
|
||||
// BeforeDelete tests whether the object can be gracefully deleted. If graceful is set the object
|
||||
|
@ -62,7 +61,7 @@ type RESTGracefulDeleteStrategy interface {
|
|||
// condition cannot be checked or the gracePeriodSeconds is invalid. The options argument may be updated with
|
||||
// default values if graceful is true. Second place where we set deletionTimestamp is pkg/registry/generic/registry/store.go
|
||||
// this function is responsible for setting deletionTimestamp during gracefulDeletion, other one for cascading deletions.
|
||||
func BeforeDelete(strategy RESTDeleteStrategy, ctx genericapirequest.Context, obj runtime.Object, options *api.DeleteOptions) (graceful, gracefulPending bool, err error) {
|
||||
func BeforeDelete(strategy RESTDeleteStrategy, ctx genericapirequest.Context, obj runtime.Object, options *metav1.DeleteOptions) (graceful, gracefulPending bool, err error) {
|
||||
objectMeta, gvk, kerr := objectMetaAndKind(strategy, obj)
|
||||
if kerr != nil {
|
||||
return false, false, kerr
|
|
@ -14,5 +14,5 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package rest defines common logic around changes to Kubernetes resources.
|
||||
package rest // import "k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
// Package rest defines common logic around changes to Kubernetes-style resources.
|
||||
package rest // import "k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
|
@ -18,10 +18,14 @@ package rest
|
|||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
// RESTExportStrategy is the interface that defines how to export a Kubernetes object
|
||||
// RESTExportStrategy is the interface that defines how to export a Kubernetes
|
||||
// object. An exported object is stripped of non-user-settable fields and
|
||||
// optionally, the identifying information related to the object's identity in
|
||||
// the cluster so that it can be loaded into a different namespace or entirely
|
||||
// different cluster without conflict.
|
||||
type RESTExportStrategy interface {
|
||||
// Export strips fields that can not be set by the user. If 'exact' is false
|
||||
// fields specific to the cluster are also stripped
|
|
@ -18,13 +18,12 @@ package rest
|
|||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/util/uuid"
|
||||
)
|
||||
|
||||
// FillObjectMetaSystemFields populates fields that are managed by the system on ObjectMeta.
|
||||
func FillObjectMetaSystemFields(ctx genericapirequest.Context, meta *api.ObjectMeta) {
|
||||
func FillObjectMetaSystemFields(ctx genericapirequest.Context, meta *metav1.ObjectMeta) {
|
||||
meta.CreationTimestamp = metav1.Now()
|
||||
// allows admission controllers to assign a UID earlier in the request processing
|
||||
// to support tracking resources pending creation.
|
||||
|
@ -36,9 +35,12 @@ func FillObjectMetaSystemFields(ctx genericapirequest.Context, meta *api.ObjectM
|
|||
meta.SelfLink = ""
|
||||
}
|
||||
|
||||
// ValidNamespace returns false if the namespace on the context differs from the resource. If the resource has no namespace, it is set to the value in the context.
|
||||
// TODO(sttts): move into pkg/genericapiserver/api
|
||||
func ValidNamespace(ctx genericapirequest.Context, resource *api.ObjectMeta) bool {
|
||||
// ValidNamespace returns false if the namespace on the context differs from
|
||||
// the resource. If the resource has no namespace, it is set to the value in
|
||||
// the context.
|
||||
//
|
||||
// TODO(sttts): move into pkg/genericapiserver/endpoints
|
||||
func ValidNamespace(ctx genericapirequest.Context, resource *metav1.ObjectMeta) bool {
|
||||
ns, ok := genericapirequest.NamespaceFrom(ctx)
|
||||
if len(resource.Namespace) == 0 {
|
||||
resource.Namespace = ns
|
|
@ -19,7 +19,8 @@ package rest
|
|||
import (
|
||||
"testing"
|
||||
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/util/uuid"
|
||||
)
|
||||
|
@ -27,7 +28,7 @@ import (
|
|||
// TestFillObjectMetaSystemFields validates that system populated fields are set on an object
|
||||
func TestFillObjectMetaSystemFields(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
resource := api.ObjectMeta{}
|
||||
resource := metav1.ObjectMeta{}
|
||||
FillObjectMetaSystemFields(ctx, &resource)
|
||||
if resource.CreationTimestamp.Time.IsZero() {
|
||||
t.Errorf("resource.CreationTimestamp is zero")
|
||||
|
@ -37,7 +38,7 @@ func TestFillObjectMetaSystemFields(t *testing.T) {
|
|||
// verify we can inject a UID
|
||||
uid := uuid.NewUUID()
|
||||
ctx = genericapirequest.WithUID(ctx, uid)
|
||||
resource = api.ObjectMeta{}
|
||||
resource = metav1.ObjectMeta{}
|
||||
FillObjectMetaSystemFields(ctx, &resource)
|
||||
if resource.UID != uid {
|
||||
t.Errorf("resource.UID expected: %v, actual: %v", uid, resource.UID)
|
||||
|
@ -47,7 +48,7 @@ func TestFillObjectMetaSystemFields(t *testing.T) {
|
|||
// TestHasObjectMetaSystemFieldValues validates that true is returned if and only if all fields are populated
|
||||
func TestHasObjectMetaSystemFieldValues(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
resource := api.ObjectMeta{}
|
||||
resource := metav1.ObjectMeta{}
|
||||
if api.HasObjectMetaSystemFieldValues(&resource) {
|
||||
t.Errorf("the resource does not have all fields yet populated, but incorrectly reports it does")
|
||||
}
|
||||
|
@ -68,7 +69,7 @@ func TestValidNamespace(t *testing.T) {
|
|||
if namespace != resource.Namespace {
|
||||
t.Fatalf("expected resource to have the default namespace assigned during validation")
|
||||
}
|
||||
resource = api.ReplicationController{ObjectMeta: api.ObjectMeta{Namespace: "other"}}
|
||||
resource = api.ReplicationController{ObjectMeta: metav1.ObjectMeta{Namespace: "other"}}
|
||||
if ValidNamespace(ctx, &resource.ObjectMeta) {
|
||||
t.Fatalf("Expected error that resource and context errors do not match because resource has different namespace")
|
||||
}
|
|
@ -21,11 +21,12 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
|
||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
|
@ -71,7 +72,7 @@ type Lister interface {
|
|||
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
|
||||
NewList() runtime.Object
|
||||
// List selects resources in the storage which match to the selector. 'options' can be nil.
|
||||
List(ctx genericapirequest.Context, options *api.ListOptions) (runtime.Object, error)
|
||||
List(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (runtime.Object, error)
|
||||
}
|
||||
|
||||
// Exporter is an object that knows how to strip a RESTful resource for export
|
||||
|
@ -131,7 +132,7 @@ type GracefulDeleter interface {
|
|||
// returned error value err when the specified resource is not found.
|
||||
// Delete *may* return the object that was deleted, or a status object indicating additional
|
||||
// information about deletion.
|
||||
Delete(ctx genericapirequest.Context, name string, options *api.DeleteOptions) (runtime.Object, error)
|
||||
Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, error)
|
||||
}
|
||||
|
||||
// GracefulDeleteAdapter adapts the Deleter interface to GracefulDeleter
|
||||
|
@ -140,7 +141,7 @@ type GracefulDeleteAdapter struct {
|
|||
}
|
||||
|
||||
// Delete implements RESTGracefulDeleter in terms of Deleter
|
||||
func (w GracefulDeleteAdapter) Delete(ctx genericapirequest.Context, name string, options *api.DeleteOptions) (runtime.Object, error) {
|
||||
func (w GracefulDeleteAdapter) Delete(ctx genericapirequest.Context, name string, options *metav1.DeleteOptions) (runtime.Object, error) {
|
||||
return w.Deleter.Delete(ctx, name)
|
||||
}
|
||||
|
||||
|
@ -152,7 +153,7 @@ type CollectionDeleter interface {
|
|||
// them or return an invalid request error.
|
||||
// DeleteCollection may not be atomic - i.e. it may delete some objects and still
|
||||
// return an error after it. On success, returns a list of deleted objects.
|
||||
DeleteCollection(ctx genericapirequest.Context, options *api.DeleteOptions, listOptions *api.ListOptions) (runtime.Object, error)
|
||||
DeleteCollection(ctx genericapirequest.Context, options *metav1.DeleteOptions, listOptions *metainternalversion.ListOptions) (runtime.Object, error)
|
||||
}
|
||||
|
||||
// Creater is an object that can create an instance of a RESTful object.
|
||||
|
@ -225,7 +226,7 @@ type Watcher interface {
|
|||
// are supported; an error should be returned if 'field' tries to select on a field that
|
||||
// isn't supported. 'resourceVersion' allows for continuing/starting a watch at a
|
||||
// particular version.
|
||||
Watch(ctx genericapirequest.Context, options *api.ListOptions) (watch.Interface, error)
|
||||
Watch(ctx genericapirequest.Context, options *metainternalversion.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// StandardStorage is an interface covering the common verbs. Provided for testing whether a
|
|
@ -14,16 +14,17 @@ go_library(
|
|||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/validation/path:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/internalversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/conversion",
|
||||
"//vendor:k8s.io/apimachinery/pkg/fields",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
],
|
||||
)
|
||||
|
|
@ -24,17 +24,18 @@ import (
|
|||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/validation/path"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/registry/rest"
|
||||
)
|
||||
|
||||
type Tester struct {
|
||||
|
@ -90,7 +91,7 @@ func (t *Tester) ReturnDeletedObject() *Tester {
|
|||
// Returns NamespaceNone for cluster-scoped objects.
|
||||
func (t *Tester) TestNamespace() string {
|
||||
if t.clusterScope {
|
||||
return api.NamespaceNone
|
||||
return metav1.NamespaceNone
|
||||
}
|
||||
return "test"
|
||||
}
|
||||
|
@ -104,8 +105,8 @@ func (t *Tester) TestContext() genericapirequest.Context {
|
|||
return genericapirequest.WithNamespace(genericapirequest.NewContext(), t.TestNamespace())
|
||||
}
|
||||
|
||||
func (t *Tester) getObjectMetaOrFail(obj runtime.Object) *api.ObjectMeta {
|
||||
meta, err := api.ObjectMetaFor(obj)
|
||||
func (t *Tester) getObjectMetaOrFail(obj runtime.Object) *metav1.ObjectMeta {
|
||||
meta, err := metav1.ObjectMetaFor(obj)
|
||||
if err != nil {
|
||||
t.Fatalf("object does not have ObjectMeta: %v\n%#v", err, obj)
|
||||
}
|
||||
|
@ -116,7 +117,7 @@ func (t *Tester) setObjectMeta(obj runtime.Object, name string) {
|
|||
meta := t.getObjectMetaOrFail(obj)
|
||||
meta.Name = name
|
||||
if t.clusterScope {
|
||||
meta.Namespace = api.NamespaceNone
|
||||
meta.Namespace = metav1.NamespaceNone
|
||||
} else {
|
||||
meta.Namespace = genericapirequest.NamespaceValue(t.TestContext())
|
||||
}
|
||||
|
@ -169,7 +170,7 @@ func (t *Tester) TestUpdate(valid runtime.Object, createFn CreateFunc, getFn Get
|
|||
t.testUpdateFailsOnVersionTooOld(copyOrDie(valid), createFn, getFn)
|
||||
t.testUpdateOnNotFound(copyOrDie(valid))
|
||||
if !t.clusterScope {
|
||||
t.testUpdateRejectsMismatchedNamespace(copyOrDie(valid), createFn)
|
||||
t.testUpdateRejectsMismatchedNamespace(copyOrDie(valid), createFn, getFn)
|
||||
}
|
||||
t.testUpdateInvokesValidation(copyOrDie(valid), createFn, invalidUpdateFn...)
|
||||
t.testUpdateWithWrongUID(copyOrDie(valid), createFn, getFn)
|
||||
|
@ -225,7 +226,7 @@ func (t *Tester) TestWatch(
|
|||
// Creation tests.
|
||||
|
||||
func (t *Tester) delete(ctx genericapirequest.Context, obj runtime.Object) error {
|
||||
objectMeta, err := api.ObjectMetaFor(obj)
|
||||
objectMeta, err := metav1.ObjectMetaFor(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -293,7 +294,7 @@ func (t *Tester) testCreateDiscardsObjectNamespace(valid runtime.Object) {
|
|||
}
|
||||
defer t.delete(t.TestContext(), created)
|
||||
createdObjectMeta := t.getObjectMetaOrFail(created)
|
||||
if createdObjectMeta.Namespace != api.NamespaceNone {
|
||||
if createdObjectMeta.Namespace != metav1.NamespaceNone {
|
||||
t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.Namespace)
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +343,7 @@ func (t *Tester) testCreateIgnoresContextNamespace(valid runtime.Object) {
|
|||
}
|
||||
defer t.delete(ctx, created)
|
||||
createdObjectMeta := t.getObjectMetaOrFail(created)
|
||||
if createdObjectMeta.Namespace != api.NamespaceNone {
|
||||
if createdObjectMeta.Namespace != metav1.NamespaceNone {
|
||||
t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.Namespace)
|
||||
}
|
||||
}
|
||||
|
@ -361,7 +362,7 @@ func (t *Tester) testCreateIgnoresMismatchedNamespace(valid runtime.Object) {
|
|||
}
|
||||
defer t.delete(ctx, created)
|
||||
createdObjectMeta := t.getObjectMetaOrFail(created)
|
||||
if createdObjectMeta.Namespace != api.NamespaceNone {
|
||||
if createdObjectMeta.Namespace != metav1.NamespaceNone {
|
||||
t.Errorf("Expected empty namespace on created object, got '%v'", createdObjectMeta.Namespace)
|
||||
}
|
||||
}
|
||||
|
@ -686,7 +687,7 @@ func (t *Tester) testUpdateOnNotFound(obj runtime.Object) {
|
|||
}
|
||||
}
|
||||
|
||||
func (t *Tester) testUpdateRejectsMismatchedNamespace(obj runtime.Object, createFn CreateFunc) {
|
||||
func (t *Tester) testUpdateRejectsMismatchedNamespace(obj runtime.Object, createFn CreateFunc, getFn GetFunc) {
|
||||
ctx := t.TestContext()
|
||||
|
||||
foo := copyOrDie(obj)
|
||||
|
@ -695,11 +696,16 @@ func (t *Tester) testUpdateRejectsMismatchedNamespace(obj runtime.Object, create
|
|||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
objectMeta := t.getObjectMetaOrFail(obj)
|
||||
storedFoo, err := getFn(ctx, foo)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
objectMeta := t.getObjectMetaOrFail(storedFoo)
|
||||
objectMeta.Name = t.namer(1)
|
||||
objectMeta.Namespace = "not-default"
|
||||
|
||||
obj, updated, err := t.storage.(rest.Updater).Update(t.TestContext(), "foo1", rest.DefaultUpdatedObjectInfo(obj, api.Scheme))
|
||||
obj, updated, err := t.storage.(rest.Updater).Update(t.TestContext(), "foo1", rest.DefaultUpdatedObjectInfo(storedFoo, api.Scheme))
|
||||
if obj != nil || updated {
|
||||
t.Errorf("expected nil object and not updated")
|
||||
}
|
||||
|
@ -757,7 +763,7 @@ func (t *Tester) testDeleteNoGraceful(obj runtime.Object, createFn CreateFunc, g
|
|||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
objectMeta := t.getObjectMetaOrFail(foo)
|
||||
obj, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(10))
|
||||
obj, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, metav1.NewDeleteOptions(10))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -797,12 +803,12 @@ func (t *Tester) testDeleteWithUID(obj runtime.Object, createFn CreateFunc, getF
|
|||
if err := createFn(ctx, foo); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
obj, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewPreconditionDeleteOptions("UID1111"))
|
||||
obj, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, metav1.NewPreconditionDeleteOptions("UID1111"))
|
||||
if err == nil || !errors.IsConflict(err) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
obj, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewPreconditionDeleteOptions("UID0000"))
|
||||
obj, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, metav1.NewPreconditionDeleteOptions("UID0000"))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -834,7 +840,7 @@ func (t *Tester) testDeleteGracefulHasDefault(obj runtime.Object, createFn Creat
|
|||
}
|
||||
objectMeta := t.getObjectMetaOrFail(foo)
|
||||
generation := objectMeta.Generation
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, &api.DeleteOptions{})
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, &metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -865,7 +871,7 @@ func (t *Tester) testDeleteGracefulWithValue(obj runtime.Object, createFn Create
|
|||
}
|
||||
objectMeta := t.getObjectMetaOrFail(foo)
|
||||
generation := objectMeta.Generation
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace+2))
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, metav1.NewDeleteOptions(expectedGrace+2))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -896,7 +902,7 @@ func (t *Tester) testDeleteGracefulExtend(obj runtime.Object, createFn CreateFun
|
|||
}
|
||||
objectMeta := t.getObjectMetaOrFail(foo)
|
||||
generation := objectMeta.Generation
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace))
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, metav1.NewDeleteOptions(expectedGrace))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -905,7 +911,7 @@ func (t *Tester) testDeleteGracefulExtend(obj runtime.Object, createFn CreateFun
|
|||
}
|
||||
|
||||
// second delete duration is ignored
|
||||
_, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace+2))
|
||||
_, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, metav1.NewDeleteOptions(expectedGrace+2))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -932,7 +938,7 @@ func (t *Tester) testDeleteGracefulImmediate(obj runtime.Object, createFn Create
|
|||
}
|
||||
objectMeta := t.getObjectMetaOrFail(foo)
|
||||
generation := objectMeta.Generation
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace))
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, metav1.NewDeleteOptions(expectedGrace))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -941,7 +947,7 @@ func (t *Tester) testDeleteGracefulImmediate(obj runtime.Object, createFn Create
|
|||
}
|
||||
|
||||
// second delete is immediate, resource is deleted
|
||||
out, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(0))
|
||||
out, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, metav1.NewDeleteOptions(0))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -991,7 +997,7 @@ func (t *Tester) testDeleteGracefulShorten(obj runtime.Object, createFn CreateFu
|
|||
bigGrace = 2 * expectedGrace
|
||||
}
|
||||
objectMeta := t.getObjectMetaOrFail(foo)
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(bigGrace))
|
||||
_, err := t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, metav1.NewDeleteOptions(bigGrace))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -1003,7 +1009,7 @@ func (t *Tester) testDeleteGracefulShorten(obj runtime.Object, createFn CreateFu
|
|||
deletionTimestamp := *objectMeta.DeletionTimestamp
|
||||
|
||||
// second delete duration is ignored
|
||||
_, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, api.NewDeleteOptions(expectedGrace))
|
||||
_, err = t.storage.(rest.GracefulDeleter).Delete(ctx, objectMeta.Name, metav1.NewDeleteOptions(expectedGrace))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
@ -1191,7 +1197,7 @@ func (t *Tester) testListMatchLabels(obj runtime.Object, assignFn AssignFunc) {
|
|||
filtered := []runtime.Object{objs[1]}
|
||||
|
||||
selector := labels.SelectorFromSet(labels.Set(testLabels))
|
||||
options := &api.ListOptions{LabelSelector: selector}
|
||||
options := &metainternalversion.ListOptions{LabelSelector: selector}
|
||||
listObj, err := t.storage.(rest.Lister).List(ctx, options)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
|
@ -1233,7 +1239,7 @@ func (t *Tester) testWatchFields(obj runtime.Object, emitFn EmitFunc, fieldsPass
|
|||
|
||||
for _, field := range fieldsPass {
|
||||
for _, action := range actions {
|
||||
options := &api.ListOptions{FieldSelector: field.AsSelector(), ResourceVersion: "1"}
|
||||
options := &metainternalversion.ListOptions{FieldSelector: field.AsSelector(), ResourceVersion: "1"}
|
||||
watcher, err := t.storage.(rest.Watcher).Watch(ctx, options)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v, %v", err, action)
|
||||
|
@ -1257,7 +1263,7 @@ func (t *Tester) testWatchFields(obj runtime.Object, emitFn EmitFunc, fieldsPass
|
|||
|
||||
for _, field := range fieldsFail {
|
||||
for _, action := range actions {
|
||||
options := &api.ListOptions{FieldSelector: field.AsSelector(), ResourceVersion: "1"}
|
||||
options := &metainternalversion.ListOptions{FieldSelector: field.AsSelector(), ResourceVersion: "1"}
|
||||
watcher, err := t.storage.(rest.Watcher).Watch(ctx, options)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
|
@ -1282,7 +1288,7 @@ func (t *Tester) testWatchLabels(obj runtime.Object, emitFn EmitFunc, labelsPass
|
|||
|
||||
for _, label := range labelsPass {
|
||||
for _, action := range actions {
|
||||
options := &api.ListOptions{LabelSelector: label.AsSelector(), ResourceVersion: "1"}
|
||||
options := &metainternalversion.ListOptions{LabelSelector: label.AsSelector(), ResourceVersion: "1"}
|
||||
watcher, err := t.storage.(rest.Watcher).Watch(ctx, options)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
|
@ -1305,7 +1311,7 @@ func (t *Tester) testWatchLabels(obj runtime.Object, emitFn EmitFunc, labelsPass
|
|||
|
||||
for _, label := range labelsFail {
|
||||
for _, action := range actions {
|
||||
options := &api.ListOptions{LabelSelector: label.AsSelector(), ResourceVersion: "1"}
|
||||
options := &metainternalversion.ListOptions{LabelSelector: label.AsSelector(), ResourceVersion: "1"}
|
||||
watcher, err := t.storage.(rest.Watcher).Watch(ctx, options)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
|
@ -21,9 +21,10 @@ import (
|
|||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/validation/genericvalidation"
|
||||
)
|
||||
|
@ -47,8 +48,11 @@ type RESTUpdateStrategy interface {
|
|||
// filled in before the object is persisted. This method should not mutate
|
||||
// the object.
|
||||
ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList
|
||||
// Canonicalize is invoked after validation has succeeded but before the
|
||||
// object has been persisted. This method may mutate the object.
|
||||
// Canonicalize allows an object to be mutated into a canonical form. This
|
||||
// ensures that code that operates on these objects can rely on the common
|
||||
// form for things like comparison. Canonicalize is invoked after
|
||||
// validation has succeeded but before the object has been persisted.
|
||||
// This method may mutate the object.
|
||||
Canonicalize(obj runtime.Object)
|
||||
// AllowUnconditionalUpdate returns true if the object can be updated
|
||||
// unconditionally (irrespective of the latest resource version), when
|
||||
|
@ -59,11 +63,11 @@ type RESTUpdateStrategy interface {
|
|||
// TODO: add other common fields that require global validation.
|
||||
func validateCommonFields(obj, old runtime.Object) (field.ErrorList, error) {
|
||||
allErrs := field.ErrorList{}
|
||||
objectMeta, err := api.ObjectMetaFor(obj)
|
||||
objectMeta, err := metav1.ObjectMetaFor(obj)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get new object metadata: %v", err)
|
||||
}
|
||||
oldObjectMeta, err := api.ObjectMetaFor(old)
|
||||
oldObjectMeta, err := metav1.ObjectMetaFor(old)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get old object metadata: %v", err)
|
||||
}
|
||||
|
@ -85,10 +89,10 @@ func BeforeUpdate(strategy RESTUpdateStrategy, ctx genericapirequest.Context, ob
|
|||
return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
|
||||
}
|
||||
} else {
|
||||
objectMeta.Namespace = api.NamespaceNone
|
||||
objectMeta.Namespace = metav1.NamespaceNone
|
||||
}
|
||||
// Ensure requests cannot update generation
|
||||
oldMeta, err := api.ObjectMetaFor(old)
|
||||
oldMeta, err := metav1.ObjectMetaFor(old)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
131
vendor/k8s.io/kubernetes/pkg/genericapiserver/server/BUILD
generated
vendored
Normal file
131
vendor/k8s.io/kubernetes/pkg/genericapiserver/server/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"genericapiserver_test.go",
|
||||
"resource_config_test.go",
|
||||
"serve_test.go",
|
||||
"server_run_options_test.go",
|
||||
"storage_factory_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/autoscaling:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||
"//pkg/generated/openapi:go_default_library",
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//pkg/genericapiserver/server/options:go_default_library",
|
||||
"//pkg/storage/etcd/testing:go_default_library",
|
||||
"//pkg/storage/storagebackend:go_default_library",
|
||||
"//pkg/util/config:go_default_library",
|
||||
"//vendor:github.com/go-openapi/spec",
|
||||
"//vendor:github.com/stretchr/testify/assert",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apimachinery",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/apimachinery/pkg/version",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
"//vendor:k8s.io/client-go/util/cert",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"config.go",
|
||||
"config_selfclient.go",
|
||||
"discovery.go",
|
||||
"doc.go",
|
||||
"genericapiserver.go",
|
||||
"healthz.go",
|
||||
"hooks.go",
|
||||
"resource_config.go",
|
||||
"resource_encoding_config.go",
|
||||
"serve.go",
|
||||
"storage_factory.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/genericapiserver/authenticator:go_default_library",
|
||||
"//pkg/genericapiserver/authorizer:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/filters:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/openapi:go_default_library",
|
||||
"//pkg/genericapiserver/registry/rest:go_default_library",
|
||||
"//pkg/genericapiserver/server/filters:go_default_library",
|
||||
"//pkg/genericapiserver/server/mux:go_default_library",
|
||||
"//pkg/genericapiserver/server/options:go_default_library",
|
||||
"//pkg/genericapiserver/server/routes:go_default_library",
|
||||
"//pkg/storage/storagebackend:go_default_library",
|
||||
"//vendor:github.com/coreos/go-systemd/daemon",
|
||||
"//vendor:github.com/emicklei/go-restful",
|
||||
"//vendor:github.com/emicklei/go-restful/swagger",
|
||||
"//vendor:github.com/go-openapi/spec",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:github.com/pborman/uuid",
|
||||
"//vendor:github.com/pkg/errors",
|
||||
"//vendor:gopkg.in/natefinch/lumberjack.v2",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apimachinery",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/openapi",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation",
|
||||
"//vendor:k8s.io/apimachinery/pkg/version",
|
||||
"//vendor:k8s.io/apiserver/pkg/admission",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/authenticator",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/request/union",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/union",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/server/healthz",
|
||||
"//vendor:k8s.io/client-go/rest",
|
||||
"//vendor:k8s.io/client-go/util/cert",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/genericapiserver/server/filters:all-srcs",
|
||||
"//pkg/genericapiserver/server/mux:all-srcs",
|
||||
"//pkg/genericapiserver/server/openapi:all-srcs",
|
||||
"//pkg/genericapiserver/server/options:all-srcs",
|
||||
"//pkg/genericapiserver/server/routes:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package genericapiserver
|
||||
package server
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
|
@ -40,27 +40,26 @@ import (
|
|||
openapicommon "k8s.io/apimachinery/pkg/openapi"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
authenticatorunion "k8s.io/apiserver/pkg/authentication/request/union"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
authorizerunion "k8s.io/apiserver/pkg/authorization/union"
|
||||
"k8s.io/apiserver/pkg/healthz"
|
||||
apirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/admission"
|
||||
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/server/healthz"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
certutil "k8s.io/client-go/util/cert"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
authhandlers "k8s.io/kubernetes/pkg/auth/handlers"
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
genericapifilters "k8s.io/kubernetes/pkg/genericapiserver/api/filters"
|
||||
apiopenapi "k8s.io/kubernetes/pkg/genericapiserver/api/openapi"
|
||||
genericauthenticator "k8s.io/kubernetes/pkg/genericapiserver/authenticator"
|
||||
genericauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||
genericfilters "k8s.io/kubernetes/pkg/genericapiserver/filters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/mux"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/options"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/routes"
|
||||
certutil "k8s.io/kubernetes/pkg/util/cert"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
genericapifilters "k8s.io/kubernetes/pkg/genericapiserver/endpoints/filters"
|
||||
apiopenapi "k8s.io/kubernetes/pkg/genericapiserver/endpoints/openapi"
|
||||
genericfilters "k8s.io/kubernetes/pkg/genericapiserver/server/filters"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/server/mux"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/server/options"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/server/routes"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -573,7 +572,7 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) (secure, insec
|
|||
handler = genericapifilters.WithAuthorization(handler, c.RequestContextMapper, c.Authorizer)
|
||||
handler = genericapifilters.WithImpersonation(handler, c.RequestContextMapper, c.Authorizer)
|
||||
handler = audit(handler) // before impersonation to read original user
|
||||
handler = authhandlers.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, authhandlers.Unauthorized(c.SupportsBasicAuth))
|
||||
handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, genericapifilters.Unauthorized(c.SupportsBasicAuth))
|
||||
return handler
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package genericapiserver
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -24,7 +24,7 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
|
||||
"k8s.io/kubernetes/pkg/client/restclient"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package genericapiserver
|
||||
package server
|
||||
|
||||
import (
|
||||
"net"
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
Copyright 2015 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.
|
||||
|
@ -14,5 +14,5 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
// package common holds shared codes and types between open API code generator and spec generator.
|
||||
package common
|
||||
// Package server contains the plumbing to create kubernetes-like API server command.
|
||||
package server // import "k8s.io/kubernetes/pkg/genericapiserver/server"
|
|
@ -20,14 +20,14 @@ go_library(
|
|||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/util:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/apiserver/pkg/httplog",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/server/httplog",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -41,10 +41,11 @@ go_test(
|
|||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/genericapiserver/api/filters:go_default_library",
|
||||
"//pkg/genericapiserver/endpoints/filters:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
],
|
||||
)
|
||||
|
|
@ -16,4 +16,4 @@ limitations under the License.
|
|||
|
||||
// Package filters contains all the http handler chain filters which
|
||||
// are not api related.
|
||||
package filters // import "k8s.io/kubernetes/pkg/genericapiserver/filters"
|
||||
package filters // import "k8s.io/kubernetes/pkg/genericapiserver/server/filters"
|
|
@ -20,7 +20,7 @@ import (
|
|||
"net/http"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
apirequest "k8s.io/apiserver/pkg/request"
|
||||
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
)
|
||||
|
||||
// LongRunningRequestCheck is a predicate which is true for long-running http requests.
|
|
@ -22,9 +22,9 @@ import (
|
|||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/httplog"
|
||||
apirequest "k8s.io/apiserver/pkg/request"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/server/httplog"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue