move dynamic and discovery clients
This commit is contained in:
@@ -16,8 +16,8 @@ go_library(
|
|||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
"//cmd/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1alpha1:go_default_library",
|
"//cmd/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1alpha1:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/util/flowcontrol",
|
"//vendor:k8s.io/client-go/util/flowcontrol",
|
||||||
|
@@ -18,11 +18,11 @@ package clientset
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
discovery "k8s.io/client-go/discovery"
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
"k8s.io/client-go/util/flowcontrol"
|
||||||
v1alpha1apiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1alpha1"
|
v1alpha1apiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1alpha1"
|
||||||
discovery "k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
|
@@ -20,10 +20,10 @@ go_library(
|
|||||||
"//cmd/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1alpha1/fake:go_default_library",
|
"//cmd/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1alpha1/fake:go_default_library",
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/client/testing/core:go_default_library",
|
"//pkg/client/testing/core:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/discovery/fake:go_default_library",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/discovery/fake",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -19,13 +19,13 @@ package fake
|
|||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||||
clientset "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/clientset"
|
clientset "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||||
v1alpha1apiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1alpha1"
|
v1alpha1apiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1alpha1"
|
||||||
fakev1alpha1apiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1alpha1/fake"
|
fakev1alpha1apiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1alpha1/fake"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
"k8s.io/kubernetes/pkg/client/testing/core"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
fakediscovery "k8s.io/kubernetes/pkg/client/typed/discovery/fake"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||||
|
@@ -16,8 +16,8 @@ go_library(
|
|||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
"//cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion:go_default_library",
|
"//cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/util/flowcontrol",
|
"//vendor:k8s.io/client-go/util/flowcontrol",
|
||||||
|
@@ -18,11 +18,11 @@ package internalclientset
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
discovery "k8s.io/client-go/discovery"
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
"k8s.io/client-go/util/flowcontrol"
|
||||||
internalversionapiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion"
|
internalversionapiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion"
|
||||||
discovery "k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
|
@@ -20,10 +20,10 @@ go_library(
|
|||||||
"//cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake:go_default_library",
|
"//cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake:go_default_library",
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/client/testing/core:go_default_library",
|
"//pkg/client/testing/core:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/discovery/fake:go_default_library",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/discovery/fake",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -19,13 +19,13 @@ package fake
|
|||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||||
clientset "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset"
|
clientset "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset"
|
||||||
internalversionapiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion"
|
internalversionapiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion"
|
||||||
fakeinternalversionapiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake"
|
fakeinternalversionapiregistration "k8s.io/kubernetes/cmd/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion/fake"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
"k8s.io/kubernetes/pkg/client/testing/core"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
fakediscovery "k8s.io/kubernetes/pkg/client/typed/discovery/fake"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||||
|
@@ -34,8 +34,6 @@ go_library(
|
|||||||
"//pkg/client/leaderelection:go_default_library",
|
"//pkg/client/leaderelection:go_default_library",
|
||||||
"//pkg/client/leaderelection/resourcelock:go_default_library",
|
"//pkg/client/leaderelection/resourcelock:go_default_library",
|
||||||
"//pkg/client/record:go_default_library",
|
"//pkg/client/record:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//pkg/cloudprovider:go_default_library",
|
"//pkg/cloudprovider:go_default_library",
|
||||||
"//pkg/cloudprovider/providers:go_default_library",
|
"//pkg/cloudprovider/providers:go_default_library",
|
||||||
"//pkg/cloudprovider/providers/aws:go_default_library",
|
"//pkg/cloudprovider/providers/aws:go_default_library",
|
||||||
@@ -99,6 +97,8 @@ go_library(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||||
"//vendor:k8s.io/apiserver/pkg/server/healthz",
|
"//vendor:k8s.io/apiserver/pkg/server/healthz",
|
||||||
"//vendor:k8s.io/apiserver/pkg/util/feature",
|
"//vendor:k8s.io/apiserver/pkg/util/feature",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd",
|
"//vendor:k8s.io/client-go/tools/clientcmd",
|
||||||
"//vendor:k8s.io/client-go/util/cert",
|
"//vendor:k8s.io/client-go/util/cert",
|
||||||
|
@@ -36,6 +36,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apiserver/pkg/server/healthz"
|
"k8s.io/apiserver/pkg/server/healthz"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
certutil "k8s.io/client-go/util/cert"
|
certutil "k8s.io/client-go/util/cert"
|
||||||
@@ -46,7 +47,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/client/leaderelection"
|
"k8s.io/kubernetes/pkg/client/leaderelection"
|
||||||
"k8s.io/kubernetes/pkg/client/leaderelection/resourcelock"
|
"k8s.io/kubernetes/pkg/client/leaderelection/resourcelock"
|
||||||
"k8s.io/kubernetes/pkg/client/record"
|
"k8s.io/kubernetes/pkg/client/record"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
"k8s.io/kubernetes/pkg/controller/informers"
|
"k8s.io/kubernetes/pkg/controller/informers"
|
||||||
|
@@ -26,11 +26,11 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint"
|
endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint"
|
||||||
"k8s.io/kubernetes/pkg/controller/garbagecollector"
|
"k8s.io/kubernetes/pkg/controller/garbagecollector"
|
||||||
|
@@ -45,9 +45,9 @@ go_test(
|
|||||||
deps = [
|
deps = [
|
||||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/version",
|
"//vendor:k8s.io/apimachinery/pkg/version",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@@ -24,10 +24,10 @@ import (
|
|||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/version"
|
"k8s.io/apimachinery/pkg/version"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEstablishMasterConnection(t *testing.T) {
|
func TestEstablishMasterConnection(t *testing.T) {
|
||||||
|
@@ -71,8 +71,8 @@ func (g *genClientset) Imports(c *generator.Context) (imports []string) {
|
|||||||
imports = append(imports,
|
imports = append(imports,
|
||||||
"k8s.io/kubernetes/pkg/api",
|
"k8s.io/kubernetes/pkg/api",
|
||||||
"k8s.io/kubernetes/pkg/client/testing/core",
|
"k8s.io/kubernetes/pkg/client/testing/core",
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery",
|
"k8s.io/client-go/discovery",
|
||||||
"fakediscovery \"k8s.io/kubernetes/pkg/client/typed/discovery/fake\"",
|
"fakediscovery \"k8s.io/client-go/discovery/fake\"",
|
||||||
"k8s.io/apimachinery/pkg/runtime",
|
"k8s.io/apimachinery/pkg/runtime",
|
||||||
"k8s.io/apimachinery/pkg/watch",
|
"k8s.io/apimachinery/pkg/watch",
|
||||||
)
|
)
|
||||||
|
@@ -72,7 +72,7 @@ func (g *genClientset) GenerateType(c *generator.Context, t *types.Type, w io.Wr
|
|||||||
// TODO: We actually don't need any type information to generate the clientset,
|
// TODO: We actually don't need any type information to generate the clientset,
|
||||||
// perhaps we can adapt the go2ild framework to this kind of usage.
|
// perhaps we can adapt the go2ild framework to this kind of usage.
|
||||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||||
const pkgDiscovery = "k8s.io/kubernetes/pkg/client/typed/discovery"
|
const pkgDiscovery = "k8s.io/client-go/discovery"
|
||||||
const pkgRESTClient = "k8s.io/client-go/rest"
|
const pkgRESTClient = "k8s.io/client-go/rest"
|
||||||
|
|
||||||
allGroups := clientgentypes.ToGroupVersionPackages(g.groups)
|
allGroups := clientgentypes.ToGroupVersionPackages(g.groups)
|
||||||
|
@@ -17,8 +17,8 @@ go_library(
|
|||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
"//cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion:go_default_library",
|
"//cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/util/flowcontrol",
|
"//vendor:k8s.io/client-go/util/flowcontrol",
|
||||||
|
@@ -18,11 +18,11 @@ package test_internalclientset
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
discovery "k8s.io/client-go/discovery"
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
"k8s.io/client-go/util/flowcontrol"
|
||||||
internalversiontestgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion"
|
internalversiontestgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion"
|
||||||
discovery "k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
|
@@ -20,10 +20,10 @@ go_library(
|
|||||||
"//cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion/fake:go_default_library",
|
"//cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion/fake:go_default_library",
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/client/testing/core:go_default_library",
|
"//pkg/client/testing/core:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/discovery/fake:go_default_library",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/discovery/fake",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -19,13 +19,13 @@ package fake
|
|||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||||
clientset "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset"
|
clientset "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset"
|
||||||
internalversiontestgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion"
|
internalversiontestgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion"
|
||||||
fakeinternalversiontestgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion/fake"
|
fakeinternalversiontestgroup "k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testoutput/clientset_generated/test_internalclientset/typed/testgroup/internalversion/fake"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
"k8s.io/kubernetes/pkg/client/testing/core"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
fakediscovery "k8s.io/kubernetes/pkg/client/typed/discovery/fake"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||||
|
@@ -22,8 +22,8 @@ go_library(
|
|||||||
"//federation/client/clientset_generated/federation_clientset/typed/core/v1:go_default_library",
|
"//federation/client/clientset_generated/federation_clientset/typed/core/v1:go_default_library",
|
||||||
"//federation/client/clientset_generated/federation_clientset/typed/extensions/v1beta1:go_default_library",
|
"//federation/client/clientset_generated/federation_clientset/typed/extensions/v1beta1:go_default_library",
|
||||||
"//federation/client/clientset_generated/federation_clientset/typed/federation/v1beta1:go_default_library",
|
"//federation/client/clientset_generated/federation_clientset/typed/federation/v1beta1:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/util/flowcontrol",
|
"//vendor:k8s.io/client-go/util/flowcontrol",
|
||||||
|
@@ -18,6 +18,7 @@ package federation_clientset
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
discovery "k8s.io/client-go/discovery"
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
"k8s.io/client-go/util/flowcontrol"
|
||||||
@@ -26,7 +27,6 @@ import (
|
|||||||
v1core "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/core/v1"
|
v1core "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/core/v1"
|
||||||
v1beta1extensions "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/extensions/v1beta1"
|
v1beta1extensions "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/extensions/v1beta1"
|
||||||
v1beta1federation "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/federation/v1beta1"
|
v1beta1federation "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/federation/v1beta1"
|
||||||
discovery "k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
|
@@ -28,10 +28,10 @@ go_library(
|
|||||||
"//federation/client/clientset_generated/federation_clientset/typed/federation/v1beta1/fake:go_default_library",
|
"//federation/client/clientset_generated/federation_clientset/typed/federation/v1beta1/fake:go_default_library",
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/client/testing/core:go_default_library",
|
"//pkg/client/testing/core:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/discovery/fake:go_default_library",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/discovery/fake",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -19,6 +19,8 @@ package fake
|
|||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||||
clientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
clientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
||||||
v1autoscaling "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/autoscaling/v1"
|
v1autoscaling "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/autoscaling/v1"
|
||||||
fakev1autoscaling "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/autoscaling/v1/fake"
|
fakev1autoscaling "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/autoscaling/v1/fake"
|
||||||
@@ -32,8 +34,6 @@ import (
|
|||||||
fakev1beta1federation "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/federation/v1beta1/fake"
|
fakev1beta1federation "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/typed/federation/v1beta1/fake"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
"k8s.io/kubernetes/pkg/client/testing/core"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
fakediscovery "k8s.io/kubernetes/pkg/client/typed/discovery/fake"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||||
|
@@ -22,8 +22,8 @@ go_library(
|
|||||||
"//federation/client/clientset_generated/federation_internalclientset/typed/core/internalversion:go_default_library",
|
"//federation/client/clientset_generated/federation_internalclientset/typed/core/internalversion:go_default_library",
|
||||||
"//federation/client/clientset_generated/federation_internalclientset/typed/extensions/internalversion:go_default_library",
|
"//federation/client/clientset_generated/federation_internalclientset/typed/extensions/internalversion:go_default_library",
|
||||||
"//federation/client/clientset_generated/federation_internalclientset/typed/federation/internalversion:go_default_library",
|
"//federation/client/clientset_generated/federation_internalclientset/typed/federation/internalversion:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/util/flowcontrol",
|
"//vendor:k8s.io/client-go/util/flowcontrol",
|
||||||
|
@@ -18,6 +18,7 @@ package federation_internalclientset
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
discovery "k8s.io/client-go/discovery"
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
"k8s.io/client-go/util/flowcontrol"
|
||||||
@@ -26,7 +27,6 @@ import (
|
|||||||
internalversioncore "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/core/internalversion"
|
internalversioncore "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/core/internalversion"
|
||||||
internalversionextensions "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/extensions/internalversion"
|
internalversionextensions "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/extensions/internalversion"
|
||||||
internalversionfederation "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/federation/internalversion"
|
internalversionfederation "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/federation/internalversion"
|
||||||
discovery "k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
|
@@ -28,10 +28,10 @@ go_library(
|
|||||||
"//federation/client/clientset_generated/federation_internalclientset/typed/federation/internalversion/fake:go_default_library",
|
"//federation/client/clientset_generated/federation_internalclientset/typed/federation/internalversion/fake:go_default_library",
|
||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/client/testing/core:go_default_library",
|
"//pkg/client/testing/core:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/discovery/fake:go_default_library",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/discovery/fake",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -19,6 +19,8 @@ package fake
|
|||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||||
clientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset"
|
clientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset"
|
||||||
internalversionautoscaling "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/autoscaling/internalversion"
|
internalversionautoscaling "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/autoscaling/internalversion"
|
||||||
fakeinternalversionautoscaling "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/autoscaling/internalversion/fake"
|
fakeinternalversionautoscaling "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/autoscaling/internalversion/fake"
|
||||||
@@ -32,8 +34,6 @@ import (
|
|||||||
fakeinternalversionfederation "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/federation/internalversion/fake"
|
fakeinternalversionfederation "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/federation/internalversion/fake"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
"k8s.io/kubernetes/pkg/client/testing/core"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
fakediscovery "k8s.io/kubernetes/pkg/client/typed/discovery/fake"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||||
|
@@ -32,7 +32,6 @@ go_library(
|
|||||||
"//federation/pkg/federation-controller/secret:go_default_library",
|
"//federation/pkg/federation-controller/secret:go_default_library",
|
||||||
"//federation/pkg/federation-controller/service:go_default_library",
|
"//federation/pkg/federation-controller/service:go_default_library",
|
||||||
"//federation/pkg/federation-controller/util:go_default_library",
|
"//federation/pkg/federation-controller/util:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/util/configz:go_default_library",
|
"//pkg/util/configz:go_default_library",
|
||||||
"//pkg/version:go_default_library",
|
"//pkg/version:go_default_library",
|
||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
@@ -44,6 +43,7 @@ go_library(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||||
"//vendor:k8s.io/apiserver/pkg/server/healthz",
|
"//vendor:k8s.io/apiserver/pkg/server/healthz",
|
||||||
"//vendor:k8s.io/apiserver/pkg/util/flag",
|
"//vendor:k8s.io/apiserver/pkg/util/flag",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd",
|
"//vendor:k8s.io/client-go/tools/clientcmd",
|
||||||
],
|
],
|
||||||
|
@@ -53,7 +53,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@@ -24,7 +24,6 @@ go_library(
|
|||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/controller:go_default_library",
|
"//pkg/controller:go_default_library",
|
||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
@@ -33,6 +32,7 @@ go_library(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/tools/cache",
|
"//vendor:k8s.io/client-go/tools/cache",
|
||||||
],
|
],
|
||||||
|
@@ -23,13 +23,13 @@ import (
|
|||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
federation_v1beta1 "k8s.io/kubernetes/federation/apis/federation/v1beta1"
|
federation_v1beta1 "k8s.io/kubernetes/federation/apis/federation/v1beta1"
|
||||||
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
|
"k8s.io/kubernetes/federation/pkg/federation-controller/util"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@@ -53,12 +53,12 @@ go_test(
|
|||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/api/testapi:go_default_library",
|
"//pkg/api/testapi:go_default_library",
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//pkg/kubectl/cmd/testing:go_default_library",
|
"//pkg/kubectl/cmd/testing:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/diff",
|
"//vendor:k8s.io/apimachinery/pkg/util/diff",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/rest/fake",
|
"//vendor:k8s.io/client-go/rest/fake",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd",
|
"//vendor:k8s.io/client-go/tools/clientcmd",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd/api",
|
"//vendor:k8s.io/client-go/tools/clientcmd/api",
|
||||||
|
@@ -46,13 +46,13 @@ go_test(
|
|||||||
"//pkg/api/testapi:go_default_library",
|
"//pkg/api/testapi:go_default_library",
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//pkg/kubectl/cmd/testing:go_default_library",
|
"//pkg/kubectl/cmd/testing:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//pkg/util/intstr:go_default_library",
|
"//pkg/util/intstr:go_default_library",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/diff",
|
"//vendor:k8s.io/apimachinery/pkg/util/diff",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/rest/fake",
|
"//vendor:k8s.io/client-go/rest/fake",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd",
|
"//vendor:k8s.io/client-go/tools/clientcmd",
|
||||||
],
|
],
|
||||||
|
@@ -33,6 +33,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
kubefedtesting "k8s.io/kubernetes/federation/pkg/kubefed/testing"
|
kubefedtesting "k8s.io/kubernetes/federation/pkg/kubefed/testing"
|
||||||
@@ -42,7 +43,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"k8s.io/kubernetes/pkg/util/intstr"
|
"k8s.io/kubernetes/pkg/util/intstr"
|
||||||
|
@@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||||
@@ -34,7 +35,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
)
|
)
|
||||||
|
@@ -25,12 +25,12 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
federationapi "k8s.io/kubernetes/federation/apis/federation"
|
federationapi "k8s.io/kubernetes/federation/apis/federation"
|
||||||
kubefedtesting "k8s.io/kubernetes/federation/pkg/kubefed/testing"
|
kubefedtesting "k8s.io/kubernetes/federation/pkg/kubefed/testing"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
)
|
)
|
||||||
|
@@ -73,8 +73,6 @@ filegroup(
|
|||||||
"//pkg/client/testing/cache:all-srcs",
|
"//pkg/client/testing/cache:all-srcs",
|
||||||
"//pkg/client/testing/core:all-srcs",
|
"//pkg/client/testing/core:all-srcs",
|
||||||
"//pkg/client/tests:all-srcs",
|
"//pkg/client/tests:all-srcs",
|
||||||
"//pkg/client/typed/discovery:all-srcs",
|
|
||||||
"//pkg/client/typed/dynamic:all-srcs",
|
|
||||||
"//pkg/client/unversioned:all-srcs",
|
"//pkg/client/unversioned:all-srcs",
|
||||||
"//pkg/cloudprovider:all-srcs",
|
"//pkg/cloudprovider:all-srcs",
|
||||||
"//pkg/controller:all-srcs",
|
"//pkg/controller:all-srcs",
|
||||||
|
@@ -41,8 +41,8 @@ go_library(
|
|||||||
"//pkg/client/clientset_generated/clientset/typed/rbac/v1alpha1:go_default_library",
|
"//pkg/client/clientset_generated/clientset/typed/rbac/v1alpha1:go_default_library",
|
||||||
"//pkg/client/clientset_generated/clientset/typed/rbac/v1beta1:go_default_library",
|
"//pkg/client/clientset_generated/clientset/typed/rbac/v1beta1:go_default_library",
|
||||||
"//pkg/client/clientset_generated/clientset/typed/storage/v1beta1:go_default_library",
|
"//pkg/client/clientset_generated/clientset/typed/storage/v1beta1:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/util/flowcontrol",
|
"//vendor:k8s.io/client-go/util/flowcontrol",
|
||||||
|
@@ -18,6 +18,7 @@ package clientset
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
discovery "k8s.io/client-go/discovery"
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
"k8s.io/client-go/util/flowcontrol"
|
||||||
@@ -34,7 +35,6 @@ import (
|
|||||||
v1alpha1rbac "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/rbac/v1alpha1"
|
v1alpha1rbac "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/rbac/v1alpha1"
|
||||||
v1beta1rbac "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/rbac/v1beta1"
|
v1beta1rbac "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/rbac/v1beta1"
|
||||||
v1beta1storage "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/storage/v1beta1"
|
v1beta1storage "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/storage/v1beta1"
|
||||||
discovery "k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
|
@@ -44,10 +44,10 @@ go_library(
|
|||||||
"//pkg/client/clientset_generated/clientset/typed/storage/v1beta1:go_default_library",
|
"//pkg/client/clientset_generated/clientset/typed/storage/v1beta1:go_default_library",
|
||||||
"//pkg/client/clientset_generated/clientset/typed/storage/v1beta1/fake:go_default_library",
|
"//pkg/client/clientset_generated/clientset/typed/storage/v1beta1/fake:go_default_library",
|
||||||
"//pkg/client/testing/core:go_default_library",
|
"//pkg/client/testing/core:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/discovery/fake:go_default_library",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/discovery/fake",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -19,6 +19,8 @@ package fake
|
|||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
v1beta1apps "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/apps/v1beta1"
|
v1beta1apps "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/apps/v1beta1"
|
||||||
@@ -48,8 +50,6 @@ import (
|
|||||||
v1beta1storage "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/storage/v1beta1"
|
v1beta1storage "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/storage/v1beta1"
|
||||||
fakev1beta1storage "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/storage/v1beta1/fake"
|
fakev1beta1storage "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/storage/v1beta1/fake"
|
||||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
"k8s.io/kubernetes/pkg/client/testing/core"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
fakediscovery "k8s.io/kubernetes/pkg/client/typed/discovery/fake"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||||
|
@@ -40,8 +40,8 @@ go_library(
|
|||||||
"//pkg/client/clientset_generated/internalclientset/typed/policy/internalversion:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset/typed/policy/internalversion:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/storage/internalversion:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset/typed/storage/internalversion:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/util/flowcontrol",
|
"//vendor:k8s.io/client-go/util/flowcontrol",
|
||||||
|
@@ -18,6 +18,7 @@ package internalclientset
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
discovery "k8s.io/client-go/discovery"
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
rest "k8s.io/client-go/rest"
|
rest "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
"k8s.io/client-go/util/flowcontrol"
|
||||||
@@ -32,7 +33,6 @@ import (
|
|||||||
internalversionpolicy "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion"
|
internalversionpolicy "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/policy/internalversion"
|
||||||
internalversionrbac "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
internalversionrbac "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||||
internalversionstorage "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion"
|
internalversionstorage "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion"
|
||||||
discovery "k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
|
@@ -40,10 +40,10 @@ go_library(
|
|||||||
"//pkg/client/clientset_generated/internalclientset/typed/storage/internalversion:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset/typed/storage/internalversion:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake:go_default_library",
|
||||||
"//pkg/client/testing/core:go_default_library",
|
"//pkg/client/testing/core:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/discovery/fake:go_default_library",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/discovery/fake",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -19,6 +19,8 @@ package fake
|
|||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
internalversionapps "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion"
|
internalversionapps "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/apps/internalversion"
|
||||||
@@ -44,8 +46,6 @@ import (
|
|||||||
internalversionstorage "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion"
|
internalversionstorage "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion"
|
||||||
fakeinternalversionstorage "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake"
|
fakeinternalversionstorage "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/storage/internalversion/fake"
|
||||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
"k8s.io/kubernetes/pkg/client/testing/core"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
fakediscovery "k8s.io/kubernetes/pkg/client/typed/discovery/fake"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||||
|
@@ -1,15 +0,0 @@
|
|||||||
reviewers:
|
|
||||||
- smarterclayton
|
|
||||||
- wojtek-t
|
|
||||||
- deads2k
|
|
||||||
- derekwaynecarr
|
|
||||||
- caesarxuchao
|
|
||||||
- nikhiljindal
|
|
||||||
- soltysh
|
|
||||||
- piosz
|
|
||||||
- hongchaodeng
|
|
||||||
- krousey
|
|
||||||
- jdef
|
|
||||||
- jessfraz
|
|
||||||
- pweil-
|
|
||||||
- goltermann
|
|
@@ -1,79 +0,0 @@
|
|||||||
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 = [
|
|
||||||
"discovery_client.go",
|
|
||||||
"helper.go",
|
|
||||||
"restmapper.go",
|
|
||||||
"unstructured.go",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
deps = [
|
|
||||||
"//pkg/api:go_default_library",
|
|
||||||
"//pkg/api/v1:go_default_library",
|
|
||||||
"//pkg/version:go_default_library",
|
|
||||||
"//vendor:github.com/emicklei/go-restful/swagger",
|
|
||||||
"//vendor:github.com/golang/glog",
|
|
||||||
"//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/runtime",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/version",
|
|
||||||
"//vendor:k8s.io/client-go/plugin/pkg/client/auth",
|
|
||||||
"//vendor:k8s.io/client-go/rest",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_test(
|
|
||||||
name = "go_default_xtest",
|
|
||||||
srcs = [
|
|
||||||
"discovery_client_test.go",
|
|
||||||
"helper_blackbox_test.go",
|
|
||||||
"restmapper_test.go",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
deps = [
|
|
||||||
"//pkg/api:go_default_library",
|
|
||||||
"//pkg/api/testapi:go_default_library",
|
|
||||||
"//pkg/api/v1:go_default_library",
|
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//vendor:github.com/emicklei/go-restful/swagger",
|
|
||||||
"//vendor:github.com/stretchr/testify/assert",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
|
||||||
"//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/sets",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/version",
|
|
||||||
"//vendor:k8s.io/client-go/rest",
|
|
||||||
"//vendor:k8s.io/client-go/rest/fake",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [
|
|
||||||
":package-srcs",
|
|
||||||
"//pkg/client/typed/discovery/fake:all-srcs",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
)
|
|
@@ -1,437 +0,0 @@
|
|||||||
/*
|
|
||||||
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 discovery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/emicklei/go-restful/swagger"
|
|
||||||
|
|
||||||
"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/runtime/serializer"
|
|
||||||
"k8s.io/apimachinery/pkg/version"
|
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// defaultRetries is the number of times a resource discovery is repeated if an api group disappears on the fly (e.g. ThirdPartyResources).
|
|
||||||
const defaultRetries = 2
|
|
||||||
|
|
||||||
// DiscoveryInterface holds the methods that discover server-supported API groups,
|
|
||||||
// versions and resources.
|
|
||||||
type DiscoveryInterface interface {
|
|
||||||
RESTClient() restclient.Interface
|
|
||||||
ServerGroupsInterface
|
|
||||||
ServerResourcesInterface
|
|
||||||
ServerVersionInterface
|
|
||||||
SwaggerSchemaInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
// CachedDiscoveryInterface is a DiscoveryInterface with cache invalidation and freshness.
|
|
||||||
type CachedDiscoveryInterface interface {
|
|
||||||
DiscoveryInterface
|
|
||||||
// Fresh returns true if no cached data was used that had been retrieved before the instantiation.
|
|
||||||
Fresh() bool
|
|
||||||
// Invalidate enforces that no cached data is used in the future that is older than the current time.
|
|
||||||
Invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerGroupsInterface has methods for obtaining supported groups on the API server
|
|
||||||
type ServerGroupsInterface interface {
|
|
||||||
// ServerGroups returns the supported groups, with information like supported versions and the
|
|
||||||
// preferred version.
|
|
||||||
ServerGroups() (*metav1.APIGroupList, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerResourcesInterface has methods for obtaining supported resources on the API server
|
|
||||||
type ServerResourcesInterface interface {
|
|
||||||
// ServerResourcesForGroupVersion returns the supported resources for a group and version.
|
|
||||||
ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error)
|
|
||||||
// ServerResources returns the supported resources for all groups and versions.
|
|
||||||
ServerResources() ([]*metav1.APIResourceList, error)
|
|
||||||
// ServerPreferredResources returns the supported resources with the version preferred by the
|
|
||||||
// server.
|
|
||||||
ServerPreferredResources() ([]*metav1.APIResourceList, error)
|
|
||||||
// ServerPreferredNamespacedResources returns the supported namespaced resources with the
|
|
||||||
// version preferred by the server.
|
|
||||||
ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerVersionInterface has a method for retrieving the server's version.
|
|
||||||
type ServerVersionInterface interface {
|
|
||||||
// ServerVersion retrieves and parses the server's version (git version).
|
|
||||||
ServerVersion() (*version.Info, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwaggerSchemaInterface has a method to retrieve the swagger schema.
|
|
||||||
type SwaggerSchemaInterface interface {
|
|
||||||
// SwaggerSchema retrieves and parses the swagger API schema the server supports.
|
|
||||||
SwaggerSchema(version schema.GroupVersion) (*swagger.ApiDeclaration, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DiscoveryClient implements the functions that discover server-supported API groups,
|
|
||||||
// versions and resources.
|
|
||||||
type DiscoveryClient struct {
|
|
||||||
restClient restclient.Interface
|
|
||||||
|
|
||||||
LegacyPrefix string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert metav1.APIVersions to metav1.APIGroup. APIVersions is used by legacy v1, so
|
|
||||||
// group would be "".
|
|
||||||
func apiVersionsToAPIGroup(apiVersions *metav1.APIVersions) (apiGroup metav1.APIGroup) {
|
|
||||||
groupVersions := []metav1.GroupVersionForDiscovery{}
|
|
||||||
for _, version := range apiVersions.Versions {
|
|
||||||
groupVersion := metav1.GroupVersionForDiscovery{
|
|
||||||
GroupVersion: version,
|
|
||||||
Version: version,
|
|
||||||
}
|
|
||||||
groupVersions = append(groupVersions, groupVersion)
|
|
||||||
}
|
|
||||||
apiGroup.Versions = groupVersions
|
|
||||||
// There should be only one groupVersion returned at /api
|
|
||||||
apiGroup.PreferredVersion = groupVersions[0]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerGroups returns the supported groups, with information like supported versions and the
|
|
||||||
// preferred version.
|
|
||||||
func (d *DiscoveryClient) ServerGroups() (apiGroupList *metav1.APIGroupList, err error) {
|
|
||||||
// Get the groupVersions exposed at /api
|
|
||||||
v := &metav1.APIVersions{}
|
|
||||||
err = d.restClient.Get().AbsPath(d.LegacyPrefix).Do().Into(v)
|
|
||||||
apiGroup := metav1.APIGroup{}
|
|
||||||
if err == nil {
|
|
||||||
apiGroup = apiVersionsToAPIGroup(v)
|
|
||||||
}
|
|
||||||
if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the groupVersions exposed at /apis
|
|
||||||
apiGroupList = &metav1.APIGroupList{}
|
|
||||||
err = d.restClient.Get().AbsPath("/apis").Do().Into(apiGroupList)
|
|
||||||
if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// to be compatible with a v1.0 server, if it's a 403 or 404, ignore and return whatever we got from /api
|
|
||||||
if err != nil && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
|
|
||||||
apiGroupList = &metav1.APIGroupList{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// append the group retrieved from /api to the list
|
|
||||||
apiGroupList.Groups = append(apiGroupList.Groups, apiGroup)
|
|
||||||
return apiGroupList, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerResourcesForGroupVersion returns the supported resources for a group and version.
|
|
||||||
func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (resources *metav1.APIResourceList, err error) {
|
|
||||||
url := url.URL{}
|
|
||||||
if len(groupVersion) == 0 {
|
|
||||||
return nil, fmt.Errorf("groupVersion shouldn't be empty")
|
|
||||||
}
|
|
||||||
if len(d.LegacyPrefix) > 0 && groupVersion == "v1" {
|
|
||||||
url.Path = d.LegacyPrefix + "/" + groupVersion
|
|
||||||
} else {
|
|
||||||
url.Path = "/apis/" + groupVersion
|
|
||||||
}
|
|
||||||
resources = &metav1.APIResourceList{
|
|
||||||
GroupVersion: groupVersion,
|
|
||||||
}
|
|
||||||
err = d.restClient.Get().AbsPath(url.String()).Do().Into(resources)
|
|
||||||
if err != nil {
|
|
||||||
// ignore 403 or 404 error to be compatible with an v1.0 server.
|
|
||||||
if groupVersion == "v1" && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
|
|
||||||
return resources, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return resources, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// serverResources returns the supported resources for all groups and versions.
|
|
||||||
func (d *DiscoveryClient) serverResources(failEarly bool) ([]*metav1.APIResourceList, error) {
|
|
||||||
apiGroups, err := d.ServerGroups()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := []*metav1.APIResourceList{}
|
|
||||||
failedGroups := make(map[schema.GroupVersion]error)
|
|
||||||
|
|
||||||
for _, apiGroup := range apiGroups.Groups {
|
|
||||||
for _, version := range apiGroup.Versions {
|
|
||||||
gv := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version}
|
|
||||||
resources, err := d.ServerResourcesForGroupVersion(version.GroupVersion)
|
|
||||||
if err != nil {
|
|
||||||
// TODO: maybe restrict this to NotFound errors
|
|
||||||
failedGroups[gv] = err
|
|
||||||
if failEarly {
|
|
||||||
return nil, &ErrGroupDiscoveryFailed{Groups: failedGroups}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
result = append(result, resources)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(failedGroups) == 0 {
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, &ErrGroupDiscoveryFailed{Groups: failedGroups}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerResources returns the supported resources for all groups and versions.
|
|
||||||
func (d *DiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) {
|
|
||||||
return withRetries(defaultRetries, d.serverResources)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrGroupDiscoveryFailed is returned if one or more API groups fail to load.
|
|
||||||
type ErrGroupDiscoveryFailed struct {
|
|
||||||
// Groups is a list of the groups that failed to load and the error cause
|
|
||||||
Groups map[schema.GroupVersion]error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface
|
|
||||||
func (e *ErrGroupDiscoveryFailed) Error() string {
|
|
||||||
var groups []string
|
|
||||||
for k, v := range e.Groups {
|
|
||||||
groups = append(groups, fmt.Sprintf("%s: %v", k, v))
|
|
||||||
}
|
|
||||||
sort.Strings(groups)
|
|
||||||
return fmt.Sprintf("unable to retrieve the complete list of server APIs: %s", strings.Join(groups, ", "))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsGroupDiscoveryFailedError returns true if the provided error indicates the server was unable to discover
|
|
||||||
// a complete list of APIs for the client to use.
|
|
||||||
func IsGroupDiscoveryFailedError(err error) bool {
|
|
||||||
_, ok := err.(*ErrGroupDiscoveryFailed)
|
|
||||||
return err != nil && ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// serverPreferredResources returns the supported resources with the version preferred by the server.
|
|
||||||
func (d *DiscoveryClient) serverPreferredResources(failEarly bool) ([]*metav1.APIResourceList, error) {
|
|
||||||
serverGroupList, err := d.ServerGroups()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result := []*metav1.APIResourceList{}
|
|
||||||
failedGroups := make(map[schema.GroupVersion]error)
|
|
||||||
|
|
||||||
grVersions := map[schema.GroupResource]string{} // selected version of a GroupResource
|
|
||||||
grApiResources := map[schema.GroupResource]*metav1.APIResource{} // selected APIResource for a GroupResource
|
|
||||||
gvApiResourceLists := map[schema.GroupVersion]*metav1.APIResourceList{} // blueprint for a APIResourceList for later grouping
|
|
||||||
|
|
||||||
for _, apiGroup := range serverGroupList.Groups {
|
|
||||||
for _, version := range apiGroup.Versions {
|
|
||||||
groupVersion := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version}
|
|
||||||
apiResourceList, err := d.ServerResourcesForGroupVersion(version.GroupVersion)
|
|
||||||
if err != nil {
|
|
||||||
// TODO: maybe restrict this to NotFound errors
|
|
||||||
failedGroups[groupVersion] = err
|
|
||||||
if failEarly {
|
|
||||||
return nil, &ErrGroupDiscoveryFailed{Groups: failedGroups}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// create empty list which is filled later in another loop
|
|
||||||
emptyApiResourceList := metav1.APIResourceList{
|
|
||||||
GroupVersion: version.GroupVersion,
|
|
||||||
}
|
|
||||||
gvApiResourceLists[groupVersion] = &emptyApiResourceList
|
|
||||||
result = append(result, &emptyApiResourceList)
|
|
||||||
|
|
||||||
for i := range apiResourceList.APIResources {
|
|
||||||
apiResource := &apiResourceList.APIResources[i]
|
|
||||||
if strings.Contains(apiResource.Name, "/") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
gv := schema.GroupResource{Group: apiGroup.Name, Resource: apiResource.Name}
|
|
||||||
if _, ok := grApiResources[gv]; ok && version.Version != apiGroup.PreferredVersion.Version {
|
|
||||||
// only override with preferred version
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
grVersions[gv] = version.Version
|
|
||||||
grApiResources[gv] = apiResource
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// group selected APIResources according to GroupVersion into APIResourceLists
|
|
||||||
for groupResource, apiResource := range grApiResources {
|
|
||||||
version := grVersions[groupResource]
|
|
||||||
groupVersion := schema.GroupVersion{Group: groupResource.Group, Version: version}
|
|
||||||
apiResourceList := gvApiResourceLists[groupVersion]
|
|
||||||
apiResourceList.APIResources = append(apiResourceList.APIResources, *apiResource)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(failedGroups) == 0 {
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, &ErrGroupDiscoveryFailed{Groups: failedGroups}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerPreferredResources returns the supported resources with the version preferred by the
|
|
||||||
// server.
|
|
||||||
func (d *DiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
|
|
||||||
return withRetries(defaultRetries, func(retryEarly bool) ([]*metav1.APIResourceList, error) {
|
|
||||||
return d.serverPreferredResources(retryEarly)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerPreferredNamespacedResources returns the supported namespaced resources with the
|
|
||||||
// version preferred by the server.
|
|
||||||
func (d *DiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
|
|
||||||
all, err := d.ServerPreferredResources()
|
|
||||||
return FilteredBy(ResourcePredicateFunc(func(groupVersion string, r *metav1.APIResource) bool {
|
|
||||||
return r.Namespaced
|
|
||||||
}), all), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServerVersion retrieves and parses the server's version (git version).
|
|
||||||
func (d *DiscoveryClient) ServerVersion() (*version.Info, error) {
|
|
||||||
body, err := d.restClient.Get().AbsPath("/version").Do().Raw()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var info version.Info
|
|
||||||
err = json.Unmarshal(body, &info)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("got '%s': %v", string(body), err)
|
|
||||||
}
|
|
||||||
return &info, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwaggerSchema retrieves and parses the swagger API schema the server supports.
|
|
||||||
func (d *DiscoveryClient) SwaggerSchema(version schema.GroupVersion) (*swagger.ApiDeclaration, error) {
|
|
||||||
if version.Empty() {
|
|
||||||
return nil, fmt.Errorf("groupVersion cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
groupList, err := d.ServerGroups()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
groupVersions := metav1.ExtractGroupVersions(groupList)
|
|
||||||
// This check also takes care the case that kubectl is newer than the running endpoint
|
|
||||||
if stringDoesntExistIn(version.String(), groupVersions) {
|
|
||||||
return nil, fmt.Errorf("API version: %v is not supported by the server. Use one of: %v", version, groupVersions)
|
|
||||||
}
|
|
||||||
var path string
|
|
||||||
if len(d.LegacyPrefix) > 0 && version == v1.SchemeGroupVersion {
|
|
||||||
path = "/swaggerapi" + d.LegacyPrefix + "/" + version.Version
|
|
||||||
} else {
|
|
||||||
path = "/swaggerapi/apis/" + version.Group + "/" + version.Version
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := d.restClient.Get().AbsPath(path).Do().Raw()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var schema swagger.ApiDeclaration
|
|
||||||
err = json.Unmarshal(body, &schema)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("got '%s': %v", string(body), err)
|
|
||||||
}
|
|
||||||
return &schema, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// withRetries retries the given recovery function in case the groups supported by the server change after ServerGroup() returns.
|
|
||||||
func withRetries(maxRetries int, f func(failEarly bool) ([]*metav1.APIResourceList, error)) ([]*metav1.APIResourceList, error) {
|
|
||||||
var result []*metav1.APIResourceList
|
|
||||||
var err error
|
|
||||||
for i := 0; i < maxRetries; i++ {
|
|
||||||
failEarly := i < maxRetries-1
|
|
||||||
result, err = f(failEarly)
|
|
||||||
if err == nil {
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
if _, ok := err.(*ErrGroupDiscoveryFailed); !ok {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func setDiscoveryDefaults(config *restclient.Config) error {
|
|
||||||
config.APIPath = ""
|
|
||||||
config.GroupVersion = nil
|
|
||||||
codec := runtime.NoopEncoder{Decoder: api.Codecs.UniversalDecoder()}
|
|
||||||
config.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})
|
|
||||||
if len(config.UserAgent) == 0 {
|
|
||||||
config.UserAgent = restclient.DefaultKubernetesUserAgent()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDiscoveryClientForConfig creates a new DiscoveryClient for the given config. This client
|
|
||||||
// can be used to discover supported resources in the API server.
|
|
||||||
func NewDiscoveryClientForConfig(c *restclient.Config) (*DiscoveryClient, error) {
|
|
||||||
config := *c
|
|
||||||
if err := setDiscoveryDefaults(&config); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
client, err := restclient.UnversionedRESTClientFor(&config)
|
|
||||||
return &DiscoveryClient{restClient: client, LegacyPrefix: "/api"}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDiscoveryClientForConfig creates a new DiscoveryClient for the given config. If
|
|
||||||
// there is an error, it panics.
|
|
||||||
func NewDiscoveryClientForConfigOrDie(c *restclient.Config) *DiscoveryClient {
|
|
||||||
client, err := NewDiscoveryClientForConfig(c)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return client
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new DiscoveryClient for the given RESTClient.
|
|
||||||
func NewDiscoveryClient(c restclient.Interface) *DiscoveryClient {
|
|
||||||
return &DiscoveryClient{restClient: c, LegacyPrefix: "/api"}
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringDoesntExistIn(str string, slice []string) bool {
|
|
||||||
for _, s := range slice {
|
|
||||||
if s == str {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// RESTClient returns a RESTClient that is used to communicate
|
|
||||||
// with API server by this client implementation.
|
|
||||||
func (c *DiscoveryClient) RESTClient() restclient.Interface {
|
|
||||||
if c == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return c.restClient
|
|
||||||
}
|
|
@@ -1,740 +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 discovery_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/emicklei/go-restful/swagger"
|
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
|
||||||
"k8s.io/apimachinery/pkg/version"
|
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
. "k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetServerVersion(t *testing.T) {
|
|
||||||
expect := version.Info{
|
|
||||||
Major: "foo",
|
|
||||||
Minor: "bar",
|
|
||||||
GitCommit: "baz",
|
|
||||||
}
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
output, err := json.Marshal(expect)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
|
||||||
|
|
||||||
got, err := client.ServerVersion()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected encoding error: %v", err)
|
|
||||||
}
|
|
||||||
if e, a := expect, *got; !reflect.DeepEqual(e, a) {
|
|
||||||
t.Errorf("expected %v, got %v", e, a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetServerGroupsWithV1Server(t *testing.T) {
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
var obj interface{}
|
|
||||||
switch req.URL.Path {
|
|
||||||
case "/api":
|
|
||||||
obj = &metav1.APIVersions{
|
|
||||||
Versions: []string{
|
|
||||||
"v1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
output, err := json.Marshal(obj)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected encoding error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
|
||||||
// ServerGroups should not return an error even if server returns error at /api and /apis
|
|
||||||
apiGroupList, err := client.ServerGroups()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
groupVersions := metav1.ExtractGroupVersions(apiGroupList)
|
|
||||||
if !reflect.DeepEqual(groupVersions, []string{"v1"}) {
|
|
||||||
t.Errorf("expected: %q, got: %q", []string{"v1"}, groupVersions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetServerGroupsWithBrokenServer(t *testing.T) {
|
|
||||||
for _, statusCode := range []int{http.StatusNotFound, http.StatusForbidden} {
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
w.WriteHeader(statusCode)
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
|
||||||
// ServerGroups should not return an error even if server returns Not Found or Forbidden error at all end points
|
|
||||||
apiGroupList, err := client.ServerGroups()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
groupVersions := metav1.ExtractGroupVersions(apiGroupList)
|
|
||||||
if len(groupVersions) != 0 {
|
|
||||||
t.Errorf("expected empty list, got: %q", groupVersions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetServerResourcesWithV1Server(t *testing.T) {
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
var obj interface{}
|
|
||||||
switch req.URL.Path {
|
|
||||||
case "/api":
|
|
||||||
obj = &metav1.APIVersions{
|
|
||||||
Versions: []string{
|
|
||||||
"v1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
output, err := json.Marshal(obj)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
|
||||||
// ServerResources should not return an error even if server returns error at /api/v1.
|
|
||||||
serverResources, err := client.ServerResources()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
gvs := groupVersions(serverResources)
|
|
||||||
if !sets.NewString(gvs...).Has("v1") {
|
|
||||||
t.Errorf("missing v1 in resource list: %v", serverResources)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetServerResources(t *testing.T) {
|
|
||||||
stable := metav1.APIResourceList{
|
|
||||||
GroupVersion: "v1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "pods", Namespaced: true, Kind: "Pod"},
|
|
||||||
{Name: "services", Namespaced: true, Kind: "Service"},
|
|
||||||
{Name: "namespaces", Namespaced: false, Kind: "Namespace"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
beta := metav1.APIResourceList{
|
|
||||||
GroupVersion: "extensions/v1beta1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "deployments", Namespaced: true, Kind: "Deployment"},
|
|
||||||
{Name: "ingresses", Namespaced: true, Kind: "Ingress"},
|
|
||||||
{Name: "jobs", Namespaced: true, Kind: "Job"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
resourcesList *metav1.APIResourceList
|
|
||||||
path string
|
|
||||||
request string
|
|
||||||
expectErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
resourcesList: &stable,
|
|
||||||
path: "/api/v1",
|
|
||||||
request: "v1",
|
|
||||||
expectErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resourcesList: &beta,
|
|
||||||
path: "/apis/extensions/v1beta1",
|
|
||||||
request: "extensions/v1beta1",
|
|
||||||
expectErr: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resourcesList: &stable,
|
|
||||||
path: "/api/v1",
|
|
||||||
request: "foobar",
|
|
||||||
expectErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
var list interface{}
|
|
||||||
switch req.URL.Path {
|
|
||||||
case "/api/v1":
|
|
||||||
list = &stable
|
|
||||||
case "/apis/extensions/v1beta1":
|
|
||||||
list = &beta
|
|
||||||
case "/api":
|
|
||||||
list = &metav1.APIVersions{
|
|
||||||
Versions: []string{
|
|
||||||
"v1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
case "/apis":
|
|
||||||
list = &metav1.APIGroupList{
|
|
||||||
Groups: []metav1.APIGroup{
|
|
||||||
{
|
|
||||||
Versions: []metav1.GroupVersionForDiscovery{
|
|
||||||
{GroupVersion: "extensions/v1beta1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
t.Logf("unexpected request: %s", req.URL.Path)
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
output, err := json.Marshal(list)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
|
||||||
for _, test := range tests {
|
|
||||||
got, err := client.ServerResourcesForGroupVersion(test.request)
|
|
||||||
if test.expectErr {
|
|
||||||
if err == nil {
|
|
||||||
t.Error("unexpected non-error")
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(got, test.resourcesList) {
|
|
||||||
t.Errorf("expected:\n%v\ngot:\n%v\n", test.resourcesList, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
serverResources, err := client.ServerResources()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
serverGroupVersions := sets.NewString(groupVersions(serverResources)...)
|
|
||||||
for _, api := range []string{"v1", "extensions/v1beta1"} {
|
|
||||||
if !serverGroupVersions.Has(api) {
|
|
||||||
t.Errorf("missing expected api %q in %v", api, serverResources)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func swaggerSchemaFakeServer() (*httptest.Server, error) {
|
|
||||||
request := 1
|
|
||||||
var sErr error
|
|
||||||
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
var resp interface{}
|
|
||||||
if request == 1 {
|
|
||||||
resp = metav1.APIVersions{Versions: []string{"v1", "v2", "v3"}}
|
|
||||||
request++
|
|
||||||
} else {
|
|
||||||
resp = swagger.ApiDeclaration{}
|
|
||||||
}
|
|
||||||
output, err := json.Marshal(resp)
|
|
||||||
if err != nil {
|
|
||||||
sErr = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
}))
|
|
||||||
return server, sErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetSwaggerSchema(t *testing.T) {
|
|
||||||
expect := swagger.ApiDeclaration{}
|
|
||||||
|
|
||||||
server, err := swaggerSchemaFakeServer()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
}
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
|
||||||
got, err := client.SwaggerSchema(v1.SchemeGroupVersion)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected encoding error: %v", err)
|
|
||||||
}
|
|
||||||
if e, a := expect, *got; !reflect.DeepEqual(e, a) {
|
|
||||||
t.Errorf("expected %v, got %v", e, a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetSwaggerSchemaFail(t *testing.T) {
|
|
||||||
expErr := "API version: api.group/v4 is not supported by the server. Use one of: [v1 v2 v3]"
|
|
||||||
|
|
||||||
server, err := swaggerSchemaFakeServer()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
}
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
|
||||||
got, err := client.SwaggerSchema(schema.GroupVersion{Group: "api.group", Version: "v4"})
|
|
||||||
if got != nil {
|
|
||||||
t.Fatalf("unexpected response: %v", got)
|
|
||||||
}
|
|
||||||
if err.Error() != expErr {
|
|
||||||
t.Errorf("expected an error, got %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestServerPreferredResources(t *testing.T) {
|
|
||||||
stable := metav1.APIResourceList{
|
|
||||||
GroupVersion: "v1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "pods", Namespaced: true, Kind: "Pod"},
|
|
||||||
{Name: "services", Namespaced: true, Kind: "Service"},
|
|
||||||
{Name: "namespaces", Namespaced: false, Kind: "Namespace"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
resourcesList []*metav1.APIResourceList
|
|
||||||
response func(w http.ResponseWriter, req *http.Request)
|
|
||||||
expectErr func(err error) bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
resourcesList: []*metav1.APIResourceList{&stable},
|
|
||||||
expectErr: IsGroupDiscoveryFailedError,
|
|
||||||
response: func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
var list interface{}
|
|
||||||
switch req.URL.Path {
|
|
||||||
case "/apis/extensions/v1beta1":
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
case "/api/v1":
|
|
||||||
list = &stable
|
|
||||||
case "/api":
|
|
||||||
list = &metav1.APIVersions{
|
|
||||||
Versions: []string{
|
|
||||||
"v1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
case "/apis":
|
|
||||||
list = &metav1.APIGroupList{
|
|
||||||
Groups: []metav1.APIGroup{
|
|
||||||
{
|
|
||||||
Versions: []metav1.GroupVersionForDiscovery{
|
|
||||||
{GroupVersion: "extensions/v1beta1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
t.Logf("unexpected request: %s", req.URL.Path)
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
output, err := json.Marshal(list)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
resourcesList: nil,
|
|
||||||
expectErr: IsGroupDiscoveryFailedError,
|
|
||||||
response: func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
var list interface{}
|
|
||||||
switch req.URL.Path {
|
|
||||||
case "/apis/extensions/v1beta1":
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
case "/api/v1":
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
case "/api":
|
|
||||||
list = &metav1.APIVersions{
|
|
||||||
Versions: []string{
|
|
||||||
"v1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
case "/apis":
|
|
||||||
list = &metav1.APIGroupList{
|
|
||||||
Groups: []metav1.APIGroup{
|
|
||||||
{
|
|
||||||
Versions: []metav1.GroupVersionForDiscovery{
|
|
||||||
{GroupVersion: "extensions/v1beta1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
t.Logf("unexpected request: %s", req.URL.Path)
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
output, err := json.Marshal(list)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(test.response))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
|
||||||
resources, err := client.ServerPreferredResources()
|
|
||||||
if test.expectErr != nil {
|
|
||||||
if err == nil {
|
|
||||||
t.Error("unexpected non-error")
|
|
||||||
}
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
got, err := GroupVersionResources(resources)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
expected, _ := GroupVersionResources(test.resourcesList)
|
|
||||||
if !reflect.DeepEqual(got, expected) {
|
|
||||||
t.Errorf("expected:\n%v\ngot:\n%v\n", test.resourcesList, got)
|
|
||||||
}
|
|
||||||
server.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestServerPreferredResourcesRetries(t *testing.T) {
|
|
||||||
stable := metav1.APIResourceList{
|
|
||||||
GroupVersion: "v1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "pods", Namespaced: true, Kind: "Pod"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
beta := metav1.APIResourceList{
|
|
||||||
GroupVersion: "extensions/v1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "deployments", Namespaced: true, Kind: "Deployment"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
response := func(numErrors int) http.HandlerFunc {
|
|
||||||
var i = 0
|
|
||||||
return func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
var list interface{}
|
|
||||||
switch req.URL.Path {
|
|
||||||
case "/apis/extensions/v1beta1":
|
|
||||||
if i < numErrors {
|
|
||||||
i++
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
list = &beta
|
|
||||||
case "/api/v1":
|
|
||||||
list = &stable
|
|
||||||
case "/api":
|
|
||||||
list = &metav1.APIVersions{
|
|
||||||
Versions: []string{
|
|
||||||
"v1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
case "/apis":
|
|
||||||
list = &metav1.APIGroupList{
|
|
||||||
Groups: []metav1.APIGroup{
|
|
||||||
{
|
|
||||||
Name: "extensions",
|
|
||||||
Versions: []metav1.GroupVersionForDiscovery{
|
|
||||||
{GroupVersion: "extensions/v1beta1"},
|
|
||||||
},
|
|
||||||
PreferredVersion: metav1.GroupVersionForDiscovery{
|
|
||||||
GroupVersion: "extensions/v1beta1",
|
|
||||||
Version: "v1beta1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
t.Logf("unexpected request: %s", req.URL.Path)
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
output, err := json.Marshal(list)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
responseErrors int
|
|
||||||
expectResources int
|
|
||||||
expectedError func(err error) bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
responseErrors: 1,
|
|
||||||
expectResources: 2,
|
|
||||||
expectedError: func(err error) bool {
|
|
||||||
return err == nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
responseErrors: 2,
|
|
||||||
expectResources: 1,
|
|
||||||
expectedError: IsGroupDiscoveryFailedError,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, tc := range tests {
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(response(tc.responseErrors)))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
|
||||||
resources, err := client.ServerPreferredResources()
|
|
||||||
if !tc.expectedError(err) {
|
|
||||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
|
||||||
}
|
|
||||||
got, err := GroupVersionResources(resources)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("case %d: unexpected error: %v", i, err)
|
|
||||||
}
|
|
||||||
if len(got) != tc.expectResources {
|
|
||||||
t.Errorf("case %d: expect %d resources, got %#v", i, tc.expectResources, got)
|
|
||||||
}
|
|
||||||
server.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestServerPreferredNamespacedResources(t *testing.T) {
|
|
||||||
stable := metav1.APIResourceList{
|
|
||||||
GroupVersion: "v1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "pods", Namespaced: true, Kind: "Pod"},
|
|
||||||
{Name: "services", Namespaced: true, Kind: "Service"},
|
|
||||||
{Name: "namespaces", Namespaced: false, Kind: "Namespace"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
batchv1 := metav1.APIResourceList{
|
|
||||||
GroupVersion: "batch/v1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "jobs", Namespaced: true, Kind: "Job"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
batchv2alpha1 := metav1.APIResourceList{
|
|
||||||
GroupVersion: "batch/v2alpha1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "jobs", Namespaced: true, Kind: "Job"},
|
|
||||||
{Name: "cronjobs", Namespaced: true, Kind: "CronJob"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
batchv3alpha1 := metav1.APIResourceList{
|
|
||||||
GroupVersion: "batch/v3alpha1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "jobs", Namespaced: true, Kind: "Job"},
|
|
||||||
{Name: "cronjobs", Namespaced: true, Kind: "CronJob"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
response func(w http.ResponseWriter, req *http.Request)
|
|
||||||
expected map[schema.GroupVersionResource]struct{}
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
response: func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
var list interface{}
|
|
||||||
switch req.URL.Path {
|
|
||||||
case "/api/v1":
|
|
||||||
list = &stable
|
|
||||||
case "/api":
|
|
||||||
list = &metav1.APIVersions{
|
|
||||||
Versions: []string{
|
|
||||||
"v1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
t.Logf("unexpected request: %s", req.URL.Path)
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
output, err := json.Marshal(list)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
},
|
|
||||||
expected: map[schema.GroupVersionResource]struct{}{
|
|
||||||
schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}: {},
|
|
||||||
schema.GroupVersionResource{Group: "", Version: "v1", Resource: "services"}: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
response: func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
var list interface{}
|
|
||||||
switch req.URL.Path {
|
|
||||||
case "/apis":
|
|
||||||
list = &metav1.APIGroupList{
|
|
||||||
Groups: []metav1.APIGroup{
|
|
||||||
{
|
|
||||||
Name: "batch",
|
|
||||||
Versions: []metav1.GroupVersionForDiscovery{
|
|
||||||
{GroupVersion: "batch/v1", Version: "v1"},
|
|
||||||
{GroupVersion: "batch/v2alpha1", Version: "v2alpha1"},
|
|
||||||
{GroupVersion: "batch/v3alpha1", Version: "v3alpha1"},
|
|
||||||
},
|
|
||||||
PreferredVersion: metav1.GroupVersionForDiscovery{GroupVersion: "batch/v1", Version: "v1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
case "/apis/batch/v1":
|
|
||||||
list = &batchv1
|
|
||||||
case "/apis/batch/v2alpha1":
|
|
||||||
list = &batchv2alpha1
|
|
||||||
case "/apis/batch/v3alpha1":
|
|
||||||
list = &batchv3alpha1
|
|
||||||
default:
|
|
||||||
t.Logf("unexpected request: %s", req.URL.Path)
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
output, err := json.Marshal(list)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
},
|
|
||||||
expected: map[schema.GroupVersionResource]struct{}{
|
|
||||||
schema.GroupVersionResource{Group: "batch", Version: "v1", Resource: "jobs"}: {},
|
|
||||||
schema.GroupVersionResource{Group: "batch", Version: "v2alpha1", Resource: "cronjobs"}: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
response: func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
var list interface{}
|
|
||||||
switch req.URL.Path {
|
|
||||||
case "/apis":
|
|
||||||
list = &metav1.APIGroupList{
|
|
||||||
Groups: []metav1.APIGroup{
|
|
||||||
{
|
|
||||||
Name: "batch",
|
|
||||||
Versions: []metav1.GroupVersionForDiscovery{
|
|
||||||
{GroupVersion: "batch/v1", Version: "v1"},
|
|
||||||
{GroupVersion: "batch/v2alpha1", Version: "v2alpha1"},
|
|
||||||
{GroupVersion: "batch/v3alpha1", Version: "v3alpha1"},
|
|
||||||
},
|
|
||||||
PreferredVersion: metav1.GroupVersionForDiscovery{GroupVersion: "batch/v2alpha", Version: "v2alpha1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
case "/apis/batch/v1":
|
|
||||||
list = &batchv1
|
|
||||||
case "/apis/batch/v2alpha1":
|
|
||||||
list = &batchv2alpha1
|
|
||||||
case "/apis/batch/v3alpha1":
|
|
||||||
list = &batchv3alpha1
|
|
||||||
default:
|
|
||||||
t.Logf("unexpected request: %s", req.URL.Path)
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
output, err := json.Marshal(list)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected encoding error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write(output)
|
|
||||||
},
|
|
||||||
expected: map[schema.GroupVersionResource]struct{}{
|
|
||||||
schema.GroupVersionResource{Group: "batch", Version: "v2alpha1", Resource: "jobs"}: {},
|
|
||||||
schema.GroupVersionResource{Group: "batch", Version: "v2alpha1", Resource: "cronjobs"}: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for i, test := range tests {
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(test.response))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
|
|
||||||
resources, err := client.ServerPreferredNamespacedResources()
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("[%d] unexpected error: %v", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
got, err := GroupVersionResources(resources)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("[%d] unexpected error: %v", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(got, test.expected) {
|
|
||||||
t.Errorf("[%d] expected:\n%v\ngot:\n%v\n", i, test.expected, got)
|
|
||||||
}
|
|
||||||
server.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func groupVersions(resources []*metav1.APIResourceList) []string {
|
|
||||||
result := []string{}
|
|
||||||
for _, resourceList := range resources {
|
|
||||||
result = append(result, resourceList.GroupVersion)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
@@ -1,37 +0,0 @@
|
|||||||
package(default_visibility = ["//visibility:public"])
|
|
||||||
|
|
||||||
licenses(["notice"])
|
|
||||||
|
|
||||||
load(
|
|
||||||
"@io_bazel_rules_go//go:def.bzl",
|
|
||||||
"go_library",
|
|
||||||
)
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "go_default_library",
|
|
||||||
srcs = ["discovery.go"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
deps = [
|
|
||||||
"//pkg/api/v1:go_default_library",
|
|
||||||
"//pkg/client/testing/core:go_default_library",
|
|
||||||
"//pkg/version:go_default_library",
|
|
||||||
"//vendor:github.com/emicklei/go-restful/swagger",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/version",
|
|
||||||
"//vendor:k8s.io/client-go/rest",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
)
|
|
@@ -1,97 +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 fake
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/emicklei/go-restful/swagger"
|
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/version"
|
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
|
||||||
kubeversion "k8s.io/kubernetes/pkg/version"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FakeDiscovery struct {
|
|
||||||
*core.Fake
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) {
|
|
||||||
action := core.ActionImpl{
|
|
||||||
Verb: "get",
|
|
||||||
Resource: schema.GroupVersionResource{Resource: "resource"},
|
|
||||||
}
|
|
||||||
c.Invokes(action, nil)
|
|
||||||
for _, resourceList := range c.Resources {
|
|
||||||
if resourceList.GroupVersion == groupVersion {
|
|
||||||
return resourceList, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("GroupVersion %q not found", groupVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *FakeDiscovery) ServerResources() ([]*metav1.APIResourceList, error) {
|
|
||||||
action := core.ActionImpl{
|
|
||||||
Verb: "get",
|
|
||||||
Resource: schema.GroupVersionResource{Resource: "resource"},
|
|
||||||
}
|
|
||||||
c.Invokes(action, nil)
|
|
||||||
return c.Resources, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *FakeDiscovery) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *FakeDiscovery) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *FakeDiscovery) ServerGroups() (*metav1.APIGroupList, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *FakeDiscovery) ServerVersion() (*version.Info, error) {
|
|
||||||
action := core.ActionImpl{}
|
|
||||||
action.Verb = "get"
|
|
||||||
action.Resource = schema.GroupVersionResource{Resource: "version"}
|
|
||||||
|
|
||||||
c.Invokes(action, nil)
|
|
||||||
versionInfo := kubeversion.Get()
|
|
||||||
return &versionInfo, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *FakeDiscovery) SwaggerSchema(version schema.GroupVersion) (*swagger.ApiDeclaration, error) {
|
|
||||||
action := core.ActionImpl{}
|
|
||||||
action.Verb = "get"
|
|
||||||
if version == v1.SchemeGroupVersion {
|
|
||||||
action.Resource = schema.GroupVersionResource{Resource: "/swaggerapi/api/" + version.Version}
|
|
||||||
} else {
|
|
||||||
action.Resource = schema.GroupVersionResource{Resource: "/swaggerapi/apis/" + version.Group + "/" + version.Version}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Invokes(action, nil)
|
|
||||||
return &swagger.ApiDeclaration{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *FakeDiscovery) RESTClient() restclient.Interface {
|
|
||||||
return nil
|
|
||||||
}
|
|
@@ -1,162 +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 discovery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
|
||||||
"k8s.io/kubernetes/pkg/version"
|
|
||||||
// Import solely to initialize client auth plugins.
|
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MatchesServerVersion queries the server to compares the build version
|
|
||||||
// (git hash) of the client with the server's build version. It returns an error
|
|
||||||
// if it failed to contact the server or if the versions are not an exact match.
|
|
||||||
func MatchesServerVersion(client DiscoveryInterface) error {
|
|
||||||
cVer := version.Get()
|
|
||||||
sVer, err := client.ServerVersion()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("couldn't read version from server: %v\n", err)
|
|
||||||
}
|
|
||||||
// GitVersion includes GitCommit and GitTreeState, but best to be safe?
|
|
||||||
if cVer.GitVersion != sVer.GitVersion || cVer.GitCommit != sVer.GitCommit || cVer.GitTreeState != sVer.GitTreeState {
|
|
||||||
return fmt.Errorf("server version (%#v) differs from client version (%#v)!\n", sVer, cVer)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NegotiateVersion queries the server's supported api versions to find
|
|
||||||
// a version that both client and server support.
|
|
||||||
// - If no version is provided, try registered client versions in order of
|
|
||||||
// preference.
|
|
||||||
// - If version is provided and the server does not support it,
|
|
||||||
// return an error.
|
|
||||||
func NegotiateVersion(client DiscoveryInterface, requiredGV *schema.GroupVersion, clientRegisteredGVs []schema.GroupVersion) (*schema.GroupVersion, error) {
|
|
||||||
clientVersions := sets.String{}
|
|
||||||
for _, gv := range clientRegisteredGVs {
|
|
||||||
clientVersions.Insert(gv.String())
|
|
||||||
}
|
|
||||||
groups, err := client.ServerGroups()
|
|
||||||
if err != nil {
|
|
||||||
// This is almost always a connection error, and higher level code should treat this as a generic error,
|
|
||||||
// not a negotiation specific error.
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
versions := metav1.ExtractGroupVersions(groups)
|
|
||||||
serverVersions := sets.String{}
|
|
||||||
for _, v := range versions {
|
|
||||||
serverVersions.Insert(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If version explicitly requested verify that both client and server support it.
|
|
||||||
// If server does not support warn, but try to negotiate a lower version.
|
|
||||||
if requiredGV != nil {
|
|
||||||
if !clientVersions.Has(requiredGV.String()) {
|
|
||||||
return nil, fmt.Errorf("client does not support API version %q; client supported API versions: %v", requiredGV, clientVersions)
|
|
||||||
|
|
||||||
}
|
|
||||||
// If the server supports no versions, then we should just use the preferredGV
|
|
||||||
// This can happen because discovery fails due to 403 Forbidden errors
|
|
||||||
if len(serverVersions) == 0 {
|
|
||||||
return requiredGV, nil
|
|
||||||
}
|
|
||||||
if serverVersions.Has(requiredGV.String()) {
|
|
||||||
return requiredGV, nil
|
|
||||||
}
|
|
||||||
// If we are using an explicit config version the server does not support, fail.
|
|
||||||
return nil, fmt.Errorf("server does not support API version %q", requiredGV)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, clientGV := range clientRegisteredGVs {
|
|
||||||
if serverVersions.Has(clientGV.String()) {
|
|
||||||
// Version was not explicitly requested in command config (--api-version).
|
|
||||||
// Ok to fall back to a supported version with a warning.
|
|
||||||
// TODO: caesarxuchao: enable the warning message when we have
|
|
||||||
// proper fix. Please refer to issue #14895.
|
|
||||||
// if len(version) != 0 {
|
|
||||||
// glog.Warningf("Server does not support API version '%s'. Falling back to '%s'.", version, clientVersion)
|
|
||||||
// }
|
|
||||||
t := clientGV
|
|
||||||
return &t, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we have no server versions and we have no required version, choose the first clientRegisteredVersion
|
|
||||||
if len(serverVersions) == 0 && len(clientRegisteredGVs) > 0 {
|
|
||||||
return &clientRegisteredGVs[0], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("failed to negotiate an api version; server supports: %v, client supports: %v",
|
|
||||||
serverVersions, clientVersions)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GroupVersionResources converts APIResourceLists to the GroupVersionResources.
|
|
||||||
func GroupVersionResources(rls []*metav1.APIResourceList) (map[schema.GroupVersionResource]struct{}, error) {
|
|
||||||
gvrs := map[schema.GroupVersionResource]struct{}{}
|
|
||||||
for _, rl := range rls {
|
|
||||||
gv, err := schema.ParseGroupVersion(rl.GroupVersion)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for i := range rl.APIResources {
|
|
||||||
gvrs[schema.GroupVersionResource{Group: gv.Group, Version: gv.Version, Resource: rl.APIResources[i].Name}] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return gvrs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilteredBy filters by the given predicate. Empty APIResourceLists are dropped.
|
|
||||||
func FilteredBy(pred ResourcePredicate, rls []*metav1.APIResourceList) []*metav1.APIResourceList {
|
|
||||||
result := []*metav1.APIResourceList{}
|
|
||||||
for _, rl := range rls {
|
|
||||||
filtered := *rl
|
|
||||||
filtered.APIResources = nil
|
|
||||||
for i := range rl.APIResources {
|
|
||||||
if pred.Match(rl.GroupVersion, &rl.APIResources[i]) {
|
|
||||||
filtered.APIResources = append(filtered.APIResources, rl.APIResources[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if filtered.APIResources != nil {
|
|
||||||
result = append(result, &filtered)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResourcePredicate interface {
|
|
||||||
Match(groupVersion string, r *metav1.APIResource) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResourcePredicateFunc func(groupVersion string, r *metav1.APIResource) bool
|
|
||||||
|
|
||||||
func (fn ResourcePredicateFunc) Match(groupVersion string, r *metav1.APIResource) bool {
|
|
||||||
return fn(groupVersion, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SupportsAllVerbs is a predicate matching a resource iff all given verbs are supported.
|
|
||||||
type SupportsAllVerbs struct {
|
|
||||||
Verbs []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p SupportsAllVerbs) Match(groupVersion string, r *metav1.APIResource) bool {
|
|
||||||
return sets.NewString([]string(r.Verbs)...).HasAll(p.Verbs...)
|
|
||||||
}
|
|
@@ -1,230 +0,0 @@
|
|||||||
/*
|
|
||||||
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 discovery_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
uapi "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
"k8s.io/client-go/rest/fake"
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
|
||||||
|
|
||||||
func objBody(object interface{}) io.ReadCloser {
|
|
||||||
output, err := json.MarshalIndent(object, "", "")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return ioutil.NopCloser(bytes.NewReader([]byte(output)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNegotiateVersion(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
requiredVersion *schema.GroupVersion
|
|
||||||
expectedVersion *schema.GroupVersion
|
|
||||||
serverVersions []string
|
|
||||||
clientVersions []schema.GroupVersion
|
|
||||||
expectErr func(err error) bool
|
|
||||||
sendErr error
|
|
||||||
statusCode int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "server supports client default",
|
|
||||||
serverVersions: []string{"version1", api.Registry.GroupOrDie(api.GroupName).GroupVersion.String()},
|
|
||||||
clientVersions: []schema.GroupVersion{{Version: "version1"}, api.Registry.GroupOrDie(api.GroupName).GroupVersion},
|
|
||||||
expectedVersion: &schema.GroupVersion{Version: "version1"},
|
|
||||||
statusCode: http.StatusOK,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "server falls back to client supported",
|
|
||||||
serverVersions: []string{"version1"},
|
|
||||||
clientVersions: []schema.GroupVersion{{Version: "version1"}, api.Registry.GroupOrDie(api.GroupName).GroupVersion},
|
|
||||||
expectedVersion: &schema.GroupVersion{Version: "version1"},
|
|
||||||
statusCode: http.StatusOK,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "explicit version supported",
|
|
||||||
requiredVersion: &schema.GroupVersion{Version: "v1"},
|
|
||||||
serverVersions: []string{"/version1", api.Registry.GroupOrDie(api.GroupName).GroupVersion.String()},
|
|
||||||
clientVersions: []schema.GroupVersion{{Version: "version1"}, api.Registry.GroupOrDie(api.GroupName).GroupVersion},
|
|
||||||
expectedVersion: &schema.GroupVersion{Version: "v1"},
|
|
||||||
statusCode: http.StatusOK,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "explicit version not supported on server",
|
|
||||||
requiredVersion: &schema.GroupVersion{Version: "v1"},
|
|
||||||
serverVersions: []string{"version1"},
|
|
||||||
clientVersions: []schema.GroupVersion{{Version: "version1"}, api.Registry.GroupOrDie(api.GroupName).GroupVersion},
|
|
||||||
expectErr: func(err error) bool { return strings.Contains(err.Error(), `server does not support API version "v1"`) },
|
|
||||||
statusCode: http.StatusOK,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "explicit version not supported on client",
|
|
||||||
requiredVersion: &schema.GroupVersion{Version: "v1"},
|
|
||||||
serverVersions: []string{"v1"},
|
|
||||||
clientVersions: []schema.GroupVersion{{Version: "version1"}},
|
|
||||||
expectErr: func(err error) bool { return strings.Contains(err.Error(), `client does not support API version "v1"`) },
|
|
||||||
statusCode: http.StatusOK,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "connection refused error",
|
|
||||||
serverVersions: []string{"version1"},
|
|
||||||
clientVersions: []schema.GroupVersion{{Version: "version1"}, api.Registry.GroupOrDie(api.GroupName).GroupVersion},
|
|
||||||
sendErr: errors.New("connection refused"),
|
|
||||||
expectErr: func(err error) bool { return strings.Contains(err.Error(), "connection refused") },
|
|
||||||
statusCode: http.StatusOK,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "discovery fails due to 403 Forbidden errors and thus serverVersions is empty, use default GroupVersion",
|
|
||||||
clientVersions: []schema.GroupVersion{{Version: "version1"}, api.Registry.GroupOrDie(api.GroupName).GroupVersion},
|
|
||||||
expectedVersion: &schema.GroupVersion{Version: "version1"},
|
|
||||||
statusCode: http.StatusForbidden,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "discovery fails due to 404 Not Found errors and thus serverVersions is empty, use requested GroupVersion",
|
|
||||||
requiredVersion: &schema.GroupVersion{Version: "version1"},
|
|
||||||
clientVersions: []schema.GroupVersion{{Version: "version1"}, api.Registry.GroupOrDie(api.GroupName).GroupVersion},
|
|
||||||
expectedVersion: &schema.GroupVersion{Version: "version1"},
|
|
||||||
statusCode: http.StatusNotFound,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "discovery fails due to 403 Forbidden errors and thus serverVersions is empty, no fallback GroupVersion",
|
|
||||||
expectErr: func(err error) bool { return strings.Contains(err.Error(), "failed to negotiate an api version;") },
|
|
||||||
statusCode: http.StatusForbidden,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
fakeClient := &fake.RESTClient{
|
|
||||||
APIRegistry: api.Registry,
|
|
||||||
NegotiatedSerializer: testapi.Default.NegotiatedSerializer(),
|
|
||||||
Resp: &http.Response{
|
|
||||||
StatusCode: test.statusCode,
|
|
||||||
Body: objBody(&uapi.APIVersions{Versions: test.serverVersions}),
|
|
||||||
},
|
|
||||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
|
||||||
if test.sendErr != nil {
|
|
||||||
return nil, test.sendErr
|
|
||||||
}
|
|
||||||
header := http.Header{}
|
|
||||||
header.Set("Content-Type", runtime.ContentTypeJSON)
|
|
||||||
return &http.Response{StatusCode: test.statusCode, Header: header, Body: objBody(&uapi.APIVersions{Versions: test.serverVersions})}, nil
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
c := discovery.NewDiscoveryClientForConfigOrDie(&restclient.Config{})
|
|
||||||
c.RESTClient().(*restclient.RESTClient).Client = fakeClient.Client
|
|
||||||
response, err := discovery.NegotiateVersion(c, test.requiredVersion, test.clientVersions)
|
|
||||||
if err == nil && test.expectErr != nil {
|
|
||||||
t.Errorf("expected error, got nil for [%s].", test.name)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
if test.expectErr == nil || !test.expectErr(err) {
|
|
||||||
t.Errorf("unexpected error for [%s]: %v.", test.name, err)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if *response != *test.expectedVersion {
|
|
||||||
t.Errorf("%s: expected version %s, got %s.", test.name, test.expectedVersion, response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilteredBy(t *testing.T) {
|
|
||||||
all := discovery.ResourcePredicateFunc(func(gv string, r *metav1.APIResource) bool {
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
none := discovery.ResourcePredicateFunc(func(gv string, r *metav1.APIResource) bool {
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
onlyV2 := discovery.ResourcePredicateFunc(func(gv string, r *metav1.APIResource) bool {
|
|
||||||
return strings.HasSuffix(gv, "/v2") || gv == "v2"
|
|
||||||
})
|
|
||||||
onlyBar := discovery.ResourcePredicateFunc(func(gv string, r *metav1.APIResource) bool {
|
|
||||||
return r.Kind == "Bar"
|
|
||||||
})
|
|
||||||
|
|
||||||
foo := []*metav1.APIResourceList{
|
|
||||||
{
|
|
||||||
GroupVersion: "foo/v1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "bar", Kind: "Bar"},
|
|
||||||
{Name: "test", Kind: "Test"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
GroupVersion: "foo/v2",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{Name: "bar", Kind: "Bar"},
|
|
||||||
{Name: "test", Kind: "Test"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
GroupVersion: "foo/v3",
|
|
||||||
APIResources: []metav1.APIResource{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
input []*metav1.APIResourceList
|
|
||||||
pred discovery.ResourcePredicate
|
|
||||||
expectedResources []string
|
|
||||||
}{
|
|
||||||
{nil, all, []string{}},
|
|
||||||
{[]*metav1.APIResourceList{
|
|
||||||
{GroupVersion: "foo/v1"},
|
|
||||||
}, all, []string{}},
|
|
||||||
{foo, all, []string{"foo/v1.bar", "foo/v1.test", "foo/v2.bar", "foo/v2.test"}},
|
|
||||||
{foo, onlyV2, []string{"foo/v2.bar", "foo/v2.test"}},
|
|
||||||
{foo, onlyBar, []string{"foo/v1.bar", "foo/v2.bar"}},
|
|
||||||
{foo, none, []string{}},
|
|
||||||
}
|
|
||||||
for i, test := range tests {
|
|
||||||
filtered := discovery.FilteredBy(test.pred, test.input)
|
|
||||||
|
|
||||||
if expected, got := sets.NewString(test.expectedResources...), sets.NewString(stringify(filtered)...); !expected.Equal(got) {
|
|
||||||
t.Errorf("[%d] unexpected group versions: expected=%v, got=%v", i, test.expectedResources, stringify(filtered))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringify(rls []*metav1.APIResourceList) []string {
|
|
||||||
result := []string{}
|
|
||||||
for _, rl := range rls {
|
|
||||||
for _, r := range rl.APIResources {
|
|
||||||
result = append(result, rl.GroupVersion+"."+r.Name)
|
|
||||||
}
|
|
||||||
if len(rl.APIResources) == 0 {
|
|
||||||
result = append(result, rl.GroupVersion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
@@ -1,319 +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 discovery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"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/schema"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// APIGroupResources is an API group with a mapping of versions to
|
|
||||||
// resources.
|
|
||||||
type APIGroupResources struct {
|
|
||||||
Group metav1.APIGroup
|
|
||||||
// A mapping of version string to a slice of APIResources for
|
|
||||||
// that version.
|
|
||||||
VersionedResources map[string][]metav1.APIResource
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRESTMapper returns a PriorityRESTMapper based on the discovered
|
|
||||||
// groups and resources passed in.
|
|
||||||
func NewRESTMapper(groupResources []*APIGroupResources, versionInterfaces meta.VersionInterfacesFunc) meta.RESTMapper {
|
|
||||||
unionMapper := meta.MultiRESTMapper{}
|
|
||||||
|
|
||||||
var groupPriority []string
|
|
||||||
var resourcePriority []schema.GroupVersionResource
|
|
||||||
var kindPriority []schema.GroupVersionKind
|
|
||||||
|
|
||||||
for _, group := range groupResources {
|
|
||||||
groupPriority = append(groupPriority, group.Group.Name)
|
|
||||||
|
|
||||||
if len(group.Group.PreferredVersion.Version) != 0 {
|
|
||||||
preferred := group.Group.PreferredVersion.Version
|
|
||||||
if _, ok := group.VersionedResources[preferred]; ok {
|
|
||||||
resourcePriority = append(resourcePriority, schema.GroupVersionResource{
|
|
||||||
Group: group.Group.Name,
|
|
||||||
Version: group.Group.PreferredVersion.Version,
|
|
||||||
Resource: meta.AnyResource,
|
|
||||||
})
|
|
||||||
|
|
||||||
kindPriority = append(kindPriority, schema.GroupVersionKind{
|
|
||||||
Group: group.Group.Name,
|
|
||||||
Version: group.Group.PreferredVersion.Version,
|
|
||||||
Kind: meta.AnyKind,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, discoveryVersion := range group.Group.Versions {
|
|
||||||
resources, ok := group.VersionedResources[discoveryVersion.Version]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version}
|
|
||||||
versionMapper := meta.NewDefaultRESTMapper([]schema.GroupVersion{gv}, versionInterfaces)
|
|
||||||
|
|
||||||
for _, resource := range resources {
|
|
||||||
scope := meta.RESTScopeNamespace
|
|
||||||
if !resource.Namespaced {
|
|
||||||
scope = meta.RESTScopeRoot
|
|
||||||
}
|
|
||||||
versionMapper.Add(gv.WithKind(resource.Kind), scope)
|
|
||||||
// TODO only do this if it supports listing
|
|
||||||
versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope)
|
|
||||||
}
|
|
||||||
// TODO why is this type not in discovery (at least for "v1")
|
|
||||||
versionMapper.Add(gv.WithKind("List"), meta.RESTScopeRoot)
|
|
||||||
unionMapper = append(unionMapper, versionMapper)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, group := range groupPriority {
|
|
||||||
resourcePriority = append(resourcePriority, schema.GroupVersionResource{
|
|
||||||
Group: group,
|
|
||||||
Version: meta.AnyVersion,
|
|
||||||
Resource: meta.AnyResource,
|
|
||||||
})
|
|
||||||
kindPriority = append(kindPriority, schema.GroupVersionKind{
|
|
||||||
Group: group,
|
|
||||||
Version: meta.AnyVersion,
|
|
||||||
Kind: meta.AnyKind,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta.PriorityRESTMapper{
|
|
||||||
Delegate: unionMapper,
|
|
||||||
ResourcePriority: resourcePriority,
|
|
||||||
KindPriority: kindPriority,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAPIGroupResources uses the provided discovery client to gather
|
|
||||||
// discovery information and populate a slice of APIGroupResources.
|
|
||||||
func GetAPIGroupResources(cl DiscoveryInterface) ([]*APIGroupResources, error) {
|
|
||||||
apiGroups, err := cl.ServerGroups()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var result []*APIGroupResources
|
|
||||||
for _, group := range apiGroups.Groups {
|
|
||||||
groupResources := &APIGroupResources{
|
|
||||||
Group: group,
|
|
||||||
VersionedResources: make(map[string][]metav1.APIResource),
|
|
||||||
}
|
|
||||||
for _, version := range group.Versions {
|
|
||||||
resources, err := cl.ServerResourcesForGroupVersion(version.GroupVersion)
|
|
||||||
if err != nil {
|
|
||||||
if errors.IsNotFound(err) {
|
|
||||||
continue // ignore as this can race with deletion of 3rd party APIs
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
groupResources.VersionedResources[version.Version] = resources.APIResources
|
|
||||||
}
|
|
||||||
result = append(result, groupResources)
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeferredDiscoveryRESTMapper is a RESTMapper that will defer
|
|
||||||
// initialization of the RESTMapper until the first mapping is
|
|
||||||
// requested.
|
|
||||||
type DeferredDiscoveryRESTMapper struct {
|
|
||||||
initMu sync.Mutex
|
|
||||||
delegate meta.RESTMapper
|
|
||||||
cl CachedDiscoveryInterface
|
|
||||||
versionInterface meta.VersionInterfacesFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDeferredDiscoveryRESTMapper returns a
|
|
||||||
// DeferredDiscoveryRESTMapper that will lazily query the provided
|
|
||||||
// client for discovery information to do REST mappings.
|
|
||||||
func NewDeferredDiscoveryRESTMapper(cl CachedDiscoveryInterface, versionInterface meta.VersionInterfacesFunc) *DeferredDiscoveryRESTMapper {
|
|
||||||
return &DeferredDiscoveryRESTMapper{
|
|
||||||
cl: cl,
|
|
||||||
versionInterface: versionInterface,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) getDelegate() (meta.RESTMapper, error) {
|
|
||||||
d.initMu.Lock()
|
|
||||||
defer d.initMu.Unlock()
|
|
||||||
|
|
||||||
if d.delegate != nil {
|
|
||||||
return d.delegate, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
groupResources, err := GetAPIGroupResources(d.cl)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
d.delegate = NewRESTMapper(groupResources, d.versionInterface)
|
|
||||||
return d.delegate, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset resets the internally cached Discovery information and will
|
|
||||||
// cause the next mapping request to re-discover.
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) Reset() {
|
|
||||||
glog.V(5).Info("Invalidating discovery information")
|
|
||||||
|
|
||||||
d.initMu.Lock()
|
|
||||||
defer d.initMu.Unlock()
|
|
||||||
|
|
||||||
d.cl.Invalidate()
|
|
||||||
d.delegate = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// KindFor takes a partial resource and returns back the single match.
|
|
||||||
// It returns an error if there are multiple matches.
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) KindFor(resource schema.GroupVersionResource) (gvk schema.GroupVersionKind, err error) {
|
|
||||||
del, err := d.getDelegate()
|
|
||||||
if err != nil {
|
|
||||||
return schema.GroupVersionKind{}, err
|
|
||||||
}
|
|
||||||
gvk, err = del.KindFor(resource)
|
|
||||||
if err != nil && !d.cl.Fresh() {
|
|
||||||
d.Reset()
|
|
||||||
gvk, err = d.KindFor(resource)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// KindsFor takes a partial resource and returns back the list of
|
|
||||||
// potential kinds in priority order.
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) KindsFor(resource schema.GroupVersionResource) (gvks []schema.GroupVersionKind, err error) {
|
|
||||||
del, err := d.getDelegate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
gvks, err = del.KindsFor(resource)
|
|
||||||
if len(gvks) == 0 && !d.cl.Fresh() {
|
|
||||||
d.Reset()
|
|
||||||
gvks, err = d.KindsFor(resource)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResourceFor takes a partial resource and returns back the single
|
|
||||||
// match. It returns an error if there are multiple matches.
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) ResourceFor(input schema.GroupVersionResource) (gvr schema.GroupVersionResource, err error) {
|
|
||||||
del, err := d.getDelegate()
|
|
||||||
if err != nil {
|
|
||||||
return schema.GroupVersionResource{}, err
|
|
||||||
}
|
|
||||||
gvr, err = del.ResourceFor(input)
|
|
||||||
if err != nil && !d.cl.Fresh() {
|
|
||||||
d.Reset()
|
|
||||||
gvr, err = d.ResourceFor(input)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResourcesFor takes a partial resource and returns back the list of
|
|
||||||
// potential resource in priority order.
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) ResourcesFor(input schema.GroupVersionResource) (gvrs []schema.GroupVersionResource, err error) {
|
|
||||||
del, err := d.getDelegate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
gvrs, err = del.ResourcesFor(input)
|
|
||||||
if len(gvrs) == 0 && !d.cl.Fresh() {
|
|
||||||
d.Reset()
|
|
||||||
gvrs, err = d.ResourcesFor(input)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// RESTMapping identifies a preferred resource mapping for the
|
|
||||||
// provided group kind.
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (m *meta.RESTMapping, err error) {
|
|
||||||
del, err := d.getDelegate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
m, err = del.RESTMapping(gk, versions...)
|
|
||||||
if err != nil && !d.cl.Fresh() {
|
|
||||||
d.Reset()
|
|
||||||
m, err = d.RESTMapping(gk, versions...)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// RESTMappings returns the RESTMappings for the provided group kind
|
|
||||||
// in a rough internal preferred order. If no kind is found, it will
|
|
||||||
// return a NoResourceMatchError.
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) (ms []*meta.RESTMapping, err error) {
|
|
||||||
del, err := d.getDelegate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ms, err = del.RESTMappings(gk, versions...)
|
|
||||||
if len(ms) == 0 && !d.cl.Fresh() {
|
|
||||||
d.Reset()
|
|
||||||
ms, err = d.RESTMappings(gk, versions...)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// AliasesForResource returns whether a resource has an alias or not.
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) AliasesForResource(resource string) (as []string, ok bool) {
|
|
||||||
del, err := d.getDelegate()
|
|
||||||
if err != nil {
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
as, ok = del.AliasesForResource(resource)
|
|
||||||
if len(as) == 0 && !d.cl.Fresh() {
|
|
||||||
d.Reset()
|
|
||||||
as, ok = d.AliasesForResource(resource)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResourceSingularizer converts a resource name from plural to
|
|
||||||
// singular (e.g., from pods to pod).
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
|
|
||||||
del, err := d.getDelegate()
|
|
||||||
if err != nil {
|
|
||||||
return resource, err
|
|
||||||
}
|
|
||||||
singular, err = del.ResourceSingularizer(resource)
|
|
||||||
if err != nil && !d.cl.Fresh() {
|
|
||||||
d.Reset()
|
|
||||||
singular, err = d.ResourceSingularizer(resource)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *DeferredDiscoveryRESTMapper) String() string {
|
|
||||||
del, err := d.getDelegate()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Sprintf("DeferredDiscoveryRESTMapper{%v}", err)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("DeferredDiscoveryRESTMapper{\n\t%v\n}", del)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure it satisfies the interface
|
|
||||||
var _ meta.RESTMapper = &DeferredDiscoveryRESTMapper{}
|
|
@@ -1,330 +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 discovery_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/version"
|
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
"k8s.io/client-go/rest/fake"
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
|
||||||
. "k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
|
|
||||||
"github.com/emicklei/go-restful/swagger"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRESTMapper(t *testing.T) {
|
|
||||||
resources := []*APIGroupResources{
|
|
||||||
{
|
|
||||||
Group: metav1.APIGroup{
|
|
||||||
Versions: []metav1.GroupVersionForDiscovery{
|
|
||||||
{Version: "v1"},
|
|
||||||
{Version: "v2"},
|
|
||||||
},
|
|
||||||
PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1"},
|
|
||||||
},
|
|
||||||
VersionedResources: map[string][]metav1.APIResource{
|
|
||||||
"v1": {
|
|
||||||
{Name: "pods", Namespaced: true, Kind: "Pod"},
|
|
||||||
},
|
|
||||||
"v2": {
|
|
||||||
{Name: "pods", Namespaced: true, Kind: "Pod"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Group: metav1.APIGroup{
|
|
||||||
Name: "extensions",
|
|
||||||
Versions: []metav1.GroupVersionForDiscovery{
|
|
||||||
{Version: "v1beta"},
|
|
||||||
},
|
|
||||||
PreferredVersion: metav1.GroupVersionForDiscovery{Version: "v1beta"},
|
|
||||||
},
|
|
||||||
VersionedResources: map[string][]metav1.APIResource{
|
|
||||||
"v1beta": {
|
|
||||||
{Name: "jobs", Namespaced: true, Kind: "Job"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
restMapper := NewRESTMapper(resources, nil)
|
|
||||||
|
|
||||||
kindTCs := []struct {
|
|
||||||
input schema.GroupVersionResource
|
|
||||||
want schema.GroupVersionKind
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: schema.GroupVersionResource{
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "pods",
|
|
||||||
},
|
|
||||||
want: schema.GroupVersionKind{
|
|
||||||
Version: "v1",
|
|
||||||
Kind: "Pod",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: schema.GroupVersionResource{
|
|
||||||
Version: "v2",
|
|
||||||
Resource: "pods",
|
|
||||||
},
|
|
||||||
want: schema.GroupVersionKind{
|
|
||||||
Version: "v2",
|
|
||||||
Kind: "Pod",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: schema.GroupVersionResource{
|
|
||||||
Resource: "pods",
|
|
||||||
},
|
|
||||||
want: schema.GroupVersionKind{
|
|
||||||
Version: "v1",
|
|
||||||
Kind: "Pod",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: schema.GroupVersionResource{
|
|
||||||
Resource: "jobs",
|
|
||||||
},
|
|
||||||
want: schema.GroupVersionKind{
|
|
||||||
Group: "extensions",
|
|
||||||
Version: "v1beta",
|
|
||||||
Kind: "Job",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range kindTCs {
|
|
||||||
got, err := restMapper.KindFor(tc.input)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("KindFor(%#v) unexpected error: %v", tc.input, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(got, tc.want) {
|
|
||||||
t.Errorf("KindFor(%#v) = %#v, want %#v", tc.input, got, tc.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resourceTCs := []struct {
|
|
||||||
input schema.GroupVersionResource
|
|
||||||
want schema.GroupVersionResource
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
input: schema.GroupVersionResource{
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "pods",
|
|
||||||
},
|
|
||||||
want: schema.GroupVersionResource{
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "pods",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: schema.GroupVersionResource{
|
|
||||||
Version: "v2",
|
|
||||||
Resource: "pods",
|
|
||||||
},
|
|
||||||
want: schema.GroupVersionResource{
|
|
||||||
Version: "v2",
|
|
||||||
Resource: "pods",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: schema.GroupVersionResource{
|
|
||||||
Resource: "pods",
|
|
||||||
},
|
|
||||||
want: schema.GroupVersionResource{
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "pods",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: schema.GroupVersionResource{
|
|
||||||
Resource: "jobs",
|
|
||||||
},
|
|
||||||
want: schema.GroupVersionResource{
|
|
||||||
Group: "extensions",
|
|
||||||
Version: "v1beta",
|
|
||||||
Resource: "jobs",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range resourceTCs {
|
|
||||||
got, err := restMapper.ResourceFor(tc.input)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("ResourceFor(%#v) unexpected error: %v", tc.input, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(got, tc.want) {
|
|
||||||
t.Errorf("ResourceFor(%#v) = %#v, want %#v", tc.input, got, tc.want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeferredDiscoveryRESTMapper_CacheMiss(t *testing.T) {
|
|
||||||
assert := assert.New(t)
|
|
||||||
|
|
||||||
cdc := fakeCachedDiscoveryInterface{fresh: false}
|
|
||||||
m := NewDeferredDiscoveryRESTMapper(&cdc, api.Registry.InterfacesFor)
|
|
||||||
assert.False(cdc.fresh, "should NOT be fresh after instantiation")
|
|
||||||
assert.Zero(cdc.invalidateCalls, "should not have called Invalidate()")
|
|
||||||
|
|
||||||
gvk, err := m.KindFor(schema.GroupVersionResource{
|
|
||||||
Group: "a",
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "foo",
|
|
||||||
})
|
|
||||||
assert.NoError(err)
|
|
||||||
assert.True(cdc.fresh, "should be fresh after a cache-miss")
|
|
||||||
assert.Equal(cdc.invalidateCalls, 1, "should have called Invalidate() once")
|
|
||||||
assert.Equal(gvk.Kind, "Foo")
|
|
||||||
|
|
||||||
gvk, err = m.KindFor(schema.GroupVersionResource{
|
|
||||||
Group: "a",
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "foo",
|
|
||||||
})
|
|
||||||
assert.NoError(err)
|
|
||||||
assert.Equal(cdc.invalidateCalls, 1, "should NOT have called Invalidate() again")
|
|
||||||
|
|
||||||
gvk, err = m.KindFor(schema.GroupVersionResource{
|
|
||||||
Group: "a",
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "bar",
|
|
||||||
})
|
|
||||||
assert.Error(err)
|
|
||||||
assert.Equal(cdc.invalidateCalls, 1, "should NOT have called Invalidate() again after another cache-miss, but with fresh==true")
|
|
||||||
|
|
||||||
cdc.fresh = false
|
|
||||||
gvk, err = m.KindFor(schema.GroupVersionResource{
|
|
||||||
Group: "a",
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "bar",
|
|
||||||
})
|
|
||||||
assert.Error(err)
|
|
||||||
assert.Equal(cdc.invalidateCalls, 2, "should HAVE called Invalidate() again after another cache-miss, but with fresh==false")
|
|
||||||
}
|
|
||||||
|
|
||||||
type fakeCachedDiscoveryInterface struct {
|
|
||||||
invalidateCalls int
|
|
||||||
fresh bool
|
|
||||||
enabledA bool
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ CachedDiscoveryInterface = &fakeCachedDiscoveryInterface{}
|
|
||||||
|
|
||||||
func (c *fakeCachedDiscoveryInterface) Fresh() bool {
|
|
||||||
return c.fresh
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeCachedDiscoveryInterface) Invalidate() {
|
|
||||||
c.invalidateCalls = c.invalidateCalls + 1
|
|
||||||
c.fresh = true
|
|
||||||
c.enabledA = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeCachedDiscoveryInterface) RESTClient() restclient.Interface {
|
|
||||||
return &fake.RESTClient{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeCachedDiscoveryInterface) ServerGroups() (*metav1.APIGroupList, error) {
|
|
||||||
if c.enabledA {
|
|
||||||
return &metav1.APIGroupList{
|
|
||||||
Groups: []metav1.APIGroup{
|
|
||||||
{
|
|
||||||
Name: "a",
|
|
||||||
Versions: []metav1.GroupVersionForDiscovery{
|
|
||||||
{
|
|
||||||
GroupVersion: "a/v1",
|
|
||||||
Version: "v1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
PreferredVersion: metav1.GroupVersionForDiscovery{
|
|
||||||
GroupVersion: "a/v1",
|
|
||||||
Version: "v1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
return &metav1.APIGroupList{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeCachedDiscoveryInterface) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) {
|
|
||||||
if c.enabledA && groupVersion == "a/v1" {
|
|
||||||
return &metav1.APIResourceList{
|
|
||||||
GroupVersion: "a/v1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{
|
|
||||||
Name: "foo",
|
|
||||||
Kind: "Foo",
|
|
||||||
Namespaced: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.NewNotFound(schema.GroupResource{}, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeCachedDiscoveryInterface) ServerResources() ([]*metav1.APIResourceList, error) {
|
|
||||||
if c.enabledA {
|
|
||||||
av1, _ := c.ServerResourcesForGroupVersion("a/v1")
|
|
||||||
return []*metav1.APIResourceList{av1}, nil
|
|
||||||
}
|
|
||||||
return []*metav1.APIResourceList{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeCachedDiscoveryInterface) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
|
|
||||||
if c.enabledA {
|
|
||||||
return []*metav1.APIResourceList{
|
|
||||||
{
|
|
||||||
GroupVersion: "a/v1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{
|
|
||||||
Name: "foo",
|
|
||||||
Kind: "Foo",
|
|
||||||
Verbs: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeCachedDiscoveryInterface) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeCachedDiscoveryInterface) ServerVersion() (*version.Info, error) {
|
|
||||||
return &version.Info{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *fakeCachedDiscoveryInterface) SwaggerSchema(version schema.GroupVersion) (*swagger.ApiDeclaration, error) {
|
|
||||||
return &swagger.ApiDeclaration{}, nil
|
|
||||||
}
|
|
@@ -1,95 +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 discovery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnstructuredObjectTyper provides a runtime.ObjectTyper implmentation for
|
|
||||||
// runtime.Unstructured object based on discovery information.
|
|
||||||
type UnstructuredObjectTyper struct {
|
|
||||||
registered map[schema.GroupVersionKind]bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUnstructuredObjectTyper returns a runtime.ObjectTyper for
|
|
||||||
// unstructred objects based on discovery information.
|
|
||||||
func NewUnstructuredObjectTyper(groupResources []*APIGroupResources) *UnstructuredObjectTyper {
|
|
||||||
dot := &UnstructuredObjectTyper{registered: make(map[schema.GroupVersionKind]bool)}
|
|
||||||
for _, group := range groupResources {
|
|
||||||
for _, discoveryVersion := range group.Group.Versions {
|
|
||||||
resources, ok := group.VersionedResources[discoveryVersion.Version]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version}
|
|
||||||
for _, resource := range resources {
|
|
||||||
dot.registered[gv.WithKind(resource.Kind)] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dot
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectKind returns the group,version,kind of the provided object, or an error
|
|
||||||
// if the object in not runtime.Unstructured or has no group,version,kind
|
|
||||||
// information.
|
|
||||||
func (d *UnstructuredObjectTyper) ObjectKind(obj runtime.Object) (schema.GroupVersionKind, error) {
|
|
||||||
if _, ok := obj.(runtime.Unstructured); !ok {
|
|
||||||
return schema.GroupVersionKind{}, fmt.Errorf("type %T is invalid for dynamic object typer", obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj.GetObjectKind().GroupVersionKind(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectKinds returns a slice of one element with the group,version,kind of the
|
|
||||||
// provided object, or an error if the object is not runtime.Unstructured or
|
|
||||||
// has no group,version,kind information. unversionedType will always be false
|
|
||||||
// because runtime.Unstructured object should always have group,version,kind
|
|
||||||
// information set.
|
|
||||||
func (d *UnstructuredObjectTyper) ObjectKinds(obj runtime.Object) (gvks []schema.GroupVersionKind, unversionedType bool, err error) {
|
|
||||||
gvk, err := d.ObjectKind(obj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return []schema.GroupVersionKind{gvk}, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recognizes returns true if the provided group,version,kind was in the
|
|
||||||
// discovery information.
|
|
||||||
func (d *UnstructuredObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool {
|
|
||||||
return d.registered[gvk]
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsUnversioned returns false always because runtime.Unstructured objects
|
|
||||||
// should always have group,version,kind information set. ok will be true if the
|
|
||||||
// object's group,version,kind is api.Registry.
|
|
||||||
func (d *UnstructuredObjectTyper) IsUnversioned(obj runtime.Object) (unversioned bool, ok bool) {
|
|
||||||
gvk, err := d.ObjectKind(obj)
|
|
||||||
if err != nil {
|
|
||||||
return false, false
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, d.registered[gvk]
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ runtime.ObjectTyper = &UnstructuredObjectTyper{}
|
|
@@ -1,68 +0,0 @@
|
|||||||
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 = [
|
|
||||||
"client.go",
|
|
||||||
"client_pool.go",
|
|
||||||
"dynamic_util.go",
|
|
||||||
],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
deps = [
|
|
||||||
"//pkg/api:go_default_library",
|
|
||||||
"//pkg/api/v1:go_default_library",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/api/meta",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/conversion/queryparams",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
|
||||||
"//vendor:k8s.io/client-go/rest",
|
|
||||||
"//vendor:k8s.io/client-go/util/flowcontrol",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_test(
|
|
||||||
name = "go_default_test",
|
|
||||||
srcs = [
|
|
||||||
"client_test.go",
|
|
||||||
"dynamic_util_test.go",
|
|
||||||
],
|
|
||||||
library = ":go_default_library",
|
|
||||||
tags = ["automanaged"],
|
|
||||||
deps = [
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
|
|
||||||
"//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/watch",
|
|
||||||
"//vendor:k8s.io/client-go/rest",
|
|
||||||
"//vendor:k8s.io/client-go/rest/watch",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "package-srcs",
|
|
||||||
srcs = glob(["**"]),
|
|
||||||
tags = ["automanaged"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "all-srcs",
|
|
||||||
srcs = [":package-srcs"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
)
|
|
@@ -1,301 +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 dynamic provides a client interface to arbitrary Kubernetes
|
|
||||||
// APIs that exposes common high level operations and exposes common
|
|
||||||
// metadata.
|
|
||||||
package dynamic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
||||||
"k8s.io/apimachinery/pkg/conversion/queryparams"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Client is a Kubernetes client that allows you to access metadata
|
|
||||||
// and manipulate metadata of a Kubernetes API group.
|
|
||||||
type Client struct {
|
|
||||||
cl *restclient.RESTClient
|
|
||||||
parameterCodec runtime.ParameterCodec
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClient returns a new client based on the passed in config. The
|
|
||||||
// codec is ignored, as the dynamic client uses it's own codec.
|
|
||||||
func NewClient(conf *restclient.Config) (*Client, error) {
|
|
||||||
// avoid changing the original config
|
|
||||||
confCopy := *conf
|
|
||||||
conf = &confCopy
|
|
||||||
|
|
||||||
contentConfig := ContentConfig()
|
|
||||||
contentConfig.GroupVersion = conf.GroupVersion
|
|
||||||
if conf.NegotiatedSerializer != nil {
|
|
||||||
contentConfig.NegotiatedSerializer = conf.NegotiatedSerializer
|
|
||||||
}
|
|
||||||
conf.ContentConfig = contentConfig
|
|
||||||
|
|
||||||
if conf.APIPath == "" {
|
|
||||||
conf.APIPath = "/api"
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(conf.UserAgent) == 0 {
|
|
||||||
conf.UserAgent = restclient.DefaultKubernetesUserAgent()
|
|
||||||
}
|
|
||||||
|
|
||||||
cl, err := restclient.RESTClientFor(conf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Client{cl: cl}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRateLimiter returns rate limier.
|
|
||||||
func (c *Client) GetRateLimiter() flowcontrol.RateLimiter {
|
|
||||||
return c.cl.GetRateLimiter()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resource returns an API interface to the specified resource for this client's
|
|
||||||
// group and version. If resource is not a namespaced resource, then namespace
|
|
||||||
// is ignored. The ResourceClient inherits the parameter codec of c.
|
|
||||||
func (c *Client) Resource(resource *metav1.APIResource, namespace string) *ResourceClient {
|
|
||||||
return &ResourceClient{
|
|
||||||
cl: c.cl,
|
|
||||||
resource: resource,
|
|
||||||
ns: namespace,
|
|
||||||
parameterCodec: c.parameterCodec,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParameterCodec returns a client with the provided parameter codec.
|
|
||||||
func (c *Client) ParameterCodec(parameterCodec runtime.ParameterCodec) *Client {
|
|
||||||
return &Client{
|
|
||||||
cl: c.cl,
|
|
||||||
parameterCodec: parameterCodec,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResourceClient is an API interface to a specific resource under a
|
|
||||||
// dynamic client.
|
|
||||||
type ResourceClient struct {
|
|
||||||
cl *restclient.RESTClient
|
|
||||||
resource *metav1.APIResource
|
|
||||||
ns string
|
|
||||||
parameterCodec runtime.ParameterCodec
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns a list of objects for this resource.
|
|
||||||
func (rc *ResourceClient) List(opts runtime.Object) (runtime.Object, error) {
|
|
||||||
parameterEncoder := rc.parameterCodec
|
|
||||||
if parameterEncoder == nil {
|
|
||||||
parameterEncoder = defaultParameterEncoder
|
|
||||||
}
|
|
||||||
return rc.cl.Get().
|
|
||||||
NamespaceIfScoped(rc.ns, rc.resource.Namespaced).
|
|
||||||
Resource(rc.resource.Name).
|
|
||||||
VersionedParams(opts, parameterEncoder).
|
|
||||||
Do().
|
|
||||||
Get()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gets the resource with the specified name.
|
|
||||||
func (rc *ResourceClient) Get(name string) (*unstructured.Unstructured, error) {
|
|
||||||
result := new(unstructured.Unstructured)
|
|
||||||
err := rc.cl.Get().
|
|
||||||
NamespaceIfScoped(rc.ns, rc.resource.Namespaced).
|
|
||||||
Resource(rc.resource.Name).
|
|
||||||
Name(name).
|
|
||||||
Do().
|
|
||||||
Into(result)
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete deletes the resource with the specified name.
|
|
||||||
func (rc *ResourceClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
|
||||||
return rc.cl.Delete().
|
|
||||||
NamespaceIfScoped(rc.ns, rc.resource.Namespaced).
|
|
||||||
Resource(rc.resource.Name).
|
|
||||||
Name(name).
|
|
||||||
Body(opts).
|
|
||||||
Do().
|
|
||||||
Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteCollection deletes a collection of objects.
|
|
||||||
func (rc *ResourceClient) DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions runtime.Object) error {
|
|
||||||
parameterEncoder := rc.parameterCodec
|
|
||||||
if parameterEncoder == nil {
|
|
||||||
parameterEncoder = defaultParameterEncoder
|
|
||||||
}
|
|
||||||
return rc.cl.Delete().
|
|
||||||
NamespaceIfScoped(rc.ns, rc.resource.Namespaced).
|
|
||||||
Resource(rc.resource.Name).
|
|
||||||
VersionedParams(listOptions, parameterEncoder).
|
|
||||||
Body(deleteOptions).
|
|
||||||
Do().
|
|
||||||
Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create creates the provided resource.
|
|
||||||
func (rc *ResourceClient) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
|
||||||
result := new(unstructured.Unstructured)
|
|
||||||
err := rc.cl.Post().
|
|
||||||
NamespaceIfScoped(rc.ns, rc.resource.Namespaced).
|
|
||||||
Resource(rc.resource.Name).
|
|
||||||
Body(obj).
|
|
||||||
Do().
|
|
||||||
Into(result)
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update updates the provided resource.
|
|
||||||
func (rc *ResourceClient) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
|
||||||
result := new(unstructured.Unstructured)
|
|
||||||
if len(obj.GetName()) == 0 {
|
|
||||||
return result, errors.New("object missing name")
|
|
||||||
}
|
|
||||||
err := rc.cl.Put().
|
|
||||||
NamespaceIfScoped(rc.ns, rc.resource.Namespaced).
|
|
||||||
Resource(rc.resource.Name).
|
|
||||||
Name(obj.GetName()).
|
|
||||||
Body(obj).
|
|
||||||
Do().
|
|
||||||
Into(result)
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch returns a watch.Interface that watches the resource.
|
|
||||||
func (rc *ResourceClient) Watch(opts runtime.Object) (watch.Interface, error) {
|
|
||||||
parameterEncoder := rc.parameterCodec
|
|
||||||
if parameterEncoder == nil {
|
|
||||||
parameterEncoder = defaultParameterEncoder
|
|
||||||
}
|
|
||||||
return rc.cl.Get().
|
|
||||||
Prefix("watch").
|
|
||||||
NamespaceIfScoped(rc.ns, rc.resource.Namespaced).
|
|
||||||
Resource(rc.resource.Name).
|
|
||||||
VersionedParams(opts, parameterEncoder).
|
|
||||||
Watch()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rc *ResourceClient) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) {
|
|
||||||
result := new(unstructured.Unstructured)
|
|
||||||
err := rc.cl.Patch(pt).
|
|
||||||
NamespaceIfScoped(rc.ns, rc.resource.Namespaced).
|
|
||||||
Resource(rc.resource.Name).
|
|
||||||
Name(name).
|
|
||||||
Body(data).
|
|
||||||
Do().
|
|
||||||
Into(result)
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// dynamicCodec is a codec that wraps the standard unstructured codec
|
|
||||||
// with special handling for Status objects.
|
|
||||||
type dynamicCodec struct{}
|
|
||||||
|
|
||||||
func (dynamicCodec) Decode(data []byte, gvk *schema.GroupVersionKind, obj runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
|
|
||||||
obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(data, gvk, obj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := obj.(*metav1.Status); !ok && strings.ToLower(gvk.Kind) == "status" {
|
|
||||||
obj = &metav1.Status{}
|
|
||||||
err := json.Unmarshal(data, obj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj, gvk, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dynamicCodec) Encode(obj runtime.Object, w io.Writer) error {
|
|
||||||
return unstructured.UnstructuredJSONScheme.Encode(obj, w)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContentConfig returns a restclient.ContentConfig for dynamic types.
|
|
||||||
func ContentConfig() restclient.ContentConfig {
|
|
||||||
var jsonInfo runtime.SerializerInfo
|
|
||||||
// TODO: api.Codecs here should become "pkg/apis/server/scheme" which is the minimal core you need
|
|
||||||
// to talk to a kubernetes server
|
|
||||||
for _, info := range api.Codecs.SupportedMediaTypes() {
|
|
||||||
if info.MediaType == runtime.ContentTypeJSON {
|
|
||||||
jsonInfo = info
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonInfo.Serializer = dynamicCodec{}
|
|
||||||
jsonInfo.PrettySerializer = nil
|
|
||||||
return restclient.ContentConfig{
|
|
||||||
AcceptContentTypes: runtime.ContentTypeJSON,
|
|
||||||
ContentType: runtime.ContentTypeJSON,
|
|
||||||
NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(jsonInfo),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// paramaterCodec is a codec converts an API object to query
|
|
||||||
// parameters without trying to convert to the target version.
|
|
||||||
type parameterCodec struct{}
|
|
||||||
|
|
||||||
func (parameterCodec) EncodeParameters(obj runtime.Object, to schema.GroupVersion) (url.Values, error) {
|
|
||||||
return queryparams.Convert(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (parameterCodec) DecodeParameters(parameters url.Values, from schema.GroupVersion, into runtime.Object) error {
|
|
||||||
return errors.New("DecodeParameters not implemented on dynamic parameterCodec")
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultParameterEncoder runtime.ParameterCodec = parameterCodec{}
|
|
||||||
|
|
||||||
type versionedParameterEncoderWithV1Fallback struct{}
|
|
||||||
|
|
||||||
func (versionedParameterEncoderWithV1Fallback) EncodeParameters(obj runtime.Object, to schema.GroupVersion) (url.Values, error) {
|
|
||||||
ret, err := api.ParameterCodec.EncodeParameters(obj, to)
|
|
||||||
if err != nil && runtime.IsNotRegisteredError(err) {
|
|
||||||
// fallback to v1
|
|
||||||
return api.ParameterCodec.EncodeParameters(obj, v1.SchemeGroupVersion)
|
|
||||||
}
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (versionedParameterEncoderWithV1Fallback) DecodeParameters(parameters url.Values, from schema.GroupVersion, into runtime.Object) error {
|
|
||||||
return errors.New("DecodeParameters not implemented on versionedParameterEncoderWithV1Fallback")
|
|
||||||
}
|
|
||||||
|
|
||||||
// VersionedParameterEncoderWithV1Fallback is useful for encoding query
|
|
||||||
// parameters for thirdparty resources. It tries to convert object to the
|
|
||||||
// specified version before converting it to query parameters, and falls back to
|
|
||||||
// converting to v1 if the object is not registered in the specified version.
|
|
||||||
// For the record, currently API server always treats query parameters sent to a
|
|
||||||
// thirdparty resource endpoint as v1.
|
|
||||||
var VersionedParameterEncoderWithV1Fallback runtime.ParameterCodec = versionedParameterEncoderWithV1Fallback{}
|
|
@@ -1,115 +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 dynamic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ClientPool manages a pool of dynamic clients.
|
|
||||||
type ClientPool interface {
|
|
||||||
// ClientForGroupVersionKind returns a client configured for the specified groupVersionResource.
|
|
||||||
// Resource may be empty.
|
|
||||||
ClientForGroupVersionResource(resource schema.GroupVersionResource) (*Client, error)
|
|
||||||
// ClientForGroupVersionKind returns a client configured for the specified groupVersionKind.
|
|
||||||
// Kind may be empty.
|
|
||||||
ClientForGroupVersionKind(kind schema.GroupVersionKind) (*Client, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is
|
|
||||||
// optional.
|
|
||||||
type APIPathResolverFunc func(kind schema.GroupVersionKind) string
|
|
||||||
|
|
||||||
// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API.
|
|
||||||
func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string {
|
|
||||||
if len(kind.Group) == 0 {
|
|
||||||
return "/api"
|
|
||||||
}
|
|
||||||
return "/apis"
|
|
||||||
}
|
|
||||||
|
|
||||||
// clientPoolImpl implements ClientPool and caches clients for the resource group versions
|
|
||||||
// is asked to retrieve. This type is thread safe.
|
|
||||||
type clientPoolImpl struct {
|
|
||||||
lock sync.RWMutex
|
|
||||||
config *restclient.Config
|
|
||||||
clients map[schema.GroupVersion]*Client
|
|
||||||
apiPathResolverFunc APIPathResolverFunc
|
|
||||||
mapper meta.RESTMapper
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClientPool returns a ClientPool from the specified config. It reuses clients for the the same
|
|
||||||
// group version. It is expected this type may be wrapped by specific logic that special cases certain
|
|
||||||
// resources or groups.
|
|
||||||
func NewClientPool(config *restclient.Config, mapper meta.RESTMapper, apiPathResolverFunc APIPathResolverFunc) ClientPool {
|
|
||||||
confCopy := *config
|
|
||||||
|
|
||||||
return &clientPoolImpl{
|
|
||||||
config: &confCopy,
|
|
||||||
clients: map[schema.GroupVersion]*Client{},
|
|
||||||
apiPathResolverFunc: apiPathResolverFunc,
|
|
||||||
mapper: mapper,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClientForGroupVersionResource uses the provided RESTMapper to identify the appropriate resource. Resource may
|
|
||||||
// be empty. If no matching kind is found the underlying client for that group is still returned.
|
|
||||||
func (c *clientPoolImpl) ClientForGroupVersionResource(resource schema.GroupVersionResource) (*Client, error) {
|
|
||||||
kinds, err := c.mapper.KindsFor(resource)
|
|
||||||
if err != nil {
|
|
||||||
if meta.IsNoMatchError(err) {
|
|
||||||
return c.ClientForGroupVersionKind(schema.GroupVersionKind{Group: resource.Group, Version: resource.Version})
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return c.ClientForGroupVersionKind(kinds[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClientForGroupVersion returns a client for the specified groupVersion, creates one if none exists. Kind
|
|
||||||
// in the GroupVersionKind may be empty.
|
|
||||||
func (c *clientPoolImpl) ClientForGroupVersionKind(kind schema.GroupVersionKind) (*Client, error) {
|
|
||||||
c.lock.Lock()
|
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
gv := kind.GroupVersion()
|
|
||||||
|
|
||||||
// do we have a client already configured?
|
|
||||||
if existingClient, found := c.clients[gv]; found {
|
|
||||||
return existingClient, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// avoid changing the original config
|
|
||||||
confCopy := *c.config
|
|
||||||
conf := &confCopy
|
|
||||||
|
|
||||||
// we need to set the api path based on group version, if no group, default to legacy path
|
|
||||||
conf.APIPath = c.apiPathResolverFunc(kind)
|
|
||||||
|
|
||||||
// we need to make a client
|
|
||||||
conf.GroupVersion = &gv
|
|
||||||
|
|
||||||
dynamicClient, err := NewClient(conf)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c.clients[gv] = dynamicClient
|
|
||||||
return dynamicClient, nil
|
|
||||||
}
|
|
@@ -1,552 +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 dynamic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
|
||||||
restclient "k8s.io/client-go/rest"
|
|
||||||
restclientwatch "k8s.io/client-go/rest/watch"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getJSON(version, kind, name string) []byte {
|
|
||||||
return []byte(fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "metadata": {"name": %q}}`, version, kind, name))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getListJSON(version, kind string, items ...[]byte) []byte {
|
|
||||||
json := fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "items": [%s]}`,
|
|
||||||
version, kind, bytes.Join(items, []byte(",")))
|
|
||||||
return []byte(json)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getObject(version, kind, name string) *unstructured.Unstructured {
|
|
||||||
return &unstructured.Unstructured{
|
|
||||||
Object: map[string]interface{}{
|
|
||||||
"apiVersion": version,
|
|
||||||
"kind": kind,
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": name,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getClientServer(gv *schema.GroupVersion, h func(http.ResponseWriter, *http.Request)) (*Client, *httptest.Server, error) {
|
|
||||||
srv := httptest.NewServer(http.HandlerFunc(h))
|
|
||||||
cl, err := NewClient(&restclient.Config{
|
|
||||||
Host: srv.URL,
|
|
||||||
ContentConfig: restclient.ContentConfig{GroupVersion: gv},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
srv.Close()
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
return cl, srv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestList(t *testing.T) {
|
|
||||||
tcs := []struct {
|
|
||||||
name string
|
|
||||||
namespace string
|
|
||||||
path string
|
|
||||||
resp []byte
|
|
||||||
want *unstructured.UnstructuredList
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "normal_list",
|
|
||||||
path: "/api/gtest/vtest/rtest",
|
|
||||||
resp: getListJSON("vTest", "rTestList",
|
|
||||||
getJSON("vTest", "rTest", "item1"),
|
|
||||||
getJSON("vTest", "rTest", "item2")),
|
|
||||||
want: &unstructured.UnstructuredList{
|
|
||||||
Object: map[string]interface{}{
|
|
||||||
"apiVersion": "vTest",
|
|
||||||
"kind": "rTestList",
|
|
||||||
},
|
|
||||||
Items: []*unstructured.Unstructured{
|
|
||||||
getObject("vTest", "rTest", "item1"),
|
|
||||||
getObject("vTest", "rTest", "item2"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "namespaced_list",
|
|
||||||
namespace: "nstest",
|
|
||||||
path: "/api/gtest/vtest/namespaces/nstest/rtest",
|
|
||||||
resp: getListJSON("vTest", "rTestList",
|
|
||||||
getJSON("vTest", "rTest", "item1"),
|
|
||||||
getJSON("vTest", "rTest", "item2")),
|
|
||||||
want: &unstructured.UnstructuredList{
|
|
||||||
Object: map[string]interface{}{
|
|
||||||
"apiVersion": "vTest",
|
|
||||||
"kind": "rTestList",
|
|
||||||
},
|
|
||||||
Items: []*unstructured.Unstructured{
|
|
||||||
getObject("vTest", "rTest", "item1"),
|
|
||||||
getObject("vTest", "rTest", "item2"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range tcs {
|
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "GET" {
|
|
||||||
t.Errorf("List(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.URL.Path != tc.path {
|
|
||||||
t.Errorf("List(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
|
|
||||||
w.Write(tc.resp)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when creating client: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer srv.Close()
|
|
||||||
|
|
||||||
got, err := cl.Resource(resource, tc.namespace).List(&metav1.ListOptions{})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when listing %q: %v", tc.name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(got, tc.want) {
|
|
||||||
t.Errorf("List(%q) want: %v\ngot: %v", tc.name, tc.want, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGet(t *testing.T) {
|
|
||||||
tcs := []struct {
|
|
||||||
namespace string
|
|
||||||
name string
|
|
||||||
path string
|
|
||||||
resp []byte
|
|
||||||
want *unstructured.Unstructured
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "normal_get",
|
|
||||||
path: "/api/gtest/vtest/rtest/normal_get",
|
|
||||||
resp: getJSON("vTest", "rTest", "normal_get"),
|
|
||||||
want: getObject("vTest", "rTest", "normal_get"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
namespace: "nstest",
|
|
||||||
name: "namespaced_get",
|
|
||||||
path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_get",
|
|
||||||
resp: getJSON("vTest", "rTest", "namespaced_get"),
|
|
||||||
want: getObject("vTest", "rTest", "namespaced_get"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range tcs {
|
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "GET" {
|
|
||||||
t.Errorf("Get(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.URL.Path != tc.path {
|
|
||||||
t.Errorf("Get(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
|
|
||||||
w.Write(tc.resp)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when creating client: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer srv.Close()
|
|
||||||
|
|
||||||
got, err := cl.Resource(resource, tc.namespace).Get(tc.name)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when getting %q: %v", tc.name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(got, tc.want) {
|
|
||||||
t.Errorf("Get(%q) want: %v\ngot: %v", tc.name, tc.want, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDelete(t *testing.T) {
|
|
||||||
statusOK := &metav1.Status{
|
|
||||||
TypeMeta: metav1.TypeMeta{Kind: "Status"},
|
|
||||||
Status: metav1.StatusSuccess,
|
|
||||||
}
|
|
||||||
tcs := []struct {
|
|
||||||
namespace string
|
|
||||||
name string
|
|
||||||
path string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "normal_delete",
|
|
||||||
path: "/api/gtest/vtest/rtest/normal_delete",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
namespace: "nstest",
|
|
||||||
name: "namespaced_delete",
|
|
||||||
path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_delete",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range tcs {
|
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "DELETE" {
|
|
||||||
t.Errorf("Delete(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.URL.Path != tc.path {
|
|
||||||
t.Errorf("Delete(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
|
|
||||||
unstructured.UnstructuredJSONScheme.Encode(statusOK, w)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when creating client: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer srv.Close()
|
|
||||||
|
|
||||||
err = cl.Resource(resource, tc.namespace).Delete(tc.name, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when deleting %q: %v", tc.name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDeleteCollection(t *testing.T) {
|
|
||||||
statusOK := &metav1.Status{
|
|
||||||
TypeMeta: metav1.TypeMeta{Kind: "Status"},
|
|
||||||
Status: metav1.StatusSuccess,
|
|
||||||
}
|
|
||||||
tcs := []struct {
|
|
||||||
namespace string
|
|
||||||
name string
|
|
||||||
path string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "normal_delete_collection",
|
|
||||||
path: "/api/gtest/vtest/rtest",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
namespace: "nstest",
|
|
||||||
name: "namespaced_delete_collection",
|
|
||||||
path: "/api/gtest/vtest/namespaces/nstest/rtest",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range tcs {
|
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "DELETE" {
|
|
||||||
t.Errorf("DeleteCollection(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.URL.Path != tc.path {
|
|
||||||
t.Errorf("DeleteCollection(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
|
|
||||||
unstructured.UnstructuredJSONScheme.Encode(statusOK, w)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when creating client: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer srv.Close()
|
|
||||||
|
|
||||||
err = cl.Resource(resource, tc.namespace).DeleteCollection(nil, &metav1.ListOptions{})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCreate(t *testing.T) {
|
|
||||||
tcs := []struct {
|
|
||||||
name string
|
|
||||||
namespace string
|
|
||||||
obj *unstructured.Unstructured
|
|
||||||
path string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "normal_create",
|
|
||||||
path: "/api/gtest/vtest/rtest",
|
|
||||||
obj: getObject("vTest", "rTest", "normal_create"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "namespaced_create",
|
|
||||||
namespace: "nstest",
|
|
||||||
path: "/api/gtest/vtest/namespaces/nstest/rtest",
|
|
||||||
obj: getObject("vTest", "rTest", "namespaced_create"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range tcs {
|
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "POST" {
|
|
||||||
t.Errorf("Create(%q) got HTTP method %s. wanted POST", tc.name, r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.URL.Path != tc.path {
|
|
||||||
t.Errorf("Create(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
|
|
||||||
data, err := ioutil.ReadAll(r.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Create(%q) unexpected error reading body: %v", tc.name, err)
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Write(data)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when creating client: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer srv.Close()
|
|
||||||
|
|
||||||
got, err := cl.Resource(resource, tc.namespace).Create(tc.obj)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when creating %q: %v", tc.name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(got, tc.obj) {
|
|
||||||
t.Errorf("Create(%q) want: %v\ngot: %v", tc.name, tc.obj, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUpdate(t *testing.T) {
|
|
||||||
tcs := []struct {
|
|
||||||
name string
|
|
||||||
namespace string
|
|
||||||
obj *unstructured.Unstructured
|
|
||||||
path string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "normal_update",
|
|
||||||
path: "/api/gtest/vtest/rtest/normal_update",
|
|
||||||
obj: getObject("vTest", "rTest", "normal_update"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "namespaced_update",
|
|
||||||
namespace: "nstest",
|
|
||||||
path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_update",
|
|
||||||
obj: getObject("vTest", "rTest", "namespaced_update"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range tcs {
|
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "PUT" {
|
|
||||||
t.Errorf("Update(%q) got HTTP method %s. wanted PUT", tc.name, r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.URL.Path != tc.path {
|
|
||||||
t.Errorf("Update(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
|
|
||||||
data, err := ioutil.ReadAll(r.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Update(%q) unexpected error reading body: %v", tc.name, err)
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Write(data)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when creating client: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer srv.Close()
|
|
||||||
|
|
||||||
got, err := cl.Resource(resource, tc.namespace).Update(tc.obj)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when updating %q: %v", tc.name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(got, tc.obj) {
|
|
||||||
t.Errorf("Update(%q) want: %v\ngot: %v", tc.name, tc.obj, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWatch(t *testing.T) {
|
|
||||||
tcs := []struct {
|
|
||||||
name string
|
|
||||||
namespace string
|
|
||||||
events []watch.Event
|
|
||||||
path string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "normal_watch",
|
|
||||||
path: "/api/gtest/vtest/watch/rtest",
|
|
||||||
events: []watch.Event{
|
|
||||||
{Type: watch.Added, Object: getObject("vTest", "rTest", "normal_watch")},
|
|
||||||
{Type: watch.Modified, Object: getObject("vTest", "rTest", "normal_watch")},
|
|
||||||
{Type: watch.Deleted, Object: getObject("vTest", "rTest", "normal_watch")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "namespaced_watch",
|
|
||||||
namespace: "nstest",
|
|
||||||
path: "/api/gtest/vtest/watch/namespaces/nstest/rtest",
|
|
||||||
events: []watch.Event{
|
|
||||||
{Type: watch.Added, Object: getObject("vTest", "rTest", "namespaced_watch")},
|
|
||||||
{Type: watch.Modified, Object: getObject("vTest", "rTest", "namespaced_watch")},
|
|
||||||
{Type: watch.Deleted, Object: getObject("vTest", "rTest", "namespaced_watch")},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range tcs {
|
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "GET" {
|
|
||||||
t.Errorf("Watch(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.URL.Path != tc.path {
|
|
||||||
t.Errorf("Watch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, dynamicCodec{}), dynamicCodec{})
|
|
||||||
for _, e := range tc.events {
|
|
||||||
enc.Encode(&e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when creating client: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer srv.Close()
|
|
||||||
|
|
||||||
watcher, err := cl.Resource(resource, tc.namespace).Watch(&metav1.ListOptions{})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when watching %q: %v", tc.name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, want := range tc.events {
|
|
||||||
got := <-watcher.ResultChan()
|
|
||||||
if !reflect.DeepEqual(got, want) {
|
|
||||||
t.Errorf("Watch(%q) want: %v\ngot: %v", tc.name, want, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPatch(t *testing.T) {
|
|
||||||
tcs := []struct {
|
|
||||||
name string
|
|
||||||
namespace string
|
|
||||||
patch []byte
|
|
||||||
want *unstructured.Unstructured
|
|
||||||
path string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "normal_patch",
|
|
||||||
path: "/api/gtest/vtest/rtest/normal_patch",
|
|
||||||
patch: getJSON("vTest", "rTest", "normal_patch"),
|
|
||||||
want: getObject("vTest", "rTest", "normal_patch"),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "namespaced_patch",
|
|
||||||
namespace: "nstest",
|
|
||||||
path: "/api/gtest/vtest/namespaces/nstest/rtest/namespaced_patch",
|
|
||||||
patch: getJSON("vTest", "rTest", "namespaced_patch"),
|
|
||||||
want: getObject("vTest", "rTest", "namespaced_patch"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tc := range tcs {
|
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "PATCH" {
|
|
||||||
t.Errorf("Patch(%q) got HTTP method %s. wanted PATCH", tc.name, r.Method)
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.URL.Path != tc.path {
|
|
||||||
t.Errorf("Patch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
content := r.Header.Get("Content-Type")
|
|
||||||
if content != string(types.StrategicMergePatchType) {
|
|
||||||
t.Errorf("Patch(%q) got Content-Type %s. wanted %s", tc.name, content, types.StrategicMergePatchType)
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(r.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Patch(%q) unexpected error reading body: %v", tc.name, err)
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
w.Write(data)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when creating client: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
defer srv.Close()
|
|
||||||
|
|
||||||
got, err := cl.Resource(resource, tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error when patching %q: %v", tc.name, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(got, tc.want) {
|
|
||||||
t.Errorf("Patch(%q) want: %v\ngot: %v", tc.name, tc.want, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,96 +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 dynamic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
// VersionInterfaces provides an object converter and metadata
|
|
||||||
// accessor appropriate for use with unstructured objects.
|
|
||||||
func VersionInterfaces(schema.GroupVersion) (*meta.VersionInterfaces, error) {
|
|
||||||
return &meta.VersionInterfaces{
|
|
||||||
ObjectConvertor: &unstructured.UnstructuredObjectConverter{},
|
|
||||||
MetadataAccessor: meta.NewAccessor(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDiscoveryRESTMapper returns a RESTMapper based on discovery information.
|
|
||||||
func NewDiscoveryRESTMapper(resources []*metav1.APIResourceList, versionFunc meta.VersionInterfacesFunc) (*meta.DefaultRESTMapper, error) {
|
|
||||||
rm := meta.NewDefaultRESTMapper(nil, versionFunc)
|
|
||||||
for _, resourceList := range resources {
|
|
||||||
gv, err := schema.ParseGroupVersion(resourceList.GroupVersion)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, resource := range resourceList.APIResources {
|
|
||||||
gvk := gv.WithKind(resource.Kind)
|
|
||||||
scope := meta.RESTScopeRoot
|
|
||||||
if resource.Namespaced {
|
|
||||||
scope = meta.RESTScopeNamespace
|
|
||||||
}
|
|
||||||
rm.Add(gvk, scope)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rm, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectTyper provides an ObjectTyper implementation for
|
|
||||||
// unstructured.Unstructured object based on discovery information.
|
|
||||||
type ObjectTyper struct {
|
|
||||||
registered map[schema.GroupVersionKind]bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewObjectTyper constructs an ObjectTyper from discovery information.
|
|
||||||
func NewObjectTyper(resources []*metav1.APIResourceList) (runtime.ObjectTyper, error) {
|
|
||||||
ot := &ObjectTyper{registered: make(map[schema.GroupVersionKind]bool)}
|
|
||||||
for _, resourceList := range resources {
|
|
||||||
gv, err := schema.ParseGroupVersion(resourceList.GroupVersion)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, resource := range resourceList.APIResources {
|
|
||||||
ot.registered[gv.WithKind(resource.Kind)] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ot, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ObjectKinds returns a slice of one element with the
|
|
||||||
// group,version,kind of the provided object, or an error if the
|
|
||||||
// object is not *unstructured.Unstructured or has no group,version,kind
|
|
||||||
// information.
|
|
||||||
func (ot *ObjectTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
|
|
||||||
if _, ok := obj.(*unstructured.Unstructured); !ok {
|
|
||||||
return nil, false, fmt.Errorf("type %T is invalid for dynamic object typer", obj)
|
|
||||||
}
|
|
||||||
return []schema.GroupVersionKind{obj.GetObjectKind().GroupVersionKind()}, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recognizes returns true if the provided group,version,kind was in
|
|
||||||
// the discovery information.
|
|
||||||
func (ot *ObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool {
|
|
||||||
return ot.registered[gvk]
|
|
||||||
}
|
|
@@ -1,79 +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 dynamic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDiscoveryRESTMapper(t *testing.T) {
|
|
||||||
resources := []*metav1.APIResourceList{
|
|
||||||
{
|
|
||||||
GroupVersion: "test/beta1",
|
|
||||||
APIResources: []metav1.APIResource{
|
|
||||||
{
|
|
||||||
Name: "test_kinds",
|
|
||||||
Namespaced: true,
|
|
||||||
Kind: "test_kind",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
gvk := schema.GroupVersionKind{
|
|
||||||
Group: "test",
|
|
||||||
Version: "beta1",
|
|
||||||
Kind: "test_kind",
|
|
||||||
}
|
|
||||||
|
|
||||||
mapper, err := NewDiscoveryRESTMapper(resources, VersionInterfaces)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error creating mapper: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, res := range []schema.GroupVersionResource{
|
|
||||||
{
|
|
||||||
Group: "test",
|
|
||||||
Version: "beta1",
|
|
||||||
Resource: "test_kinds",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Version: "beta1",
|
|
||||||
Resource: "test_kinds",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Group: "test",
|
|
||||||
Resource: "test_kinds",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Resource: "test_kinds",
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
got, err := mapper.KindFor(res)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("KindFor(%#v) unexpected error: %s", res, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if got != gvk {
|
|
||||||
t.Errorf("KindFor(%#v) = %#v; want %#v", res, got, gvk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -19,7 +19,6 @@ go_library(
|
|||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//pkg/controller/garbagecollector/metaonly:go_default_library",
|
"//pkg/controller/garbagecollector/metaonly:go_default_library",
|
||||||
"//pkg/util/metrics:go_default_library",
|
"//pkg/util/metrics:go_default_library",
|
||||||
"//pkg/util/workqueue:go_default_library",
|
"//pkg/util/workqueue:go_default_library",
|
||||||
@@ -38,6 +37,7 @@ go_library(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/tools/cache",
|
"//vendor:k8s.io/client-go/tools/cache",
|
||||||
"//vendor:k8s.io/client-go/util/clock",
|
"//vendor:k8s.io/client-go/util/clock",
|
||||||
],
|
],
|
||||||
@@ -52,7 +52,6 @@ go_test(
|
|||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/api/install:go_default_library",
|
"//pkg/api/install:go_default_library",
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//pkg/controller/garbagecollector/metaonly:go_default_library",
|
"//pkg/controller/garbagecollector/metaonly:go_default_library",
|
||||||
"//pkg/util/workqueue:go_default_library",
|
"//pkg/util/workqueue:go_default_library",
|
||||||
"//vendor:github.com/stretchr/testify/assert",
|
"//vendor:github.com/stretchr/testify/assert",
|
||||||
@@ -62,6 +61,7 @@ go_test(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/json",
|
"//vendor:k8s.io/apimachinery/pkg/util/json",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/util/clock",
|
"//vendor:k8s.io/client-go/util/clock",
|
||||||
],
|
],
|
||||||
|
@@ -35,10 +35,10 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/client-go/util/clock"
|
"k8s.io/client-go/util/clock"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
"k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly"
|
"k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly"
|
||||||
"k8s.io/kubernetes/pkg/util/workqueue"
|
"k8s.io/kubernetes/pkg/util/workqueue"
|
||||||
)
|
)
|
||||||
|
@@ -33,11 +33,11 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/json"
|
"k8s.io/apimachinery/pkg/util/json"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/clock"
|
"k8s.io/client-go/util/clock"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
"k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly"
|
"k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly"
|
||||||
"k8s.io/kubernetes/pkg/util/workqueue"
|
"k8s.io/kubernetes/pkg/util/workqueue"
|
||||||
)
|
)
|
||||||
|
@@ -22,7 +22,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/kubernetes/pkg/util/metrics"
|
"k8s.io/kubernetes/pkg/util/metrics"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -19,8 +19,6 @@ go_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//pkg/controller:go_default_library",
|
"//pkg/controller:go_default_library",
|
||||||
"//pkg/util/metrics:go_default_library",
|
"//pkg/util/metrics:go_default_library",
|
||||||
"//pkg/util/workqueue:go_default_library",
|
"//pkg/util/workqueue:go_default_library",
|
||||||
@@ -34,6 +32,8 @@ go_library(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/tools/cache",
|
"//vendor:k8s.io/client-go/tools/cache",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -49,13 +49,13 @@ go_test(
|
|||||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||||
"//pkg/client/clientset_generated/clientset/fake:go_default_library",
|
"//pkg/client/clientset_generated/clientset/fake:go_default_library",
|
||||||
"//pkg/client/testing/core:go_default_library",
|
"//pkg/client/testing/core:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@@ -26,10 +26,10 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
"k8s.io/kubernetes/pkg/util/metrics"
|
"k8s.io/kubernetes/pkg/util/metrics"
|
||||||
"k8s.io/kubernetes/pkg/util/workqueue"
|
"k8s.io/kubernetes/pkg/util/workqueue"
|
||||||
|
@@ -30,14 +30,14 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
|
||||||
"k8s.io/kubernetes/pkg/client/testing/core"
|
"k8s.io/kubernetes/pkg/client/testing/core"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFinalized(t *testing.T) {
|
func TestFinalized(t *testing.T) {
|
||||||
|
@@ -28,10 +28,10 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// contentRemainingError is used to inform the caller that content is not fully removed from the namespace
|
// contentRemainingError is used to inform the caller that content is not fully removed from the namespace
|
||||||
|
@@ -72,7 +72,6 @@ go_library(
|
|||||||
"//pkg/apis/policy:go_default_library",
|
"//pkg/apis/policy:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/unversioned:go_default_library",
|
"//pkg/client/unversioned:go_default_library",
|
||||||
"//pkg/client/unversioned/portforward:go_default_library",
|
"//pkg/client/unversioned/portforward:go_default_library",
|
||||||
"//pkg/client/unversioned/remotecommand:go_default_library",
|
"//pkg/client/unversioned/remotecommand:go_default_library",
|
||||||
@@ -122,6 +121,7 @@ go_library(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/util/yaml",
|
"//vendor:k8s.io/apimachinery/pkg/util/yaml",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
"//vendor:k8s.io/apiserver/pkg/util/flag",
|
"//vendor:k8s.io/apiserver/pkg/util/flag",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd",
|
"//vendor:k8s.io/client-go/tools/clientcmd",
|
||||||
],
|
],
|
||||||
@@ -181,7 +181,6 @@ go_test(
|
|||||||
"//pkg/apis/batch:go_default_library",
|
"//pkg/apis/batch:go_default_library",
|
||||||
"//pkg/apis/extensions:go_default_library",
|
"//pkg/apis/extensions:go_default_library",
|
||||||
"//pkg/apis/policy:go_default_library",
|
"//pkg/apis/policy:go_default_library",
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//pkg/kubectl:go_default_library",
|
"//pkg/kubectl:go_default_library",
|
||||||
"//pkg/kubectl/cmd/testing:go_default_library",
|
"//pkg/kubectl/cmd/testing:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
@@ -202,6 +201,7 @@ go_test(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/util/strategicpatch",
|
"//vendor:k8s.io/apimachinery/pkg/util/strategicpatch",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/rest/fake",
|
"//vendor:k8s.io/client-go/rest/fake",
|
||||||
"//vendor:k8s.io/client-go/rest/watch",
|
"//vendor:k8s.io/client-go/rest/watch",
|
||||||
|
@@ -21,9 +21,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -26,10 +26,10 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
|
@@ -22,9 +22,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -31,11 +31,11 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
batchv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
|
batchv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
||||||
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
conditions "k8s.io/kubernetes/pkg/client/unversioned"
|
conditions "k8s.io/kubernetes/pkg/client/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||||
|
@@ -17,7 +17,6 @@ go_library(
|
|||||||
"//pkg/api/testapi:go_default_library",
|
"//pkg/api/testapi:go_default_library",
|
||||||
"//pkg/api/validation:go_default_library",
|
"//pkg/api/validation:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/kubectl:go_default_library",
|
"//pkg/kubectl:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//pkg/kubectl/resource:go_default_library",
|
"//pkg/kubectl/resource:go_default_library",
|
||||||
@@ -29,6 +28,7 @@ go_library(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer",
|
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/rest/fake",
|
"//vendor:k8s.io/client-go/rest/fake",
|
||||||
],
|
],
|
||||||
|
@@ -30,6 +30,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset"
|
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset"
|
||||||
@@ -37,7 +38,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/api/validation"
|
"k8s.io/kubernetes/pkg/api/validation"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||||
|
@@ -34,8 +34,6 @@ go_library(
|
|||||||
"//pkg/apis/extensions:go_default_library",
|
"//pkg/apis/extensions:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//pkg/client/unversioned:go_default_library",
|
"//pkg/client/unversioned:go_default_library",
|
||||||
"//pkg/controller:go_default_library",
|
"//pkg/controller:go_default_library",
|
||||||
"//pkg/kubectl:go_default_library",
|
"//pkg/kubectl:go_default_library",
|
||||||
@@ -61,6 +59,8 @@ go_library(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/version",
|
"//vendor:k8s.io/apimachinery/pkg/version",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
"//vendor:k8s.io/apiserver/pkg/util/flag",
|
"//vendor:k8s.io/apiserver/pkg/util/flag",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd",
|
"//vendor:k8s.io/client-go/tools/clientcmd",
|
||||||
"//vendor:k8s.io/client-go/util/homedir",
|
"//vendor:k8s.io/client-go/util/homedir",
|
||||||
@@ -89,7 +89,6 @@ go_test(
|
|||||||
"//pkg/apis/extensions:go_default_library",
|
"//pkg/apis/extensions:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||||
"//pkg/client/testing/core:go_default_library",
|
"//pkg/client/testing/core:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/controller:go_default_library",
|
"//pkg/controller:go_default_library",
|
||||||
"//pkg/kubectl:go_default_library",
|
"//pkg/kubectl:go_default_library",
|
||||||
"//pkg/kubectl/resource:go_default_library",
|
"//pkg/kubectl/resource:go_default_library",
|
||||||
@@ -106,6 +105,7 @@ go_test(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/version",
|
"//vendor:k8s.io/apimachinery/pkg/version",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
"//vendor:k8s.io/apiserver/pkg/util/flag",
|
"//vendor:k8s.io/apiserver/pkg/util/flag",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/rest/fake",
|
"//vendor:k8s.io/client-go/rest/fake",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd",
|
"//vendor:k8s.io/client-go/tools/clientcmd",
|
||||||
|
@@ -31,9 +31,9 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/version"
|
"k8s.io/apimachinery/pkg/version"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CachedDiscoveryClient implements the functions that discovery server-supported API groups,
|
// CachedDiscoveryClient implements the functions that discovery server-supported API groups,
|
||||||
|
@@ -29,9 +29,9 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/version"
|
"k8s.io/apimachinery/pkg/version"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCachedDiscoveryClient_Fresh(t *testing.T) {
|
func TestCachedDiscoveryClient_Fresh(t *testing.T) {
|
||||||
|
@@ -20,12 +20,12 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset"
|
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
oldclient "k8s.io/kubernetes/pkg/client/unversioned"
|
oldclient "k8s.io/kubernetes/pkg/client/unversioned"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -40,6 +40,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset"
|
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset"
|
||||||
@@ -48,7 +49,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/validation"
|
"k8s.io/kubernetes/pkg/api/validation"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||||
"k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata"
|
"k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata"
|
||||||
|
@@ -36,6 +36,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
utilflag "k8s.io/apiserver/pkg/util/flag"
|
utilflag "k8s.io/apiserver/pkg/util/flag"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
"k8s.io/client-go/util/homedir"
|
"k8s.io/client-go/util/homedir"
|
||||||
@@ -46,7 +47,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/apis/batch"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||||
"k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata"
|
"k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata"
|
||||||
|
@@ -34,6 +34,8 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/kubernetes/federation/apis/federation"
|
"k8s.io/kubernetes/federation/apis/federation"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
@@ -41,8 +43,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/validation"
|
"k8s.io/kubernetes/pkg/api/validation"
|
||||||
"k8s.io/kubernetes/pkg/apis/batch"
|
"k8s.io/kubernetes/pkg/apis/batch"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
|
@@ -21,7 +21,7 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -69,6 +69,8 @@ function save() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# save everything for which the staging directory is the source of truth
|
# save everything for which the staging directory is the source of truth
|
||||||
|
save "discovery"
|
||||||
|
save "dynamic"
|
||||||
save "rest"
|
save "rest"
|
||||||
save "tools/auth"
|
save "tools/auth"
|
||||||
save "tools/cache"
|
save "tools/cache"
|
||||||
@@ -93,7 +95,6 @@ mkcp "/pkg/client/record" "/pkg/client"
|
|||||||
mkcp "/pkg/client/testing" "/pkg/client"
|
mkcp "/pkg/client/testing" "/pkg/client"
|
||||||
# remove this test because it imports the internal clientset
|
# remove this test because it imports the internal clientset
|
||||||
rm "${CLIENT_REPO_TEMP}"/pkg/client/testing/core/fake_test.go
|
rm "${CLIENT_REPO_TEMP}"/pkg/client/testing/core/fake_test.go
|
||||||
mkcp "/pkg/client/typed" "/pkg/client"
|
|
||||||
|
|
||||||
mkcp "/pkg/client/unversioned/portforward" "/pkg/client/unversioned"
|
mkcp "/pkg/client/unversioned/portforward" "/pkg/client/unversioned"
|
||||||
|
|
||||||
@@ -182,20 +183,16 @@ function mvfolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mvfolder "pkg/client/clientset_generated/${CLIENTSET}" kubernetes
|
mvfolder "pkg/client/clientset_generated/${CLIENTSET}" kubernetes
|
||||||
mvfolder pkg/client/typed/discovery discovery
|
|
||||||
mvfolder pkg/client/typed/dynamic dynamic
|
|
||||||
mvfolder pkg/client/record tools/record
|
mvfolder pkg/client/record tools/record
|
||||||
mvfolder pkg/client/unversioned/portforward tools/portforward
|
mvfolder pkg/client/unversioned/portforward tools/portforward
|
||||||
mvfolder pkg/client/testing/core testing
|
mvfolder pkg/client/testing/core testing
|
||||||
mvfolder pkg/client/testing/cache tools/cache/testing
|
mvfolder pkg/client/testing/cache tools/cache/testing
|
||||||
mvfolder cmd/kubeadm/app/apis/kubeadm pkg/apis/kubeadm
|
|
||||||
if [ "$(find "${CLIENT_REPO_TEMP}"/pkg/client -type f -name "*.go")" ]; then
|
if [ "$(find "${CLIENT_REPO_TEMP}"/pkg/client -type f -name "*.go")" ]; then
|
||||||
echo "${CLIENT_REPO_TEMP}/pkg/client is expected to be empty"
|
echo "${CLIENT_REPO_TEMP}/pkg/client is expected to be empty"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
rm -r "${CLIENT_REPO_TEMP}"/pkg/client
|
rm -r "${CLIENT_REPO_TEMP}"/pkg/client
|
||||||
fi
|
fi
|
||||||
mvfolder federation pkg/federation
|
|
||||||
|
|
||||||
echo "running gofmt"
|
echo "running gofmt"
|
||||||
find "${CLIENT_REPO_TEMP}" -type f -name "*.go" -print0 | xargs -0 gofmt -w
|
find "${CLIENT_REPO_TEMP}" -type f -name "*.go" -print0 | xargs -0 gofmt -w
|
||||||
|
@@ -50,8 +50,6 @@ go_library(
|
|||||||
"//pkg/client/clientset_generated/clientset/typed/rbac/v1beta1:go_default_library",
|
"//pkg/client/clientset_generated/clientset/typed/rbac/v1beta1:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||||
"//pkg/client/conditions:go_default_library",
|
"//pkg/client/conditions:go_default_library",
|
||||||
"//pkg/client/typed/discovery:go_default_library",
|
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//pkg/client/unversioned/remotecommand:go_default_library",
|
"//pkg/client/unversioned/remotecommand:go_default_library",
|
||||||
"//pkg/cloudprovider:go_default_library",
|
"//pkg/cloudprovider:go_default_library",
|
||||||
"//pkg/cloudprovider/providers/gce:go_default_library",
|
"//pkg/cloudprovider/providers/gce:go_default_library",
|
||||||
@@ -105,6 +103,8 @@ go_library(
|
|||||||
"//vendor:k8s.io/apimachinery/pkg/util/validation",
|
"//vendor:k8s.io/apimachinery/pkg/util/validation",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||||
|
"//vendor:k8s.io/client-go/discovery",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/kubernetes",
|
"//vendor:k8s.io/client-go/kubernetes",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd",
|
"//vendor:k8s.io/client-go/tools/clientcmd",
|
||||||
|
@@ -32,6 +32,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
staging "k8s.io/client-go/kubernetes"
|
staging "k8s.io/client-go/kubernetes"
|
||||||
clientreporestclient "k8s.io/client-go/rest"
|
clientreporestclient "k8s.io/client-go/rest"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
@@ -39,7 +40,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
"k8s.io/kubernetes/pkg/metrics"
|
"k8s.io/kubernetes/pkg/metrics"
|
||||||
"k8s.io/kubernetes/pkg/util/intstr"
|
"k8s.io/kubernetes/pkg/util/intstr"
|
||||||
testutils "k8s.io/kubernetes/test/utils"
|
testutils "k8s.io/kubernetes/test/utils"
|
||||||
|
@@ -63,6 +63,8 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||||
@@ -76,8 +78,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||||
"k8s.io/kubernetes/pkg/client/conditions"
|
"k8s.io/kubernetes/pkg/client/conditions"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
|
gcecloud "k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
|
||||||
"k8s.io/kubernetes/pkg/controller"
|
"k8s.io/kubernetes/pkg/controller"
|
||||||
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
|
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
|
||||||
|
@@ -26,7 +26,6 @@ go_library(
|
|||||||
"//pkg/api:go_default_library",
|
"//pkg/api:go_default_library",
|
||||||
"//pkg/api/v1:go_default_library",
|
"//pkg/api/v1:go_default_library",
|
||||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||||
"//pkg/client/typed/dynamic:go_default_library",
|
|
||||||
"//pkg/controller/namespace:go_default_library",
|
"//pkg/controller/namespace:go_default_library",
|
||||||
"//test/e2e/framework:go_default_library",
|
"//test/e2e/framework:go_default_library",
|
||||||
"//test/e2e_node/builder:go_default_library",
|
"//test/e2e_node/builder:go_default_library",
|
||||||
@@ -38,6 +37,7 @@ go_library(
|
|||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
"//vendor:github.com/kardianos/osext",
|
"//vendor:github.com/kardianos/osext",
|
||||||
"//vendor:k8s.io/apiserver/pkg/util/feature",
|
"//vendor:k8s.io/apiserver/pkg/util/feature",
|
||||||
|
"//vendor:k8s.io/client-go/dynamic",
|
||||||
"//vendor:k8s.io/client-go/rest",
|
"//vendor:k8s.io/client-go/rest",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@@ -19,11 +19,11 @@ package services
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
namespacecontroller "k8s.io/kubernetes/pkg/controller/namespace"
|
namespacecontroller "k8s.io/kubernetes/pkg/controller/namespace"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
)
|
)
|
||||||
|
@@ -25,12 +25,12 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/testapi"
|
"k8s.io/kubernetes/pkg/api/testapi"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
"k8s.io/kubernetes/test/integration/framework"
|
"k8s.io/kubernetes/test/integration/framework"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -34,12 +34,12 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/pkg/client/typed/discovery"
|
|
||||||
"k8s.io/kubernetes/pkg/client/typed/dynamic"
|
|
||||||
"k8s.io/kubernetes/pkg/controller/garbagecollector"
|
"k8s.io/kubernetes/pkg/controller/garbagecollector"
|
||||||
"k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly"
|
"k8s.io/kubernetes/pkg/controller/garbagecollector/metaonly"
|
||||||
"k8s.io/kubernetes/test/integration"
|
"k8s.io/kubernetes/test/integration"
|
||||||
|
19
vendor/BUILD
vendored
19
vendor/BUILD
vendored
@@ -13947,25 +13947,6 @@ go_library(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
go_test(
|
|
||||||
name = "k8s.io/client-go/tools/cache_xtest",
|
|
||||||
srcs = ["k8s.io/client-go/tools/cache/listwatch_test.go"],
|
|
||||||
tags = ["automanaged"],
|
|
||||||
deps = [
|
|
||||||
"//pkg/api:go_default_library",
|
|
||||||
"//pkg/api/testapi:go_default_library",
|
|
||||||
"//pkg/api/v1:go_default_library",
|
|
||||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
|
||||||
"//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/watch",
|
|
||||||
"//vendor:k8s.io/client-go/rest",
|
|
||||||
"//vendor:k8s.io/client-go/tools/cache",
|
|
||||||
"//vendor:k8s.io/client-go/util/testing",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "k8s.io/apimachinery/pkg/util/strategicpatch_test",
|
name = "k8s.io/apimachinery/pkg/util/strategicpatch_test",
|
||||||
srcs = ["k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go"],
|
srcs = ["k8s.io/apimachinery/pkg/util/strategicpatch/patch_test.go"],
|
||||||
|
Reference in New Issue
Block a user