diff --git a/pkg/kubecrd/network_test.go b/pkg/kubecrd/network_test.go
new file mode 100644
index 0000000..86867e5
--- /dev/null
+++ b/pkg/kubecrd/network_test.go
@@ -0,0 +1,72 @@
+/*
+Copyright (c) 2017 OpenStack Foundation.
+
+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 kubecrd
+
+import (
+	"fmt"
+	"reflect"
+	"testing"
+
+	crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
+
+	"github.com/stretchr/testify/assert"
+	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
+	apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
+	apiextensionsclientfake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func createNetworkCRD(clientset apiextensionsclient.Interface) (*apiextensionsv1beta1.CustomResourceDefinition, error) {
+	crd := &apiextensionsv1beta1.CustomResourceDefinition{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: networkCRDName,
+		},
+		Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
+			Group:   crv1.GroupName,
+			Version: crv1.SchemeGroupVersion.Version,
+			Scope:   apiextensionsv1beta1.NamespaceScoped,
+			Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
+				Plural: crv1.NetworkResourcePlural,
+				Kind:   reflect.TypeOf(crv1.Network{}).Name(),
+			},
+		},
+	}
+	_, err := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd)
+	if err != nil {
+		return nil, err
+	}
+
+	return nil, nil
+}
+
+func TestCreateNetworkCRD(t *testing.T) {
+	clientset := apiextensionsclientfake.NewSimpleClientset()
+
+	_, err := createNetworkCRD(clientset)
+	assert.NoError(t, err)
+
+	networkCRD, err := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Get(networkCRDName, metav1.GetOptions{})
+	if err != nil {
+		panic(fmt.Errorf("CustomResourceDefinitions.Create: %+v", err))
+	}
+
+	assert.Equal(t, networkCRDName, networkCRD.ObjectMeta.Name)
+	assert.Equal(t, "networks", networkCRD.Spec.Names.Plural)
+	assert.Equal(t, "stackube.kubernetes.io", networkCRD.Spec.Group)
+	assert.Equal(t, "v1", networkCRD.Spec.Version)
+	assert.Equal(t, apiextensionsv1beta1.NamespaceScoped, networkCRD.Spec.Scope)
+}
diff --git a/pkg/kubecrd/tenant_test.go b/pkg/kubecrd/tenant_test.go
new file mode 100644
index 0000000..bc5d8fc
--- /dev/null
+++ b/pkg/kubecrd/tenant_test.go
@@ -0,0 +1,72 @@
+/*
+Copyright (c) 2017 OpenStack Foundation.
+
+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 kubecrd
+
+import (
+	"fmt"
+	"reflect"
+	"testing"
+
+	crv1 "git.openstack.org/openstack/stackube/pkg/apis/v1"
+
+	"github.com/stretchr/testify/assert"
+	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
+	apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
+	apiextensionsclientfake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func createTenantCRD(clientset apiextensionsclient.Interface) (*apiextensionsv1beta1.CustomResourceDefinition, error) {
+	crd := &apiextensionsv1beta1.CustomResourceDefinition{
+		ObjectMeta: metav1.ObjectMeta{
+			Name: tenantCRDName,
+		},
+		Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
+			Group:   crv1.GroupName,
+			Version: crv1.SchemeGroupVersion.Version,
+			Scope:   apiextensionsv1beta1.NamespaceScoped,
+			Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
+				Plural: crv1.TenantResourcePlural,
+				Kind:   reflect.TypeOf(crv1.Tenant{}).Name(),
+			},
+		},
+	}
+	_, err := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Create(crd)
+	if err != nil {
+		return nil, err
+	}
+
+	return nil, nil
+}
+
+func TestCreateTenantCRD(t *testing.T) {
+	clientset := apiextensionsclientfake.NewSimpleClientset()
+
+	_, err := createTenantCRD(clientset)
+	assert.NoError(t, err)
+
+	tenantCRD, err := clientset.ApiextensionsV1beta1().CustomResourceDefinitions().Get(tenantCRDName, metav1.GetOptions{})
+	if err != nil {
+		panic(fmt.Errorf("CustomResourceDefinitions.Create: %+v", err))
+	}
+
+	assert.Equal(t, tenantCRDName, tenantCRD.ObjectMeta.Name)
+	assert.Equal(t, "tenants", tenantCRD.Spec.Names.Plural)
+	assert.Equal(t, "stackube.kubernetes.io", tenantCRD.Spec.Group)
+	assert.Equal(t, "v1", tenantCRD.Spec.Version)
+	assert.Equal(t, apiextensionsv1beta1.NamespaceScoped, tenantCRD.Spec.Scope)
+}
diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/BUILD b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/BUILD
new file mode 100644
index 0000000..865adf9
--- /dev/null
+++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/BUILD
@@ -0,0 +1,32 @@
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+load(
+    "@io_bazel_rules_go//go:def.bzl",
+    "go_library",
+)
+
+go_library(
+    name = "go_default_library",
+    srcs = [
+        "clientset_generated.go",
+        "doc.go",
+        "register.go",
+    ],
+    tags = ["automanaged"],
+    deps = [
+        "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
+        "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library",
+        "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1:go_default_library",
+        "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/watch:go_default_library",
+        "//vendor/k8s.io/client-go/discovery:go_default_library",
+        "//vendor/k8s.io/client-go/discovery/fake:go_default_library",
+        "//vendor/k8s.io/client-go/testing:go_default_library",
+    ],
+)
diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go
new file mode 100644
index 0000000..84d7740
--- /dev/null
+++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go
@@ -0,0 +1,71 @@
+/*
+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
+
+import (
+	clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
+	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
+	fakeapiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/watch"
+	"k8s.io/client-go/discovery"
+	fakediscovery "k8s.io/client-go/discovery/fake"
+	"k8s.io/client-go/testing"
+)
+
+// NewSimpleClientset returns a clientset that will respond with the provided objects.
+// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
+// without applying any validations and/or defaults. It shouldn't be considered a replacement
+// for a real clientset and is mostly useful in simple unit tests.
+func NewSimpleClientset(objects ...runtime.Object) *Clientset {
+	o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
+	for _, obj := range objects {
+		if err := o.Add(obj); err != nil {
+			panic(err)
+		}
+	}
+
+	fakePtr := testing.Fake{}
+	fakePtr.AddReactor("*", "*", testing.ObjectReaction(o))
+
+	fakePtr.AddWatchReactor("*", testing.DefaultWatchReactor(watch.NewFake(), nil))
+
+	return &Clientset{fakePtr}
+}
+
+// Clientset implements clientset.Interface. Meant to be embedded into a
+// struct to get a default implementation. This makes faking out just the method
+// you want to test easier.
+type Clientset struct {
+	testing.Fake
+}
+
+func (c *Clientset) Discovery() discovery.DiscoveryInterface {
+	return &fakediscovery.FakeDiscovery{Fake: &c.Fake}
+}
+
+var _ clientset.Interface = &Clientset{}
+
+// ApiextensionsV1beta1 retrieves the ApiextensionsV1beta1Client
+func (c *Clientset) ApiextensionsV1beta1() apiextensionsv1beta1.ApiextensionsV1beta1Interface {
+	return &fakeapiextensionsv1beta1.FakeApiextensionsV1beta1{Fake: &c.Fake}
+}
+
+// Apiextensions retrieves the ApiextensionsV1beta1Client
+func (c *Clientset) Apiextensions() apiextensionsv1beta1.ApiextensionsV1beta1Interface {
+	return &fakeapiextensionsv1beta1.FakeApiextensionsV1beta1{Fake: &c.Fake}
+}
diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go
new file mode 100644
index 0000000..5f565b3
--- /dev/null
+++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+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.
+*/
+
+// This package is generated by client-gen with custom arguments.
+
+// This package has the automatically generated fake clientset.
+package fake
diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go
new file mode 100644
index 0000000..857e10e
--- /dev/null
+++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go
@@ -0,0 +1,53 @@
+/*
+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
+
+import (
+	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	serializer "k8s.io/apimachinery/pkg/runtime/serializer"
+)
+
+var scheme = runtime.NewScheme()
+var codecs = serializer.NewCodecFactory(scheme)
+var parameterCodec = runtime.NewParameterCodec(scheme)
+
+func init() {
+	v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
+	AddToScheme(scheme)
+}
+
+// AddToScheme adds all types of this clientset into the given scheme. This allows composition
+// of clientsets, like in:
+//
+//   import (
+//     "k8s.io/client-go/kubernetes"
+//     clientsetscheme "k8s.io/client-go/kuberentes/scheme"
+//     aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
+//   )
+//
+//   kclientset, _ := kubernetes.NewForConfig(c)
+//   aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
+//
+// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
+// correctly.
+func AddToScheme(scheme *runtime.Scheme) {
+	apiextensionsv1beta1.AddToScheme(scheme)
+
+}
diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/BUILD b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/BUILD
new file mode 100644
index 0000000..b2b9197
--- /dev/null
+++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/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 = [
+        "doc.go",
+        "fake_apiextensions_client.go",
+        "fake_customresourcedefinition.go",
+    ],
+    tags = ["automanaged"],
+    deps = [
+        "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
+        "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/labels: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/rest:go_default_library",
+        "//vendor/k8s.io/client-go/testing:go_default_library",
+    ],
+)
diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go
new file mode 100644
index 0000000..c654833
--- /dev/null
+++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go
@@ -0,0 +1,20 @@
+/*
+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.
+*/
+
+// This package is generated by client-gen with custom arguments.
+
+// Package fake has the automatically generated clients.
+package fake
diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go
new file mode 100644
index 0000000..252845f
--- /dev/null
+++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go
@@ -0,0 +1,38 @@
+/*
+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
+
+import (
+	v1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
+	rest "k8s.io/client-go/rest"
+	testing "k8s.io/client-go/testing"
+)
+
+type FakeApiextensionsV1beta1 struct {
+	*testing.Fake
+}
+
+func (c *FakeApiextensionsV1beta1) CustomResourceDefinitions() v1beta1.CustomResourceDefinitionInterface {
+	return &FakeCustomResourceDefinitions{c}
+}
+
+// RESTClient returns a RESTClient that is used to communicate
+// with API server by this client implementation.
+func (c *FakeApiextensionsV1beta1) RESTClient() rest.Interface {
+	var ret *rest.RESTClient
+	return ret
+}
diff --git a/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go
new file mode 100644
index 0000000..16d128d
--- /dev/null
+++ b/vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go
@@ -0,0 +1,121 @@
+/*
+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
+
+import (
+	v1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	labels "k8s.io/apimachinery/pkg/labels"
+	schema "k8s.io/apimachinery/pkg/runtime/schema"
+	types "k8s.io/apimachinery/pkg/types"
+	watch "k8s.io/apimachinery/pkg/watch"
+	testing "k8s.io/client-go/testing"
+)
+
+// FakeCustomResourceDefinitions implements CustomResourceDefinitionInterface
+type FakeCustomResourceDefinitions struct {
+	Fake *FakeApiextensionsV1beta1
+}
+
+var customresourcedefinitionsResource = schema.GroupVersionResource{Group: "apiextensions.k8s.io", Version: "v1beta1", Resource: "customresourcedefinitions"}
+
+var customresourcedefinitionsKind = schema.GroupVersionKind{Group: "apiextensions.k8s.io", Version: "v1beta1", Kind: "CustomResourceDefinition"}
+
+func (c *FakeCustomResourceDefinitions) Create(customResourceDefinition *v1beta1.CustomResourceDefinition) (result *v1beta1.CustomResourceDefinition, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootCreateAction(customresourcedefinitionsResource, customResourceDefinition), &v1beta1.CustomResourceDefinition{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1beta1.CustomResourceDefinition), err
+}
+
+func (c *FakeCustomResourceDefinitions) Update(customResourceDefinition *v1beta1.CustomResourceDefinition) (result *v1beta1.CustomResourceDefinition, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootUpdateAction(customresourcedefinitionsResource, customResourceDefinition), &v1beta1.CustomResourceDefinition{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1beta1.CustomResourceDefinition), err
+}
+
+func (c *FakeCustomResourceDefinitions) UpdateStatus(customResourceDefinition *v1beta1.CustomResourceDefinition) (*v1beta1.CustomResourceDefinition, error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootUpdateSubresourceAction(customresourcedefinitionsResource, "status", customResourceDefinition), &v1beta1.CustomResourceDefinition{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1beta1.CustomResourceDefinition), err
+}
+
+func (c *FakeCustomResourceDefinitions) Delete(name string, options *v1.DeleteOptions) error {
+	_, err := c.Fake.
+		Invokes(testing.NewRootDeleteAction(customresourcedefinitionsResource, name), &v1beta1.CustomResourceDefinition{})
+	return err
+}
+
+func (c *FakeCustomResourceDefinitions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
+	action := testing.NewRootDeleteCollectionAction(customresourcedefinitionsResource, listOptions)
+
+	_, err := c.Fake.Invokes(action, &v1beta1.CustomResourceDefinitionList{})
+	return err
+}
+
+func (c *FakeCustomResourceDefinitions) Get(name string, options v1.GetOptions) (result *v1beta1.CustomResourceDefinition, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootGetAction(customresourcedefinitionsResource, name), &v1beta1.CustomResourceDefinition{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1beta1.CustomResourceDefinition), err
+}
+
+func (c *FakeCustomResourceDefinitions) List(opts v1.ListOptions) (result *v1beta1.CustomResourceDefinitionList, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootListAction(customresourcedefinitionsResource, customresourcedefinitionsKind, opts), &v1beta1.CustomResourceDefinitionList{})
+	if obj == nil {
+		return nil, err
+	}
+
+	label, _, _ := testing.ExtractFromListOptions(opts)
+	if label == nil {
+		label = labels.Everything()
+	}
+	list := &v1beta1.CustomResourceDefinitionList{}
+	for _, item := range obj.(*v1beta1.CustomResourceDefinitionList).Items {
+		if label.Matches(labels.Set(item.Labels)) {
+			list.Items = append(list.Items, item)
+		}
+	}
+	return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested customResourceDefinitions.
+func (c *FakeCustomResourceDefinitions) Watch(opts v1.ListOptions) (watch.Interface, error) {
+	return c.Fake.
+		InvokesWatch(testing.NewRootWatchAction(customresourcedefinitionsResource, opts))
+}
+
+// Patch applies the patch and returns the patched customResourceDefinition.
+func (c *FakeCustomResourceDefinitions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CustomResourceDefinition, err error) {
+	obj, err := c.Fake.
+		Invokes(testing.NewRootPatchSubresourceAction(customresourcedefinitionsResource, name, data, subresources...), &v1beta1.CustomResourceDefinition{})
+	if obj == nil {
+		return nil, err
+	}
+	return obj.(*v1beta1.CustomResourceDefinition), err
+}
diff --git a/vendor/k8s.io/client-go/discovery/fake/BUILD b/vendor/k8s.io/client-go/discovery/fake/BUILD
new file mode 100644
index 0000000..8f8f078
--- /dev/null
+++ b/vendor/k8s.io/client-go/discovery/fake/BUILD
@@ -0,0 +1,25 @@
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+load(
+    "@io_bazel_rules_go//go:def.bzl",
+    "go_library",
+)
+
+go_library(
+    name = "go_default_library",
+    srcs = ["discovery.go"],
+    tags = ["automanaged"],
+    deps = [
+        "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library",
+        "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library",
+        "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/version:go_default_library",
+        "//vendor/k8s.io/client-go/pkg/version:go_default_library",
+        "//vendor/k8s.io/client-go/rest:go_default_library",
+        "//vendor/k8s.io/client-go/testing:go_default_library",
+    ],
+)
diff --git a/vendor/k8s.io/client-go/discovery/fake/discovery.go b/vendor/k8s.io/client-go/discovery/fake/discovery.go
new file mode 100644
index 0000000..02e77cf
--- /dev/null
+++ b/vendor/k8s.io/client-go/discovery/fake/discovery.go
@@ -0,0 +1,102 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package fake
+
+import (
+	"fmt"
+
+	"github.com/emicklei/go-restful-swagger12"
+	"github.com/googleapis/gnostic/OpenAPIv2"
+
+	"k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/version"
+	kubeversion "k8s.io/client-go/pkg/version"
+	restclient "k8s.io/client-go/rest"
+	"k8s.io/client-go/testing"
+)
+
+type FakeDiscovery struct {
+	*testing.Fake
+}
+
+func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) {
+	action := testing.ActionImpl{
+		Verb:     "get",
+		Resource: schema.GroupVersionResource{Resource: "resource"},
+	}
+	c.Invokes(action, nil)
+	for _, resourceList := range c.Resources {
+		if resourceList.GroupVersion == groupVersion {
+			return resourceList, nil
+		}
+	}
+	return nil, fmt.Errorf("GroupVersion %q not found", groupVersion)
+}
+
+func (c *FakeDiscovery) ServerResources() ([]*metav1.APIResourceList, error) {
+	action := testing.ActionImpl{
+		Verb:     "get",
+		Resource: schema.GroupVersionResource{Resource: "resource"},
+	}
+	c.Invokes(action, nil)
+	return c.Resources, nil
+}
+
+func (c *FakeDiscovery) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
+	return nil, nil
+}
+
+func (c *FakeDiscovery) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
+	return nil, nil
+}
+
+func (c *FakeDiscovery) ServerGroups() (*metav1.APIGroupList, error) {
+	return nil, nil
+}
+
+func (c *FakeDiscovery) ServerVersion() (*version.Info, error) {
+	action := testing.ActionImpl{}
+	action.Verb = "get"
+	action.Resource = schema.GroupVersionResource{Resource: "version"}
+
+	c.Invokes(action, nil)
+	versionInfo := kubeversion.Get()
+	return &versionInfo, nil
+}
+
+func (c *FakeDiscovery) SwaggerSchema(version schema.GroupVersion) (*swagger.ApiDeclaration, error) {
+	action := testing.ActionImpl{}
+	action.Verb = "get"
+	if version == v1.SchemeGroupVersion {
+		action.Resource = schema.GroupVersionResource{Resource: "/swaggerapi/api/" + version.Version}
+	} else {
+		action.Resource = schema.GroupVersionResource{Resource: "/swaggerapi/apis/" + version.Group + "/" + version.Version}
+	}
+
+	c.Invokes(action, nil)
+	return &swagger.ApiDeclaration{}, nil
+}
+
+func (c *FakeDiscovery) OpenAPISchema() (*openapi_v2.Document, error) {
+	return &openapi_v2.Document{}, nil
+}
+
+func (c *FakeDiscovery) RESTClient() restclient.Interface {
+	return nil
+}
diff --git a/vendor/k8s.io/client-go/testing/BUILD b/vendor/k8s.io/client-go/testing/BUILD
new file mode 100644
index 0000000..82bc5c1
--- /dev/null
+++ b/vendor/k8s.io/client-go/testing/BUILD
@@ -0,0 +1,31 @@
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+load(
+    "@io_bazel_rules_go//go:def.bzl",
+    "go_library",
+)
+
+go_library(
+    name = "go_default_library",
+    srcs = [
+        "actions.go",
+        "fake.go",
+        "fixture.go",
+    ],
+    tags = ["automanaged"],
+    deps = [
+        "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
+        "//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/fields: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/version:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
+        "//vendor/k8s.io/client-go/pkg/version:go_default_library",
+        "//vendor/k8s.io/client-go/rest:go_default_library",
+    ],
+)
diff --git a/vendor/k8s.io/client-go/testing/actions.go b/vendor/k8s.io/client-go/testing/actions.go
new file mode 100644
index 0000000..12a2ecf
--- /dev/null
+++ b/vendor/k8s.io/client-go/testing/actions.go
@@ -0,0 +1,478 @@
+/*
+Copyright 2015 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package testing
+
+import (
+	"fmt"
+	"path"
+	"strings"
+
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/fields"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+func NewRootGetAction(resource schema.GroupVersionResource, name string) GetActionImpl {
+	action := GetActionImpl{}
+	action.Verb = "get"
+	action.Resource = resource
+	action.Name = name
+
+	return action
+}
+
+func NewGetAction(resource schema.GroupVersionResource, namespace, name string) GetActionImpl {
+	action := GetActionImpl{}
+	action.Verb = "get"
+	action.Resource = resource
+	action.Namespace = namespace
+	action.Name = name
+
+	return action
+}
+
+func NewRootListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, opts interface{}) ListActionImpl {
+	action := ListActionImpl{}
+	action.Verb = "list"
+	action.Resource = resource
+	action.Kind = kind
+	labelSelector, fieldSelector, _ := ExtractFromListOptions(opts)
+	action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector}
+
+	return action
+}
+
+func NewListAction(resource schema.GroupVersionResource, kind schema.GroupVersionKind, namespace string, opts interface{}) ListActionImpl {
+	action := ListActionImpl{}
+	action.Verb = "list"
+	action.Resource = resource
+	action.Kind = kind
+	action.Namespace = namespace
+	labelSelector, fieldSelector, _ := ExtractFromListOptions(opts)
+	action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector}
+
+	return action
+}
+
+func NewRootCreateAction(resource schema.GroupVersionResource, object runtime.Object) CreateActionImpl {
+	action := CreateActionImpl{}
+	action.Verb = "create"
+	action.Resource = resource
+	action.Object = object
+
+	return action
+}
+
+func NewCreateAction(resource schema.GroupVersionResource, namespace string, object runtime.Object) CreateActionImpl {
+	action := CreateActionImpl{}
+	action.Verb = "create"
+	action.Resource = resource
+	action.Namespace = namespace
+	action.Object = object
+
+	return action
+}
+
+func NewRootUpdateAction(resource schema.GroupVersionResource, object runtime.Object) UpdateActionImpl {
+	action := UpdateActionImpl{}
+	action.Verb = "update"
+	action.Resource = resource
+	action.Object = object
+
+	return action
+}
+
+func NewUpdateAction(resource schema.GroupVersionResource, namespace string, object runtime.Object) UpdateActionImpl {
+	action := UpdateActionImpl{}
+	action.Verb = "update"
+	action.Resource = resource
+	action.Namespace = namespace
+	action.Object = object
+
+	return action
+}
+
+func NewRootPatchAction(resource schema.GroupVersionResource, name string, patch []byte) PatchActionImpl {
+	action := PatchActionImpl{}
+	action.Verb = "patch"
+	action.Resource = resource
+	action.Name = name
+	action.Patch = patch
+
+	return action
+}
+
+func NewPatchAction(resource schema.GroupVersionResource, namespace string, name string, patch []byte) PatchActionImpl {
+	action := PatchActionImpl{}
+	action.Verb = "patch"
+	action.Resource = resource
+	action.Namespace = namespace
+	action.Name = name
+	action.Patch = patch
+
+	return action
+}
+
+func NewRootPatchSubresourceAction(resource schema.GroupVersionResource, name string, patch []byte, subresources ...string) PatchActionImpl {
+	action := PatchActionImpl{}
+	action.Verb = "patch"
+	action.Resource = resource
+	action.Subresource = path.Join(subresources...)
+	action.Name = name
+	action.Patch = patch
+
+	return action
+}
+
+func NewPatchSubresourceAction(resource schema.GroupVersionResource, namespace, name string, patch []byte, subresources ...string) PatchActionImpl {
+	action := PatchActionImpl{}
+	action.Verb = "patch"
+	action.Resource = resource
+	action.Subresource = path.Join(subresources...)
+	action.Namespace = namespace
+	action.Name = name
+	action.Patch = patch
+
+	return action
+}
+
+func NewRootUpdateSubresourceAction(resource schema.GroupVersionResource, subresource string, object runtime.Object) UpdateActionImpl {
+	action := UpdateActionImpl{}
+	action.Verb = "update"
+	action.Resource = resource
+	action.Subresource = subresource
+	action.Object = object
+
+	return action
+}
+func NewUpdateSubresourceAction(resource schema.GroupVersionResource, subresource string, namespace string, object runtime.Object) UpdateActionImpl {
+	action := UpdateActionImpl{}
+	action.Verb = "update"
+	action.Resource = resource
+	action.Subresource = subresource
+	action.Namespace = namespace
+	action.Object = object
+
+	return action
+}
+
+func NewRootDeleteAction(resource schema.GroupVersionResource, name string) DeleteActionImpl {
+	action := DeleteActionImpl{}
+	action.Verb = "delete"
+	action.Resource = resource
+	action.Name = name
+
+	return action
+}
+
+func NewDeleteAction(resource schema.GroupVersionResource, namespace, name string) DeleteActionImpl {
+	action := DeleteActionImpl{}
+	action.Verb = "delete"
+	action.Resource = resource
+	action.Namespace = namespace
+	action.Name = name
+
+	return action
+}
+
+func NewRootDeleteCollectionAction(resource schema.GroupVersionResource, opts interface{}) DeleteCollectionActionImpl {
+	action := DeleteCollectionActionImpl{}
+	action.Verb = "delete-collection"
+	action.Resource = resource
+	labelSelector, fieldSelector, _ := ExtractFromListOptions(opts)
+	action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector}
+
+	return action
+}
+
+func NewDeleteCollectionAction(resource schema.GroupVersionResource, namespace string, opts interface{}) DeleteCollectionActionImpl {
+	action := DeleteCollectionActionImpl{}
+	action.Verb = "delete-collection"
+	action.Resource = resource
+	action.Namespace = namespace
+	labelSelector, fieldSelector, _ := ExtractFromListOptions(opts)
+	action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector}
+
+	return action
+}
+
+func NewRootWatchAction(resource schema.GroupVersionResource, opts interface{}) WatchActionImpl {
+	action := WatchActionImpl{}
+	action.Verb = "watch"
+	action.Resource = resource
+	labelSelector, fieldSelector, resourceVersion := ExtractFromListOptions(opts)
+	action.WatchRestrictions = WatchRestrictions{labelSelector, fieldSelector, resourceVersion}
+
+	return action
+}
+
+func ExtractFromListOptions(opts interface{}) (labelSelector labels.Selector, fieldSelector fields.Selector, resourceVersion string) {
+	var err error
+	switch t := opts.(type) {
+	case metav1.ListOptions:
+		labelSelector, err = labels.Parse(t.LabelSelector)
+		if err != nil {
+			panic(fmt.Errorf("invalid selector %q: %v", t.LabelSelector, err))
+		}
+		fieldSelector, err = fields.ParseSelector(t.FieldSelector)
+		if err != nil {
+			panic(fmt.Errorf("invalid selector %q: %v", t.FieldSelector, err))
+		}
+		resourceVersion = t.ResourceVersion
+	default:
+		panic(fmt.Errorf("expect a ListOptions %T", opts))
+	}
+	if labelSelector == nil {
+		labelSelector = labels.Everything()
+	}
+	if fieldSelector == nil {
+		fieldSelector = fields.Everything()
+	}
+	return labelSelector, fieldSelector, resourceVersion
+}
+
+func NewWatchAction(resource schema.GroupVersionResource, namespace string, opts interface{}) WatchActionImpl {
+	action := WatchActionImpl{}
+	action.Verb = "watch"
+	action.Resource = resource
+	action.Namespace = namespace
+	labelSelector, fieldSelector, resourceVersion := ExtractFromListOptions(opts)
+	action.WatchRestrictions = WatchRestrictions{labelSelector, fieldSelector, resourceVersion}
+
+	return action
+}
+
+func NewProxyGetAction(resource schema.GroupVersionResource, namespace, scheme, name, port, path string, params map[string]string) ProxyGetActionImpl {
+	action := ProxyGetActionImpl{}
+	action.Verb = "get"
+	action.Resource = resource
+	action.Namespace = namespace
+	action.Scheme = scheme
+	action.Name = name
+	action.Port = port
+	action.Path = path
+	action.Params = params
+	return action
+}
+
+type ListRestrictions struct {
+	Labels labels.Selector
+	Fields fields.Selector
+}
+type WatchRestrictions struct {
+	Labels          labels.Selector
+	Fields          fields.Selector
+	ResourceVersion string
+}
+
+type Action interface {
+	GetNamespace() string
+	GetVerb() string
+	GetResource() schema.GroupVersionResource
+	GetSubresource() string
+	Matches(verb, resource string) bool
+}
+
+type GenericAction interface {
+	Action
+	GetValue() interface{}
+}
+
+type GetAction interface {
+	Action
+	GetName() string
+}
+
+type ListAction interface {
+	Action
+	GetListRestrictions() ListRestrictions
+}
+
+type CreateAction interface {
+	Action
+	GetObject() runtime.Object
+}
+
+type UpdateAction interface {
+	Action
+	GetObject() runtime.Object
+}
+
+type DeleteAction interface {
+	Action
+	GetName() string
+}
+
+type WatchAction interface {
+	Action
+	GetWatchRestrictions() WatchRestrictions
+}
+
+type ProxyGetAction interface {
+	Action
+	GetScheme() string
+	GetName() string
+	GetPort() string
+	GetPath() string
+	GetParams() map[string]string
+}
+
+type ActionImpl struct {
+	Namespace   string
+	Verb        string
+	Resource    schema.GroupVersionResource
+	Subresource string
+}
+
+func (a ActionImpl) GetNamespace() string {
+	return a.Namespace
+}
+func (a ActionImpl) GetVerb() string {
+	return a.Verb
+}
+func (a ActionImpl) GetResource() schema.GroupVersionResource {
+	return a.Resource
+}
+func (a ActionImpl) GetSubresource() string {
+	return a.Subresource
+}
+func (a ActionImpl) Matches(verb, resource string) bool {
+	return strings.ToLower(verb) == strings.ToLower(a.Verb) &&
+		strings.ToLower(resource) == strings.ToLower(a.Resource.Resource)
+}
+
+type GenericActionImpl struct {
+	ActionImpl
+	Value interface{}
+}
+
+func (a GenericActionImpl) GetValue() interface{} {
+	return a.Value
+}
+
+type GetActionImpl struct {
+	ActionImpl
+	Name string
+}
+
+func (a GetActionImpl) GetName() string {
+	return a.Name
+}
+
+type ListActionImpl struct {
+	ActionImpl
+	Kind             schema.GroupVersionKind
+	ListRestrictions ListRestrictions
+}
+
+func (a ListActionImpl) GetKind() schema.GroupVersionKind {
+	return a.Kind
+}
+
+func (a ListActionImpl) GetListRestrictions() ListRestrictions {
+	return a.ListRestrictions
+}
+
+type CreateActionImpl struct {
+	ActionImpl
+	Object runtime.Object
+}
+
+func (a CreateActionImpl) GetObject() runtime.Object {
+	return a.Object
+}
+
+type UpdateActionImpl struct {
+	ActionImpl
+	Object runtime.Object
+}
+
+func (a UpdateActionImpl) GetObject() runtime.Object {
+	return a.Object
+}
+
+type PatchActionImpl struct {
+	ActionImpl
+	Name  string
+	Patch []byte
+}
+
+func (a PatchActionImpl) GetName() string {
+	return a.Name
+}
+
+func (a PatchActionImpl) GetPatch() []byte {
+	return a.Patch
+}
+
+type DeleteActionImpl struct {
+	ActionImpl
+	Name string
+}
+
+func (a DeleteActionImpl) GetName() string {
+	return a.Name
+}
+
+type DeleteCollectionActionImpl struct {
+	ActionImpl
+	ListRestrictions ListRestrictions
+}
+
+func (a DeleteCollectionActionImpl) GetListRestrictions() ListRestrictions {
+	return a.ListRestrictions
+}
+
+type WatchActionImpl struct {
+	ActionImpl
+	WatchRestrictions WatchRestrictions
+}
+
+func (a WatchActionImpl) GetWatchRestrictions() WatchRestrictions {
+	return a.WatchRestrictions
+}
+
+type ProxyGetActionImpl struct {
+	ActionImpl
+	Scheme string
+	Name   string
+	Port   string
+	Path   string
+	Params map[string]string
+}
+
+func (a ProxyGetActionImpl) GetScheme() string {
+	return a.Scheme
+}
+
+func (a ProxyGetActionImpl) GetName() string {
+	return a.Name
+}
+
+func (a ProxyGetActionImpl) GetPort() string {
+	return a.Port
+}
+
+func (a ProxyGetActionImpl) GetPath() string {
+	return a.Path
+}
+
+func (a ProxyGetActionImpl) GetParams() map[string]string {
+	return a.Params
+}
diff --git a/vendor/k8s.io/client-go/testing/fake.go b/vendor/k8s.io/client-go/testing/fake.go
new file mode 100644
index 0000000..da47b23
--- /dev/null
+++ b/vendor/k8s.io/client-go/testing/fake.go
@@ -0,0 +1,259 @@
+/*
+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 testing
+
+import (
+	"fmt"
+	"sync"
+
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/version"
+	"k8s.io/apimachinery/pkg/watch"
+	kubeversion "k8s.io/client-go/pkg/version"
+	restclient "k8s.io/client-go/rest"
+)
+
+// Fake implements client.Interface. Meant to be embedded into a struct to get
+// a default implementation. This makes faking out just the method you want to
+// test easier.
+type Fake struct {
+	sync.RWMutex
+	actions []Action // these may be castable to other types, but "Action" is the minimum
+
+	// ReactionChain is the list of reactors that will be attempted for every
+	// request in the order they are tried.
+	ReactionChain []Reactor
+	// WatchReactionChain is the list of watch reactors that will be attempted
+	// for every request in the order they are tried.
+	WatchReactionChain []WatchReactor
+	// ProxyReactionChain is the list of proxy reactors that will be attempted
+	// for every request in the order they are tried.
+	ProxyReactionChain []ProxyReactor
+
+	Resources []*metav1.APIResourceList
+}
+
+// Reactor is an interface to allow the composition of reaction functions.
+type Reactor interface {
+	// Handles indicates whether or not this Reactor deals with a given
+	// action.
+	Handles(action Action) bool
+	// React handles the action and returns results.  It may choose to
+	// delegate by indicated handled=false.
+	React(action Action) (handled bool, ret runtime.Object, err error)
+}
+
+// WatchReactor is an interface to allow the composition of watch functions.
+type WatchReactor interface {
+	// Handles indicates whether or not this Reactor deals with a given
+	// action.
+	Handles(action Action) bool
+	// React handles a watch action and returns results.  It may choose to
+	// delegate by indicating handled=false.
+	React(action Action) (handled bool, ret watch.Interface, err error)
+}
+
+// ProxyReactor is an interface to allow the composition of proxy get
+// functions.
+type ProxyReactor interface {
+	// Handles indicates whether or not this Reactor deals with a given
+	// action.
+	Handles(action Action) bool
+	// React handles a watch action and returns results.  It may choose to
+	// delegate by indicating handled=false.
+	React(action Action) (handled bool, ret restclient.ResponseWrapper, err error)
+}
+
+// ReactionFunc is a function that returns an object or error for a given
+// Action.  If "handled" is false, then the test client will ignore the
+// results and continue to the next ReactionFunc.  A ReactionFunc can describe
+// reactions on subresources by testing the result of the action's
+// GetSubresource() method.
+type ReactionFunc func(action Action) (handled bool, ret runtime.Object, err error)
+
+// WatchReactionFunc is a function that returns a watch interface.  If
+// "handled" is false, then the test client will ignore the results and
+// continue to the next ReactionFunc.
+type WatchReactionFunc func(action Action) (handled bool, ret watch.Interface, err error)
+
+// ProxyReactionFunc is a function that returns a ResponseWrapper interface
+// for a given Action.  If "handled" is false, then the test client will
+// ignore the results and continue to the next ProxyReactionFunc.
+type ProxyReactionFunc func(action Action) (handled bool, ret restclient.ResponseWrapper, err error)
+
+// AddReactor appends a reactor to the end of the chain.
+func (c *Fake) AddReactor(verb, resource string, reaction ReactionFunc) {
+	c.ReactionChain = append(c.ReactionChain, &SimpleReactor{verb, resource, reaction})
+}
+
+// PrependReactor adds a reactor to the beginning of the chain.
+func (c *Fake) PrependReactor(verb, resource string, reaction ReactionFunc) {
+	c.ReactionChain = append([]Reactor{&SimpleReactor{verb, resource, reaction}}, c.ReactionChain...)
+}
+
+// AddWatchReactor appends a reactor to the end of the chain.
+func (c *Fake) AddWatchReactor(resource string, reaction WatchReactionFunc) {
+	c.WatchReactionChain = append(c.WatchReactionChain, &SimpleWatchReactor{resource, reaction})
+}
+
+// PrependWatchReactor adds a reactor to the beginning of the chain.
+func (c *Fake) PrependWatchReactor(resource string, reaction WatchReactionFunc) {
+	c.WatchReactionChain = append([]WatchReactor{&SimpleWatchReactor{resource, reaction}}, c.WatchReactionChain...)
+}
+
+// AddProxyReactor appends a reactor to the end of the chain.
+func (c *Fake) AddProxyReactor(resource string, reaction ProxyReactionFunc) {
+	c.ProxyReactionChain = append(c.ProxyReactionChain, &SimpleProxyReactor{resource, reaction})
+}
+
+// PrependProxyReactor adds a reactor to the beginning of the chain.
+func (c *Fake) PrependProxyReactor(resource string, reaction ProxyReactionFunc) {
+	c.ProxyReactionChain = append([]ProxyReactor{&SimpleProxyReactor{resource, reaction}}, c.ProxyReactionChain...)
+}
+
+// Invokes records the provided Action and then invokes the ReactionFunc that
+// handles the action if one exists. defaultReturnObj is expected to be of the
+// same type a normal call would return.
+func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime.Object, error) {
+	c.Lock()
+	defer c.Unlock()
+
+	c.actions = append(c.actions, action)
+	for _, reactor := range c.ReactionChain {
+		if !reactor.Handles(action) {
+			continue
+		}
+
+		handled, ret, err := reactor.React(action)
+		if !handled {
+			continue
+		}
+
+		return ret, err
+	}
+
+	return defaultReturnObj, nil
+}
+
+// InvokesWatch records the provided Action and then invokes the ReactionFunc
+// that handles the action if one exists.
+func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) {
+	c.Lock()
+	defer c.Unlock()
+
+	c.actions = append(c.actions, action)
+	for _, reactor := range c.WatchReactionChain {
+		if !reactor.Handles(action) {
+			continue
+		}
+
+		handled, ret, err := reactor.React(action)
+		if !handled {
+			continue
+		}
+
+		return ret, err
+	}
+
+	return nil, fmt.Errorf("unhandled watch: %#v", action)
+}
+
+// InvokesProxy records the provided Action and then invokes the ReactionFunc
+// that handles the action if one exists.
+func (c *Fake) InvokesProxy(action Action) restclient.ResponseWrapper {
+	c.Lock()
+	defer c.Unlock()
+
+	c.actions = append(c.actions, action)
+	for _, reactor := range c.ProxyReactionChain {
+		if !reactor.Handles(action) {
+			continue
+		}
+
+		handled, ret, err := reactor.React(action)
+		if !handled || err != nil {
+			continue
+		}
+
+		return ret
+	}
+
+	return nil
+}
+
+// ClearActions clears the history of actions called on the fake client.
+func (c *Fake) ClearActions() {
+	c.Lock()
+	defer c.Unlock()
+
+	c.actions = make([]Action, 0)
+}
+
+// Actions returns a chronologically ordered slice fake actions called on the
+// fake client.
+func (c *Fake) Actions() []Action {
+	c.RLock()
+	defer c.RUnlock()
+	fa := make([]Action, len(c.actions))
+	copy(fa, c.actions)
+	return fa
+}
+
+// TODO: this probably should be moved to somewhere else.
+type FakeDiscovery struct {
+	*Fake
+}
+
+func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) {
+	action := ActionImpl{
+		Verb:     "get",
+		Resource: schema.GroupVersionResource{Resource: "resource"},
+	}
+	c.Invokes(action, nil)
+	for _, rl := range c.Resources {
+		if rl.GroupVersion == groupVersion {
+			return rl, nil
+		}
+	}
+
+	return nil, fmt.Errorf("GroupVersion %q not found", groupVersion)
+}
+
+func (c *FakeDiscovery) ServerResources() ([]*metav1.APIResourceList, error) {
+	action := ActionImpl{
+		Verb:     "get",
+		Resource: schema.GroupVersionResource{Resource: "resource"},
+	}
+	c.Invokes(action, nil)
+	return c.Resources, nil
+}
+
+func (c *FakeDiscovery) ServerGroups() (*metav1.APIGroupList, error) {
+	return nil, nil
+}
+
+func (c *FakeDiscovery) ServerVersion() (*version.Info, error) {
+	action := ActionImpl{}
+	action.Verb = "get"
+	action.Resource = schema.GroupVersionResource{Resource: "version"}
+
+	c.Invokes(action, nil)
+	versionInfo := kubeversion.Get()
+	return &versionInfo, nil
+}
diff --git a/vendor/k8s.io/client-go/testing/fixture.go b/vendor/k8s.io/client-go/testing/fixture.go
new file mode 100644
index 0000000..a53c960
--- /dev/null
+++ b/vendor/k8s.io/client-go/testing/fixture.go
@@ -0,0 +1,464 @@
+/*
+Copyright 2015 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package testing
+
+import (
+	"fmt"
+	"sync"
+
+	"k8s.io/apimachinery/pkg/api/errors"
+	"k8s.io/apimachinery/pkg/api/meta"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/watch"
+	restclient "k8s.io/client-go/rest"
+)
+
+// ObjectTracker keeps track of objects. It is intended to be used to
+// fake calls to a server by returning objects based on their kind,
+// namespace and name.
+type ObjectTracker interface {
+	// Add adds an object to the tracker. If object being added
+	// is a list, its items are added separately.
+	Add(obj runtime.Object) error
+
+	// Get retrieves the object by its kind, namespace and name.
+	Get(gvr schema.GroupVersionResource, ns, name string) (runtime.Object, error)
+
+	// Create adds an object to the tracker in the specified namespace.
+	Create(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error
+
+	// Update updates an existing object in the tracker in the specified namespace.
+	Update(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error
+
+	// List retrieves all objects of a given kind in the given
+	// namespace. Only non-List kinds are accepted.
+	List(gvr schema.GroupVersionResource, gvk schema.GroupVersionKind, ns string) (runtime.Object, error)
+
+	// Delete deletes an existing object from the tracker. If object
+	// didn't exist in the tracker prior to deletion, Delete returns
+	// no error.
+	Delete(gvr schema.GroupVersionResource, ns, name string) error
+}
+
+// ObjectScheme abstracts the implementation of common operations on objects.
+type ObjectScheme interface {
+	runtime.ObjectCreater
+	runtime.ObjectCopier
+	runtime.ObjectTyper
+}
+
+// ObjectReaction returns a ReactionFunc that applies core.Action to
+// the given tracker.
+func ObjectReaction(tracker ObjectTracker) ReactionFunc {
+	return func(action Action) (bool, runtime.Object, error) {
+		ns := action.GetNamespace()
+		gvr := action.GetResource()
+
+		// Here and below we need to switch on implementation types,
+		// not on interfaces, as some interfaces are identical
+		// (e.g. UpdateAction and CreateAction), so if we use them,
+		// updates and creates end up matching the same case branch.
+		switch action := action.(type) {
+
+		case ListActionImpl:
+			obj, err := tracker.List(gvr, action.GetKind(), ns)
+			return true, obj, err
+
+		case GetActionImpl:
+			obj, err := tracker.Get(gvr, ns, action.GetName())
+			return true, obj, err
+
+		case CreateActionImpl:
+			objMeta, err := meta.Accessor(action.GetObject())
+			if err != nil {
+				return true, nil, err
+			}
+			if action.GetSubresource() == "" {
+				err = tracker.Create(gvr, action.GetObject(), ns)
+			} else {
+				// TODO: Currently we're handling subresource creation as an update
+				// on the enclosing resource. This works for some subresources but
+				// might not be generic enough.
+				err = tracker.Update(gvr, action.GetObject(), ns)
+			}
+			if err != nil {
+				return true, nil, err
+			}
+			obj, err := tracker.Get(gvr, ns, objMeta.GetName())
+			return true, obj, err
+
+		case UpdateActionImpl:
+			objMeta, err := meta.Accessor(action.GetObject())
+			if err != nil {
+				return true, nil, err
+			}
+			err = tracker.Update(gvr, action.GetObject(), ns)
+			if err != nil {
+				return true, nil, err
+			}
+			obj, err := tracker.Get(gvr, ns, objMeta.GetName())
+			return true, obj, err
+
+		case DeleteActionImpl:
+			err := tracker.Delete(gvr, ns, action.GetName())
+			if err != nil {
+				return true, nil, err
+			}
+			return true, nil, nil
+
+		default:
+			return false, nil, fmt.Errorf("no reaction implemented for %s", action)
+		}
+	}
+}
+
+type tracker struct {
+	scheme  ObjectScheme
+	decoder runtime.Decoder
+	lock    sync.RWMutex
+	objects map[schema.GroupVersionResource][]runtime.Object
+}
+
+var _ ObjectTracker = &tracker{}
+
+// NewObjectTracker returns an ObjectTracker that can be used to keep track
+// of objects for the fake clientset. Mostly useful for unit tests.
+func NewObjectTracker(scheme ObjectScheme, decoder runtime.Decoder) ObjectTracker {
+	return &tracker{
+		scheme:  scheme,
+		decoder: decoder,
+		objects: make(map[schema.GroupVersionResource][]runtime.Object),
+	}
+}
+
+func (t *tracker) List(gvr schema.GroupVersionResource, gvk schema.GroupVersionKind, ns string) (runtime.Object, error) {
+	// Heuristic for list kind: original kind + List suffix. Might
+	// not always be true but this tracker has a pretty limited
+	// understanding of the actual API model.
+	listGVK := gvk
+	listGVK.Kind = listGVK.Kind + "List"
+	// GVK does have the concept of "internal version". The scheme recognizes
+	// the runtime.APIVersionInternal, but not the empty string.
+	if listGVK.Version == "" {
+		listGVK.Version = runtime.APIVersionInternal
+	}
+
+	list, err := t.scheme.New(listGVK)
+	if err != nil {
+		return nil, err
+	}
+
+	if !meta.IsListType(list) {
+		return nil, fmt.Errorf("%q is not a list type", listGVK.Kind)
+	}
+
+	t.lock.RLock()
+	defer t.lock.RUnlock()
+
+	objs, ok := t.objects[gvr]
+	if !ok {
+		return list, nil
+	}
+
+	matchingObjs, err := filterByNamespaceAndName(objs, ns, "")
+	if err != nil {
+		return nil, err
+	}
+	if err := meta.SetList(list, matchingObjs); err != nil {
+		return nil, err
+	}
+	if list, err = t.scheme.Copy(list); err != nil {
+		return nil, err
+	}
+	return list, nil
+}
+
+func (t *tracker) Get(gvr schema.GroupVersionResource, ns, name string) (runtime.Object, error) {
+	errNotFound := errors.NewNotFound(gvr.GroupResource(), name)
+
+	t.lock.RLock()
+	defer t.lock.RUnlock()
+
+	objs, ok := t.objects[gvr]
+	if !ok {
+		return nil, errNotFound
+	}
+
+	matchingObjs, err := filterByNamespaceAndName(objs, ns, name)
+	if err != nil {
+		return nil, err
+	}
+	if len(matchingObjs) == 0 {
+		return nil, errNotFound
+	}
+	if len(matchingObjs) > 1 {
+		return nil, fmt.Errorf("more than one object matched gvr %s, ns: %q name: %q", gvr, ns, name)
+	}
+
+	// Only one object should match in the tracker if it works
+	// correctly, as Add/Update methods enforce kind/namespace/name
+	// uniqueness.
+	obj, err := t.scheme.Copy(matchingObjs[0])
+	if err != nil {
+		return nil, err
+	}
+
+	if status, ok := obj.(*metav1.Status); ok {
+		if status.Status != metav1.StatusSuccess {
+			return nil, &errors.StatusError{ErrStatus: *status}
+		}
+	}
+
+	return obj, nil
+}
+
+func (t *tracker) Add(obj runtime.Object) error {
+	if meta.IsListType(obj) {
+		return t.addList(obj, false)
+	}
+	objMeta, err := meta.Accessor(obj)
+	if err != nil {
+		return err
+	}
+	gvks, _, err := t.scheme.ObjectKinds(obj)
+	if err != nil {
+		return err
+	}
+	if len(gvks) == 0 {
+		return fmt.Errorf("no registered kinds for %v", obj)
+	}
+	for _, gvk := range gvks {
+		// NOTE: UnsafeGuessKindToResource is a heuristic and default match. The
+		// actual registration in apiserver can specify arbitrary route for a
+		// gvk. If a test uses such objects, it cannot preset the tracker with
+		// objects via Add(). Instead, it should trigger the Create() function
+		// of the tracker, where an arbitrary gvr can be specified.
+		gvr, _ := meta.UnsafeGuessKindToResource(gvk)
+		// Resource doesn't have the concept of "__internal" version, just set it to "".
+		if gvr.Version == runtime.APIVersionInternal {
+			gvr.Version = ""
+		}
+
+		err := t.add(gvr, obj, objMeta.GetNamespace(), false)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (t *tracker) Create(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error {
+	return t.add(gvr, obj, ns, false)
+}
+
+func (t *tracker) Update(gvr schema.GroupVersionResource, obj runtime.Object, ns string) error {
+	return t.add(gvr, obj, ns, true)
+}
+
+func (t *tracker) add(gvr schema.GroupVersionResource, obj runtime.Object, ns string, replaceExisting bool) error {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	gr := gvr.GroupResource()
+
+	// To avoid the object from being accidentally modified by caller
+	// after it's been added to the tracker, we always store the deep
+	// copy.
+	obj, err := t.scheme.Copy(obj)
+	if err != nil {
+		return err
+	}
+
+	newMeta, err := meta.Accessor(obj)
+	if err != nil {
+		return err
+	}
+
+	// Propagate namespace to the new object if hasn't already been set.
+	if len(newMeta.GetNamespace()) == 0 {
+		newMeta.SetNamespace(ns)
+	}
+
+	if ns != newMeta.GetNamespace() {
+		msg := fmt.Sprintf("request namespace does not match object namespace, request: %q object: %q", ns, newMeta.GetNamespace())
+		return errors.NewBadRequest(msg)
+	}
+
+	for i, existingObj := range t.objects[gvr] {
+		oldMeta, err := meta.Accessor(existingObj)
+		if err != nil {
+			return err
+		}
+		if oldMeta.GetNamespace() == newMeta.GetNamespace() && oldMeta.GetName() == newMeta.GetName() {
+			if replaceExisting {
+				t.objects[gvr][i] = obj
+				return nil
+			}
+			return errors.NewAlreadyExists(gr, newMeta.GetName())
+		}
+	}
+
+	if replaceExisting {
+		// Tried to update but no matching object was found.
+		return errors.NewNotFound(gr, newMeta.GetName())
+	}
+
+	t.objects[gvr] = append(t.objects[gvr], obj)
+
+	return nil
+}
+
+func (t *tracker) addList(obj runtime.Object, replaceExisting bool) error {
+	list, err := meta.ExtractList(obj)
+	if err != nil {
+		return err
+	}
+	errs := runtime.DecodeList(list, t.decoder)
+	if len(errs) > 0 {
+		return errs[0]
+	}
+	for _, obj := range list {
+		if err := t.Add(obj); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (t *tracker) Delete(gvr schema.GroupVersionResource, ns, name string) error {
+	t.lock.Lock()
+	defer t.lock.Unlock()
+
+	found := false
+
+	for i, existingObj := range t.objects[gvr] {
+		objMeta, err := meta.Accessor(existingObj)
+		if err != nil {
+			return err
+		}
+		if objMeta.GetNamespace() == ns && objMeta.GetName() == name {
+			t.objects[gvr] = append(t.objects[gvr][:i], t.objects[gvr][i+1:]...)
+			found = true
+			break
+		}
+	}
+
+	if found {
+		return nil
+	}
+
+	return errors.NewNotFound(gvr.GroupResource(), name)
+}
+
+// filterByNamespaceAndName returns all objects in the collection that
+// match provided namespace and name. Empty namespace matches
+// non-namespaced objects.
+func filterByNamespaceAndName(objs []runtime.Object, ns, name string) ([]runtime.Object, error) {
+	var res []runtime.Object
+
+	for _, obj := range objs {
+		acc, err := meta.Accessor(obj)
+		if err != nil {
+			return nil, err
+		}
+		if ns != "" && acc.GetNamespace() != ns {
+			continue
+		}
+		if name != "" && acc.GetName() != name {
+			continue
+		}
+		res = append(res, obj)
+	}
+
+	return res, nil
+}
+
+func DefaultWatchReactor(watchInterface watch.Interface, err error) WatchReactionFunc {
+	return func(action Action) (bool, watch.Interface, error) {
+		return true, watchInterface, err
+	}
+}
+
+// SimpleReactor is a Reactor.  Each reaction function is attached to a given verb,resource tuple.  "*" in either field matches everything for that value.
+// For instance, *,pods matches all verbs on pods.  This allows for easier composition of reaction functions
+type SimpleReactor struct {
+	Verb     string
+	Resource string
+
+	Reaction ReactionFunc
+}
+
+func (r *SimpleReactor) Handles(action Action) bool {
+	verbCovers := r.Verb == "*" || r.Verb == action.GetVerb()
+	if !verbCovers {
+		return false
+	}
+	resourceCovers := r.Resource == "*" || r.Resource == action.GetResource().Resource
+	if !resourceCovers {
+		return false
+	}
+
+	return true
+}
+
+func (r *SimpleReactor) React(action Action) (bool, runtime.Object, error) {
+	return r.Reaction(action)
+}
+
+// SimpleWatchReactor is a WatchReactor.  Each reaction function is attached to a given resource.  "*" matches everything for that value.
+// For instance, *,pods matches all verbs on pods.  This allows for easier composition of reaction functions
+type SimpleWatchReactor struct {
+	Resource string
+
+	Reaction WatchReactionFunc
+}
+
+func (r *SimpleWatchReactor) Handles(action Action) bool {
+	resourceCovers := r.Resource == "*" || r.Resource == action.GetResource().Resource
+	if !resourceCovers {
+		return false
+	}
+
+	return true
+}
+
+func (r *SimpleWatchReactor) React(action Action) (bool, watch.Interface, error) {
+	return r.Reaction(action)
+}
+
+// SimpleProxyReactor is a ProxyReactor.  Each reaction function is attached to a given resource.  "*" matches everything for that value.
+// For instance, *,pods matches all verbs on pods.  This allows for easier composition of reaction functions.
+type SimpleProxyReactor struct {
+	Resource string
+
+	Reaction ProxyReactionFunc
+}
+
+func (r *SimpleProxyReactor) Handles(action Action) bool {
+	resourceCovers := r.Resource == "*" || r.Resource == action.GetResource().Resource
+	if !resourceCovers {
+		return false
+	}
+
+	return true
+}
+
+func (r *SimpleProxyReactor) React(action Action) (bool, restclient.ResponseWrapper, error) {
+	return r.Reaction(action)
+}
diff --git a/vendor/vendor.json b/vendor/vendor.json
index 2fd3d78..2be99b0 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -698,6 +698,12 @@
 			"revision": "c682349b0d1c12975d8e24a9799b66747255d7a5",
 			"revisionTime": "2017-07-19T03:55:28Z"
 		},
+		{
+			"checksumSHA1": "SF0kMDL2AeliElitbRMmYIH+jkQ=",
+			"path": "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake",
+			"revision": "c682349b0d1c12975d8e24a9799b66747255d7a5",
+			"revisionTime": "2017-07-19T03:55:28Z"
+		},
 		{
 			"checksumSHA1": "SSFu3lvYgKBMom6Gfm5uMqbXUH4=",
 			"path": "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme",
@@ -710,6 +716,12 @@
 			"revision": "c682349b0d1c12975d8e24a9799b66747255d7a5",
 			"revisionTime": "2017-07-19T03:55:28Z"
 		},
+		{
+			"checksumSHA1": "HoiSunwjyP3dx84Nbsgt+4195rE=",
+			"path": "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake",
+			"revision": "c682349b0d1c12975d8e24a9799b66747255d7a5",
+			"revisionTime": "2017-07-19T03:55:28Z"
+		},
 		{
 			"checksumSHA1": "tyJ8yrI3lC+JdiVumOFFugx0264=",
 			"path": "k8s.io/apimachinery/pkg/api/equality",
@@ -956,6 +968,12 @@
 			"revision": "7c69e980210777a6292351ac6873de083526f08e",
 			"revisionTime": "2017-07-19T03:39:24Z"
 		},
+		{
+			"checksumSHA1": "LyjvTsA0LHDfMzmjud/Yoq0DigE=",
+			"path": "k8s.io/client-go/discovery/fake",
+			"revision": "45673e060eb921b510677b1123737ad1158e49fa",
+			"revisionTime": "2017-08-01T23:46:53Z"
+		},
 		{
 			"checksumSHA1": "PoqDZ+IUEwrfA4Y5QMvVcPOKFOM=",
 			"path": "k8s.io/client-go/informers",
@@ -1388,6 +1406,12 @@
 			"revision": "7c69e980210777a6292351ac6873de083526f08e",
 			"revisionTime": "2017-07-19T03:39:24Z"
 		},
+		{
+			"checksumSHA1": "TWwjnZsYjqNez4P8IYle+dsLr0Y=",
+			"path": "k8s.io/client-go/testing",
+			"revision": "45673e060eb921b510677b1123737ad1158e49fa",
+			"revisionTime": "2017-08-01T23:46:53Z"
+		},
 		{
 			"checksumSHA1": "1ckiORH3dJD8v3R8tLEZ/5wttAk=",
 			"path": "k8s.io/client-go/tools/auth",