From d9c32d7ac47a1c1aa1f9ca5e0b5d88061b4fefeb Mon Sep 17 00:00:00 2001 From: Solly Ross Date: Fri, 5 May 2017 14:47:38 -0400 Subject: [PATCH] [client-go] Add fake dynamic Client/ClientPool This introduces fake implementations of dynamic.Client and dynamic.ClientPool. They function similarly to the fake generated clientsets, since they're also based in testing.Fake. Kubernetes-commit: 3e6bf24e08645512a7b40d91bd61f0f2ea175026 --- dynamic/fake/BUILD | 29 +++++++ dynamic/fake/client.go | 163 ++++++++++++++++++++++++++++++++++++ dynamic/fake/client_pool.go | 48 +++++++++++ 3 files changed, 240 insertions(+) create mode 100644 dynamic/fake/BUILD create mode 100644 dynamic/fake/client.go create mode 100644 dynamic/fake/client_pool.go diff --git a/dynamic/fake/BUILD b/dynamic/fake/BUILD new file mode 100644 index 00000000..f2e8d40c --- /dev/null +++ b/dynamic/fake/BUILD @@ -0,0 +1,29 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "client.go", + "client_pool.go", + ], + tags = ["automanaged"], + 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/labels: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/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/testing:go_default_library", + "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", + ], +) diff --git a/dynamic/fake/client.go b/dynamic/fake/client.go new file mode 100644 index 00000000..6c11d422 --- /dev/null +++ b/dynamic/fake/client.go @@ -0,0 +1,163 @@ +/* +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 paramater 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 +} diff --git a/dynamic/fake/client_pool.go b/dynamic/fake/client_pool.go new file mode 100644 index 00000000..7ec11489 --- /dev/null +++ b/dynamic/fake/client_pool.go @@ -0,0 +1,48 @@ +/* +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 +}