mirror of
https://github.com/optim-enterprises-bv/kubernetes.git
synced 2025-11-25 19:05:13 +00:00
Merge pull request #63446 from deads2k/client-08-remove-old
Automatic merge from submit-queue (batch tested with PRs 63367, 63718, 63446, 63723, 63720). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. finish new dynamic client and deprecate old dynamic client Builds on a couple other pulls. This completes the transition to the new dynamic client. @kubernetes/sig-api-machinery-pr-reviews @caesarxuchao @sttts ```release-note The old dynamic client has been replaced by a new one. The previous dynamic client will exist for one release in `client-go/deprecated-dynamic`. Switch as soon as possible. ```
This commit is contained in:
@@ -33,7 +33,7 @@ import (
|
|||||||
// ClientBackedDryRunGetter implements the DryRunGetter interface for use in NewDryRunClient() and proxies all GET and LIST requests to the backing API server reachable via rest.Config
|
// ClientBackedDryRunGetter implements the DryRunGetter interface for use in NewDryRunClient() and proxies all GET and LIST requests to the backing API server reachable via rest.Config
|
||||||
type ClientBackedDryRunGetter struct {
|
type ClientBackedDryRunGetter struct {
|
||||||
client clientset.Interface
|
client clientset.Interface
|
||||||
dynamicClient dynamic.DynamicInterface
|
dynamicClient dynamic.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitDryRunGetter should implement the DryRunGetter interface
|
// InitDryRunGetter should implement the DryRunGetter interface
|
||||||
|
|||||||
@@ -581,6 +581,7 @@ staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc
|
|||||||
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest
|
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest
|
||||||
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook
|
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook
|
||||||
staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook
|
staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook
|
||||||
|
staging/src/k8s.io/client-go/deprecated-dynamic
|
||||||
staging/src/k8s.io/client-go/discovery/cached
|
staging/src/k8s.io/client-go/discovery/cached
|
||||||
staging/src/k8s.io/client-go/dynamic
|
staging/src/k8s.io/client-go/dynamic
|
||||||
staging/src/k8s.io/client-go/dynamic/fake
|
staging/src/k8s.io/client-go/dynamic/fake
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ const ResourceResyncTime time.Duration = 0
|
|||||||
// up to date as the notification is sent.
|
// up to date as the notification is sent.
|
||||||
type GarbageCollector struct {
|
type GarbageCollector struct {
|
||||||
restMapper resettableRESTMapper
|
restMapper resettableRESTMapper
|
||||||
dynamicClient dynamic.DynamicInterface
|
dynamicClient dynamic.Interface
|
||||||
// garbage collector attempts to delete the items in attemptToDelete queue when the time is ripe.
|
// garbage collector attempts to delete the items in attemptToDelete queue when the time is ripe.
|
||||||
attemptToDelete workqueue.RateLimitingInterface
|
attemptToDelete workqueue.RateLimitingInterface
|
||||||
// garbage collector attempts to orphan the dependents of the items in the attemptToOrphan queue, then deletes the items.
|
// garbage collector attempts to orphan the dependents of the items in the attemptToOrphan queue, then deletes the items.
|
||||||
@@ -74,7 +74,7 @@ type GarbageCollector struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewGarbageCollector(
|
func NewGarbageCollector(
|
||||||
dynamicClient dynamic.DynamicInterface,
|
dynamicClient dynamic.Interface,
|
||||||
mapper resettableRESTMapper,
|
mapper resettableRESTMapper,
|
||||||
deletableResources map[schema.GroupVersionResource]struct{},
|
deletableResources map[schema.GroupVersionResource]struct{},
|
||||||
ignoredResources map[schema.GroupResource]struct{},
|
ignoredResources map[schema.GroupResource]struct{},
|
||||||
|
|||||||
@@ -91,10 +91,7 @@ type GraphBuilder struct {
|
|||||||
// it is protected by monitorLock.
|
// it is protected by monitorLock.
|
||||||
running bool
|
running bool
|
||||||
|
|
||||||
dynamicClient dynamic.DynamicInterface
|
dynamicClient dynamic.Interface
|
||||||
// metaOnlyClientPool uses a special codec, which removes fields except for
|
|
||||||
// apiVersion, kind, and metadata during decoding.
|
|
||||||
metaOnlyClientPool dynamic.ClientPool
|
|
||||||
// monitors are the producer of the graphChanges queue, graphBuilder alters
|
// monitors are the producer of the graphChanges queue, graphBuilder alters
|
||||||
// the in-memory graph according to the changes.
|
// the in-memory graph according to the changes.
|
||||||
graphChanges workqueue.RateLimitingInterface
|
graphChanges workqueue.RateLimitingInterface
|
||||||
@@ -128,7 +125,7 @@ func (m *monitor) Run() {
|
|||||||
|
|
||||||
type monitors map[schema.GroupVersionResource]*monitor
|
type monitors map[schema.GroupVersionResource]*monitor
|
||||||
|
|
||||||
func listWatcher(client dynamic.DynamicInterface, resource schema.GroupVersionResource) *cache.ListWatch {
|
func listWatcher(client dynamic.Interface, resource schema.GroupVersionResource) *cache.ListWatch {
|
||||||
return &cache.ListWatch{
|
return &cache.ListWatch{
|
||||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||||
// We want to list this resource in all namespaces if it's namespace scoped, so not passing namespace is ok.
|
// We want to list this resource in all namespaces if it's namespace scoped, so not passing namespace is ok.
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ type NamespacedResourcesDeleterInterface interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewNamespacedResourcesDeleter(nsClient v1clientset.NamespaceInterface,
|
func NewNamespacedResourcesDeleter(nsClient v1clientset.NamespaceInterface,
|
||||||
dynamicClient dynamic.DynamicInterface, podsGetter v1clientset.PodsGetter,
|
dynamicClient dynamic.Interface, podsGetter v1clientset.PodsGetter,
|
||||||
discoverResourcesFn func() ([]*metav1.APIResourceList, error),
|
discoverResourcesFn func() ([]*metav1.APIResourceList, error),
|
||||||
finalizerToken v1.FinalizerName, deleteNamespaceWhenDone bool) NamespacedResourcesDeleterInterface {
|
finalizerToken v1.FinalizerName, deleteNamespaceWhenDone bool) NamespacedResourcesDeleterInterface {
|
||||||
d := &namespacedResourcesDeleter{
|
d := &namespacedResourcesDeleter{
|
||||||
@@ -68,7 +68,7 @@ type namespacedResourcesDeleter struct {
|
|||||||
// Client to manipulate the namespace.
|
// Client to manipulate the namespace.
|
||||||
nsClient v1clientset.NamespaceInterface
|
nsClient v1clientset.NamespaceInterface
|
||||||
// Dynamic client to list and delete all namespaced resources.
|
// Dynamic client to list and delete all namespaced resources.
|
||||||
dynamicClient dynamic.DynamicInterface
|
dynamicClient dynamic.Interface
|
||||||
// Interface to get PodInterface.
|
// Interface to get PodInterface.
|
||||||
podsGetter v1clientset.PodsGetter
|
podsGetter v1clientset.PodsGetter
|
||||||
// Cache of what operations are not supported on each group version resource.
|
// Cache of what operations are not supported on each group version resource.
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ type NamespaceController struct {
|
|||||||
// NewNamespaceController creates a new NamespaceController
|
// NewNamespaceController creates a new NamespaceController
|
||||||
func NewNamespaceController(
|
func NewNamespaceController(
|
||||||
kubeClient clientset.Interface,
|
kubeClient clientset.Interface,
|
||||||
dynamicClient dynamic.DynamicInterface,
|
dynamicClient dynamic.Interface,
|
||||||
discoverResourcesFn func() ([]*metav1.APIResourceList, error),
|
discoverResourcesFn func() ([]*metav1.APIResourceList, error),
|
||||||
namespaceInformer coreinformers.NamespaceInformer,
|
namespaceInformer coreinformers.NamespaceInformer,
|
||||||
resyncPeriod time.Duration,
|
resyncPeriod time.Duration,
|
||||||
|
|||||||
@@ -226,7 +226,6 @@ go_test(
|
|||||||
"//vendor/k8s.io/apimachinery/pkg/util/strategicpatch/testing:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/strategicpatch/testing:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/version:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/version:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/rest/fake:go_default_library",
|
"//vendor/k8s.io/client-go/rest/fake:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/scale/fake:go_default_library",
|
"//vendor/k8s.io/client-go/scale/fake:go_default_library",
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ type ApplyOptions struct {
|
|||||||
Builder *resource.Builder
|
Builder *resource.Builder
|
||||||
Mapper meta.RESTMapper
|
Mapper meta.RESTMapper
|
||||||
Scaler scaleclient.ScalesGetter
|
Scaler scaleclient.ScalesGetter
|
||||||
DynamicClient dynamic.DynamicInterface
|
DynamicClient dynamic.Interface
|
||||||
ClientSetFunc func() (internalclientset.Interface, error)
|
ClientSetFunc func() (internalclientset.Interface, error)
|
||||||
OpenAPISchema openapi.Resources
|
OpenAPISchema openapi.Resources
|
||||||
|
|
||||||
@@ -580,7 +580,7 @@ func getRESTMappings(mapper meta.RESTMapper, pruneResources *[]pruneResource) (n
|
|||||||
|
|
||||||
type pruner struct {
|
type pruner struct {
|
||||||
mapper meta.RESTMapper
|
mapper meta.RESTMapper
|
||||||
dynamicClient dynamic.DynamicInterface
|
dynamicClient dynamic.Interface
|
||||||
clientsetFunc func() (internalclientset.Interface, error)
|
clientsetFunc func() (internalclientset.Interface, error)
|
||||||
|
|
||||||
visitedUids sets.String
|
visitedUids sets.String
|
||||||
@@ -649,7 +649,7 @@ func (p *pruner) delete(namespace, name string, mapping *meta.RESTMapping, scale
|
|||||||
return runDelete(namespace, name, mapping, p.dynamicClient, p.cascade, p.gracePeriod, p.clientsetFunc, scaleClient)
|
return runDelete(namespace, name, mapping, p.dynamicClient, p.cascade, p.gracePeriod, p.clientsetFunc, scaleClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDelete(namespace, name string, mapping *meta.RESTMapping, c dynamic.DynamicInterface, cascade bool, gracePeriod int, clientsetFunc func() (internalclientset.Interface, error), scaleClient scaleclient.ScalesGetter) error {
|
func runDelete(namespace, name string, mapping *meta.RESTMapping, c dynamic.Interface, cascade bool, gracePeriod int, clientsetFunc func() (internalclientset.Interface, error), scaleClient scaleclient.ScalesGetter) error {
|
||||||
if !cascade {
|
if !cascade {
|
||||||
return c.Resource(mapping.Resource).Namespace(namespace).Delete(name, nil)
|
return c.Resource(mapping.Resource).Namespace(namespace).Delete(name, nil)
|
||||||
}
|
}
|
||||||
@@ -681,7 +681,7 @@ func (p *patcher) delete(namespace, name string) error {
|
|||||||
type patcher struct {
|
type patcher struct {
|
||||||
mapping *meta.RESTMapping
|
mapping *meta.RESTMapping
|
||||||
helper *resource.Helper
|
helper *resource.Helper
|
||||||
dynamicClient dynamic.DynamicInterface
|
dynamicClient dynamic.Interface
|
||||||
clientsetFunc func() (internalclientset.Interface, error)
|
clientsetFunc func() (internalclientset.Interface, error)
|
||||||
|
|
||||||
overwrite bool
|
overwrite bool
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ go_test(
|
|||||||
"//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/kubectl/genericclioptions:go_default_library",
|
"//pkg/kubectl/genericclioptions:go_default_library",
|
||||||
|
"//pkg/kubectl/genericclioptions/resource:go_default_library",
|
||||||
"//pkg/kubectl/scheme:go_default_library",
|
"//pkg/kubectl/scheme:go_default_library",
|
||||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||||
"//vendor/k8s.io/api/batch/v1:go_default_library",
|
"//vendor/k8s.io/api/batch/v1:go_default_library",
|
||||||
@@ -94,7 +95,6 @@ go_test(
|
|||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/kubernetes/fake:go_default_library",
|
"//vendor/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/rest/fake:go_default_library",
|
"//vendor/k8s.io/client-go/rest/fake:go_default_library",
|
||||||
|
|||||||
@@ -348,7 +348,7 @@ type CreateSubcommandOptions struct {
|
|||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
|
|
||||||
Mapper meta.RESTMapper
|
Mapper meta.RESTMapper
|
||||||
DynamicClient dynamic.DynamicInterface
|
DynamicClient dynamic.Interface
|
||||||
|
|
||||||
PrintObj func(obj kruntime.Object) error
|
PrintObj func(obj kruntime.Object) error
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ 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/client-go/dynamic"
|
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||||
@@ -30,6 +29,7 @@ import (
|
|||||||
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/kubectl/genericclioptions"
|
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||||
|
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ func TestCreateDirectory(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var unstructuredSerializer = dynamic.ContentConfig().NegotiatedSerializer
|
var unstructuredSerializer = resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer
|
||||||
|
|
||||||
func initTestErrorHandler(t *testing.T) {
|
func initTestErrorHandler(t *testing.T) {
|
||||||
cmdutil.BehaviorOnFatal(func(str string, code int) {
|
cmdutil.BehaviorOnFatal(func(str string, code int) {
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ 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"
|
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
@@ -42,7 +41,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||||
)
|
)
|
||||||
|
|
||||||
var unstructuredSerializer = dynamic.ContentConfig().NegotiatedSerializer
|
var unstructuredSerializer = resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer
|
||||||
|
|
||||||
func fakecmd() *cobra.Command {
|
func fakecmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ type ExposeServiceOptions struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
Mapper meta.RESTMapper
|
Mapper meta.RESTMapper
|
||||||
|
|
||||||
DynamicClient dynamic.DynamicInterface
|
DynamicClient dynamic.Interface
|
||||||
Builder *resource.Builder
|
Builder *resource.Builder
|
||||||
|
|
||||||
Recorder genericclioptions.Recorder
|
Recorder genericclioptions.Recorder
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ go_test(
|
|||||||
"//pkg/kubectl/cmd/util/openapi:go_default_library",
|
"//pkg/kubectl/cmd/util/openapi:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util/openapi/testing:go_default_library",
|
"//pkg/kubectl/cmd/util/openapi/testing:go_default_library",
|
||||||
"//pkg/kubectl/genericclioptions:go_default_library",
|
"//pkg/kubectl/genericclioptions:go_default_library",
|
||||||
|
"//pkg/kubectl/genericclioptions/resource:go_default_library",
|
||||||
"//pkg/kubectl/scheme:go_default_library",
|
"//pkg/kubectl/scheme:go_default_library",
|
||||||
"//pkg/printers:go_default_library",
|
"//pkg/printers:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
@@ -85,7 +86,6 @@ go_test(
|
|||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/rest/fake:go_default_library",
|
"//vendor/k8s.io/client-go/rest/fake:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/rest/watch:go_default_library",
|
"//vendor/k8s.io/client-go/rest/watch:go_default_library",
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
|
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"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"
|
||||||
restclientwatch "k8s.io/client-go/rest/watch"
|
restclientwatch "k8s.io/client-go/rest/watch"
|
||||||
@@ -49,6 +48,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
|
||||||
openapitesting "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing"
|
openapitesting "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/testing"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||||
|
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ func init() {
|
|||||||
scheme.Scheme.AddConversionFuncs(v1.Convert_v1_PodSecurityContext_To_core_PodSecurityContext)
|
scheme.Scheme.AddConversionFuncs(v1.Convert_v1_PodSecurityContext_To_core_PodSecurityContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
var unstructuredSerializer = dynamic.ContentConfig().NegotiatedSerializer
|
var unstructuredSerializer = resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer
|
||||||
|
|
||||||
func defaultHeader() http.Header {
|
func defaultHeader() http.Header {
|
||||||
header := http.Header{}
|
header := http.Header{}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ type RunOptions struct {
|
|||||||
PrintObj func(runtime.Object) error
|
PrintObj func(runtime.Object) error
|
||||||
Recorder genericclioptions.Recorder
|
Recorder genericclioptions.Recorder
|
||||||
|
|
||||||
DynamicClient dynamic.DynamicInterface
|
DynamicClient dynamic.Interface
|
||||||
|
|
||||||
ArgsLenAtDash int
|
ArgsLenAtDash int
|
||||||
Attach bool
|
Attach bool
|
||||||
|
|||||||
@@ -398,7 +398,7 @@ func (f *TestFactory) ClientSet() (internalclientset.Interface, error) {
|
|||||||
return clientset, nil
|
return clientset, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *TestFactory) DynamicClient() (dynamic.DynamicInterface, error) {
|
func (f *TestFactory) DynamicClient() (dynamic.Interface, error) {
|
||||||
if f.FakeDynamicClient != nil {
|
if f.FakeDynamicClient != nil {
|
||||||
return f.FakeDynamicClient, nil
|
return f.FakeDynamicClient, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ type ClientAccessFactory interface {
|
|||||||
ClientSet() (internalclientset.Interface, error)
|
ClientSet() (internalclientset.Interface, error)
|
||||||
|
|
||||||
// DynamicClient returns a dynamic client ready for use
|
// DynamicClient returns a dynamic client ready for use
|
||||||
DynamicClient() (dynamic.DynamicInterface, error)
|
DynamicClient() (dynamic.Interface, error)
|
||||||
|
|
||||||
// KubernetesClientSet gives you back an external clientset
|
// KubernetesClientSet gives you back an external clientset
|
||||||
KubernetesClientSet() (*kubernetes.Clientset, error)
|
KubernetesClientSet() (*kubernetes.Clientset, error)
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ func (f *ring0Factory) ClientSet() (internalclientset.Interface, error) {
|
|||||||
return internalclientset.NewForConfig(clientConfig)
|
return internalclientset.NewForConfig(clientConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *ring0Factory) DynamicClient() (dynamic.DynamicInterface, error) {
|
func (f *ring0Factory) DynamicClient() (dynamic.Interface, error) {
|
||||||
clientConfig, err := f.ClientConfig()
|
clientConfig, err := f.ClientConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ func (f *ring1Factory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (
|
|||||||
cfg.APIPath = "/api"
|
cfg.APIPath = "/api"
|
||||||
}
|
}
|
||||||
gv := mapping.GroupVersionKind.GroupVersion()
|
gv := mapping.GroupVersionKind.GroupVersion()
|
||||||
cfg.ContentConfig = dynamic.ContentConfig()
|
cfg.ContentConfig = resource.UnstructuredPlusDefaultContentConfig()
|
||||||
cfg.GroupVersion = &gv
|
cfg.GroupVersion = &gv
|
||||||
return restclient.RESTClientFor(cfg)
|
return restclient.RESTClientFor(cfg)
|
||||||
}
|
}
|
||||||
@@ -146,13 +146,8 @@ func genericDescriber(clientAccessFactory ClientAccessFactory, mapping *meta.RES
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
clientConfigCopy := *clientConfig
|
|
||||||
clientConfigCopy.APIPath = dynamic.LegacyAPIPathResolverFunc(mapping.GroupVersionKind)
|
|
||||||
gv := mapping.GroupVersionKind.GroupVersion()
|
|
||||||
clientConfigCopy.GroupVersion = &gv
|
|
||||||
|
|
||||||
// used to fetch the resource
|
// used to fetch the resource
|
||||||
dynamicClient, err := dynamic.NewClient(&clientConfigCopy, gv)
|
dynamicClient, err := dynamic.NewForConfig(clientConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ go_library(
|
|||||||
"interfaces.go",
|
"interfaces.go",
|
||||||
"mapper.go",
|
"mapper.go",
|
||||||
"result.go",
|
"result.go",
|
||||||
|
"scheme.go",
|
||||||
"selector.go",
|
"selector.go",
|
||||||
"visitor.go",
|
"visitor.go",
|
||||||
],
|
],
|
||||||
@@ -36,7 +37,7 @@ go_library(
|
|||||||
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/discovery:go_default_library",
|
"//vendor/k8s.io/client-go/discovery:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
"//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/restmapper:go_default_library",
|
"//vendor/k8s.io/client-go/restmapper:go_default_library",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package resource
|
|||||||
import (
|
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/client-go/dynamic"
|
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ func (clientConfigFn ClientConfigFunc) unstructuredClientForGroupVersion(gv sche
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cfg.ContentConfig = dynamic.ContentConfig()
|
cfg.ContentConfig = UnstructuredPlusDefaultContentConfig()
|
||||||
cfg.GroupVersion = &gv
|
cfg.GroupVersion = &gv
|
||||||
if len(gv.Group) == 0 {
|
if len(gv.Group) == 0 {
|
||||||
cfg.APIPath = "/api"
|
cfg.APIPath = "/api"
|
||||||
|
|||||||
79
pkg/kubectl/genericclioptions/resource/scheme.go
Normal file
79
pkg/kubectl/genericclioptions/resource/scheme.go
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 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 resource
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
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"
|
||||||
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
// dynamicCodec is a codec that wraps the standard unstructured codec
|
||||||
|
// with special handling for Status objects.
|
||||||
|
// Deprecated only used by test code and its wrong
|
||||||
|
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 rest.ContentConfig for dynamic types. It includes enough codecs to act as a "normal"
|
||||||
|
// serializer for the rest.client with options, status and the like.
|
||||||
|
func UnstructuredPlusDefaultContentConfig() rest.ContentConfig {
|
||||||
|
var jsonInfo runtime.SerializerInfo
|
||||||
|
// TODO: scheme.Codecs here should become "pkg/apis/server/scheme" which is the minimal core you need
|
||||||
|
// to talk to a kubernetes server
|
||||||
|
for _, info := range scheme.Codecs.SupportedMediaTypes() {
|
||||||
|
if info.MediaType == runtime.ContentTypeJSON {
|
||||||
|
jsonInfo = info
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonInfo.Serializer = dynamicCodec{}
|
||||||
|
jsonInfo.PrettySerializer = nil
|
||||||
|
return rest.ContentConfig{
|
||||||
|
AcceptContentTypes: runtime.ContentTypeJSON,
|
||||||
|
ContentType: runtime.ContentTypeJSON,
|
||||||
|
NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(jsonInfo),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -203,12 +203,7 @@ type genericDescriber struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *genericDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (output string, err error) {
|
func (g *genericDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (output string, err error) {
|
||||||
apiResource := &metav1.APIResource{
|
obj, err := g.dynamic.Resource(g.mapping.Resource).Namespace(namespace).Get(name, metav1.GetOptions{})
|
||||||
Name: g.mapping.Resource.Resource,
|
|
||||||
Namespaced: g.mapping.Scope.Name() == meta.RESTScopeNameNamespace,
|
|
||||||
Kind: g.mapping.GroupVersionKind.Kind,
|
|
||||||
}
|
|
||||||
obj, err := g.dynamic.Resource(apiResource, namespace).Get(name, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ filegroup(
|
|||||||
"//staging/src/k8s.io/apiserver/plugin/pkg/audit:all-srcs",
|
"//staging/src/k8s.io/apiserver/plugin/pkg/audit:all-srcs",
|
||||||
"//staging/src/k8s.io/apiserver/plugin/pkg/authenticator:all-srcs",
|
"//staging/src/k8s.io/apiserver/plugin/pkg/authenticator:all-srcs",
|
||||||
"//staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook:all-srcs",
|
"//staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook:all-srcs",
|
||||||
|
"//staging/src/k8s.io/client-go/deprecated-dynamic:all-srcs",
|
||||||
"//staging/src/k8s.io/client-go/discovery:all-srcs",
|
"//staging/src/k8s.io/client-go/discovery:all-srcs",
|
||||||
"//staging/src/k8s.io/client-go/dynamic:all-srcs",
|
"//staging/src/k8s.io/client-go/dynamic:all-srcs",
|
||||||
"//staging/src/k8s.io/client-go/examples/create-update-delete-deployment:all-srcs",
|
"//staging/src/k8s.io/client-go/examples/create-update-delete-deployment:all-srcs",
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ func TestClusterScopedCRUD(t *testing.T) {
|
|||||||
testFieldSelector(t, ns, noxuDefinition, dynamicClient)
|
testFieldSelector(t, ns, noxuDefinition, dynamicClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.DynamicInterface) {
|
func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) {
|
||||||
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
||||||
initialList, err := noxuResourceClient.List(metav1.ListOptions{})
|
initialList, err := noxuResourceClient.List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -202,7 +202,7 @@ func testSimpleCRUD(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.DynamicInterface) {
|
func testFieldSelector(t *testing.T, ns string, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition, dynamicClient dynamic.Interface) {
|
||||||
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
||||||
initialList, err := noxuResourceClient.List(metav1.ListOptions{})
|
initialList, err := noxuResourceClient.List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -704,7 +704,7 @@ func TestCrossNamespaceListWatch(t *testing.T) {
|
|||||||
checkNamespacesWatchHelper(t, ns2, noxuNamespacesWatch2)
|
checkNamespacesWatchHelper(t, ns2, noxuNamespacesWatch2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createInstanceWithNamespaceHelper(t *testing.T, ns string, name string, noxuNamespacedResourceClient dynamic.DynamicResourceInterface, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition) *unstructured.Unstructured {
|
func createInstanceWithNamespaceHelper(t *testing.T, ns string, name string, noxuNamespacedResourceClient dynamic.ResourceInterface, noxuDefinition *apiextensionsv1beta1.CustomResourceDefinition) *unstructured.Unstructured {
|
||||||
createdInstance, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, name), noxuNamespacedResourceClient, noxuDefinition)
|
createdInstance, err := instantiateCustomResource(t, testserver.NewNoxuInstance(ns, name), noxuNamespacedResourceClient, noxuDefinition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create noxu Instance:%v", err)
|
t.Fatalf("unable to create noxu Instance:%v", err)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import (
|
|||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
)
|
)
|
||||||
|
|
||||||
func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.DynamicResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) {
|
func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) {
|
||||||
createdInstance, err := client.Create(instanceToCreate)
|
createdInstance, err := client.Create(instanceToCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Logf("%#v", createdInstance)
|
t.Logf("%#v", createdInstance)
|
||||||
@@ -68,7 +68,7 @@ func instantiateCustomResource(t *testing.T, instanceToCreate *unstructured.Unst
|
|||||||
return createdInstance, nil
|
return createdInstance, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNamespacedCustomResourceClient(ns string, client dynamic.DynamicInterface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.DynamicResourceInterface {
|
func NewNamespacedCustomResourceClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface {
|
||||||
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}
|
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}
|
||||||
|
|
||||||
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
||||||
@@ -77,24 +77,6 @@ func NewNamespacedCustomResourceClient(ns string, client dynamic.DynamicInterfac
|
|||||||
return client.Resource(gvr)
|
return client.Resource(gvr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNamespacedCustomResourceStatusClient(ns string, client dynamic.DynamicInterface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.DynamicResourceInterface {
|
|
||||||
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}
|
|
||||||
|
|
||||||
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
|
||||||
return client.NamespacedSubresource(gvr, "status", ns)
|
|
||||||
}
|
|
||||||
return client.ClusterSubresource(gvr, "status")
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewNamespacedCustomResourceScaleClient(ns string, client dynamic.DynamicInterface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.DynamicResourceInterface {
|
|
||||||
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}
|
|
||||||
|
|
||||||
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
|
||||||
return client.NamespacedSubresource(gvr, "scale", ns)
|
|
||||||
}
|
|
||||||
return client.ClusterSubresource(gvr, "scale")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMultipleResourceInstances(t *testing.T) {
|
func TestMultipleResourceInstances(t *testing.T) {
|
||||||
stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients()
|
stopCh, apiExtensionClient, dynamicClient, err := testserver.StartDefaultServerWithClients()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -105,7 +105,6 @@ func TestStatusSubresource(t *testing.T) {
|
|||||||
|
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
||||||
noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, dynamicClient, noxuDefinition)
|
|
||||||
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
|
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create noxu instance: %v", err)
|
t.Fatalf("unable to create noxu instance: %v", err)
|
||||||
@@ -135,7 +134,7 @@ func TestStatusSubresource(t *testing.T) {
|
|||||||
|
|
||||||
// UpdateStatus should not update spec.
|
// UpdateStatus should not update spec.
|
||||||
// Check that .spec.num = 10 and .status.num = 20
|
// Check that .spec.num = 10 and .status.num = 20
|
||||||
updatedStatusInstance, err := noxuStatusResourceClient.Update(gottenNoxuInstance)
|
updatedStatusInstance, err := noxuResourceClient.UpdateStatus(gottenNoxuInstance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to update status: %v", err)
|
t.Fatalf("unable to update status: %v", err)
|
||||||
}
|
}
|
||||||
@@ -238,7 +237,6 @@ func TestScaleSubresource(t *testing.T) {
|
|||||||
|
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
||||||
noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, dynamicClient, noxuDefinition)
|
|
||||||
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
|
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create noxu instance: %v", err)
|
t.Fatalf("unable to create noxu instance: %v", err)
|
||||||
@@ -258,7 +256,7 @@ func TestScaleSubresource(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
_, err = noxuStatusResourceClient.Update(gottenNoxuInstance)
|
_, err = noxuResourceClient.UpdateStatus(gottenNoxuInstance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to update status: %v", err)
|
t.Fatalf("unable to update status: %v", err)
|
||||||
}
|
}
|
||||||
@@ -430,7 +428,6 @@ func TestValidateOnlyStatus(t *testing.T) {
|
|||||||
}
|
}
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
||||||
noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, dynamicClient, noxuDefinition)
|
|
||||||
|
|
||||||
// set .spec.num = 10 and .status.num = 10
|
// set .spec.num = 10 and .status.num = 10
|
||||||
noxuInstance := NewNoxuSubresourceInstance(ns, "foo")
|
noxuInstance := NewNoxuSubresourceInstance(ns, "foo")
|
||||||
@@ -449,7 +446,7 @@ func TestValidateOnlyStatus(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error setting .spec.num: %v", err)
|
t.Fatalf("unexpected error setting .spec.num: %v", err)
|
||||||
}
|
}
|
||||||
createdNoxuInstance, err = noxuStatusResourceClient.Update(createdNoxuInstance)
|
createdNoxuInstance, err = noxuResourceClient.UpdateStatus(createdNoxuInstance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -459,7 +456,7 @@ func TestValidateOnlyStatus(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error setting .status.num: %v", err)
|
t.Fatalf("unexpected error setting .status.num: %v", err)
|
||||||
}
|
}
|
||||||
createdNoxuInstance, err = noxuStatusResourceClient.Update(createdNoxuInstance)
|
createdNoxuInstance, err = noxuResourceClient.UpdateStatus(createdNoxuInstance)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected error, but got none")
|
t.Fatal("expected error, but got none")
|
||||||
}
|
}
|
||||||
@@ -577,7 +574,6 @@ func TestGeneration(t *testing.T) {
|
|||||||
|
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
||||||
noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, dynamicClient, noxuDefinition)
|
|
||||||
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
|
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create noxu instance: %v", err)
|
t.Fatalf("unable to create noxu instance: %v", err)
|
||||||
@@ -599,7 +595,7 @@ func TestGeneration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateStatus does not increment generation
|
// UpdateStatus does not increment generation
|
||||||
updatedStatusInstance, err := noxuStatusResourceClient.Update(gottenNoxuInstance)
|
updatedStatusInstance, err := noxuResourceClient.UpdateStatus(gottenNoxuInstance)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to update status: %v", err)
|
t.Fatalf("unable to update status: %v", err)
|
||||||
}
|
}
|
||||||
@@ -660,8 +656,6 @@ func TestSubresourcePatch(t *testing.T) {
|
|||||||
|
|
||||||
ns := "not-the-default"
|
ns := "not-the-default"
|
||||||
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
noxuResourceClient := NewNamespacedCustomResourceClient(ns, dynamicClient, noxuDefinition)
|
||||||
noxuStatusResourceClient := NewNamespacedCustomResourceStatusClient(ns, dynamicClient, noxuDefinition)
|
|
||||||
noxuScaleResourceClient := NewNamespacedCustomResourceScaleClient(ns, dynamicClient, noxuDefinition)
|
|
||||||
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
|
_, err = instantiateCustomResource(t, NewNoxuSubresourceInstance(ns, "foo"), noxuResourceClient, noxuDefinition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create noxu instance: %v", err)
|
t.Fatalf("unable to create noxu instance: %v", err)
|
||||||
@@ -673,7 +667,7 @@ func TestSubresourcePatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
patch := []byte(`{"spec": {"num":999}, "status": {"num":999}}`)
|
patch := []byte(`{"spec": {"num":999}, "status": {"num":999}}`)
|
||||||
patchedNoxuInstance, err := noxuStatusResourceClient.Patch("foo", types.MergePatchType, patch)
|
patchedNoxuInstance, err := noxuResourceClient.Patch("foo", types.MergePatchType, patch, "status")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -708,19 +702,19 @@ func TestSubresourcePatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no-op patch
|
// no-op patch
|
||||||
_, err = noxuStatusResourceClient.Patch("foo", types.MergePatchType, patch)
|
_, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "status")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// empty patch
|
// empty patch
|
||||||
_, err = noxuStatusResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`))
|
_, err = noxuResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`), "status")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
patch = []byte(`{"spec": {"replicas":7}, "status": {"replicas":7}}`)
|
patch = []byte(`{"spec": {"replicas":7}, "status": {"replicas":7}}`)
|
||||||
patchedNoxuInstance, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, patch)
|
patchedNoxuInstance, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "scale")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -749,24 +743,24 @@ func TestSubresourcePatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no-op patch
|
// no-op patch
|
||||||
_, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, patch)
|
_, err = noxuResourceClient.Patch("foo", types.MergePatchType, patch, "scale")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// empty patch
|
// empty patch
|
||||||
_, err = noxuScaleResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`))
|
_, err = noxuResourceClient.Patch("foo", types.MergePatchType, []byte(`{}`), "scale")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure strategic merge patch is not supported for both status and scale
|
// make sure strategic merge patch is not supported for both status and scale
|
||||||
_, err = noxuStatusResourceClient.Patch("foo", types.StrategicMergePatchType, patch)
|
_, err = noxuResourceClient.Patch("foo", types.StrategicMergePatchType, patch, "status")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources")
|
t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = noxuScaleResourceClient.Patch("foo", types.StrategicMergePatchType, patch)
|
_, err = noxuResourceClient.Patch("foo", types.StrategicMergePatchType, patch, "scale")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources")
|
t.Fatalf("unexpected non-error: strategic merge patch is not supported for custom resources")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ func CreateNewCustomResourceDefinitionWatchUnsafe(crd *apiextensionsv1beta1.Cust
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateNewCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, dynamicClientSet dynamic.DynamicInterface) error {
|
func CreateNewCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceDefinition, apiExtensionsClient clientset.Interface, dynamicClientSet dynamic.Interface) error {
|
||||||
err := CreateNewCustomResourceDefinitionWatchUnsafe(crd, apiExtensionsClient)
|
err := CreateNewCustomResourceDefinitionWatchUnsafe(crd, apiExtensionsClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -209,14 +209,14 @@ func CreateNewCustomResourceDefinition(crd *apiextensionsv1beta1.CustomResourceD
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkForWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition, dynamicClientSet dynamic.DynamicInterface) error {
|
func checkForWatchCachePrimed(crd *apiextensionsv1beta1.CustomResourceDefinition, dynamicClientSet dynamic.Interface) error {
|
||||||
ns := ""
|
ns := ""
|
||||||
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
||||||
ns = "aval"
|
ns = "aval"
|
||||||
}
|
}
|
||||||
|
|
||||||
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}
|
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}
|
||||||
var resourceClient dynamic.DynamicResourceInterface
|
var resourceClient dynamic.ResourceInterface
|
||||||
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
||||||
resourceClient = dynamicClientSet.Resource(gvr).Namespace(ns)
|
resourceClient = dynamicClientSet.Resource(gvr).Namespace(ns)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ func StartDefaultServer() (chan struct{}, *rest.Config, error) {
|
|||||||
return StartServer(config)
|
return StartServer(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartDefaultServerWithClients() (chan struct{}, clientset.Interface, dynamic.DynamicInterface, error) {
|
func StartDefaultServerWithClients() (chan struct{}, clientset.Interface, dynamic.Interface, error) {
|
||||||
stopCh, config, err := StartDefaultServer()
|
stopCh, config, err := StartDefaultServer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
|
|||||||
56
staging/src/k8s.io/client-go/deprecated-dynamic/BUILD
Normal file
56
staging/src/k8s.io/client-go/deprecated-dynamic/BUILD
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"bad_debt.go",
|
||||||
|
"client.go",
|
||||||
|
"client_pool.go",
|
||||||
|
],
|
||||||
|
importpath = "k8s.io/client-go/deprecated-dynamic",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "go_default_test",
|
||||||
|
srcs = ["client_test.go"],
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
deps = [
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/streaming:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/rest/watch:go_default_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dynamic
|
package deprecated_dynamic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -17,7 +17,7 @@ limitations under the License.
|
|||||||
// Package dynamic provides a client interface to arbitrary Kubernetes
|
// Package dynamic provides a client interface to arbitrary Kubernetes
|
||||||
// APIs that exposes common high level operations and exposes common
|
// APIs that exposes common high level operations and exposes common
|
||||||
// metadata.
|
// metadata.
|
||||||
package dynamic
|
package deprecated_dynamic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
@@ -28,6 +28,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -65,13 +66,13 @@ type ResourceInterface interface {
|
|||||||
// and manipulate metadata of a Kubernetes API group, and implements Interface.
|
// and manipulate metadata of a Kubernetes API group, and implements Interface.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
version schema.GroupVersion
|
version schema.GroupVersion
|
||||||
delegate DynamicInterface
|
delegate dynamic.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a new client based on the passed in config. The
|
// NewClient returns a new client based on the passed in config. The
|
||||||
// codec is ignored, as the dynamic client uses it's own codec.
|
// codec is ignored, as the dynamic client uses it's own codec.
|
||||||
func NewClient(conf *restclient.Config, version schema.GroupVersion) (*Client, error) {
|
func NewClient(conf *restclient.Config, version schema.GroupVersion) (*Client, error) {
|
||||||
delegate, err := NewForConfig(conf)
|
delegate, err := dynamic.NewForConfig(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -84,30 +85,47 @@ func NewClient(conf *restclient.Config, version schema.GroupVersion) (*Client, e
|
|||||||
// is ignored. The ResourceInterface inherits the parameter codec of c.
|
// is ignored. The ResourceInterface inherits the parameter codec of c.
|
||||||
func (c *Client) Resource(resource *metav1.APIResource, namespace string) ResourceInterface {
|
func (c *Client) Resource(resource *metav1.APIResource, namespace string) ResourceInterface {
|
||||||
resourceTokens := strings.SplitN(resource.Name, "/", 2)
|
resourceTokens := strings.SplitN(resource.Name, "/", 2)
|
||||||
subresource := ""
|
subresources := []string{}
|
||||||
if len(resourceTokens) > 1 {
|
if len(resourceTokens) > 1 {
|
||||||
subresource = resourceTokens[1]
|
subresources = strings.Split(resourceTokens[1], "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(namespace) == 0 {
|
if len(namespace) == 0 {
|
||||||
return oldResourceShim(c.delegate.ClusterSubresource(c.version.WithResource(resourceTokens[0]), subresource))
|
return oldResourceShim(c.delegate.Resource(c.version.WithResource(resourceTokens[0])), subresources)
|
||||||
}
|
}
|
||||||
return oldResourceShim(c.delegate.NamespacedSubresource(c.version.WithResource(resourceTokens[0]), subresource, namespace))
|
return oldResourceShim(c.delegate.Resource(c.version.WithResource(resourceTokens[0])).Namespace(namespace), subresources)
|
||||||
}
|
}
|
||||||
|
|
||||||
// the old interfaces used the wrong type for lists. this fixes that
|
// the old interfaces used the wrong type for lists. this fixes that
|
||||||
func oldResourceShim(in DynamicResourceInterface) ResourceInterface {
|
func oldResourceShim(in dynamic.ResourceInterface, subresources []string) ResourceInterface {
|
||||||
return oldResourceShimType{DynamicResourceInterface: in}
|
return oldResourceShimType{ResourceInterface: in, subresources: subresources}
|
||||||
}
|
}
|
||||||
|
|
||||||
type oldResourceShimType struct {
|
type oldResourceShimType struct {
|
||||||
DynamicResourceInterface
|
dynamic.ResourceInterface
|
||||||
|
subresources []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s oldResourceShimType) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
||||||
|
return s.ResourceInterface.Create(obj, s.subresources...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s oldResourceShimType) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
||||||
|
return s.ResourceInterface.Update(obj, s.subresources...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s oldResourceShimType) Delete(name string, opts *metav1.DeleteOptions) error {
|
||||||
|
return s.ResourceInterface.Delete(name, opts, s.subresources...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s oldResourceShimType) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) {
|
||||||
|
return s.ResourceInterface.Get(name, opts, s.subresources...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s oldResourceShimType) List(opts metav1.ListOptions) (runtime.Object, error) {
|
func (s oldResourceShimType) List(opts metav1.ListOptions) (runtime.Object, error) {
|
||||||
return s.DynamicResourceInterface.List(opts)
|
return s.ResourceInterface.List(opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s oldResourceShimType) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) {
|
func (s oldResourceShimType) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) {
|
||||||
return s.DynamicResourceInterface.Patch(name, pt, data)
|
return s.ResourceInterface.Patch(name, pt, data, s.subresources...)
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package dynamic
|
package deprecated_dynamic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
623
staging/src/k8s.io/client-go/deprecated-dynamic/client_test.go
Normal file
623
staging/src/k8s.io/client-go/deprecated-dynamic/client_test.go
Normal file
@@ -0,0 +1,623 @@
|
|||||||
|
/*
|
||||||
|
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 deprecated_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)) (Interface, *httptest.Server, error) {
|
||||||
|
srv := httptest.NewServer(http.HandlerFunc(h))
|
||||||
|
cl, err := NewClient(&restclient.Config{
|
||||||
|
Host: srv.URL,
|
||||||
|
ContentConfig: restclient.ContentConfig{GroupVersion: gv},
|
||||||
|
}, *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: "/apis/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: "/apis/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 {
|
||||||
|
resource string
|
||||||
|
namespace string
|
||||||
|
name string
|
||||||
|
path string
|
||||||
|
resp []byte
|
||||||
|
want *unstructured.Unstructured
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
resource: "rtest",
|
||||||
|
name: "normal_get",
|
||||||
|
path: "/apis/gtest/vtest/rtest/normal_get",
|
||||||
|
resp: getJSON("vTest", "rTest", "normal_get"),
|
||||||
|
want: getObject("vTest", "rTest", "normal_get"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest",
|
||||||
|
namespace: "nstest",
|
||||||
|
name: "namespaced_get",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_get",
|
||||||
|
resp: getJSON("vTest", "rTest", "namespaced_get"),
|
||||||
|
want: getObject("vTest", "rTest", "namespaced_get"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest/srtest",
|
||||||
|
name: "normal_subresource_get",
|
||||||
|
path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest",
|
||||||
|
resp: getJSON("vTest", "srTest", "normal_subresource_get"),
|
||||||
|
want: getObject("vTest", "srTest", "normal_subresource_get"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest/srtest",
|
||||||
|
namespace: "nstest",
|
||||||
|
name: "namespaced_subresource_get",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest",
|
||||||
|
resp: getJSON("vTest", "srTest", "namespaced_subresource_get"),
|
||||||
|
want: getObject("vTest", "srTest", "namespaced_subresource_get"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range tcs {
|
||||||
|
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
||||||
|
resource := &metav1.APIResource{Name: tc.resource, 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, metav1.GetOptions{})
|
||||||
|
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) {
|
||||||
|
background := metav1.DeletePropagationBackground
|
||||||
|
uid := types.UID("uid")
|
||||||
|
|
||||||
|
statusOK := &metav1.Status{
|
||||||
|
TypeMeta: metav1.TypeMeta{Kind: "Status"},
|
||||||
|
Status: metav1.StatusSuccess,
|
||||||
|
}
|
||||||
|
tcs := []struct {
|
||||||
|
namespace string
|
||||||
|
name string
|
||||||
|
path string
|
||||||
|
deleteOptions *metav1.DeleteOptions
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "normal_delete",
|
||||||
|
path: "/apis/gtest/vtest/rtest/normal_delete",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
namespace: "nstest",
|
||||||
|
name: "namespaced_delete",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
namespace: "nstest",
|
||||||
|
name: "namespaced_delete_with_options",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete_with_options",
|
||||||
|
deleteOptions: &metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}, PropagationPolicy: &background},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
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, tc.deleteOptions)
|
||||||
|
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: "/apis/gtest/vtest/rtest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
namespace: "nstest",
|
||||||
|
name: "namespaced_delete_collection",
|
||||||
|
path: "/apis/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 {
|
||||||
|
resource string
|
||||||
|
name string
|
||||||
|
namespace string
|
||||||
|
obj *unstructured.Unstructured
|
||||||
|
path string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
resource: "rtest",
|
||||||
|
name: "normal_create",
|
||||||
|
path: "/apis/gtest/vtest/rtest",
|
||||||
|
obj: getObject("gtest/vTest", "rTest", "normal_create"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest",
|
||||||
|
name: "namespaced_create",
|
||||||
|
namespace: "nstest",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
|
||||||
|
obj: getObject("gtest/vTest", "rTest", "namespaced_create"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range tcs {
|
||||||
|
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
||||||
|
resource := &metav1.APIResource{Name: tc.resource, 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 {
|
||||||
|
resource string
|
||||||
|
name string
|
||||||
|
namespace string
|
||||||
|
obj *unstructured.Unstructured
|
||||||
|
path string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
resource: "rtest",
|
||||||
|
name: "normal_update",
|
||||||
|
path: "/apis/gtest/vtest/rtest/normal_update",
|
||||||
|
obj: getObject("gtest/vTest", "rTest", "normal_update"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest",
|
||||||
|
name: "namespaced_update",
|
||||||
|
namespace: "nstest",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update",
|
||||||
|
obj: getObject("gtest/vTest", "rTest", "namespaced_update"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest/srtest",
|
||||||
|
name: "normal_subresource_update",
|
||||||
|
path: "/apis/gtest/vtest/rtest/normal_update/srtest",
|
||||||
|
obj: getObject("gtest/vTest", "srTest", "normal_update"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest/srtest",
|
||||||
|
name: "namespaced_subresource_update",
|
||||||
|
namespace: "nstest",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest",
|
||||||
|
obj: getObject("gtest/vTest", "srTest", "namespaced_update"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range tcs {
|
||||||
|
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
||||||
|
resource := &metav1.APIResource{Name: tc.resource, 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
|
||||||
|
query string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "normal_watch",
|
||||||
|
path: "/apis/gtest/vtest/rtest",
|
||||||
|
query: "watch=true",
|
||||||
|
events: []watch.Event{
|
||||||
|
{Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "normal_watch")},
|
||||||
|
{Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "normal_watch")},
|
||||||
|
{Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "normal_watch")},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "namespaced_watch",
|
||||||
|
namespace: "nstest",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
|
||||||
|
query: "watch=true",
|
||||||
|
events: []watch.Event{
|
||||||
|
{Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")},
|
||||||
|
{Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")},
|
||||||
|
{Type: watch.Deleted, Object: getObject("gtest/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)
|
||||||
|
}
|
||||||
|
if r.URL.RawQuery != tc.query {
|
||||||
|
t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
resource string
|
||||||
|
name string
|
||||||
|
namespace string
|
||||||
|
patch []byte
|
||||||
|
want *unstructured.Unstructured
|
||||||
|
path string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
resource: "rtest",
|
||||||
|
name: "normal_patch",
|
||||||
|
path: "/apis/gtest/vtest/rtest/normal_patch",
|
||||||
|
patch: getJSON("gtest/vTest", "rTest", "normal_patch"),
|
||||||
|
want: getObject("gtest/vTest", "rTest", "normal_patch"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest",
|
||||||
|
name: "namespaced_patch",
|
||||||
|
namespace: "nstest",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_patch",
|
||||||
|
patch: getJSON("gtest/vTest", "rTest", "namespaced_patch"),
|
||||||
|
want: getObject("gtest/vTest", "rTest", "namespaced_patch"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest/srtest",
|
||||||
|
name: "normal_subresource_patch",
|
||||||
|
path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest",
|
||||||
|
patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"),
|
||||||
|
want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest/srtest",
|
||||||
|
name: "namespaced_subresource_patch",
|
||||||
|
namespace: "nstest",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest",
|
||||||
|
patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"),
|
||||||
|
want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range tcs {
|
||||||
|
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
||||||
|
resource := &metav1.APIResource{Name: tc.resource, 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,10 +8,7 @@ load(
|
|||||||
|
|
||||||
go_test(
|
go_test(
|
||||||
name = "go_default_test",
|
name = "go_default_test",
|
||||||
srcs = [
|
srcs = ["client_test.go"],
|
||||||
"client_test.go",
|
|
||||||
"dynamic_util_test.go",
|
|
||||||
],
|
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
@@ -29,10 +26,7 @@ go_test(
|
|||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
"bad_debt.go",
|
"interface.go",
|
||||||
"client.go",
|
|
||||||
"client_pool.go",
|
|
||||||
"dynamic_util.go",
|
|
||||||
"scheme.go",
|
"scheme.go",
|
||||||
"simple.go",
|
"simple.go",
|
||||||
],
|
],
|
||||||
@@ -49,7 +43,6 @@ go_library(
|
|||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/versioning:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
|
||||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -58,12 +58,11 @@ func getObject(version, kind, name string) *unstructured.Unstructured {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getClientServer(gv *schema.GroupVersion, h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) {
|
func getClientServer(h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) {
|
||||||
srv := httptest.NewServer(http.HandlerFunc(h))
|
srv := httptest.NewServer(http.HandlerFunc(h))
|
||||||
cl, err := NewClient(&restclient.Config{
|
cl, err := NewForConfig(&restclient.Config{
|
||||||
Host: srv.URL,
|
Host: srv.URL,
|
||||||
ContentConfig: restclient.ContentConfig{GroupVersion: gv},
|
})
|
||||||
}, *gv)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
srv.Close()
|
srv.Close()
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
@@ -116,9 +115,8 @@ func TestList(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"}
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "GET" {
|
if r.Method != "GET" {
|
||||||
t.Errorf("List(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
|
t.Errorf("List(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
|
||||||
}
|
}
|
||||||
@@ -136,7 +134,7 @@ func TestList(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
got, err := cl.Resource(resource, tc.namespace).List(metav1.ListOptions{})
|
got, err := cl.Resource(resource).Namespace(tc.namespace).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error when listing %q: %v", tc.name, err)
|
t.Errorf("unexpected error when listing %q: %v", tc.name, err)
|
||||||
continue
|
continue
|
||||||
@@ -150,12 +148,13 @@ func TestList(t *testing.T) {
|
|||||||
|
|
||||||
func TestGet(t *testing.T) {
|
func TestGet(t *testing.T) {
|
||||||
tcs := []struct {
|
tcs := []struct {
|
||||||
resource string
|
resource string
|
||||||
namespace string
|
subresource []string
|
||||||
name string
|
namespace string
|
||||||
path string
|
name string
|
||||||
resp []byte
|
path string
|
||||||
want *unstructured.Unstructured
|
resp []byte
|
||||||
|
want *unstructured.Unstructured
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
resource: "rtest",
|
resource: "rtest",
|
||||||
@@ -173,25 +172,26 @@ func TestGet(t *testing.T) {
|
|||||||
want: getObject("vTest", "rTest", "namespaced_get"),
|
want: getObject("vTest", "rTest", "namespaced_get"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
resource: "rtest/srtest",
|
resource: "rtest",
|
||||||
name: "normal_subresource_get",
|
subresource: []string{"srtest"},
|
||||||
path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest",
|
name: "normal_subresource_get",
|
||||||
resp: getJSON("vTest", "srTest", "normal_subresource_get"),
|
path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest",
|
||||||
want: getObject("vTest", "srTest", "normal_subresource_get"),
|
resp: getJSON("vTest", "srTest", "normal_subresource_get"),
|
||||||
|
want: getObject("vTest", "srTest", "normal_subresource_get"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
resource: "rtest/srtest",
|
resource: "rtest",
|
||||||
namespace: "nstest",
|
subresource: []string{"srtest"},
|
||||||
name: "namespaced_subresource_get",
|
namespace: "nstest",
|
||||||
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest",
|
name: "namespaced_subresource_get",
|
||||||
resp: getJSON("vTest", "srTest", "namespaced_subresource_get"),
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest",
|
||||||
want: getObject("vTest", "srTest", "namespaced_subresource_get"),
|
resp: getJSON("vTest", "srTest", "namespaced_subresource_get"),
|
||||||
|
want: getObject("vTest", "srTest", "namespaced_subresource_get"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource}
|
||||||
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
|
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "GET" {
|
if r.Method != "GET" {
|
||||||
t.Errorf("Get(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
|
t.Errorf("Get(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
|
||||||
}
|
}
|
||||||
@@ -209,7 +209,7 @@ func TestGet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
got, err := cl.Resource(resource, tc.namespace).Get(tc.name, metav1.GetOptions{})
|
got, err := cl.Resource(resource).Namespace(tc.namespace).Get(tc.name, metav1.GetOptions{}, tc.subresource...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error when getting %q: %v", tc.name, err)
|
t.Errorf("unexpected error when getting %q: %v", tc.name, err)
|
||||||
continue
|
continue
|
||||||
@@ -230,6 +230,7 @@ func TestDelete(t *testing.T) {
|
|||||||
Status: metav1.StatusSuccess,
|
Status: metav1.StatusSuccess,
|
||||||
}
|
}
|
||||||
tcs := []struct {
|
tcs := []struct {
|
||||||
|
subresource []string
|
||||||
namespace string
|
namespace string
|
||||||
name string
|
name string
|
||||||
path string
|
path string
|
||||||
@@ -244,6 +245,17 @@ func TestDelete(t *testing.T) {
|
|||||||
name: "namespaced_delete",
|
name: "namespaced_delete",
|
||||||
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete",
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
subresource: []string{"srtest"},
|
||||||
|
name: "normal_delete",
|
||||||
|
path: "/apis/gtest/vtest/rtest/normal_delete/srtest",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subresource: []string{"srtest"},
|
||||||
|
namespace: "nstest",
|
||||||
|
name: "namespaced_delete",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete/srtest",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
namespace: "nstest",
|
namespace: "nstest",
|
||||||
name: "namespaced_delete_with_options",
|
name: "namespaced_delete_with_options",
|
||||||
@@ -252,9 +264,8 @@ func TestDelete(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"}
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "DELETE" {
|
if r.Method != "DELETE" {
|
||||||
t.Errorf("Delete(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
|
t.Errorf("Delete(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
|
||||||
}
|
}
|
||||||
@@ -272,7 +283,7 @@ func TestDelete(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
err = cl.Resource(resource, tc.namespace).Delete(tc.name, tc.deleteOptions)
|
err = cl.Resource(resource).Namespace(tc.namespace).Delete(tc.name, tc.deleteOptions, tc.subresource...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error when deleting %q: %v", tc.name, err)
|
t.Errorf("unexpected error when deleting %q: %v", tc.name, err)
|
||||||
continue
|
continue
|
||||||
@@ -301,9 +312,8 @@ func TestDeleteCollection(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"}
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "DELETE" {
|
if r.Method != "DELETE" {
|
||||||
t.Errorf("DeleteCollection(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
|
t.Errorf("DeleteCollection(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
|
||||||
}
|
}
|
||||||
@@ -321,7 +331,7 @@ func TestDeleteCollection(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
err = cl.Resource(resource, tc.namespace).DeleteCollection(nil, metav1.ListOptions{})
|
err = cl.Resource(resource).Namespace(tc.namespace).DeleteCollection(nil, metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err)
|
t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err)
|
||||||
continue
|
continue
|
||||||
@@ -331,11 +341,12 @@ func TestDeleteCollection(t *testing.T) {
|
|||||||
|
|
||||||
func TestCreate(t *testing.T) {
|
func TestCreate(t *testing.T) {
|
||||||
tcs := []struct {
|
tcs := []struct {
|
||||||
resource string
|
resource string
|
||||||
name string
|
subresource []string
|
||||||
namespace string
|
name string
|
||||||
obj *unstructured.Unstructured
|
namespace string
|
||||||
path string
|
obj *unstructured.Unstructured
|
||||||
|
path string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
resource: "rtest",
|
resource: "rtest",
|
||||||
@@ -350,11 +361,25 @@ func TestCreate(t *testing.T) {
|
|||||||
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
|
||||||
obj: getObject("gtest/vTest", "rTest", "namespaced_create"),
|
obj: getObject("gtest/vTest", "rTest", "namespaced_create"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest",
|
||||||
|
subresource: []string{"srtest"},
|
||||||
|
name: "normal_subresource_create",
|
||||||
|
path: "/apis/gtest/vtest/rtest/normal_subresource_create/srtest",
|
||||||
|
obj: getObject("vTest", "srTest", "normal_subresource_create"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resource: "rtest/",
|
||||||
|
subresource: []string{"srtest"},
|
||||||
|
name: "namespaced_subresource_create",
|
||||||
|
namespace: "nstest",
|
||||||
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_create/srtest",
|
||||||
|
obj: getObject("vTest", "srTest", "namespaced_subresource_create"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource}
|
||||||
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
|
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "POST" {
|
if r.Method != "POST" {
|
||||||
t.Errorf("Create(%q) got HTTP method %s. wanted POST", tc.name, r.Method)
|
t.Errorf("Create(%q) got HTTP method %s. wanted POST", tc.name, r.Method)
|
||||||
}
|
}
|
||||||
@@ -379,7 +404,7 @@ func TestCreate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
got, err := cl.Resource(resource, tc.namespace).Create(tc.obj)
|
got, err := cl.Resource(resource).Namespace(tc.namespace).Create(tc.obj, tc.subresource...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error when creating %q: %v", tc.name, err)
|
t.Errorf("unexpected error when creating %q: %v", tc.name, err)
|
||||||
continue
|
continue
|
||||||
@@ -393,11 +418,12 @@ func TestCreate(t *testing.T) {
|
|||||||
|
|
||||||
func TestUpdate(t *testing.T) {
|
func TestUpdate(t *testing.T) {
|
||||||
tcs := []struct {
|
tcs := []struct {
|
||||||
resource string
|
resource string
|
||||||
name string
|
subresource []string
|
||||||
namespace string
|
name string
|
||||||
obj *unstructured.Unstructured
|
namespace string
|
||||||
path string
|
obj *unstructured.Unstructured
|
||||||
|
path string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
resource: "rtest",
|
resource: "rtest",
|
||||||
@@ -413,23 +439,24 @@ func TestUpdate(t *testing.T) {
|
|||||||
obj: getObject("gtest/vTest", "rTest", "namespaced_update"),
|
obj: getObject("gtest/vTest", "rTest", "namespaced_update"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
resource: "rtest/srtest",
|
resource: "rtest",
|
||||||
name: "normal_subresource_update",
|
subresource: []string{"srtest"},
|
||||||
path: "/apis/gtest/vtest/rtest/normal_update/srtest",
|
name: "normal_subresource_update",
|
||||||
obj: getObject("gtest/vTest", "srTest", "normal_update"),
|
path: "/apis/gtest/vtest/rtest/normal_update/srtest",
|
||||||
|
obj: getObject("gtest/vTest", "srTest", "normal_update"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
resource: "rtest/srtest",
|
resource: "rtest",
|
||||||
name: "namespaced_subresource_update",
|
subresource: []string{"srtest"},
|
||||||
namespace: "nstest",
|
name: "namespaced_subresource_update",
|
||||||
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest",
|
namespace: "nstest",
|
||||||
obj: getObject("gtest/vTest", "srTest", "namespaced_update"),
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest",
|
||||||
|
obj: getObject("gtest/vTest", "srTest", "namespaced_update"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource}
|
||||||
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
|
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "PUT" {
|
if r.Method != "PUT" {
|
||||||
t.Errorf("Update(%q) got HTTP method %s. wanted PUT", tc.name, r.Method)
|
t.Errorf("Update(%q) got HTTP method %s. wanted PUT", tc.name, r.Method)
|
||||||
}
|
}
|
||||||
@@ -454,7 +481,7 @@ func TestUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
got, err := cl.Resource(resource, tc.namespace).Update(tc.obj)
|
got, err := cl.Resource(resource).Namespace(tc.namespace).Update(tc.obj, tc.subresource...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error when updating %q: %v", tc.name, err)
|
t.Errorf("unexpected error when updating %q: %v", tc.name, err)
|
||||||
continue
|
continue
|
||||||
@@ -497,9 +524,8 @@ func TestWatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"}
|
||||||
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
|
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "GET" {
|
if r.Method != "GET" {
|
||||||
t.Errorf("Watch(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
|
t.Errorf("Watch(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
|
||||||
}
|
}
|
||||||
@@ -511,7 +537,7 @@ func TestWatch(t *testing.T) {
|
|||||||
t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query)
|
t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query)
|
||||||
}
|
}
|
||||||
|
|
||||||
enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, dynamicCodec{}), dynamicCodec{})
|
enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, unstructured.UnstructuredJSONScheme), unstructured.UnstructuredJSONScheme)
|
||||||
for _, e := range tc.events {
|
for _, e := range tc.events {
|
||||||
enc.Encode(&e)
|
enc.Encode(&e)
|
||||||
}
|
}
|
||||||
@@ -522,7 +548,7 @@ func TestWatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
watcher, err := cl.Resource(resource, tc.namespace).Watch(metav1.ListOptions{})
|
watcher, err := cl.Resource(resource).Namespace(tc.namespace).Watch(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error when watching %q: %v", tc.name, err)
|
t.Errorf("unexpected error when watching %q: %v", tc.name, err)
|
||||||
continue
|
continue
|
||||||
@@ -539,12 +565,13 @@ func TestWatch(t *testing.T) {
|
|||||||
|
|
||||||
func TestPatch(t *testing.T) {
|
func TestPatch(t *testing.T) {
|
||||||
tcs := []struct {
|
tcs := []struct {
|
||||||
resource string
|
resource string
|
||||||
name string
|
subresource []string
|
||||||
namespace string
|
name string
|
||||||
patch []byte
|
namespace string
|
||||||
want *unstructured.Unstructured
|
patch []byte
|
||||||
path string
|
want *unstructured.Unstructured
|
||||||
|
path string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
resource: "rtest",
|
resource: "rtest",
|
||||||
@@ -562,25 +589,26 @@ func TestPatch(t *testing.T) {
|
|||||||
want: getObject("gtest/vTest", "rTest", "namespaced_patch"),
|
want: getObject("gtest/vTest", "rTest", "namespaced_patch"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
resource: "rtest/srtest",
|
resource: "rtest",
|
||||||
name: "normal_subresource_patch",
|
subresource: []string{"srtest"},
|
||||||
path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest",
|
name: "normal_subresource_patch",
|
||||||
patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"),
|
path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest",
|
||||||
want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"),
|
patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"),
|
||||||
|
want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
resource: "rtest/srtest",
|
resource: "rtest",
|
||||||
name: "namespaced_subresource_patch",
|
subresource: []string{"srtest"},
|
||||||
namespace: "nstest",
|
name: "namespaced_subresource_patch",
|
||||||
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest",
|
namespace: "nstest",
|
||||||
patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"),
|
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest",
|
||||||
want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"),
|
patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"),
|
||||||
|
want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcs {
|
for _, tc := range tcs {
|
||||||
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
|
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource}
|
||||||
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
|
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
|
||||||
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "PATCH" {
|
if r.Method != "PATCH" {
|
||||||
t.Errorf("Patch(%q) got HTTP method %s. wanted PATCH", tc.name, r.Method)
|
t.Errorf("Patch(%q) got HTTP method %s. wanted PATCH", tc.name, r.Method)
|
||||||
}
|
}
|
||||||
@@ -610,7 +638,7 @@ func TestPatch(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
got, err := cl.Resource(resource, tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch)
|
got, err := cl.Resource(resource).Namespace(tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch, tc.subresource...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error when patching %q: %v", tc.name, err)
|
t.Errorf("unexpected error when patching %q: %v", tc.name, err)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -1,87 +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"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDiscoveryRESTMapper returns a RESTMapper based on discovery information.
|
|
||||||
func NewDiscoveryRESTMapper(resources []*metav1.APIResourceList) (*meta.DefaultRESTMapper, error) {
|
|
||||||
rm := meta.NewDefaultRESTMapper(nil)
|
|
||||||
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 determining dynamic object types", 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)
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,11 +7,7 @@ load(
|
|||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = ["simple.go"],
|
||||||
"client.go",
|
|
||||||
"client_pool.go",
|
|
||||||
"simple.go",
|
|
||||||
],
|
|
||||||
importpath = "k8s.io/client-go/dynamic/fake",
|
importpath = "k8s.io/client-go/dynamic/fake",
|
||||||
deps = [
|
deps = [
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||||
@@ -25,7 +21,6 @@ go_library(
|
|||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/testing:go_default_library",
|
"//vendor/k8s.io/client-go/testing:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,163 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2017 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package fake provides a fake client interface to arbitrary Kubernetes
|
|
||||||
// APIs that exposes common high level operations and exposes common
|
|
||||||
// metadata.
|
|
||||||
package fake
|
|
||||||
|
|
||||||
import (
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
|
||||||
"k8s.io/client-go/dynamic"
|
|
||||||
"k8s.io/client-go/testing"
|
|
||||||
"k8s.io/client-go/util/flowcontrol"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FakeClient is a fake implementation of dynamic.Interface.
|
|
||||||
type FakeClient struct {
|
|
||||||
GroupVersion schema.GroupVersion
|
|
||||||
|
|
||||||
*testing.Fake
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRateLimiter returns the rate limiter for this client.
|
|
||||||
func (c *FakeClient) GetRateLimiter() flowcontrol.RateLimiter {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 this client
|
|
||||||
func (c *FakeClient) Resource(resource *metav1.APIResource, namespace string) dynamic.ResourceInterface {
|
|
||||||
return &FakeResourceClient{
|
|
||||||
Resource: c.GroupVersion.WithResource(resource.Name),
|
|
||||||
Kind: c.GroupVersion.WithKind(resource.Kind),
|
|
||||||
Namespace: namespace,
|
|
||||||
|
|
||||||
Fake: c.Fake,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParameterCodec returns a client with the provided parameter codec.
|
|
||||||
func (c *FakeClient) ParameterCodec(parameterCodec runtime.ParameterCodec) dynamic.Interface {
|
|
||||||
return &FakeClient{
|
|
||||||
Fake: c.Fake,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FakeResourceClient is a fake implementation of dynamic.ResourceInterface
|
|
||||||
type FakeResourceClient struct {
|
|
||||||
Resource schema.GroupVersionResource
|
|
||||||
Kind schema.GroupVersionKind
|
|
||||||
Namespace string
|
|
||||||
|
|
||||||
*testing.Fake
|
|
||||||
}
|
|
||||||
|
|
||||||
// List returns a list of objects for this resource.
|
|
||||||
func (c *FakeResourceClient) List(opts metav1.ListOptions) (runtime.Object, error) {
|
|
||||||
obj, err := c.Fake.
|
|
||||||
Invokes(testing.NewListAction(c.Resource, c.Kind, c.Namespace, opts), &unstructured.UnstructuredList{})
|
|
||||||
|
|
||||||
if obj == nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
|
||||||
if label == nil {
|
|
||||||
label = labels.Everything()
|
|
||||||
}
|
|
||||||
list := &unstructured.UnstructuredList{}
|
|
||||||
for _, item := range obj.(*unstructured.UnstructuredList).Items {
|
|
||||||
if label.Matches(labels.Set(item.GetLabels())) {
|
|
||||||
list.Items = append(list.Items, item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get gets the resource with the specified name.
|
|
||||||
func (c *FakeResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) {
|
|
||||||
obj, err := c.Fake.
|
|
||||||
Invokes(testing.NewGetAction(c.Resource, c.Namespace, name), &unstructured.Unstructured{})
|
|
||||||
|
|
||||||
if obj == nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj.(*unstructured.Unstructured), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete deletes the resource with the specified name.
|
|
||||||
func (c *FakeResourceClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
|
||||||
_, err := c.Fake.
|
|
||||||
Invokes(testing.NewDeleteAction(c.Resource, c.Namespace, name), &unstructured.Unstructured{})
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteCollection deletes a collection of objects.
|
|
||||||
func (c *FakeResourceClient) DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
|
||||||
_, err := c.Fake.
|
|
||||||
Invokes(testing.NewDeleteCollectionAction(c.Resource, c.Namespace, listOptions), &unstructured.Unstructured{})
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create creates the provided resource.
|
|
||||||
func (c *FakeResourceClient) Create(inObj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
|
||||||
obj, err := c.Fake.
|
|
||||||
Invokes(testing.NewCreateAction(c.Resource, c.Namespace, inObj), &unstructured.Unstructured{})
|
|
||||||
|
|
||||||
if obj == nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return obj.(*unstructured.Unstructured), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update updates the provided resource.
|
|
||||||
func (c *FakeResourceClient) Update(inObj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
|
||||||
obj, err := c.Fake.
|
|
||||||
Invokes(testing.NewUpdateAction(c.Resource, c.Namespace, inObj), &unstructured.Unstructured{})
|
|
||||||
|
|
||||||
if obj == nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return obj.(*unstructured.Unstructured), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch returns a watch.Interface that watches the resource.
|
|
||||||
func (c *FakeResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
|
||||||
return c.Fake.
|
|
||||||
InvokesWatch(testing.NewWatchAction(c.Resource, c.Namespace, opts))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Patch patches the provided resource.
|
|
||||||
func (c *FakeResourceClient) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) {
|
|
||||||
obj, err := c.Fake.
|
|
||||||
Invokes(testing.NewPatchAction(c.Resource, c.Namespace, name, data), &unstructured.Unstructured{})
|
|
||||||
|
|
||||||
if obj == nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return obj.(*unstructured.Unstructured), err
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2017 The Kubernetes Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Package fake provides a fake client interface to arbitrary Kubernetes
|
|
||||||
// APIs that exposes common high level operations and exposes common
|
|
||||||
// metadata.
|
|
||||||
package fake
|
|
||||||
|
|
||||||
import (
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/client-go/dynamic"
|
|
||||||
"k8s.io/client-go/testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FakeClientPool provides a fake implementation of dynamic.ClientPool.
|
|
||||||
// It assumes resource GroupVersions are the same as their corresponding kind GroupVersions.
|
|
||||||
type FakeClientPool struct {
|
|
||||||
testing.Fake
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClientForGroupVersionKind returns a client configured for the specified groupVersionResource.
|
|
||||||
// Resource may be empty.
|
|
||||||
func (p *FakeClientPool) ClientForGroupVersionResource(resource schema.GroupVersionResource) (dynamic.Interface, error) {
|
|
||||||
return p.ClientForGroupVersionKind(resource.GroupVersion().WithKind(""))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClientForGroupVersionKind returns a client configured for the specified groupVersionKind.
|
|
||||||
// Kind may be empty.
|
|
||||||
func (p *FakeClientPool) ClientForGroupVersionKind(kind schema.GroupVersionKind) (dynamic.Interface, error) {
|
|
||||||
// we can just create a new client every time for testing purposes
|
|
||||||
return &FakeClient{
|
|
||||||
GroupVersion: kind.GroupVersion(),
|
|
||||||
Fake: &p.Fake,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
@@ -17,6 +17,8 @@ limitations under the License.
|
|||||||
package fake
|
package fake
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"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/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
@@ -63,37 +65,54 @@ type FakeDynamicClient struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type dynamicResourceClient struct {
|
type dynamicResourceClient struct {
|
||||||
client *FakeDynamicClient
|
client *FakeDynamicClient
|
||||||
namespace string
|
namespace string
|
||||||
resource schema.GroupVersionResource
|
resource schema.GroupVersionResource
|
||||||
subresource string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ dynamic.DynamicInterface = &FakeDynamicClient{}
|
var _ dynamic.Interface = &FakeDynamicClient{}
|
||||||
|
|
||||||
func (c *FakeDynamicClient) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableDynamicResourceInterface {
|
func (c *FakeDynamicClient) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableResourceInterface {
|
||||||
return &dynamicResourceClient{client: c, resource: resource}
|
return &dynamicResourceClient{client: c, resource: resource}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated, this isn't how we want to do it
|
func (c *dynamicResourceClient) Namespace(ns string) dynamic.ResourceInterface {
|
||||||
func (c *FakeDynamicClient) ClusterSubresource(resource schema.GroupVersionResource, subresource string) dynamic.DynamicResourceInterface {
|
|
||||||
return &dynamicResourceClient{client: c, resource: resource, subresource: subresource}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated, this isn't how we want to do it
|
|
||||||
func (c *FakeDynamicClient) NamespacedSubresource(resource schema.GroupVersionResource, subresource, namespace string) dynamic.DynamicResourceInterface {
|
|
||||||
return &dynamicResourceClient{client: c, resource: resource, namespace: namespace, subresource: subresource}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Namespace(ns string) dynamic.DynamicResourceInterface {
|
|
||||||
ret := *c
|
ret := *c
|
||||||
ret.namespace = ns
|
ret.namespace = ns
|
||||||
return &ret
|
return &ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) {
|
||||||
uncastRet, err := c.client.Fake.
|
var uncastRet runtime.Object
|
||||||
Invokes(testing.NewCreateAction(c.resource, c.namespace, obj), obj)
|
var err error
|
||||||
|
switch {
|
||||||
|
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootCreateAction(c.resource, obj), obj)
|
||||||
|
|
||||||
|
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||||
|
accessor, err := meta.Accessor(obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
name := accessor.GetName()
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), obj), obj)
|
||||||
|
|
||||||
|
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewCreateAction(c.resource, c.namespace, obj), obj)
|
||||||
|
|
||||||
|
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||||
|
accessor, err := meta.Accessor(obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
name := accessor.GetName()
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), c.namespace, obj), obj)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -109,9 +128,27 @@ func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstruc
|
|||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) {
|
||||||
uncastRet, err := c.client.Fake.
|
var uncastRet runtime.Object
|
||||||
Invokes(testing.NewUpdateAction(c.resource, c.namespace, obj), obj)
|
var err error
|
||||||
|
switch {
|
||||||
|
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootUpdateAction(c.resource, obj), obj)
|
||||||
|
|
||||||
|
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), obj), obj)
|
||||||
|
|
||||||
|
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewUpdateAction(c.resource, c.namespace, obj), obj)
|
||||||
|
|
||||||
|
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, obj), obj)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -128,8 +165,18 @@ func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstruc
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
||||||
uncastRet, err := c.client.Fake.
|
var uncastRet runtime.Object
|
||||||
Invokes(testing.NewUpdateSubresourceAction(c.resource, "status", c.namespace, obj), obj)
|
var err error
|
||||||
|
switch {
|
||||||
|
case len(c.namespace) == 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootUpdateSubresourceAction(c.resource, "status", obj), obj)
|
||||||
|
|
||||||
|
case len(c.namespace) > 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewUpdateSubresourceAction(c.resource, "status", c.namespace, obj), obj)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -145,23 +192,65 @@ func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*u
|
|||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
|
||||||
_, err := c.client.Fake.
|
var err error
|
||||||
Invokes(testing.NewDeleteAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic delete fail"})
|
switch {
|
||||||
|
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||||
|
_, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootDeleteAction(c.resource, name), &metav1.Status{Status: "dynamic delete fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||||
|
_, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic delete fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||||
|
_, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewDeleteAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic delete fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||||
|
_, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, name), &metav1.Status{Status: "dynamic delete fail"})
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||||
action := testing.NewDeleteCollectionAction(c.resource, c.namespace, listOptions)
|
var err error
|
||||||
|
switch {
|
||||||
|
case len(c.namespace) == 0:
|
||||||
|
action := testing.NewRootDeleteCollectionAction(c.resource, listOptions)
|
||||||
|
_, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) > 0:
|
||||||
|
action := testing.NewDeleteCollectionAction(c.resource, c.namespace, listOptions)
|
||||||
|
_, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
_, err := c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"})
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) {
|
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||||
uncastRet, err := c.client.Fake.
|
var uncastRet runtime.Object
|
||||||
Invokes(testing.NewGetAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic get fail"})
|
var err error
|
||||||
|
switch {
|
||||||
|
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootGetAction(c.resource, name), &metav1.Status{Status: "dynamic get fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootGetSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic get fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewGetAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic get fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewGetSubresourceAction(c.resource, c.namespace, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic get fail"})
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -178,8 +267,18 @@ func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstr
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
|
func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
|
||||||
obj, err := c.client.Fake.
|
var obj runtime.Object
|
||||||
Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"})
|
var err error
|
||||||
|
switch {
|
||||||
|
case len(c.namespace) == 0:
|
||||||
|
obj, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, opts), &metav1.Status{Status: "dynamic list fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) > 0:
|
||||||
|
obj, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -213,13 +312,41 @@ func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.Uns
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
return c.client.Fake.
|
switch {
|
||||||
InvokesWatch(testing.NewWatchAction(c.resource, c.namespace, opts))
|
case len(c.namespace) == 0:
|
||||||
|
return c.client.Fake.
|
||||||
|
InvokesWatch(testing.NewRootWatchAction(c.resource, opts))
|
||||||
|
|
||||||
|
case len(c.namespace) > 0:
|
||||||
|
return c.client.Fake.
|
||||||
|
InvokesWatch(testing.NewWatchAction(c.resource, c.namespace, opts))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("math broke")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error) {
|
func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error) {
|
||||||
uncastRet, err := c.client.Fake.
|
var uncastRet runtime.Object
|
||||||
Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"})
|
var err error
|
||||||
|
switch {
|
||||||
|
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootPatchAction(c.resource, name, data), &metav1.Status{Status: "dynamic patch fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewPatchAction(c.resource, c.namespace, name, data), &metav1.Status{Status: "dynamic patch fail"})
|
||||||
|
|
||||||
|
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||||
|
uncastRet, err = c.client.Fake.
|
||||||
|
Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
59
staging/src/k8s.io/client-go/dynamic/interface.go
Normal file
59
staging/src/k8s.io/client-go/dynamic/interface.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
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 (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Interface interface {
|
||||||
|
Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResourceInterface interface {
|
||||||
|
Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error)
|
||||||
|
Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error)
|
||||||
|
UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
|
||||||
|
Delete(name string, options *metav1.DeleteOptions, subresources ...string) error
|
||||||
|
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
|
||||||
|
Get(name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error)
|
||||||
|
List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
|
||||||
|
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||||
|
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type NamespaceableResourceInterface interface {
|
||||||
|
Namespace(string) ResourceInterface
|
||||||
|
ResourceInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is optional.
|
||||||
|
// TODO find a better place to move this for existing callers
|
||||||
|
type APIPathResolverFunc func(kind schema.GroupVersionKind) string
|
||||||
|
|
||||||
|
// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API.
|
||||||
|
// TODO find a better place to move this for existing callers
|
||||||
|
func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string {
|
||||||
|
if len(kind.Group) == 0 {
|
||||||
|
return "/api"
|
||||||
|
}
|
||||||
|
return "/apis"
|
||||||
|
}
|
||||||
@@ -17,7 +17,6 @@ limitations under the License.
|
|||||||
package dynamic
|
package dynamic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
@@ -31,39 +30,13 @@ import (
|
|||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DynamicInterface interface {
|
|
||||||
Resource(resource schema.GroupVersionResource) NamespaceableDynamicResourceInterface
|
|
||||||
|
|
||||||
// Deprecated, this isn't how we want to do it
|
|
||||||
ClusterSubresource(resource schema.GroupVersionResource, subresource string) DynamicResourceInterface
|
|
||||||
// Deprecated, this isn't how we want to do it
|
|
||||||
NamespacedSubresource(resource schema.GroupVersionResource, subresource, namespace string) DynamicResourceInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
type DynamicResourceInterface interface {
|
|
||||||
Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
|
|
||||||
Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
|
|
||||||
UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
|
|
||||||
Delete(name string, options *metav1.DeleteOptions) error
|
|
||||||
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
|
|
||||||
Get(name string, options metav1.GetOptions) (*unstructured.Unstructured, error)
|
|
||||||
List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
|
|
||||||
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
|
||||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type NamespaceableDynamicResourceInterface interface {
|
|
||||||
Namespace(string) DynamicResourceInterface
|
|
||||||
DynamicResourceInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
type dynamicClient struct {
|
type dynamicClient struct {
|
||||||
client *rest.RESTClient
|
client *rest.RESTClient
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ DynamicInterface = &dynamicClient{}
|
var _ Interface = &dynamicClient{}
|
||||||
|
|
||||||
func NewForConfig(inConfig *rest.Config) (DynamicInterface, error) {
|
func NewForConfig(inConfig *rest.Config) (Interface, error) {
|
||||||
config := rest.CopyConfig(inConfig)
|
config := rest.CopyConfig(inConfig)
|
||||||
// for serializing the options
|
// for serializing the options
|
||||||
config.GroupVersion = &schema.GroupVersion{}
|
config.GroupVersion = &schema.GroupVersion{}
|
||||||
@@ -84,40 +57,36 @@ func NewForConfig(inConfig *rest.Config) (DynamicInterface, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type dynamicResourceClient struct {
|
type dynamicResourceClient struct {
|
||||||
client *dynamicClient
|
client *dynamicClient
|
||||||
namespace string
|
namespace string
|
||||||
resource schema.GroupVersionResource
|
resource schema.GroupVersionResource
|
||||||
subresource string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableDynamicResourceInterface {
|
func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface {
|
||||||
return &dynamicResourceClient{client: c, resource: resource}
|
return &dynamicResourceClient{client: c, resource: resource}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicClient) ClusterSubresource(resource schema.GroupVersionResource, subresource string) DynamicResourceInterface {
|
func (c *dynamicResourceClient) Namespace(ns string) ResourceInterface {
|
||||||
return &dynamicResourceClient{client: c, resource: resource, subresource: subresource}
|
|
||||||
}
|
|
||||||
func (c *dynamicClient) NamespacedSubresource(resource schema.GroupVersionResource, subresource, namespace string) DynamicResourceInterface {
|
|
||||||
return &dynamicResourceClient{client: c, resource: resource, namespace: namespace, subresource: subresource}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Namespace(ns string) DynamicResourceInterface {
|
|
||||||
ret := *c
|
ret := *c
|
||||||
ret.namespace = ns
|
ret.namespace = ns
|
||||||
return &ret
|
return &ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) {
|
||||||
if len(c.subresource) > 0 {
|
|
||||||
return nil, fmt.Errorf("create not supported for subresources")
|
|
||||||
}
|
|
||||||
|
|
||||||
outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
|
outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
name := ""
|
||||||
|
if len(subresources) > 0 {
|
||||||
|
accessor, err := meta.Accessor(obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
name = accessor.GetName()
|
||||||
|
}
|
||||||
|
|
||||||
result := c.client.client.Post().AbsPath(c.makeURLSegments("")...).Body(outBytes).Do()
|
result := c.client.client.Post().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(outBytes).Do()
|
||||||
if err := result.Error(); err != nil {
|
if err := result.Error(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -133,7 +102,7 @@ func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstruc
|
|||||||
return uncastObj.(*unstructured.Unstructured), nil
|
return uncastObj.(*unstructured.Unstructured), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
|
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) {
|
||||||
accessor, err := meta.Accessor(obj)
|
accessor, err := meta.Accessor(obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -143,7 +112,7 @@ func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstruc
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result := c.client.client.Put().AbsPath(c.makeURLSegments(accessor.GetName())...).Body(outBytes).Do()
|
result := c.client.client.Put().AbsPath(append(c.makeURLSegments(accessor.GetName()), subresources...)...).Body(outBytes).Do()
|
||||||
if err := result.Error(); err != nil {
|
if err := result.Error(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -171,6 +140,10 @@ func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*u
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := c.client.client.Put().AbsPath(append(c.makeURLSegments(accessor.GetName()), "status")...).Body(outBytes).Do()
|
result := c.client.client.Put().AbsPath(append(c.makeURLSegments(accessor.GetName()), "status")...).Body(outBytes).Do()
|
||||||
|
if err := result.Error(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
retBytes, err := result.Raw()
|
retBytes, err := result.Raw()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -182,7 +155,7 @@ func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*u
|
|||||||
return uncastObj.(*unstructured.Unstructured), nil
|
return uncastObj.(*unstructured.Unstructured), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
|
||||||
if opts == nil {
|
if opts == nil {
|
||||||
opts = &metav1.DeleteOptions{}
|
opts = &metav1.DeleteOptions{}
|
||||||
}
|
}
|
||||||
@@ -191,15 +164,11 @@ func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result := c.client.client.Delete().AbsPath(c.makeURLSegments(name)...).Body(deleteOptionsByte).Do()
|
result := c.client.client.Delete().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(deleteOptionsByte).Do()
|
||||||
return result.Error()
|
return result.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||||
if len(c.subresource) > 0 {
|
|
||||||
return fmt.Errorf("deletecollection not supported for subresources")
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts == nil {
|
if opts == nil {
|
||||||
opts = &metav1.DeleteOptions{}
|
opts = &metav1.DeleteOptions{}
|
||||||
}
|
}
|
||||||
@@ -212,8 +181,8 @@ func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, lis
|
|||||||
return result.Error()
|
return result.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) {
|
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||||
result := c.client.client.Get().AbsPath(c.makeURLSegments(name)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
|
result := c.client.client.Get().AbsPath(append(c.makeURLSegments(name), subresources...)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
|
||||||
if err := result.Error(); err != nil {
|
if err := result.Error(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -229,10 +198,6 @@ func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstr
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
|
func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
|
||||||
if len(c.subresource) > 0 {
|
|
||||||
return nil, fmt.Errorf("list not supported for subresources")
|
|
||||||
}
|
|
||||||
|
|
||||||
result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
|
result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
|
||||||
if err := result.Error(); err != nil {
|
if err := result.Error(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -257,10 +222,6 @@ func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.Uns
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
if len(c.subresource) > 0 {
|
|
||||||
return nil, fmt.Errorf("watch not supported for subresources")
|
|
||||||
}
|
|
||||||
|
|
||||||
internalGV := schema.GroupVersions{
|
internalGV := schema.GroupVersions{
|
||||||
{Group: c.resource.Group, Version: runtime.APIVersionInternal},
|
{Group: c.resource.Group, Version: runtime.APIVersionInternal},
|
||||||
// always include the legacy group as a decoding target to handle non-error `Status` return types
|
// always include the legacy group as a decoding target to handle non-error `Status` return types
|
||||||
@@ -320,15 +281,6 @@ func (c *dynamicResourceClient) makeURLSegments(name string) []string {
|
|||||||
|
|
||||||
if len(name) > 0 {
|
if len(name) > 0 {
|
||||||
url = append(url, name)
|
url = append(url, name)
|
||||||
|
|
||||||
// subresources only work on things with names
|
|
||||||
if len(c.subresource) > 0 {
|
|
||||||
url = append(url, c.subresource)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if len(c.subresource) > 0 {
|
|
||||||
panic("somehow snuck a subresource and an empty name. programmer error")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return url
|
return url
|
||||||
|
|||||||
@@ -225,6 +225,16 @@ func NewRootDeleteAction(resource schema.GroupVersionResource, name string) Dele
|
|||||||
return action
|
return action
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewRootDeleteSubresourceAction(resource schema.GroupVersionResource, subresource string, name string) DeleteActionImpl {
|
||||||
|
action := DeleteActionImpl{}
|
||||||
|
action.Verb = "delete"
|
||||||
|
action.Resource = resource
|
||||||
|
action.Subresource = subresource
|
||||||
|
action.Name = name
|
||||||
|
|
||||||
|
return action
|
||||||
|
}
|
||||||
|
|
||||||
func NewDeleteAction(resource schema.GroupVersionResource, namespace, name string) DeleteActionImpl {
|
func NewDeleteAction(resource schema.GroupVersionResource, namespace, name string) DeleteActionImpl {
|
||||||
action := DeleteActionImpl{}
|
action := DeleteActionImpl{}
|
||||||
action.Verb = "delete"
|
action.Verb = "delete"
|
||||||
@@ -235,6 +245,17 @@ func NewDeleteAction(resource schema.GroupVersionResource, namespace, name strin
|
|||||||
return action
|
return action
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDeleteSubresourceAction(resource schema.GroupVersionResource, subresource, namespace, name string) DeleteActionImpl {
|
||||||
|
action := DeleteActionImpl{}
|
||||||
|
action.Verb = "delete"
|
||||||
|
action.Resource = resource
|
||||||
|
action.Subresource = subresource
|
||||||
|
action.Namespace = namespace
|
||||||
|
action.Name = name
|
||||||
|
|
||||||
|
return action
|
||||||
|
}
|
||||||
|
|
||||||
func NewRootDeleteCollectionAction(resource schema.GroupVersionResource, opts interface{}) DeleteCollectionActionImpl {
|
func NewRootDeleteCollectionAction(resource schema.GroupVersionResource, opts interface{}) DeleteCollectionActionImpl {
|
||||||
action := DeleteCollectionActionImpl{}
|
action := DeleteCollectionActionImpl{}
|
||||||
action.Verb = "delete-collection"
|
action.Verb = "delete-collection"
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ var _ = SIGDescribe("CustomResourceDefinition Watch", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
func watchCRWithName(crdResourceClient dynamic.DynamicResourceInterface, name string) (watch.Interface, error) {
|
func watchCRWithName(crdResourceClient dynamic.ResourceInterface, name string) (watch.Interface, error) {
|
||||||
return crdResourceClient.Watch(
|
return crdResourceClient.Watch(
|
||||||
metav1.ListOptions{
|
metav1.ListOptions{
|
||||||
FieldSelector: "metadata.name=" + name,
|
FieldSelector: "metadata.name=" + name,
|
||||||
@@ -124,7 +124,7 @@ func watchCRWithName(crdResourceClient dynamic.DynamicResourceInterface, name st
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func instantiateCustomResource(instanceToCreate *unstructured.Unstructured, client dynamic.DynamicResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) {
|
func instantiateCustomResource(instanceToCreate *unstructured.Unstructured, client dynamic.ResourceInterface, definition *apiextensionsv1beta1.CustomResourceDefinition) (*unstructured.Unstructured, error) {
|
||||||
createdInstance, err := client.Create(instanceToCreate)
|
createdInstance, err := client.Create(instanceToCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -150,11 +150,11 @@ func instantiateCustomResource(instanceToCreate *unstructured.Unstructured, clie
|
|||||||
return createdInstance, nil
|
return createdInstance, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteCustomResource(client dynamic.DynamicResourceInterface, name string) error {
|
func deleteCustomResource(client dynamic.ResourceInterface, name string) error {
|
||||||
return client.Delete(name, &metav1.DeleteOptions{})
|
return client.Delete(name, &metav1.DeleteOptions{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNamespacedCustomResourceClient(ns string, client dynamic.DynamicInterface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.DynamicResourceInterface {
|
func newNamespacedCustomResourceClient(ns string, client dynamic.Interface, crd *apiextensionsv1beta1.CustomResourceDefinition) dynamic.ResourceInterface {
|
||||||
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}
|
gvr := schema.GroupVersionResource{Group: crd.Spec.Group, Version: crd.Spec.Version, Resource: crd.Spec.Names.Plural}
|
||||||
|
|
||||||
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
if crd.Spec.Scope != apiextensionsv1beta1.ClusterScoped {
|
||||||
|
|||||||
@@ -1081,7 +1081,7 @@ func registerMutatingWebhookForCustomResource(f *framework.Framework, context *c
|
|||||||
return func() { client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Delete(configName, nil) }
|
return func() { client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Delete(configName, nil) }
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCustomResourceWebhook(f *framework.Framework, crd *apiextensionsv1beta1.CustomResourceDefinition, customResourceClient dynamic.DynamicResourceInterface) {
|
func testCustomResourceWebhook(f *framework.Framework, crd *apiextensionsv1beta1.CustomResourceDefinition, customResourceClient dynamic.ResourceInterface) {
|
||||||
By("Creating a custom resource that should be denied by the webhook")
|
By("Creating a custom resource that should be denied by the webhook")
|
||||||
crInstance := &unstructured.Unstructured{
|
crInstance := &unstructured.Unstructured{
|
||||||
Object: map[string]interface{}{
|
Object: map[string]interface{}{
|
||||||
@@ -1104,7 +1104,7 @@ func testCustomResourceWebhook(f *framework.Framework, crd *apiextensionsv1beta1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testMutatingCustomResourceWebhook(f *framework.Framework, crd *apiextensionsv1beta1.CustomResourceDefinition, customResourceClient dynamic.DynamicResourceInterface) {
|
func testMutatingCustomResourceWebhook(f *framework.Framework, crd *apiextensionsv1beta1.CustomResourceDefinition, customResourceClient dynamic.ResourceInterface) {
|
||||||
By("Creating a custom resource that should be mutated by the webhook")
|
By("Creating a custom resource that should be mutated by the webhook")
|
||||||
cr := &unstructured.Unstructured{
|
cr := &unstructured.Unstructured{
|
||||||
Object: map[string]interface{}{
|
Object: map[string]interface{}{
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ type TestCrd struct {
|
|||||||
ApiVersion string
|
ApiVersion string
|
||||||
ApiExtensionClient *crdclientset.Clientset
|
ApiExtensionClient *crdclientset.Clientset
|
||||||
Crd *apiextensionsv1beta1.CustomResourceDefinition
|
Crd *apiextensionsv1beta1.CustomResourceDefinition
|
||||||
DynamicClient dynamic.DynamicResourceInterface
|
DynamicClient dynamic.ResourceInterface
|
||||||
CleanUp CleanCrdFn
|
CleanUp CleanCrdFn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ type Framework struct {
|
|||||||
|
|
||||||
InternalClientset *internalclientset.Clientset
|
InternalClientset *internalclientset.Clientset
|
||||||
AggregatorClient *aggregatorclient.Clientset
|
AggregatorClient *aggregatorclient.Clientset
|
||||||
DynamicClient dynamic.DynamicInterface
|
DynamicClient dynamic.Interface
|
||||||
|
|
||||||
ScalesGetter scaleclient.ScalesGetter
|
ScalesGetter scaleclient.ScalesGetter
|
||||||
|
|
||||||
|
|||||||
@@ -506,7 +506,7 @@ func SkipUnlessServerVersionGTE(v *utilversion.Version, c discovery.ServerVersio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SkipIfMissingResource(dynamicClient dynamic.DynamicInterface, gvr schema.GroupVersionResource, namespace string) {
|
func SkipIfMissingResource(dynamicClient dynamic.Interface, gvr schema.GroupVersionResource, namespace string) {
|
||||||
resourceClient := dynamicClient.Resource(gvr).Namespace(namespace)
|
resourceClient := dynamicClient.Resource(gvr).Namespace(namespace)
|
||||||
_, err := resourceClient.List(metav1.ListOptions{})
|
_, err := resourceClient.List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1086,7 +1086,7 @@ func CheckTestingNSDeletedExcept(c clientset.Interface, skip string) error {
|
|||||||
|
|
||||||
// deleteNS deletes the provided namespace, waits for it to be completely deleted, and then checks
|
// deleteNS deletes the provided namespace, waits for it to be completely deleted, and then checks
|
||||||
// whether there are any pods remaining in a non-terminating state.
|
// whether there are any pods remaining in a non-terminating state.
|
||||||
func deleteNS(c clientset.Interface, dynamicClient dynamic.DynamicInterface, namespace string, timeout time.Duration) error {
|
func deleteNS(c clientset.Interface, dynamicClient dynamic.Interface, namespace string, timeout time.Duration) error {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
if err := c.CoreV1().Namespaces().Delete(namespace, nil); err != nil {
|
if err := c.CoreV1().Namespaces().Delete(namespace, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -1232,7 +1232,7 @@ func isDynamicDiscoveryError(err error) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// hasRemainingContent checks if there is remaining content in the namespace via API discovery
|
// hasRemainingContent checks if there is remaining content in the namespace via API discovery
|
||||||
func hasRemainingContent(c clientset.Interface, dynamicClient dynamic.DynamicInterface, namespace string) (bool, error) {
|
func hasRemainingContent(c clientset.Interface, dynamicClient dynamic.Interface, namespace string) (bool, error) {
|
||||||
// some tests generate their own framework.Client rather than the default
|
// some tests generate their own framework.Client rather than the default
|
||||||
// TODO: ensure every test call has a configured dynamicClient
|
// TODO: ensure every test call has a configured dynamicClient
|
||||||
if dynamicClient == nil {
|
if dynamicClient == nil {
|
||||||
|
|||||||
@@ -46,29 +46,12 @@ func TestDynamicClient(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
client := clientset.NewForConfigOrDie(config)
|
client := clientset.NewForConfigOrDie(config)
|
||||||
dynamicClient, err := dynamic.NewClient(config, *gv)
|
dynamicClient, err := dynamic.NewForConfig(config)
|
||||||
_ = dynamicClient
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error creating dynamic client: %v", err)
|
t.Fatalf("unexpected error creating dynamic client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the Pod resource
|
resource := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
|
||||||
resources, err := client.Discovery().ServerResourcesForGroupVersion(gv.String())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error listing resources: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var resource metav1.APIResource
|
|
||||||
for _, r := range resources.APIResources {
|
|
||||||
if r.Kind == "Pod" {
|
|
||||||
resource = r
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(resource.Name) == 0 {
|
|
||||||
t.Fatalf("could not find the pod resource in group/version %q", gv.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a Pod with the normal client
|
// Create a Pod with the normal client
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
@@ -91,11 +74,7 @@ func TestDynamicClient(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check dynamic list
|
// check dynamic list
|
||||||
obj, err := dynamicClient.Resource(&resource, ns.Name).List(metav1.ListOptions{})
|
unstructuredList, err := dynamicClient.Resource(resource).Namespace(ns.Name).List(metav1.ListOptions{})
|
||||||
unstructuredList, ok := obj.(*unstructured.UnstructuredList)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("expected *unstructured.UnstructuredList, got %#v", obj)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error when listing pods: %v", err)
|
t.Fatalf("unexpected error when listing pods: %v", err)
|
||||||
}
|
}
|
||||||
@@ -114,7 +93,7 @@ func TestDynamicClient(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check dynamic get
|
// check dynamic get
|
||||||
unstruct, err := dynamicClient.Resource(&resource, ns.Name).Get(actual.Name, metav1.GetOptions{})
|
unstruct, err := dynamicClient.Resource(resource).Namespace(ns.Name).Get(actual.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error when getting pod %q: %v", actual.Name, err)
|
t.Fatalf("unexpected error when getting pod %q: %v", actual.Name, err)
|
||||||
}
|
}
|
||||||
@@ -129,7 +108,7 @@ func TestDynamicClient(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete the pod dynamically
|
// delete the pod dynamically
|
||||||
err = dynamicClient.Resource(&resource, ns.Name).Delete(actual.Name, nil)
|
err = dynamicClient.Resource(resource).Namespace(ns.Name).Delete(actual.Name, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error when deleting pod: %v", err)
|
t.Fatalf("unexpected error when deleting pod: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,9 +168,9 @@ func link(t *testing.T, owner, dependent metav1.Object) {
|
|||||||
|
|
||||||
func createRandomCustomResourceDefinition(
|
func createRandomCustomResourceDefinition(
|
||||||
t *testing.T, apiExtensionClient apiextensionsclientset.Interface,
|
t *testing.T, apiExtensionClient apiextensionsclientset.Interface,
|
||||||
dynamicClient dynamic.DynamicInterface,
|
dynamicClient dynamic.Interface,
|
||||||
namespace string,
|
namespace string,
|
||||||
) (*apiextensionsv1beta1.CustomResourceDefinition, dynamic.DynamicResourceInterface) {
|
) (*apiextensionsv1beta1.CustomResourceDefinition, dynamic.ResourceInterface) {
|
||||||
// Create a random custom resource definition and ensure it's available for
|
// Create a random custom resource definition and ensure it's available for
|
||||||
// use.
|
// use.
|
||||||
definition := apiextensionstestserver.NewRandomNameCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
definition := apiextensionstestserver.NewRandomNameCustomResourceDefinition(apiextensionsv1beta1.NamespaceScoped)
|
||||||
@@ -193,7 +193,7 @@ type testContext struct {
|
|||||||
gc *garbagecollector.GarbageCollector
|
gc *garbagecollector.GarbageCollector
|
||||||
clientSet clientset.Interface
|
clientSet clientset.Interface
|
||||||
apiExtensionClient apiextensionsclientset.Interface
|
apiExtensionClient apiextensionsclientset.Interface
|
||||||
dynamicClient dynamic.DynamicInterface
|
dynamicClient dynamic.Interface
|
||||||
startGC func(workers int)
|
startGC func(workers int)
|
||||||
// syncPeriod is how often the GC started with startGC will be resynced.
|
// syncPeriod is how often the GC started with startGC will be resynced.
|
||||||
syncPeriod time.Duration
|
syncPeriod time.Duration
|
||||||
|
|||||||
@@ -150,14 +150,12 @@ func TestCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Trying to access foos.cr.bar.com with dynamic client")
|
t.Logf("Trying to access foos.cr.bar.com with dynamic client")
|
||||||
barComConfig := *result.ClientConfig
|
dynamicClient, err := dynamic.NewForConfig(result.ClientConfig)
|
||||||
barComConfig.GroupVersion = &schema.GroupVersion{Group: "cr.bar.com", Version: "v1"}
|
|
||||||
barComConfig.APIPath = "/apis"
|
|
||||||
barComClient, err := dynamic.NewClient(&barComConfig, *barComConfig.GroupVersion)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected error: %v", err)
|
t.Fatalf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
_, err = barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").List(metav1.ListOptions{})
|
fooResource := schema.GroupVersionResource{Group: "cr.bar.com", Version: "v1", Resource: "foos"}
|
||||||
|
_, err = dynamicClient.Resource(fooResource).Namespace("default").List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to list foos.cr.bar.com instances: %v", err)
|
t.Errorf("Failed to list foos.cr.bar.com instances: %v", err)
|
||||||
}
|
}
|
||||||
@@ -201,7 +199,7 @@ func TestCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
createErr := make(chan error, 1)
|
createErr := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
_, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Create(unstructuredFoo)
|
_, err := dynamicClient.Resource(fooResource).Namespace("default").Create(unstructuredFoo)
|
||||||
t.Logf("Foo instance create returned: %v", err)
|
t.Logf("Foo instance create returned: %v", err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
createErr <- err
|
createErr <- err
|
||||||
@@ -216,7 +214,7 @@ func TestCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Checking that Foo instance is visible with IncludeUninitialized=true")
|
t.Logf("Checking that Foo instance is visible with IncludeUninitialized=true")
|
||||||
_, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{
|
_, err := dynamicClient.Resource(fooResource).Namespace("default").Get(foo.ObjectMeta.Name, metav1.GetOptions{
|
||||||
IncludeUninitialized: true,
|
IncludeUninitialized: true,
|
||||||
})
|
})
|
||||||
switch {
|
switch {
|
||||||
@@ -237,7 +235,7 @@ func TestCRD(t *testing.T) {
|
|||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
// would love to replace the following with a patch, but removing strings from the intitializer array
|
// would love to replace the following with a patch, but removing strings from the intitializer array
|
||||||
// is not what JSON (Merge) patch authors had in mind.
|
// is not what JSON (Merge) patch authors had in mind.
|
||||||
fooUnstructured, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{
|
fooUnstructured, err := dynamicClient.Resource(fooResource).Namespace("default").Get(foo.ObjectMeta.Name, metav1.GetOptions{
|
||||||
IncludeUninitialized: true,
|
IncludeUninitialized: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -274,7 +272,7 @@ func TestCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
fooUnstructured.UnmarshalJSON(bs)
|
fooUnstructured.UnmarshalJSON(bs)
|
||||||
|
|
||||||
_, err = barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Update(fooUnstructured)
|
_, err = dynamicClient.Resource(fooResource).Namespace("default").Update(fooUnstructured)
|
||||||
if err != nil && !errors.IsConflict(err) {
|
if err != nil && !errors.IsConflict(err) {
|
||||||
t.Fatalf("Failed to update Foo instance: %v", err)
|
t.Fatalf("Failed to update Foo instance: %v", err)
|
||||||
} else if err == nil {
|
} else if err == nil {
|
||||||
@@ -287,7 +285,7 @@ func TestCRD(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Checking that Foo instance is visible after removing the initializer")
|
t.Logf("Checking that Foo instance is visible after removing the initializer")
|
||||||
if _, err := barComClient.Resource(&metav1.APIResource{Name: "foos", Namespaced: true}, "default").Get(foo.ObjectMeta.Name, metav1.GetOptions{}); err != nil {
|
if _, err := dynamicClient.Resource(fooResource).Namespace("default").Get(foo.ObjectMeta.Name, metav1.GetOptions{}); err != nil {
|
||||||
t.Errorf("Unexpected error: %v", err)
|
t.Errorf("Unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user