Merge pull request #65291 from misterikkit/fake-client

Automatic merge from submit-queue (batch tested with PRs 65301, 65291, 65307, 63845, 65313). 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>.

Add client-go example using fake client in test.

**What this PR does / why we need it**:

This adds an example showing the steps needed to get a working
SharedInformerFactory with a fake client for testing.

**Special notes for your reviewer**:
I had a really hard time figuring out how to use this utility correctly. I don't think this example is sufficient documentation, but it's a good start.

**Release note**:

```release-note
NONE
```
/sig api-machinery
/kind documentation

Kubernetes-commit: 8008c7dad945f7ac0748774a99148c864932288e
This commit is contained in:
Kubernetes Publisher 2018-06-22 03:08:10 -07:00
commit 8d892d34b2
4 changed files with 176 additions and 81 deletions

162
Godeps/Godeps.json generated
View File

@ -1,6 +1,6 @@
{
"ImportPath": "k8s.io/client-go",
"GoVersion": "go1.9",
"GoVersion": "go1.10",
"GodepVersion": "v80",
"Packages": [
"./..."
@ -268,323 +268,323 @@
},
{
"ImportPath": "k8s.io/api/admissionregistration/v1alpha1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/admissionregistration/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/apps/v1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/apps/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/apps/v1beta2",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/authentication/v1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/authentication/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/authorization/v1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/authorization/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/autoscaling/v1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/autoscaling/v2beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/batch/v1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/batch/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/batch/v2alpha1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/certificates/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/core/v1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/events/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/extensions/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/imagepolicy/v1alpha1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/networking/v1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/policy/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/rbac/v1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/rbac/v1alpha1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/rbac/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/scheduling/v1alpha1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/scheduling/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/settings/v1alpha1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/storage/v1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/storage/v1alpha1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/api/storage/v1beta1",
"Rev": "0629ca67c7adeabf4d1bc63cb816ce9e0d658406"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/conversion",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/fields",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/labels",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/selection",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/types",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/cache",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/clock",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/framer",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/net",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/wait",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/version",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/watch",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
"Rev": "954ae1c14eaec8ab19f63260d42de50e9ecc9961"
"Rev": "e622339dc5f39d70f000c70867b4dd20435d48ff"
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",

View File

@ -25,3 +25,7 @@ for client-go.
the custom resources.
[informer]: https://godoc.org/k8s.io/client-go/tools/cache#NewInformer
### Testing
- [**Fake Client**](./fake-client): Use a fake client in tests.

View File

@ -0,0 +1,14 @@
# Fake Client Example
This example demonstrates how to use a fake client with SharedInformerFactory in tests.
It covers:
* Creating the fake client
* Setting up real informers
* Injecting events into those informers
## Running
```
go test -v k8s.io/client-go/examples/fake-client
```

View File

@ -0,0 +1,77 @@
/*
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 fakeclient
import (
"context"
"testing"
"time"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/tools/cache"
)
// TestFakeClient demonstrates how to use a fake client with SharedInformerFactory in tests.
func TestFakeClient(t *testing.T) {
// Use a timeout to keep the test from hanging.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
// Create the fake client.
client := fake.NewSimpleClientset()
// We will create an informer that writes added pods to a channel.
pods := make(chan *v1.Pod, 1)
informers := informers.NewSharedInformerFactory(client, 0)
podInformer := informers.Core().V1().Pods().Informer()
podInformer.AddEventHandler(&cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
pod := obj.(*v1.Pod)
t.Logf("pod added: %s/%s", pod.Namespace, pod.Name)
pods <- pod
cancel()
},
})
// Make sure informers are running.
informers.Start(ctx.Done())
// This is not required in tests, but it serves as a proof-of-concept by
// ensuring that the informer goroutine have warmed up and called List before
// we send any events to it.
for !podInformer.HasSynced() {
time.Sleep(10 * time.Millisecond)
}
// Inject an event into the fake client.
p := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "my-pod"}}
_, err := client.Core().Pods("test-ns").Create(p)
if err != nil {
t.Errorf("error injecting pod add: %v", err)
}
// Wait and check result.
<-ctx.Done()
select {
case pod := <-pods:
t.Logf("Got pod from channel: %s/%s", pod.Namespace, pod.Name)
default:
t.Error("Informer did not get the added pod")
}
}