Compare commits

..

63 Commits

Author SHA1 Message Date
Kubernetes Publisher
54276fc663 Update dependencies to v0.15.8-beta.1 tag 2019-12-14 07:02:58 +00:00
Kubernetes Publisher
5f2132fc43 Merge pull request #83919 from liggitt/automated-cherry-pick-of-#83911-upstream-release-1.15
Automated cherry pick of #83911: Remove check causing informers to miss notifications

Kubernetes-commit: 0f71449be978a5e9efca3e7431941cc90211b339
2019-10-28 19:14:42 -07:00
matte21
699a46738f Remove check causing informers to miss notifications
Fix DeltaFIFO bug that caused the sync delta created by a relist
for object ID X to be dropped if the DeltaFIFO already stored a
Delete delta for X. This caused SharedIndexInformer to miss create
notifications. Also, add unit test to expose the bug.

Kubernetes-commit: d9930d43559b24743b21f2cc27b3d2c457e650a3
2019-10-14 18:19:05 +02:00
Kubernetes Publisher
b2f42092e3 Merge pull request #83434 from liggitt/automated-cherry-pick-of-#83261-upstream-release-1.15
[1.15] Automated cherry pick of #83261: bump gopkg.in/yaml.v2 v2.2.4

Kubernetes-commit: 9a83f46a506124685802559c4a3981f4f415d1de
2019-10-04 12:04:15 +00:00
Jordan Liggitt
539d9f1f03 bump gopkg.in/yaml.v2 v2.2.4
Kubernetes-commit: 8df7ee083fe4dcb39a871b6086a638401bad98c1
2019-10-02 14:46:08 -04:00
Kubernetes Publisher
637fc595d1 Merge pull request #81522 from cblecker/1.15-x/net
Update golang/x/net dependency on release-1.15

Kubernetes-commit: 2d3c76f9091b6bec110a5e63777c332469e0cba2
2019-08-17 02:15:27 +00:00
Christoph Blecker
069aa55f4a Update golang/x/net dependency
Kubernetes-commit: 842ee1f5889a4e31a48a5cd9c3cbf1edec7c6848
2019-08-16 11:01:55 -07:00
Kubernetes Publisher
44c2c549a5 Merge pull request #81355 from wojtek-t/automated-cherry-pick-of-#80978-upstream-release-1.15
Manual cherry pick of #80978 upstream release 1.15

Kubernetes-commit: 32884077729c30b123806aa5cad4af3bce63631c
2019-08-16 06:15:17 +00:00
wojtekt
96d4b4ca2c Fix events test
Kubernetes-commit: 18fdcbb5da09d64ba963b1cefcf91597a926e4d0
2019-08-13 16:14:46 +02:00
wojtekt
5abdc64bf8 Fix GetReference function
Kubernetes-commit: 363ec38db2fb9ca975411b9f864b0f5596c889c0
2019-08-05 08:37:55 +02:00
Kubernetes Publisher
e4cdb82809 Merge remote-tracking branch 'origin/master' into release-1.15
Kubernetes-commit: 6127bfb1bbd447e15fd839f3987abe1b8e5188b3
2019-06-12 21:03:32 +00:00
Krzysztof Siedlecki
3c67f637e2 Revert "Bump klog to v0.3.2"
Kubernetes-commit: 7dcec919a2e5e8e23da3d0dd61276d86c9b0e4b6
2019-06-12 10:27:41 +02:00
Kubernetes Publisher
935aad3790 Merge remote-tracking branch 'origin/master' into release-1.15
Kubernetes-commit: 3c5152b9a54ed2273710900be24e5d0828bff79b
2019-06-02 13:04:12 +00:00
Yassine TIJANI
f0e0a63eea set deprecatedEventSource to be backward compatible
Signed-off-by: Yassine TIJANI <ytijani@vmware.com>

Kubernetes-commit: 41e384397cf8505f226dc18f4250b297f98937ab
2019-05-30 13:03:20 +00:00
Kubernetes Publisher
3e37d3cec6 Merge remote-tracking branch 'origin/master' into release-1.15
Kubernetes-commit: 6be12759ea726aa785ba3a5937bbc75e479c1efd
2019-05-31 03:04:30 +00:00
Kubernetes Publisher
e85d69084a Merge pull request #78482 from tedyu/evt-expansion
Check namespaces match in UpdateWithEventNamespace

Kubernetes-commit: b3981a2f9acce4ee57f55131873ceaccf1707598
2019-05-31 13:29:21 +00:00
Kubernetes Publisher
e4ab670a95 Merge pull request #78465 from yuwenma/bump-klog
Bump klog to v0.3.2

Kubernetes-commit: b094dd9bc3a4617b587b04993931a6110691ddc0
2019-05-31 13:29:20 +00:00
Kubernetes Publisher
f6af94938b Merge remote-tracking branch 'origin/master' into release-1.15
Kubernetes-commit: 67f7c9f6ff8e61b44bd62db9ba6e0660b38c0617
2019-05-30 04:57:07 +00:00
Kubernetes Publisher
b34ddfd55a Merge pull request #78037 from yastij/fix-event-cleanup
clean singleton event when calling finishSeries

Kubernetes-commit: b0a81349effc68e19a6e063c8b7ebe0a4c8774e3
2019-05-31 13:29:18 +00:00
Kubernetes Publisher
46aef4b64f Merge pull request #78176 from yastij/event-expansion-client
add event_expansion for v1beta1 Events

Kubernetes-commit: 3978efc2167d9b3bcf266b7c2f3e7fb579f04e20
2019-05-31 13:29:17 +00:00
Kubernetes Publisher
0f8ad595c9 Merge pull request #77434 from mikedanese/watching
NewIndexerInformerWatcher: fix goroutine leak

Kubernetes-commit: 4fed75302a869c1c633e482af5e9d5fa3966fba6
2019-05-31 13:29:17 +00:00
Ted Yu
ea09349e3b Check namespaces match in UpdateWithEventNamespace
Kubernetes-commit: 5990a7d5070400616192c09e3d68f5cebcf9db2f
2019-05-29 08:40:02 -07:00
yuwenma
f78d31a2bc Bump klog to v0.3.2
Kubernetes-commit: 5cef37433e55827226f20981598ddfa2c6511809
2019-05-28 22:45:19 -07:00
Kubernetes Publisher
1d2c64df00 Merge remote-tracking branch 'origin/master' into release-1.15. Deleting CHANGELOG-1.14.md
Kubernetes-commit: 5991262b24f5e834654716148c939624536cce3a
2019-05-23 09:39:02 +00:00
Kubernetes Publisher
0810080103 Merge pull request #77793 from SataQiu/fix-golint-client-go-20190513
Fix golint failures of client-go/tools/auth client-go/tools/portforward

Kubernetes-commit: 5666982b2745e88d2009e4155d4a22f6c01061df
2019-05-28 15:52:23 +00:00
Michael Taufen
0976f4afe2 Update klog to v0.3.1
Includes recent fixes, notably https://github.com/kubernetes/klog/pull/66

Kubernetes-commit: ee7bcc53a206f669b057e38a477b51b3477aab23
2019-05-22 10:51:33 -07:00
Kubernetes Publisher
0673906c42 Merge remote-tracking branch 'origin/master' into release-1.15
Kubernetes-commit: 5b4de8c6ac4a34323a8582765a969d5ecfcf5467
2019-05-21 08:03:21 +00:00
Kubernetes Publisher
a2e13ccd49 Merge pull request #78019 from mrkm4ntr/use-constant
Change to use a constant

Kubernetes-commit: 15d88d19d33ffd50bc54bcb7f95946ecedb4e42b
2019-05-28 15:52:20 +00:00
Kubernetes Publisher
127c8ce629 Merge pull request #77991 from mikedanese/ledoc
cleanup some leader election client doc

Kubernetes-commit: 69c90d8cca62d4dbb1acb966608d5100bada5500
2019-05-28 15:52:19 +00:00
Kubernetes Publisher
26011c05ab Merge pull request #78063 from tedyu/evt-lock
Change lock type to write lock in eventBroadcasterImpl

Kubernetes-commit: 667c3ed94cdf52fb7dd26cfa9de7759df639c7d2
2019-05-28 15:52:18 +00:00
Kubernetes Publisher
9bcc910985 Merge pull request #77170 from smarterclayton/delay_queue_reentrant
DelayingQueue.ShutDown() should be reentrant

Kubernetes-commit: 4891eaa3adbfafb61d2bd264d2f0daef124ee8b9
2019-05-28 15:52:17 +00:00
Kubernetes Publisher
3ed0010e30 Merge remote-tracking branch 'origin/master' into release-1.15. Deleting CHANGELOG-1.14.md
Kubernetes-commit: 19e1375a042a0d5309e37c01e19af5835f78fce0
2019-05-18 03:23:38 +00:00
Kubernetes Publisher
c0015c0cc1 Merge pull request #78041 from yastij/fix-lastTimeObserved
update LastObservedTime instead of eventTime

Kubernetes-commit: b6f51d16d8a26558356b2eb876f7f3fdb0265aa9
2019-05-28 15:52:15 +00:00
Ted Yu
22ef81a898 Change lock type to write lock in eventBroadcasterImpl
Kubernetes-commit: 94af465819bd41a97b00acf997d5a7e077cbb654
2019-05-17 19:19:42 -07:00
Yassine TIJANI
7d76947ccd update LastObservedTime instead of eventTime
Signed-off-by: Yassine TIJANI <ytijani@vmware.com>

Kubernetes-commit: c6b224b16cff3c69b7a0d5b98b02c89777277971
2019-05-17 18:56:38 +02:00
Ted Yu
7615511cc0 Use lock in eventBroadcasterImpl#refreshExistingEventSeries
Kubernetes-commit: 32241b0751c9b9bd5d061eae9a42bd88970d8478
2019-05-17 09:30:54 -07:00
Kubernetes Publisher
a99ac36e1a Merge pull request #65782 from yastij/eventv2-eventf
Implementing logic for v1beta1.Event API

Kubernetes-commit: e67c266a72bf7b379a2b283a9989804f2282bac5
2019-05-28 15:52:14 +00:00
Kubernetes Publisher
424bde0e01 Merge pull request #77945 from michaelfig/client-go-namespaced-dynamicinformer
Honour NewFilteredDynamicSharedInformerFactory namespace argument

Kubernetes-commit: e0f28e5d0f03392e2970742426438c05a1778cb4
2019-05-28 15:52:13 +00:00
Kubernetes Publisher
958c03a8dd Merge pull request #77936 from liggitt/shorten-cert-wait
Interrupt WaitForCertificate if desired kubelet serving cert changes

Kubernetes-commit: a6b546eb72481165bc4d799d74c2ee8ae903e254
2019-05-28 15:52:12 +00:00
Kubernetes Publisher
9a62005bf9 Merge pull request #77925 from liggitt/icc-tokenfile
honor overridden tokenfile, add InClusterConfig override tests

Kubernetes-commit: 56683a2f1f4a16f592634306633a6bb3e252f051
2019-05-28 15:52:11 +00:00
Yassine TIJANI
0f3c6ef2dc clean singleton event when calling finishSeries
Signed-off-by: Yassine TIJANI <ytijani@vmware.com>

Kubernetes-commit: b6663e8d4fceb6f7de7267149341d51966276df8
2019-05-17 16:55:45 +02:00
Yassine TIJANI
4deb1a7db2 add event_expansion for v1beta1 Events
Signed-off-by: Yassine TIJANI <ytijani@vmware.com>

Kubernetes-commit: e29cb0fb7fbf5470e7caf2b3f1fc3d039bdda4ca
2019-05-17 12:12:19 +02:00
Shintaro Murakami
d64f019211 Change to use a constant
Kubernetes-commit: 2fcb248354ed5a3bf3154b1a8a0aafa237b2b37c
2019-05-17 18:40:03 +09:00
Mike Danese
73e7057101 cleanup some leader election client doc
Kubernetes-commit: 5df7f529f063ab354b050418b40c1f1dd2600175
2019-05-16 12:54:50 -07:00
Kubernetes Publisher
2c91b666c2 Merge remote-tracking branch 'origin/master' into release-1.15
Kubernetes-commit: 396d7ad1f381e46b52cc30e2fb7de8c27ede6fd3
2019-05-16 16:46:12 +00:00
Kubernetes Publisher
94836903b2 Merge pull request #77874 from yuchengwu/fix-CVE-2019-11244
fix CVE-2019-11244: `kubectl --http-cache=<world-accessible dir>` cre…

Kubernetes-commit: 730bc968b95842022c4c81d607bf6411b459a675
2019-05-28 15:52:09 +00:00
Kubernetes Publisher
4ea001dc73 Merge pull request #77585 from andyxning/fix_leader_election_start
enhance leader election doc

Kubernetes-commit: c2847e8b689c92d5cc4f1bb00d96df9dcc2cebfe
2019-05-28 15:52:08 +00:00
Kubernetes Publisher
f7ff47eb37 Merge pull request #76442 from viegasdom/fix-golint-utils-bandwith
Fix golint failures of util/bandwith/*.go

Kubernetes-commit: 37281a400d29ec4f515fb8a590d4f012689d89d7
2019-05-28 15:52:07 +00:00
viegasdom
45ef4fc0dc sync: squashed up to merge 69bd30507559be3dea905686b46bc3295c951f45 in 37281a400d29ec4f515fb8a590d4f012689d89d7 2019-05-28 15:52:07 +00:00
Kubernetes Publisher
c428844852 Merge remote-tracking branch 'origin/master' into release-1.15
Kubernetes-commit: 5d5e3fbd84b30d8bf59bfdf4c14d01196869b92f
2019-05-16 03:34:24 +00:00
Kubernetes Publisher
a0a9a3744f Merge pull request #77613 from mikedanese/fixinclusterconfig
BoundServiceAccountTokenVolume: fix InClusterConfig

Kubernetes-commit: 5c4b6528c2e9fa989bb6af9dea15d28ca6ac4ef3
2019-05-28 15:52:06 +00:00
Michael FIG
fa64ba9235 Honour NewFilteredDynamicSharedInformerFactory namespace argument
Kubernetes-commit: 2ed3272a5e428690c066a7c09e5c6a2fad3d74b6
2019-05-15 11:48:17 -06:00
Jordan Liggitt
ed62839de3 Interrupt WaitForCertificate if desired kubelet serving cert changes
Kubernetes-commit: 739a75fc32c5337ddbd13691e9bf6648fb13ff0d
2019-05-15 11:47:23 -04:00
Jordan Liggitt
85e546b378 honor overridden tokenfile, add InClusterConfig override tests
Kubernetes-commit: 7306fb7a89739a2fb48bfeb74595a5daa25060bd
2019-05-15 08:15:02 -04:00
Mike Danese
465fab1523 BoundServiceAccountTokenVolume: fix InClusterConfig
Kubernetes-commit: 4198f28855cbda6dac61408fcba6f2d576a9347c
2019-05-14 09:29:16 -07:00
Yucheng Wu
c076c6e063 fix CVE-2019-11244: kubectl --http-cache=<world-accessible dir> creates world-writeable cached schema files
Kubernetes-commit: f228ae3364729caed59087e23c42868454bc3ff4
2019-05-14 14:49:38 +08:00
Andy Xie
171f146b90 enhance leader election doc
Kubernetes-commit: 95f33ce39957e86cc3e81f4c8f325ecd133cbe9d
2019-05-14 10:36:22 +08:00
SataQiu
98cbc2c6ac fix golint failures of client-go/tools/auth client-go/tools/portforward
Kubernetes-commit: a89d75e3b822a13377373b0ef1c1969c69c616ec
2019-05-13 11:13:38 +08:00
Mike Danese
5551f5649d NewIndexerInformerWatcher: fix goroutine leak
There was some weird queuing going on. The queue was implement by
spawning goroutines that would block on the "ticketer" until it was
their turn to write to the output channel. If N events where in the
watch when the consumer of the watch stopped reading events, N
goroutines would leak. In unit tests of the certificate manager, this
was causing ~10k goroutines to leak.

Fix it with a buffering event processor that uses only one routine and
cancels correctly.

Kubernetes-commit: cafc640bfa0f7362b178b1b896085962d018afe3
2019-05-03 23:50:53 -04:00
Clayton Coleman
501db86fbe DelayingQueue.ShutDown() should be reentrant
All queue ShutDown() calls should be able to be invoked multiple times.

```
Observed a panic: "close of closed channel" (close of closed channel)
/go/src/github.com/openshift/cluster-version-operator/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go:76
/go/src/github.com/openshift/cluster-version-operator/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go:65
/go/src/github.com/openshift/cluster-version-operator/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go:51
/usr/local/go/src/runtime/asm_amd64.s:573
/usr/local/go/src/runtime/panic.go:502
/usr/local/go/src/runtime/chan.go:333
/go/src/github.com/openshift/cluster-version-operator/vendor/k8s.io/client-go/util/workqueue/delaying_queue.go:137
```

Use sync.Once to guarantee a single close.

Kubernetes-commit: d2f7eb5235a93556261c8947e7a87342aeeaee2b
2019-04-27 16:16:55 -04:00
Mike Danese
ce329ac04e vendor github.com/google/go-cmp
Kubernetes-commit: 76f683a8f3dc2977846e16b2ea14208a51c2cb6b
2019-04-22 21:41:46 -07:00
Kubernetes Publisher
dd7f3ad83f Merge pull request #77456 from MikeSpreitzer/fix-run-comment
Fix comment on SharedInformer.Run

Kubernetes-commit: e5fec6507bf1642917c34d84ef453ec53cd47dbc
2019-05-14 18:40:34 +00:00
Yassine TIJANI
ba984c792f Implementing logic for v1beta1.Event API
Signed-off-by: Yassine TIJANI <ytijani@vmware.com>

Kubernetes-commit: 464a994a10b71c45583f3426fd970291f8a5b756
2018-07-03 22:25:17 +02:00
798 changed files with 10082 additions and 32016 deletions

View File

@@ -222,7 +222,7 @@ The VolumeScheduling beta feature gate is still required for this feature.
([#67432](https://github.com/kubernetes/kubernetes/pull/67432))
* The CSI file system type is no longer defaulted to ext4.
All the production drivers listed under https://kubernetes-csi.github.io/docs/drivers.html
All the production drivers listed under https://kubernetes-csi.github.io/docs/Drivers.html
were inspected and should not be impacted after this change.
If you are using a driver not in that list,
please test the drivers on an updated test cluster first.

View File

@@ -1,6 +1,8 @@
# Contributing guidelines
Do not open pull requests directly against kubernetes/client-go repository (except for README.md); they will be ignored. Instead, please open pull requests and issues against [kubernetes/kubernetes](https://git.k8s.io/kubernetes/). Please follow the same [contributing guide](https://git.k8s.io/kubernetes/CONTRIBUTING.md) you would follow for any other pull request made to kubernetes/kubernetes.
Do not open pull requests directly against this repository. They will be ignored. Instead, please open pull requests against [kubernetes/kubernetes](https://git.k8s.io/kubernetes/).
The exception is changes to the `README.md` itself.
Please follow the same [contributing guide](https://git.k8s.io/kubernetes/CONTRIBUTING.md) you would follow for any other pull request made to kubernetes/kubernetes.
This repository is published from [kubernetes/kubernetes/staging/src/k8s.io/client-go](https://git.k8s.io/kubernetes/staging/src/k8s.io/client-go) by the [kubernetes publishing-bot](https://git.k8s.io/publishing-bot).

388
Godeps/Godeps.json generated
View File

@@ -8,99 +8,11 @@
"Deps": [
{
"ImportPath": "cloud.google.com/go",
"Rev": "v0.54.0"
},
{
"ImportPath": "cloud.google.com/go/bigquery",
"Rev": "v1.4.0"
},
{
"ImportPath": "cloud.google.com/go/datastore",
"Rev": "v1.1.0"
},
{
"ImportPath": "cloud.google.com/go/pubsub",
"Rev": "v1.2.0"
},
{
"ImportPath": "cloud.google.com/go/storage",
"Rev": "v1.6.0"
},
{
"ImportPath": "dmitri.shuralyov.com/gpu/mtl",
"Rev": "666a987793e9"
"Rev": "v0.34.0"
},
{
"ImportPath": "github.com/Azure/go-autorest",
"Rev": "v14.2.0"
},
{
"ImportPath": "github.com/Azure/go-autorest/autorest",
"Rev": "v0.11.1"
},
{
"ImportPath": "github.com/Azure/go-autorest/autorest/adal",
"Rev": "v0.9.5"
},
{
"ImportPath": "github.com/Azure/go-autorest/autorest/date",
"Rev": "v0.3.0"
},
{
"ImportPath": "github.com/Azure/go-autorest/autorest/mocks",
"Rev": "v0.4.1"
},
{
"ImportPath": "github.com/Azure/go-autorest/logger",
"Rev": "v0.2.0"
},
{
"ImportPath": "github.com/Azure/go-autorest/tracing",
"Rev": "v0.6.0"
},
{
"ImportPath": "github.com/BurntSushi/toml",
"Rev": "v0.3.1"
},
{
"ImportPath": "github.com/BurntSushi/xgb",
"Rev": "27f122750802"
},
{
"ImportPath": "github.com/NYTimes/gziphandler",
"Rev": "56545f4a5d46"
},
{
"ImportPath": "github.com/PuerkitoBio/purell",
"Rev": "v1.1.1"
},
{
"ImportPath": "github.com/PuerkitoBio/urlesc",
"Rev": "de5bf2ad4578"
},
{
"ImportPath": "github.com/asaskevich/govalidator",
"Rev": "f61b66f89f4a"
},
{
"ImportPath": "github.com/census-instrumentation/opencensus-proto",
"Rev": "v0.2.1"
},
{
"ImportPath": "github.com/chzyer/logex",
"Rev": "v1.1.10"
},
{
"ImportPath": "github.com/chzyer/readline",
"Rev": "2972be24d48e"
},
{
"ImportPath": "github.com/chzyer/test",
"Rev": "a1ea475d72b1"
},
{
"ImportPath": "github.com/client9/misspell",
"Rev": "v0.3.4"
"Rev": "v11.1.2"
},
{
"ImportPath": "github.com/davecgh/go-spew",
@@ -108,187 +20,79 @@
},
{
"ImportPath": "github.com/dgrijalva/jwt-go",
"Rev": "v3.2.0"
"Rev": "01aeca54ebda"
},
{
"ImportPath": "github.com/docker/spdystream",
"Rev": "449fdfce4d96"
},
{
"ImportPath": "github.com/docopt/docopt-go",
"Rev": "ee0de3bc6815"
},
{
"ImportPath": "github.com/elazarl/goproxy",
"Rev": "947c36da3153"
},
{
"ImportPath": "github.com/emicklei/go-restful",
"Rev": "ff4f55a20633"
},
{
"ImportPath": "github.com/envoyproxy/go-control-plane",
"Rev": "5f8ba28d4473"
},
{
"ImportPath": "github.com/envoyproxy/protoc-gen-validate",
"Rev": "v0.1.0"
"Rev": "c4fc26588b6e"
},
{
"ImportPath": "github.com/evanphx/json-patch",
"Rev": "v4.9.0"
},
{
"ImportPath": "github.com/form3tech-oss/jwt-go",
"Rev": "v3.2.2"
"Rev": "5858425f7550"
},
{
"ImportPath": "github.com/fsnotify/fsnotify",
"Rev": "v1.4.9"
},
{
"ImportPath": "github.com/ghodss/yaml",
"Rev": "73d445a93680"
},
{
"ImportPath": "github.com/go-gl/glfw",
"Rev": "e6da0acd62b1"
},
{
"ImportPath": "github.com/go-gl/glfw/v3.3/glfw",
"Rev": "6f7a984d4dc4"
},
{
"ImportPath": "github.com/go-logr/logr",
"Rev": "v0.2.0"
},
{
"ImportPath": "github.com/go-openapi/jsonpointer",
"Rev": "v0.19.3"
},
{
"ImportPath": "github.com/go-openapi/jsonreference",
"Rev": "v0.19.3"
},
{
"ImportPath": "github.com/go-openapi/spec",
"Rev": "v0.19.3"
},
{
"ImportPath": "github.com/go-openapi/swag",
"Rev": "v0.19.5"
"Rev": "v1.4.7"
},
{
"ImportPath": "github.com/gogo/protobuf",
"Rev": "v1.3.2"
},
{
"ImportPath": "github.com/golang/glog",
"Rev": "23def4e6c14b"
"Rev": "342cbe0a0415"
},
{
"ImportPath": "github.com/golang/groupcache",
"Rev": "8c9f03a8e57e"
},
{
"ImportPath": "github.com/golang/mock",
"Rev": "v1.4.1"
"Rev": "02826c3e7903"
},
{
"ImportPath": "github.com/golang/protobuf",
"Rev": "v1.4.3"
"Rev": "v1.2.0"
},
{
"ImportPath": "github.com/google/btree",
"Rev": "v1.0.0"
"Rev": "7d79101e329e"
},
{
"ImportPath": "github.com/google/go-cmp",
"Rev": "v0.5.2"
"Rev": "v0.3.0"
},
{
"ImportPath": "github.com/google/gofuzz",
"Rev": "v1.1.0"
},
{
"ImportPath": "github.com/google/martian",
"Rev": "v2.1.0"
},
{
"ImportPath": "github.com/google/pprof",
"Rev": "1ebb73c60ed3"
},
{
"ImportPath": "github.com/google/renameio",
"Rev": "v0.1.0"
"Rev": "24818f796faf"
},
{
"ImportPath": "github.com/google/uuid",
"Rev": "v1.1.2"
},
{
"ImportPath": "github.com/googleapis/gax-go/v2",
"Rev": "v2.0.5"
"Rev": "v1.0.0"
},
{
"ImportPath": "github.com/googleapis/gnostic",
"Rev": "v0.4.1"
"Rev": "0c5108395e2d"
},
{
"ImportPath": "github.com/gophercloud/gophercloud",
"Rev": "c818fa66e4c8"
},
{
"ImportPath": "github.com/gregjones/httpcache",
"Rev": "9cad4c3443a7"
"Rev": "787624de3eb7"
},
{
"ImportPath": "github.com/hashicorp/golang-lru",
"Rev": "v0.5.1"
"Rev": "v0.5.0"
},
{
"ImportPath": "github.com/hpcloud/tail",
"Rev": "v1.0.0"
},
{
"ImportPath": "github.com/ianlancetaylor/demangle",
"Rev": "5e5cf60278f6"
},
{
"ImportPath": "github.com/imdario/mergo",
"Rev": "v0.3.5"
},
{
"ImportPath": "github.com/json-iterator/go",
"Rev": "v1.1.10"
},
{
"ImportPath": "github.com/jstemmer/go-junit-report",
"Rev": "v0.9.1"
},
{
"ImportPath": "github.com/kisielk/errcheck",
"Rev": "v1.5.0"
},
{
"ImportPath": "github.com/kisielk/gotool",
"Rev": "v1.0.0"
},
{
"ImportPath": "github.com/kr/pretty",
"Rev": "v0.2.0"
},
{
"ImportPath": "github.com/kr/pty",
"Rev": "v1.1.5"
},
{
"ImportPath": "github.com/kr/text",
"Rev": "v0.1.0"
},
{
"ImportPath": "github.com/mailru/easyjson",
"Rev": "b2ccc519800e"
},
{
"ImportPath": "github.com/mitchellh/mapstructure",
"Rev": "v1.1.2"
"Rev": "ab8a2e0c74be"
},
{
"ImportPath": "github.com/modern-go/concurrent",
@@ -298,149 +102,73 @@
"ImportPath": "github.com/modern-go/reflect2",
"Rev": "v1.0.1"
},
{
"ImportPath": "github.com/munnerz/goautoneg",
"Rev": "a547fc61f48d"
},
{
"ImportPath": "github.com/mxk/go-flowrate",
"Rev": "cca7078d478f"
},
{
"ImportPath": "github.com/onsi/ginkgo",
"Rev": "v1.11.0"
"Rev": "v1.6.0"
},
{
"ImportPath": "github.com/onsi/gomega",
"Rev": "v1.7.0"
"Rev": "5533ce8a0da3"
},
{
"ImportPath": "github.com/peterbourgon/diskv",
"Rev": "v2.0.1"
},
{
"ImportPath": "github.com/pkg/errors",
"Rev": "v0.9.1"
},
{
"ImportPath": "github.com/pmezard/go-difflib",
"Rev": "v1.0.0"
},
{
"ImportPath": "github.com/prometheus/client_model",
"Rev": "14fe0d1b01d4"
},
{
"ImportPath": "github.com/rogpeppe/go-internal",
"Rev": "v1.3.0"
},
{
"ImportPath": "github.com/spf13/afero",
"Rev": "v1.2.2"
},
{
"ImportPath": "github.com/spf13/pflag",
"Rev": "v1.0.5"
},
{
"ImportPath": "github.com/stretchr/objx",
"Rev": "v0.2.0"
"Rev": "v1.0.1"
},
{
"ImportPath": "github.com/stretchr/testify",
"Rev": "v1.6.1"
},
{
"ImportPath": "github.com/yuin/goldmark",
"Rev": "v1.2.1"
},
{
"ImportPath": "go.opencensus.io",
"Rev": "v0.22.3"
"Rev": "v1.2.2"
},
{
"ImportPath": "golang.org/x/crypto",
"Rev": "7f63de1d35b0"
},
{
"ImportPath": "golang.org/x/exp",
"Rev": "6cc2880d07d6"
},
{
"ImportPath": "golang.org/x/image",
"Rev": "cff245a6509b"
},
{
"ImportPath": "golang.org/x/lint",
"Rev": "738671d3881b"
},
{
"ImportPath": "golang.org/x/mobile",
"Rev": "d2bd2a29d028"
},
{
"ImportPath": "golang.org/x/mod",
"Rev": "v0.3.0"
"Rev": "e84da0312774"
},
{
"ImportPath": "golang.org/x/net",
"Rev": "69a78807bb2b"
"Rev": "cdfb69ac37fc"
},
{
"ImportPath": "golang.org/x/oauth2",
"Rev": "bf48bf16ab8d"
"Rev": "9f3314589c9a"
},
{
"ImportPath": "golang.org/x/sync",
"Rev": "67f06af15bc9"
"Rev": "42b317875d0f"
},
{
"ImportPath": "golang.org/x/sys",
"Rev": "5cba982894dd"
"Rev": "3b5209105503"
},
{
"ImportPath": "golang.org/x/text",
"Rev": "v0.3.4"
"Rev": "e6919f6577db"
},
{
"ImportPath": "golang.org/x/time",
"Rev": "3af7569d3a1e"
"Rev": "f51c12702a4d"
},
{
"ImportPath": "golang.org/x/tools",
"Rev": "113979e3529a"
},
{
"ImportPath": "golang.org/x/xerrors",
"Rev": "5ec99f83aff1"
},
{
"ImportPath": "google.golang.org/api",
"Rev": "v0.20.0"
"Rev": "aa82965741a9"
},
{
"ImportPath": "google.golang.org/appengine",
"Rev": "v1.6.5"
},
{
"ImportPath": "google.golang.org/genproto",
"Rev": "cb27e3aa2013"
},
{
"ImportPath": "google.golang.org/grpc",
"Rev": "v1.27.1"
},
{
"ImportPath": "google.golang.org/protobuf",
"Rev": "v1.25.0"
"Rev": "v1.5.0"
},
{
"ImportPath": "gopkg.in/check.v1",
"Rev": "41f04d3bba15"
},
{
"ImportPath": "gopkg.in/errgo.v2",
"Rev": "v2.1.0"
"Rev": "20d25e280405"
},
{
"ImportPath": "gopkg.in/fsnotify.v1",
@@ -448,7 +176,7 @@
},
{
"ImportPath": "gopkg.in/inf.v0",
"Rev": "v0.9.1"
"Rev": "v0.9.0"
},
{
"ImportPath": "gopkg.in/tomb.v1",
@@ -456,59 +184,31 @@
},
{
"ImportPath": "gopkg.in/yaml.v2",
"Rev": "v2.2.8"
},
{
"ImportPath": "gopkg.in/yaml.v3",
"Rev": "9f266ea9e77c"
},
{
"ImportPath": "honnef.co/go/tools",
"Rev": "v0.0.1-2020.1.3"
"Rev": "v2.2.4"
},
{
"ImportPath": "k8s.io/api",
"Rev": "v0.20.6"
"Rev": "v0.15.8-beta.1"
},
{
"ImportPath": "k8s.io/apimachinery",
"Rev": "v0.20.6"
"Rev": "v0.15.8-beta.1"
},
{
"ImportPath": "k8s.io/gengo",
"Rev": "3a45101e95ac"
},
{
"ImportPath": "k8s.io/klog/v2",
"Rev": "v2.4.0"
"ImportPath": "k8s.io/klog",
"Rev": "v0.3.1"
},
{
"ImportPath": "k8s.io/kube-openapi",
"Rev": "d219536bb9fd"
"Rev": "b3a7cee44a30"
},
{
"ImportPath": "k8s.io/utils",
"Rev": "67b214c5f920"
},
{
"ImportPath": "rsc.io/binaryregexp",
"Rev": "v0.2.0"
},
{
"ImportPath": "rsc.io/quote/v3",
"Rev": "v3.1.0"
},
{
"ImportPath": "rsc.io/sampler",
"Rev": "v1.3.0"
},
{
"ImportPath": "sigs.k8s.io/structured-merge-diff/v4",
"Rev": "v4.0.3"
"Rev": "c2654d5206da"
},
{
"ImportPath": "sigs.k8s.io/yaml",
"Rev": "v1.2.0"
"Rev": "v1.1.0"
}
]
}

View File

@@ -19,7 +19,34 @@ and detailed dependency version info will be added to your `go.mod` file
This assumes you are using go modules with go 1.11+.
If you get a message like `cannot use path@version syntax in GOPATH mode`,
see the instructions for [enabling go modules](#enabling-go-modules).
you can choose to [opt into using go modules](#go-modules).
If you are using a version of go prior to 1.11, or do not wish to use
go modules, you can download `k8s.io/client-go` to your `$GOPATH` instead:
```sh
go get -u k8s.io/client-go/...
go get -u k8s.io/apimachinery/...
cd $GOPATH/src/k8s.io/client-go
git checkout v11.0.0
cd $GOPATH/src/k8s.io/apimachinery
git checkout kubernetes-1.14.0
```
This downloads a version of `k8s.io/client-go` prior to v1.12.0,
which includes most of its dependencies in its `k8s.io/client-go/vendor` path
(except for `k8s.io/apimachinery` and `glog`).
We excluded `k8s.io/apimachinery` and `glog` from `k8s.io/client-go/vendor` to
prevent `go get` users from hitting issues like
[#19](https://github.com/kubernetes/client-go/issues/19) and
[#83](https://github.com/kubernetes/client-go/issues/83). If your project shares
other dependencies with client-go, and you hit issues similar to #19 or #83,
then you'll need to look down at the next section.
Note: the official go policy is that libraries should not vendor their
dependencies. This was unworkable for us, since our dependencies change and HEAD
on every dependency has not necessarily been tested with client-go. In fact,
HEAD from all dependencies may not even compile with client-go!
## Dependency management for the serious (or reluctant) user
@@ -32,10 +59,15 @@ Reasons why you might need to use a dependency management system:
* You want your install to be reproducible. For example, for your CI system or
for new team members.
### Enabling go modules
There are three tools you could in theory use for this. Instructions
for each follows.
### Go modules
Dependency management tools are built into go 1.11+ in the form of [go modules](https://github.com/golang/go/wiki/Modules).
These are used by the main Kubernetes repo (>= `v1.15.0`) and `client-go` (>= `kubernetes-1.15.0`) to manage dependencies.
These are used by the main Kubernetes repo (>= 1.15) and `client-go` (on master, and v12.0.0+ once released) to manage dependencies.
When using `client-go` v12.0.0+ and go 1.11.4+, go modules are the recommended dependency management tool.
If you are using go 1.11 or 1.12 and are working with a project located within `$GOPATH`,
you must opt into using go modules:
@@ -50,28 +82,19 @@ If you do not already have one, `go mod init` will create one for you:
go mod init
```
### Add client-go as a dependency
Indicate which version of `client-go` your project requires:
- If you are using Kubernetes versions >= `v1.17.0`, use a corresponding
`v0.x.y` tag. For example, `k8s.io/client-go@v0.17.0` corresponds to Kubernetes `v1.17.0`:
Indicate which version of `client-go` your project requires.
For `client-go` on master (and once version v12.0.0 is released), this is a single step:
```sh
go get k8s.io/client-go@v0.17.0
go get k8s.io/client-go@master # or v12.0.0+ once released
```
You can also use a non-semver `kubernetes-1.x.y` tag to refer to a version
of `client-go` corresponding to a given Kubernetes release. Prior to Kubernetes
`v1.17.0` these were the only tags available for use with go modules.
For example, `kubernetes-1.16.3` corresponds to Kubernetes `v1.16.3`.
However, it is recommended to use semver-like `v0.x.y` tags over non-semver
`kubernetes-1.x.y` tags to have a seamless experience with go modules.
- If you are using Kubernetes versions < `v1.17.0` (replace `kubernetes-1.16.3` with the desired version):
For `client-go` prior to v12.0.0, you also need to indicate the required versions of `k8s.io/api` and `k8s.io/apimachinery`:
```sh
go get k8s.io/client-go@kubernetes-1.16.3
go get k8s.io/client-go@v11.0.0 # replace v11.0.0 with the required version (or use kubernetes-1.x.y tags if desired)
go get k8s.io/api@kubernetes-1.14.0 # replace kubernetes-1.14.0 with the required version
go get k8s.io/apimachinery@kubernetes-1.14.0 # replace kubernetes-1.14.0 with the required version
```
You can now import and use the `k8s.io/client-go` APIs in your project.
@@ -79,3 +102,97 @@ The next time you `go build`, `go test`, or `go run` your project,
`k8s.io/client-go` and its dependencies will be downloaded (if needed),
and detailed dependency version info will be added to your `go.mod` file
(or you can also run `go mod tidy` to do this directly).
### Glide
[Glide](https://github.com/Masterminds/glide) is another popular dependency
management tool for Go. Glide will manage your /vendor directory, but unlike
godep, will not use or modify your $GOPATH (there's no equivalent of
`godep restore` or `godep save`).
Generally, it's best to avoid Glide's many subcommands, favoring modifying
Glide's manifest file (`glide.yaml`) directly, then running
`glide update --strip-vendor`. First create a `glide.yaml` file at the root of
your project:
```yaml
package: ( your project's import path ) # e.g. github.com/foo/bar
import:
- package: k8s.io/client-go
version: v11.0.0 # replace v11.0.0 with the required version
```
Second, add a Go file that imports `client-go` somewhere in your project,
otherwise `client-go`'s dependencies will not be added to your project's
vendor/. Then run the following command in the same directory as `glide.yaml`:
```sh
glide update --strip-vendor
```
This can also be abbreviated as:
```sh
glide up -v
```
At this point, `k8s.io/client-go` should be added to your project's vendor/.
`client-go`'s dependencies should be flattened and be added to your project's
vendor/ as well.
Glide will detect the versions of dependencies `client-go` specified in
`client-go`'s Godep.json file, and automatically set the versions of these
imports in your /vendor directory. It will also record the detected version of
all dependencies in the `glide.lock` file.
Projects that require a different version of a dependency than `client-go`
requests can override the version manually in `glide.yaml`. For example:
```yaml
package: ( your project's import path ) # e.g. github.com/foo/bar
import:
- package: k8s.io/client-go
version: v11.0.0 # replace v11.0.0 with the required version
# Use a newer version of go-spew even though client-go wants an old one.
- package: github.com/davecgh/go-spew
version: v1.1.0
```
After modifying, run `glide up -v` again to re-populate your /vendor directory.
Optionally, Glide users can also use [`glide-vc`](https://github.com/sgotti/glide-vc)
after running `glide up -v` to remove unused files from /vendor.
### Godep
[godep](https://github.com/tools/godep) is an older dependency management tool, which was
used by the main Kubernetes repo (<= 1.14) and `client-go` (<= v11.0) to manage dependencies.
Before proceeding with the below instructions, you should ensure that your
$GOPATH is empty except for containing your own package and its dependencies,
and you have a copy of godep somewhere in your $PATH.
To install `client-go` and place its dependencies in your `$GOPATH`:
```sh
go get k8s.io/client-go/...
cd $GOPATH/src/k8s.io/client-go
git checkout v11.0.0 # v11.0.0 or older
# cd 1.5 # only necessary with 1.5 and 1.4 clients.
godep restore ./...
```
At this point, `client-go`'s dependencies have been placed in your $GOPATH, but
if you were to build, `client-go` would still see its own copy of its
dependencies in its `vendor` directory. You have two options at this point.
If you would like to keep dependencies in your own project's vendor directory,
then you can continue like this:
```sh
cd $GOPATH/src/<my-pkg>
godep save ./...
```
Alternatively, if you want to build using the dependencies in your `$GOPATH`,
then `rm -rf vendor/` to remove `client-go`'s copy of its dependencies.

121
README.md
View File

@@ -2,10 +2,9 @@
Go clients for talking to a [kubernetes](http://kubernetes.io/) cluster.
We recommend using the `v0.x.y` tags for Kubernetes releases >= `v1.17.0` and
`kubernetes-1.x.y` tags for Kubernetes releases < `v1.17.0`.
See [INSTALL.md](/INSTALL.md) for detailed installation instructions.
`go get k8s.io/client-go@master` works, but will fetch `master`, which may be less stable than a tagged release.
We currently recommend using the v11.0.0 tag. See [INSTALL.md](/INSTALL.md) for
detailed installation instructions. `go get k8s.io/client-go/...` works, but
will build `master`, which doesn't handle the dependencies well.
[![BuildStatus Widget]][BuildStatus Result]
[![GoReport Widget]][GoReport Status]
@@ -45,31 +44,42 @@ See [INSTALL.md](/INSTALL.md) for detailed installation instructions.
### Versioning
- For each `v1.x.y` Kubernetes release, the major version (first digit)
would remain `0`.
`client-go` follows [semver](http://semver.org/). We will not make
backwards-incompatible changes without incrementing the major version number. A
change is backwards-incompatible either if it *i)* changes the public interfaces
of `client-go`, or *ii)* makes `client-go` incompatible with otherwise supported
versions of Kubernetes clusters.
- Bugfixes will result in the patch version (third digit) changing. PRs that are
Changes that add features in a backwards-compatible way will result in bumping
the minor version (second digit) number.
Bugfixes will result in the patch version (third digit) changing. PRs that are
cherry-picked into an older Kubernetes release branch will result in an update
to the corresponding branch in `client-go`, with a corresponding new tag
changing the patch version.
A consequence of this is that `client-go` version numbers will be unrelated to
Kubernetes version numbers.
#### Branches and tags.
We will create a new branch and tag for each increment in the minor version
number. We will create only a new tag for each increment in the patch
We will create a new branch and tag for each increment in the major version number or
minor version number. We will create only a new tag for each increment in the patch
version number. See [semver](http://semver.org/) for definitions of major,
minor, and patch.
The HEAD of the master branch in client-go will track the HEAD of the master
branch in the main Kubernetes repo.
The master branch will track HEAD in the main Kubernetes repo and
accumulate changes. Consider HEAD to have the version `x.(y+1).0-alpha` or
`(x+1).0.0-alpha` (depending on whether it has accumulated a breaking change or
not), where `x` and `y` are the current major and minor versions.
#### Compatibility: your code <-> client-go
The `v0.x.y` tags indicate that go APIs may change in incompatible ways in
different versions.
See [INSTALL.md](INSTALL.md) for guidelines on requiring a specific
version of client-go.
`client-go` follows [semver](http://semver.org/), so until the major version of
client-go gets increased, your code will compile and will continue to work with
explicitly supported versions of Kubernetes clusters. You must use a dependency
management system and pin a specific major version of `client-go` to get this
benefit, as HEAD follows the upstream Kubernetes repo.
#### Compatibility: client-go <-> Kubernetes clusters
@@ -82,14 +92,16 @@ We will backport bugfixes--but not new features--into older versions of
#### Compatibility matrix
| | Kubernetes 1.15 | Kubernetes 1.16 | Kubernetes 1.17 | Kubernetes 1.18 | Kubernetes 1.19 |
|-------------------------------|-----------------|-----------------|-----------------|-----------------|-----------------|
| `kubernetes-1.15.0` | ✓ | +- | +- | +- | +- |
| `kubernetes-1.16.0` | +- | | +- | +- | +- |
| `kubernetes-1.17.0`/`v0.17.0` | +- | +- | ✓ | +- | +- |
| `kubernetes-1.18.0`/`v0.18.0` | +- | +- | +- | ✓ | +- |
| `kubernetes-1.19.0`/`v0.19.0` | +- | +- | +- | +- | ✓ |
| `HEAD` | +- | +- | +- | +- | +- |
| | Kubernetes 1.8 | Kubernetes 1.9 | Kubernetes 1.10 | Kubernetes 1.11 | Kubernetes 1.12 | Kubernetes 1.13 | Kubernetes 1.14 |
|---------------------|----------------|----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
| client-go 5.0 | ✓ | +- | +- | +- | +- | +- | +- |
| client-go 6.0 | +- | ✓ | +- | +- | +- | +- | +- |
| client-go 7.0 | +- | +- | ✓ | +- | +- | +- | +- |
| client-go 8.0 | +- | +- | +- | ✓ | +- | +- | +- |
| client-go 9.0 | +- | +- | +- | +- | ✓ | +- | +- |
| client-go 10.0 | +- | +- | +- | +- | +- | | +- |
| client-go 11.0 | +- | +- | +- | +- | +- | +- | ✓ |
| client-go HEAD | +- | +- | +- | +- | +- | +- | +- |
Key:
@@ -110,23 +122,18 @@ between client-go versions.
| Branch | Canonical source code location | Maintenance status |
|----------------|--------------------------------------|-------------------------------|
| `release-1.4` | Kubernetes main repo, 1.4 branch | = - |
| `release-1.5` | Kubernetes main repo, 1.5 branch | = - |
| `release-2.0` | Kubernetes main repo, 1.5 branch | = - |
| `release-3.0` | Kubernetes main repo, 1.6 branch | = - |
| `release-4.0` | Kubernetes main repo, 1.7 branch | = - |
| `release-5.0` | Kubernetes main repo, 1.8 branch | = - |
| `release-6.0` | Kubernetes main repo, 1.9 branch | = - |
| `release-7.0` | Kubernetes main repo, 1.10 branch | = - |
| `release-8.0` | Kubernetes main repo, 1.11 branch | =- |
| `release-9.0` | Kubernetes main repo, 1.12 branch | =- |
| `release-10.0` | Kubernetes main repo, 1.13 branch | =- |
| `release-11.0` | Kubernetes main repo, 1.14 branch | =- |
| `release-12.0` | Kubernetes main repo, 1.15 branch | =- |
| `release-13.0` | Kubernetes main repo, 1.16 branch | ✓ |
| `release-14.0` | Kubernetes main repo, 1.17 branch | ✓ |
| `release-1.18` | Kubernetes main repo, 1.18 branch | ✓ |
| `release-1.19` | Kubernetes main repo, 1.19 branch | ✓ |
| client-go 1.4 | Kubernetes main repo, 1.4 branch | = - |
| client-go 1.5 | Kubernetes main repo, 1.5 branch | = - |
| client-go 2.0 | Kubernetes main repo, 1.5 branch | = - |
| client-go 3.0 | Kubernetes main repo, 1.6 branch | = - |
| client-go 4.0 | Kubernetes main repo, 1.7 branch | = - |
| client-go 5.0 | Kubernetes main repo, 1.8 branch | = - |
| client-go 6.0 | Kubernetes main repo, 1.9 branch | = - |
| client-go 7.0 | Kubernetes main repo, 1.10 branch | = - |
| client-go 8.0 | Kubernetes main repo, 1.11 branch | =- |
| client-go 9.0 | Kubernetes main repo, 1.12 branch | |
| client-go 10.0 | Kubernetes main repo, 1.13 branch | |
| client-go 11.0 | Kubernetes main repo, 1.14 branch | |
| client-go HEAD | Kubernetes main repo, master branch | ✓ |
Key:
@@ -153,19 +160,14 @@ existing users won't be broken.
This repository is still a mirror of
[k8s.io/kubernetes/staging/src/client-go](https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/client-go),
the code development is still done in the staging area.
Since Kubernetes `v1.8.0`, when syncing the code from the staging area,
we also sync the Kubernetes version tags to client-go, prefixed with
`kubernetes-`. From Kubernetes `v1.17.0`, we also create matching semver
`v0.x.y` tags for each `v1.x.y` Kubernetes release.
For example, if you check out the `kubernetes-1.17.0` or the `v0.17.0` tag in
client-go, the code you get is exactly the same as if you check out the `v1.17.0`
tag in Kubernetes, and change directory to `staging/src/k8s.io/client-go`.
The purpose is to let users quickly find matching commits among published repos,
like [sample-apiserver](https://github.com/kubernetes/sample-apiserver),
the code development is still done in the staging area. Since Kubernetes 1.8
release, when syncing the code from the staging area, we also sync the Kubernetes
version tags to client-go, prefixed with "kubernetes-". For example, if you check
out the `kubernetes-v1.8.0` tag in client-go, the code you get is exactly the
same as if you check out the `v1.8.0` tag in kubernetes, and change directory to
`staging/src/k8s.io/client-go`. The purpose is to let users quickly find matching
commits among published repos, like
[sample-apiserver](https://github.com/kubernetes/sample-apiserver),
[apiextension-apiserver](https://github.com/kubernetes/apiextensions-apiserver),
etc. The Kubernetes version tag does NOT claim any backwards compatibility
guarantees for client-go. Please check the [semantic versions](#versioning) if
@@ -173,13 +175,10 @@ you care about backwards compatibility.
### How to get it
Use go1.11+ and fetch the desired version using the `go get` command. For example:
```
go get k8s.io/client-go@v0.19.0
```
See [INSTALL.md](/INSTALL.md) for detailed instructions.
You can use `go get k8s.io/client-go/...` to get client-go, but **you will get
the unstable master branch** and `client-go`'s vendored dependencies will not be
added to your `$GOPATH`. So we think most users will want to use a dependency
management system. See [INSTALL.md](/INSTALL.md) for detailed instructions.
### How to use it

View File

@@ -10,7 +10,8 @@
# DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE
# INSTRUCTIONS AT https://kubernetes.io/security/
caesarxuchao
deads2k
lavalamp
sttts
cjcullen
jessfraz
liggitt
philips
tallclair

View File

@@ -0,0 +1,73 @@
/*
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 deprecated_dynamic
import (
"encoding/json"
"io"
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
)
// dynamicCodec is a codec that wraps the standard unstructured codec
// with special handling for Status objects.
// Deprecated only used by test code and its wrong
type dynamicCodec struct{}
func (dynamicCodec) Decode(data []byte, gvk *schema.GroupVersionKind, obj runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
obj, gvk, err := unstructured.UnstructuredJSONScheme.Decode(data, gvk, obj)
if err != nil {
return nil, nil, err
}
if _, ok := obj.(*metav1.Status); !ok && strings.ToLower(gvk.Kind) == "status" {
obj = &metav1.Status{}
err := json.Unmarshal(data, obj)
if err != nil {
return nil, nil, err
}
}
return obj, gvk, nil
}
func (dynamicCodec) Encode(obj runtime.Object, w io.Writer) error {
return unstructured.UnstructuredJSONScheme.Encode(obj, w)
}
// ContentConfig returns a rest.ContentConfig for dynamic types.
// Deprecated only used by test code and its wrong
func ContentConfig() rest.ContentConfig {
// TODO: scheme.Codecs here should become "pkg/apis/server/scheme" which is the minimal core you need
// to talk to a kubernetes server
jsonInfo, _ := runtime.SerializerInfoForMediaType(scheme.Codecs.SupportedMediaTypes(), runtime.ContentTypeJSON)
jsonInfo.Serializer = dynamicCodec{}
jsonInfo.PrettySerializer = nil
return rest.ContentConfig{
AcceptContentTypes: runtime.ContentTypeJSON,
ContentType: runtime.ContentTypeJSON,
NegotiatedSerializer: serializer.NegotiatedSerializerWrapper(jsonInfo),
}
}

View File

@@ -0,0 +1,131 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package dynamic provides a client interface to arbitrary Kubernetes
// APIs that exposes common high level operations and exposes common
// metadata.
package deprecated_dynamic
import (
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
restclient "k8s.io/client-go/rest"
)
// Interface is a Kubernetes client that allows you to access metadata
// and manipulate metadata of a Kubernetes API group.
type Interface interface {
// 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 ResourceInterface inherits the parameter codec of this client.
Resource(resource *metav1.APIResource, namespace string) ResourceInterface
}
// ResourceInterface is an API interface to a specific resource under a
// dynamic client.
type ResourceInterface interface {
// List returns a list of objects for this resource.
List(opts metav1.ListOptions) (runtime.Object, error)
// Get gets the resource with the specified name.
Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error)
// Delete deletes the resource with the specified name.
Delete(name string, opts *metav1.DeleteOptions) error
// DeleteCollection deletes a collection of objects.
DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error
// Create creates the provided resource.
Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
// Update updates the provided resource.
Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
// Watch returns a watch.Interface that watches the resource.
Watch(opts metav1.ListOptions) (watch.Interface, error)
// Patch patches the provided resource.
Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error)
}
// Client is a Kubernetes client that allows you to access metadata
// and manipulate metadata of a Kubernetes API group, and implements Interface.
type Client struct {
version schema.GroupVersion
delegate dynamic.Interface
}
// NewClient returns a new client based on the passed in config. The
// codec is ignored, as the dynamic client uses it's own codec.
func NewClient(conf *restclient.Config, version schema.GroupVersion) (*Client, error) {
delegate, err := dynamic.NewForConfig(conf)
if err != nil {
return nil, err
}
return &Client{version: version, delegate: delegate}, 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 ResourceInterface inherits the parameter codec of c.
func (c *Client) Resource(resource *metav1.APIResource, namespace string) ResourceInterface {
resourceTokens := strings.SplitN(resource.Name, "/", 2)
subresources := []string{}
if len(resourceTokens) > 1 {
subresources = strings.Split(resourceTokens[1], "/")
}
if len(namespace) == 0 {
return oldResourceShim(c.delegate.Resource(c.version.WithResource(resourceTokens[0])), subresources)
}
return oldResourceShim(c.delegate.Resource(c.version.WithResource(resourceTokens[0])).Namespace(namespace), subresources)
}
// the old interfaces used the wrong type for lists. this fixes that
func oldResourceShim(in dynamic.ResourceInterface, subresources []string) ResourceInterface {
return oldResourceShimType{ResourceInterface: in, subresources: subresources}
}
type oldResourceShimType struct {
dynamic.ResourceInterface
subresources []string
}
func (s oldResourceShimType) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
return s.ResourceInterface.Create(obj, metav1.CreateOptions{}, s.subresources...)
}
func (s oldResourceShimType) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
return s.ResourceInterface.Update(obj, metav1.UpdateOptions{}, s.subresources...)
}
func (s oldResourceShimType) Delete(name string, opts *metav1.DeleteOptions) error {
return s.ResourceInterface.Delete(name, opts, s.subresources...)
}
func (s oldResourceShimType) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) {
return s.ResourceInterface.Get(name, opts, s.subresources...)
}
func (s oldResourceShimType) List(opts metav1.ListOptions) (runtime.Object, error) {
return s.ResourceInterface.List(opts)
}
func (s oldResourceShimType) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) {
return s.ResourceInterface.Patch(name, pt, data, metav1.PatchOptions{}, s.subresources...)
}

View File

@@ -0,0 +1,122 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package deprecated_dynamic
import (
"sync"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime/schema"
restclient "k8s.io/client-go/rest"
)
// ClientPool manages a pool of dynamic clients.
type ClientPool interface {
// ClientForGroupVersionResource returns a client configured for the specified groupVersionResource.
// Resource may be empty.
ClientForGroupVersionResource(resource schema.GroupVersionResource) (Interface, error)
// ClientForGroupVersionKind returns a client configured for the specified groupVersionKind.
// Kind may be empty.
ClientForGroupVersionKind(kind schema.GroupVersionKind) (Interface, error)
}
// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is
// optional.
type APIPathResolverFunc func(kind schema.GroupVersionKind) string
// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API.
func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string {
if len(kind.Group) == 0 {
return "/api"
}
return "/apis"
}
// clientPoolImpl implements ClientPool and caches clients for the resource group versions
// is asked to retrieve. This type is thread safe.
type clientPoolImpl struct {
lock sync.RWMutex
config *restclient.Config
clients map[schema.GroupVersion]*Client
apiPathResolverFunc APIPathResolverFunc
mapper meta.RESTMapper
}
// NewClientPool returns a ClientPool from the specified config. It reuses clients for the same
// group version. It is expected this type may be wrapped by specific logic that special cases certain
// resources or groups.
func NewClientPool(config *restclient.Config, mapper meta.RESTMapper, apiPathResolverFunc APIPathResolverFunc) ClientPool {
confCopy := *config
return &clientPoolImpl{
config: &confCopy,
clients: map[schema.GroupVersion]*Client{},
apiPathResolverFunc: apiPathResolverFunc,
mapper: mapper,
}
}
// Instantiates a new dynamic client pool with the given config.
func NewDynamicClientPool(cfg *restclient.Config) ClientPool {
// restMapper is not needed when using LegacyAPIPathResolverFunc
emptyMapper := meta.MultiRESTMapper{}
return NewClientPool(cfg, emptyMapper, LegacyAPIPathResolverFunc)
}
// ClientForGroupVersionResource uses the provided RESTMapper to identify the appropriate resource. Resource may
// be empty. If no matching kind is found the underlying client for that group is still returned.
func (c *clientPoolImpl) ClientForGroupVersionResource(resource schema.GroupVersionResource) (Interface, error) {
kinds, err := c.mapper.KindsFor(resource)
if err != nil {
if meta.IsNoMatchError(err) {
return c.ClientForGroupVersionKind(schema.GroupVersionKind{Group: resource.Group, Version: resource.Version})
}
return nil, err
}
return c.ClientForGroupVersionKind(kinds[0])
}
// ClientForGroupVersion returns a client for the specified groupVersion, creates one if none exists. Kind
// in the GroupVersionKind may be empty.
func (c *clientPoolImpl) ClientForGroupVersionKind(kind schema.GroupVersionKind) (Interface, error) {
c.lock.Lock()
defer c.lock.Unlock()
gv := kind.GroupVersion()
// do we have a client already configured?
if existingClient, found := c.clients[gv]; found {
return existingClient, nil
}
// avoid changing the original config
confCopy := *c.config
conf := &confCopy
// we need to set the api path based on group version, if no group, default to legacy path
conf.APIPath = c.apiPathResolverFunc(kind)
// we need to make a client
conf.GroupVersion = &gv
dynamicClient, err := NewClient(conf, gv)
if err != nil {
return nil, err
}
c.clients[gv] = dynamicClient
return dynamicClient, nil
}

View File

@@ -0,0 +1,623 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package deprecated_dynamic
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"reflect"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
restclient "k8s.io/client-go/rest"
restclientwatch "k8s.io/client-go/rest/watch"
)
func getJSON(version, kind, name string) []byte {
return []byte(fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "metadata": {"name": %q}}`, version, kind, name))
}
func getListJSON(version, kind string, items ...[]byte) []byte {
json := fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "items": [%s]}`,
version, kind, bytes.Join(items, []byte(",")))
return []byte(json)
}
func getObject(version, kind, name string) *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": version,
"kind": kind,
"metadata": map[string]interface{}{
"name": name,
},
},
}
}
func getClientServer(gv *schema.GroupVersion, h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) {
srv := httptest.NewServer(http.HandlerFunc(h))
cl, err := NewClient(&restclient.Config{
Host: srv.URL,
ContentConfig: restclient.ContentConfig{GroupVersion: gv},
}, *gv)
if err != nil {
srv.Close()
return nil, nil, err
}
return cl, srv, nil
}
func TestList(t *testing.T) {
tcs := []struct {
name string
namespace string
path string
resp []byte
want *unstructured.UnstructuredList
}{
{
name: "normal_list",
path: "/apis/gtest/vtest/rtest",
resp: getListJSON("vTest", "rTestList",
getJSON("vTest", "rTest", "item1"),
getJSON("vTest", "rTest", "item2")),
want: &unstructured.UnstructuredList{
Object: map[string]interface{}{
"apiVersion": "vTest",
"kind": "rTestList",
},
Items: []unstructured.Unstructured{
*getObject("vTest", "rTest", "item1"),
*getObject("vTest", "rTest", "item2"),
},
},
},
{
name: "namespaced_list",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
resp: getListJSON("vTest", "rTestList",
getJSON("vTest", "rTest", "item1"),
getJSON("vTest", "rTest", "item2")),
want: &unstructured.UnstructuredList{
Object: map[string]interface{}{
"apiVersion": "vTest",
"kind": "rTestList",
},
Items: []unstructured.Unstructured{
*getObject("vTest", "rTest", "item1"),
*getObject("vTest", "rTest", "item2"),
},
},
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("List(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("List(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
w.Write(tc.resp)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).List(metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when listing %q: %v", tc.name, err)
continue
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("List(%q) want: %v\ngot: %v", tc.name, tc.want, got)
}
}
}
func TestGet(t *testing.T) {
tcs := []struct {
resource string
namespace string
name string
path string
resp []byte
want *unstructured.Unstructured
}{
{
resource: "rtest",
name: "normal_get",
path: "/apis/gtest/vtest/rtest/normal_get",
resp: getJSON("vTest", "rTest", "normal_get"),
want: getObject("vTest", "rTest", "normal_get"),
},
{
resource: "rtest",
namespace: "nstest",
name: "namespaced_get",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_get",
resp: getJSON("vTest", "rTest", "namespaced_get"),
want: getObject("vTest", "rTest", "namespaced_get"),
},
{
resource: "rtest/srtest",
name: "normal_subresource_get",
path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest",
resp: getJSON("vTest", "srTest", "normal_subresource_get"),
want: getObject("vTest", "srTest", "normal_subresource_get"),
},
{
resource: "rtest/srtest",
namespace: "nstest",
name: "namespaced_subresource_get",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest",
resp: getJSON("vTest", "srTest", "namespaced_subresource_get"),
want: getObject("vTest", "srTest", "namespaced_subresource_get"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("Get(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Get(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
w.Write(tc.resp)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Get(tc.name, metav1.GetOptions{})
if err != nil {
t.Errorf("unexpected error when getting %q: %v", tc.name, err)
continue
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("Get(%q) want: %v\ngot: %v", tc.name, tc.want, got)
}
}
}
func TestDelete(t *testing.T) {
background := metav1.DeletePropagationBackground
uid := types.UID("uid")
statusOK := &metav1.Status{
TypeMeta: metav1.TypeMeta{Kind: "Status"},
Status: metav1.StatusSuccess,
}
tcs := []struct {
namespace string
name string
path string
deleteOptions *metav1.DeleteOptions
}{
{
name: "normal_delete",
path: "/apis/gtest/vtest/rtest/normal_delete",
},
{
namespace: "nstest",
name: "namespaced_delete",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete",
},
{
namespace: "nstest",
name: "namespaced_delete_with_options",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete_with_options",
deleteOptions: &metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}, PropagationPolicy: &background},
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "DELETE" {
t.Errorf("Delete(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Delete(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
unstructured.UnstructuredJSONScheme.Encode(statusOK, w)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
err = cl.Resource(resource, tc.namespace).Delete(tc.name, tc.deleteOptions)
if err != nil {
t.Errorf("unexpected error when deleting %q: %v", tc.name, err)
continue
}
}
}
func TestDeleteCollection(t *testing.T) {
statusOK := &metav1.Status{
TypeMeta: metav1.TypeMeta{Kind: "Status"},
Status: metav1.StatusSuccess,
}
tcs := []struct {
namespace string
name string
path string
}{
{
name: "normal_delete_collection",
path: "/apis/gtest/vtest/rtest",
},
{
namespace: "nstest",
name: "namespaced_delete_collection",
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "DELETE" {
t.Errorf("DeleteCollection(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("DeleteCollection(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
unstructured.UnstructuredJSONScheme.Encode(statusOK, w)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
err = cl.Resource(resource, tc.namespace).DeleteCollection(nil, metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err)
continue
}
}
}
func TestCreate(t *testing.T) {
tcs := []struct {
resource string
name string
namespace string
obj *unstructured.Unstructured
path string
}{
{
resource: "rtest",
name: "normal_create",
path: "/apis/gtest/vtest/rtest",
obj: getObject("gtest/vTest", "rTest", "normal_create"),
},
{
resource: "rtest",
name: "namespaced_create",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
obj: getObject("gtest/vTest", "rTest", "namespaced_create"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
t.Errorf("Create(%q) got HTTP method %s. wanted POST", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Create(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
data, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Errorf("Create(%q) unexpected error reading body: %v", tc.name, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(data)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Create(tc.obj)
if err != nil {
t.Errorf("unexpected error when creating %q: %v", tc.name, err)
continue
}
if !reflect.DeepEqual(got, tc.obj) {
t.Errorf("Create(%q) want: %v\ngot: %v", tc.name, tc.obj, got)
}
}
}
func TestUpdate(t *testing.T) {
tcs := []struct {
resource string
name string
namespace string
obj *unstructured.Unstructured
path string
}{
{
resource: "rtest",
name: "normal_update",
path: "/apis/gtest/vtest/rtest/normal_update",
obj: getObject("gtest/vTest", "rTest", "normal_update"),
},
{
resource: "rtest",
name: "namespaced_update",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update",
obj: getObject("gtest/vTest", "rTest", "namespaced_update"),
},
{
resource: "rtest/srtest",
name: "normal_subresource_update",
path: "/apis/gtest/vtest/rtest/normal_update/srtest",
obj: getObject("gtest/vTest", "srTest", "normal_update"),
},
{
resource: "rtest/srtest",
name: "namespaced_subresource_update",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest",
obj: getObject("gtest/vTest", "srTest", "namespaced_update"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PUT" {
t.Errorf("Update(%q) got HTTP method %s. wanted PUT", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Update(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
data, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Errorf("Update(%q) unexpected error reading body: %v", tc.name, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(data)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Update(tc.obj)
if err != nil {
t.Errorf("unexpected error when updating %q: %v", tc.name, err)
continue
}
if !reflect.DeepEqual(got, tc.obj) {
t.Errorf("Update(%q) want: %v\ngot: %v", tc.name, tc.obj, got)
}
}
}
func TestWatch(t *testing.T) {
tcs := []struct {
name string
namespace string
events []watch.Event
path string
query string
}{
{
name: "normal_watch",
path: "/apis/gtest/vtest/rtest",
query: "watch=true",
events: []watch.Event{
{Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "normal_watch")},
{Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "normal_watch")},
{Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "normal_watch")},
},
},
{
name: "namespaced_watch",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
query: "watch=true",
events: []watch.Event{
{Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")},
{Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")},
{Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")},
},
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("Watch(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Watch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
if r.URL.RawQuery != tc.query {
t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query)
}
enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, dynamicCodec{}), dynamicCodec{})
for _, e := range tc.events {
enc.Encode(&e)
}
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
watcher, err := cl.Resource(resource, tc.namespace).Watch(metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when watching %q: %v", tc.name, err)
continue
}
for _, want := range tc.events {
got := <-watcher.ResultChan()
if !reflect.DeepEqual(got, want) {
t.Errorf("Watch(%q) want: %v\ngot: %v", tc.name, want, got)
}
}
}
}
func TestPatch(t *testing.T) {
tcs := []struct {
resource string
name string
namespace string
patch []byte
want *unstructured.Unstructured
path string
}{
{
resource: "rtest",
name: "normal_patch",
path: "/apis/gtest/vtest/rtest/normal_patch",
patch: getJSON("gtest/vTest", "rTest", "normal_patch"),
want: getObject("gtest/vTest", "rTest", "normal_patch"),
},
{
resource: "rtest",
name: "namespaced_patch",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_patch",
patch: getJSON("gtest/vTest", "rTest", "namespaced_patch"),
want: getObject("gtest/vTest", "rTest", "namespaced_patch"),
},
{
resource: "rtest/srtest",
name: "normal_subresource_patch",
path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest",
patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"),
want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"),
},
{
resource: "rtest/srtest",
name: "namespaced_subresource_patch",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest",
patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"),
want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PATCH" {
t.Errorf("Patch(%q) got HTTP method %s. wanted PATCH", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Patch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
content := r.Header.Get("Content-Type")
if content != string(types.StrategicMergePatchType) {
t.Errorf("Patch(%q) got Content-Type %s. wanted %s", tc.name, content, types.StrategicMergePatchType)
}
data, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Errorf("Patch(%q) unexpected error reading body: %v", tc.name, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(data)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch)
if err != nil {
t.Errorf("unexpected error when patching %q: %v", tc.name, err)
continue
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("Patch(%q) want: %v\ngot: %v", tc.name, tc.want, got)
}
}
}

View File

@@ -25,8 +25,8 @@ import (
"sync"
"time"
openapi_v2 "github.com/googleapis/gnostic/openapiv2"
"k8s.io/klog/v2"
openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2"
"k8s.io/klog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
@@ -268,6 +268,8 @@ func (d *CachedDiscoveryClient) Invalidate() {
// CachedDiscoveryClient cache data. If httpCacheDir is empty, the restconfig's transport will not
// be updated with a roundtripper that understands cache responses.
// If discoveryCacheDir is empty, cached server resource data will be looked up in the current directory.
// TODO(juanvallejo): the value of "--cache-dir" should be honored. Consolidate discoveryCacheDir with httpCacheDir
// so that server resources and http-cache data are stored in the same location, provided via config flags.
func NewCachedDiscoveryClientForConfig(config *restclient.Config, discoveryCacheDir, httpCacheDir string, ttl time.Duration) (*CachedDiscoveryClient, error) {
if len(httpCacheDir) > 0 {
// update the given restconfig with a custom roundtripper that

View File

@@ -23,7 +23,7 @@ import (
"testing"
"time"
openapi_v2 "github.com/googleapis/gnostic/openapiv2"
"github.com/googleapis/gnostic/OpenAPIv2"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/api/errors"

View File

@@ -24,7 +24,7 @@ import (
"github.com/gregjones/httpcache"
"github.com/gregjones/httpcache/diskcache"
"github.com/peterbourgon/diskv"
"k8s.io/klog/v2"
"k8s.io/klog"
)
type cacheRoundTripper struct {

View File

@@ -19,10 +19,12 @@ package memory
import (
"errors"
"fmt"
"net"
"net/url"
"sync"
"syscall"
openapi_v2 "github.com/googleapis/gnostic/openapiv2"
"github.com/googleapis/gnostic/OpenAPIv2"
errorsutil "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -62,11 +64,19 @@ var _ discovery.CachedDiscoveryInterface = &memCacheClient{}
// "Connection reset" error which usually means that apiserver is temporarily
// unavailable.
func isTransientConnectionError(err error) bool {
var errno syscall.Errno
if errors.As(err, &errno) {
return errno == syscall.ECONNREFUSED || errno == syscall.ECONNRESET
urlError, ok := err.(*url.Error)
if !ok {
return false
}
return false
opError, ok := urlError.Err.(*net.OpError)
if !ok {
return false
}
errno, ok := opError.Err.(syscall.Errno)
if !ok {
return false
}
return errno == syscall.ECONNREFUSED || errno == syscall.ECONNRESET
}
func isTransientError(err error) bool {
@@ -180,29 +190,16 @@ func (d *memCacheClient) refreshLocked() error {
return err
}
wg := &sync.WaitGroup{}
resultLock := &sync.Mutex{}
rl := map[string]*cacheEntry{}
for _, g := range gl.Groups {
for _, v := range g.Versions {
gv := v.GroupVersion
wg.Add(1)
go func() {
defer wg.Done()
defer utilruntime.HandleCrash()
r, err := d.serverResourcesForGroupVersion(gv)
if err != nil {
utilruntime.HandleError(fmt.Errorf("couldn't get resource list for %v: %v", gv, err))
}
resultLock.Lock()
defer resultLock.Unlock()
rl[gv] = &cacheEntry{r, err}
}()
r, err := d.serverResourcesForGroupVersion(v.GroupVersion)
rl[v.GroupVersion] = &cacheEntry{r, err}
if err != nil {
utilruntime.HandleError(fmt.Errorf("couldn't get resource list for %v: %v", v.GroupVersion, err))
}
}
}
wg.Wait()
d.groupToServerResources, d.groupList = rl, gl
d.cacheValid = true

View File

@@ -95,9 +95,6 @@ func TestClient(t *testing.T) {
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if e, a := fake.groupList, g; !reflect.DeepEqual(e, a) {
t.Errorf("Expected %#v, got %#v", e, a)
}
if !c.Fresh() {
t.Errorf("Expected fresh.")
}
@@ -208,22 +205,16 @@ func TestServerGroupsFails(t *testing.T) {
func TestPartialPermanentFailure(t *testing.T) {
fake := &fakeDiscovery{
groupList: &metav1.APIGroupList{
Groups: []metav1.APIGroup{
{
Name: "astronomy",
Versions: []metav1.GroupVersionForDiscovery{{
GroupVersion: "astronomy/v8beta1",
Version: "v8beta1",
}},
},
{
Name: "astronomy2",
Versions: []metav1.GroupVersionForDiscovery{{
GroupVersion: "astronomy2/v8beta1",
Version: "v8beta1",
}},
},
},
Groups: []metav1.APIGroup{{
Name: "astronomy",
Versions: []metav1.GroupVersionForDiscovery{{
GroupVersion: "astronomy/v8beta1",
Version: "v8beta1",
}, {
GroupVersion: "astronomy2/v8beta1",
Version: "v8beta1",
}},
}},
},
resourceMap: map[string]*resourceMapEntry{
"astronomy/v8beta1": {
@@ -295,22 +286,16 @@ func TestPartialPermanentFailure(t *testing.T) {
func TestPartialRetryableFailure(t *testing.T) {
fake := &fakeDiscovery{
groupList: &metav1.APIGroupList{
Groups: []metav1.APIGroup{
{
Name: "astronomy",
Versions: []metav1.GroupVersionForDiscovery{{
GroupVersion: "astronomy/v8beta1",
Version: "v8beta1",
}},
},
{
Name: "astronomy2",
Versions: []metav1.GroupVersionForDiscovery{{
GroupVersion: "astronomy2/v8beta1",
Version: "v8beta1",
}},
},
},
Groups: []metav1.APIGroup{{
Name: "astronomy",
Versions: []metav1.GroupVersionForDiscovery{{
GroupVersion: "astronomy/v8beta1",
Version: "v8beta1",
}, {
GroupVersion: "astronomy2/v8beta1",
Version: "v8beta1",
}},
}},
},
resourceMap: map[string]*resourceMapEntry{
"astronomy/v8beta1": {

View File

@@ -17,7 +17,6 @@ limitations under the License.
package discovery
import (
"context"
"encoding/json"
"fmt"
"net/url"
@@ -27,7 +26,7 @@ import (
"time"
"github.com/golang/protobuf/proto"
openapi_v2 "github.com/googleapis/gnostic/openapiv2"
openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -156,7 +155,7 @@ func apiVersionsToAPIGroup(apiVersions *metav1.APIVersions) (apiGroup metav1.API
func (d *DiscoveryClient) ServerGroups() (apiGroupList *metav1.APIGroupList, err error) {
// Get the groupVersions exposed at /api
v := &metav1.APIVersions{}
err = d.restClient.Get().AbsPath(d.LegacyPrefix).Do(context.TODO()).Into(v)
err = d.restClient.Get().AbsPath(d.LegacyPrefix).Do().Into(v)
apiGroup := metav1.APIGroup{}
if err == nil && len(v.Versions) != 0 {
apiGroup = apiVersionsToAPIGroup(v)
@@ -167,7 +166,7 @@ func (d *DiscoveryClient) ServerGroups() (apiGroupList *metav1.APIGroupList, err
// Get the groupVersions exposed at /apis
apiGroupList = &metav1.APIGroupList{}
err = d.restClient.Get().AbsPath("/apis").Do(context.TODO()).Into(apiGroupList)
err = d.restClient.Get().AbsPath("/apis").Do().Into(apiGroupList)
if err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err) {
return nil, err
}
@@ -197,7 +196,7 @@ func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (r
resources = &metav1.APIResourceList{
GroupVersion: groupVersion,
}
err = d.restClient.Get().AbsPath(url.String()).Do(context.TODO()).Into(resources)
err = d.restClient.Get().AbsPath(url.String()).Do().Into(resources)
if err != nil {
// ignore 403 or 404 error to be compatible with an v1.0 server.
if groupVersion == "v1" && (errors.IsNotFound(err) || errors.IsForbidden(err)) {
@@ -406,7 +405,7 @@ func ServerPreferredNamespacedResources(d DiscoveryInterface) ([]*metav1.APIReso
// ServerVersion retrieves and parses the server's version (git version).
func (d *DiscoveryClient) ServerVersion() (*version.Info, error) {
body, err := d.restClient.Get().AbsPath("/version").Do(context.TODO()).Raw()
body, err := d.restClient.Get().AbsPath("/version").Do().Raw()
if err != nil {
return nil, err
}
@@ -420,12 +419,12 @@ func (d *DiscoveryClient) ServerVersion() (*version.Info, error) {
// OpenAPISchema fetches the open api schema using a rest client and parses the proto.
func (d *DiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) {
data, err := d.restClient.Get().AbsPath("/openapi/v2").SetHeader("Accept", mimePb).Do(context.TODO()).Raw()
data, err := d.restClient.Get().AbsPath("/openapi/v2").SetHeader("Accept", mimePb).Do().Raw()
if err != nil {
if errors.IsForbidden(err) || errors.IsNotFound(err) || errors.IsNotAcceptable(err) {
// single endpoint not found/registered in old server, try to fetch old endpoint
// TODO: remove this when kubectl/client-go don't work with 1.9 server
data, err = d.restClient.Get().AbsPath("/swagger-2.0.0.pb-v1").Do(context.TODO()).Raw()
data, err = d.restClient.Get().AbsPath("/swagger-2.0.0.pb-v1").Do().Raw()
if err != nil {
return nil, err
}
@@ -464,13 +463,6 @@ func setDiscoveryDefaults(config *restclient.Config) error {
if config.Timeout == 0 {
config.Timeout = defaultTimeout
}
if config.Burst == 0 && config.QPS < 100 {
// discovery is expected to be bursty, increase the default burst
// to accommodate looking up resource info for many API groups.
// matches burst set by ConfigFlags#ToDiscoveryClient().
// see https://issue.k8s.io/86149
config.Burst = 100
}
codec := runtime.NoopEncoder{Decoder: scheme.Codecs.UniversalDecoder()}
config.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})
if len(config.UserAgent) == 0 {
@@ -501,7 +493,7 @@ func NewDiscoveryClientForConfigOrDie(c *restclient.Config) *DiscoveryClient {
}
// NewDiscoveryClient returns a new DiscoveryClient for the given RESTClient.
// NewDiscoveryClient returns a new DiscoveryClient for the given RESTClient.
func NewDiscoveryClient(c restclient.Interface) *DiscoveryClient {
return &DiscoveryClient{restClient: c, LegacyPrefix: "/api"}
}

View File

@@ -24,10 +24,9 @@ import (
"net/http/httptest"
"reflect"
"testing"
"time"
"github.com/gogo/protobuf/proto"
openapi_v2 "github.com/googleapis/gnostic/openapiv2"
"github.com/googleapis/gnostic/OpenAPIv2"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -199,26 +198,6 @@ func TestGetServerResources(t *testing.T) {
{Name: "jobs", Namespaced: true, Kind: "Job"},
},
}
extensionsbeta3 := metav1.APIResourceList{GroupVersion: "extensions/v1beta3", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
extensionsbeta4 := metav1.APIResourceList{GroupVersion: "extensions/v1beta4", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
extensionsbeta5 := metav1.APIResourceList{GroupVersion: "extensions/v1beta5", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
extensionsbeta6 := metav1.APIResourceList{GroupVersion: "extensions/v1beta6", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
extensionsbeta7 := metav1.APIResourceList{GroupVersion: "extensions/v1beta7", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
extensionsbeta8 := metav1.APIResourceList{GroupVersion: "extensions/v1beta8", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
extensionsbeta9 := metav1.APIResourceList{GroupVersion: "extensions/v1beta9", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
extensionsbeta10 := metav1.APIResourceList{GroupVersion: "extensions/v1beta10", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
appsbeta1 := metav1.APIResourceList{GroupVersion: "apps/v1beta1", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
appsbeta2 := metav1.APIResourceList{GroupVersion: "apps/v1beta2", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
appsbeta3 := metav1.APIResourceList{GroupVersion: "apps/v1beta3", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
appsbeta4 := metav1.APIResourceList{GroupVersion: "apps/v1beta4", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
appsbeta5 := metav1.APIResourceList{GroupVersion: "apps/v1beta5", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
appsbeta6 := metav1.APIResourceList{GroupVersion: "apps/v1beta6", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
appsbeta7 := metav1.APIResourceList{GroupVersion: "apps/v1beta7", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
appsbeta8 := metav1.APIResourceList{GroupVersion: "apps/v1beta8", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
appsbeta9 := metav1.APIResourceList{GroupVersion: "apps/v1beta9", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
appsbeta10 := metav1.APIResourceList{GroupVersion: "apps/v1beta10", APIResources: []metav1.APIResource{{Name: "deployments", Namespaced: true, Kind: "Deployment"}}}
tests := []struct {
resourcesList *metav1.APIResourceList
path string
@@ -253,42 +232,6 @@ func TestGetServerResources(t *testing.T) {
list = &beta
case "/apis/extensions/v1beta2":
list = &beta2
case "/apis/extensions/v1beta3":
list = &extensionsbeta3
case "/apis/extensions/v1beta4":
list = &extensionsbeta4
case "/apis/extensions/v1beta5":
list = &extensionsbeta5
case "/apis/extensions/v1beta6":
list = &extensionsbeta6
case "/apis/extensions/v1beta7":
list = &extensionsbeta7
case "/apis/extensions/v1beta8":
list = &extensionsbeta8
case "/apis/extensions/v1beta9":
list = &extensionsbeta9
case "/apis/extensions/v1beta10":
list = &extensionsbeta10
case "/apis/apps/v1beta1":
list = &appsbeta1
case "/apis/apps/v1beta2":
list = &appsbeta2
case "/apis/apps/v1beta3":
list = &appsbeta3
case "/apis/apps/v1beta4":
list = &appsbeta4
case "/apis/apps/v1beta5":
list = &appsbeta5
case "/apis/apps/v1beta6":
list = &appsbeta6
case "/apis/apps/v1beta7":
list = &appsbeta7
case "/apis/apps/v1beta8":
list = &appsbeta8
case "/apis/apps/v1beta9":
list = &appsbeta9
case "/apis/apps/v1beta10":
list = &appsbeta10
case "/api":
list = &metav1.APIVersions{
Versions: []string{
@@ -298,34 +241,11 @@ func TestGetServerResources(t *testing.T) {
case "/apis":
list = &metav1.APIGroupList{
Groups: []metav1.APIGroup{
{
Name: "apps",
Versions: []metav1.GroupVersionForDiscovery{
{GroupVersion: "apps/v1beta1", Version: "v1beta1"},
{GroupVersion: "apps/v1beta2", Version: "v1beta2"},
{GroupVersion: "apps/v1beta3", Version: "v1beta3"},
{GroupVersion: "apps/v1beta4", Version: "v1beta4"},
{GroupVersion: "apps/v1beta5", Version: "v1beta5"},
{GroupVersion: "apps/v1beta6", Version: "v1beta6"},
{GroupVersion: "apps/v1beta7", Version: "v1beta7"},
{GroupVersion: "apps/v1beta8", Version: "v1beta8"},
{GroupVersion: "apps/v1beta9", Version: "v1beta9"},
{GroupVersion: "apps/v1beta10", Version: "v1beta10"},
},
},
{
Name: "extensions",
Versions: []metav1.GroupVersionForDiscovery{
{GroupVersion: "extensions/v1beta1", Version: "v1beta1"},
{GroupVersion: "extensions/v1beta2", Version: "v1beta2"},
{GroupVersion: "extensions/v1beta3", Version: "v1beta3"},
{GroupVersion: "extensions/v1beta4", Version: "v1beta4"},
{GroupVersion: "extensions/v1beta5", Version: "v1beta5"},
{GroupVersion: "extensions/v1beta6", Version: "v1beta6"},
{GroupVersion: "extensions/v1beta7", Version: "v1beta7"},
{GroupVersion: "extensions/v1beta8", Version: "v1beta8"},
{GroupVersion: "extensions/v1beta9", Version: "v1beta9"},
{GroupVersion: "extensions/v1beta10", Version: "v1beta10"},
},
},
},
@@ -345,8 +265,8 @@ func TestGetServerResources(t *testing.T) {
w.Write(output)
}))
defer server.Close()
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
for _, test := range tests {
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
got, err := client.ServerResourcesForGroupVersion(test.request)
if test.expectErr {
if err == nil {
@@ -363,83 +283,53 @@ func TestGetServerResources(t *testing.T) {
}
}
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
start := time.Now()
serverResources, err := client.ServerResources()
if err != nil {
t.Errorf("unexpected error: %v", err)
}
end := time.Now()
if d := end.Sub(start); d > time.Second {
t.Errorf("took too long to perform discovery: %s", d)
}
serverGroupVersions := groupVersions(serverResources)
expectedGroupVersions := []string{
"v1",
"apps/v1beta1",
"apps/v1beta2",
"apps/v1beta3",
"apps/v1beta4",
"apps/v1beta5",
"apps/v1beta6",
"apps/v1beta7",
"apps/v1beta8",
"apps/v1beta9",
"apps/v1beta10",
"extensions/v1beta1",
"extensions/v1beta2",
"extensions/v1beta3",
"extensions/v1beta4",
"extensions/v1beta5",
"extensions/v1beta6",
"extensions/v1beta7",
"extensions/v1beta8",
"extensions/v1beta9",
"extensions/v1beta10",
}
expectedGroupVersions := []string{"v1", "extensions/v1beta1", "extensions/v1beta2"}
if !reflect.DeepEqual(expectedGroupVersions, serverGroupVersions) {
t.Errorf("unexpected group versions: %v", diff.ObjectReflectDiff(expectedGroupVersions, serverGroupVersions))
}
}
func returnedOpenAPI() *openapi_v2.Document {
return &openapi_v2.Document{
Definitions: &openapi_v2.Definitions{
AdditionalProperties: []*openapi_v2.NamedSchema{
{
Name: "fake.type.1",
Value: &openapi_v2.Schema{
Properties: &openapi_v2.Properties{
AdditionalProperties: []*openapi_v2.NamedSchema{
{
Name: "count",
Value: &openapi_v2.Schema{
Type: &openapi_v2.TypeItem{
Value: []string{"integer"},
},
var returnedOpenAPI = openapi_v2.Document{
Definitions: &openapi_v2.Definitions{
AdditionalProperties: []*openapi_v2.NamedSchema{
{
Name: "fake.type.1",
Value: &openapi_v2.Schema{
Properties: &openapi_v2.Properties{
AdditionalProperties: []*openapi_v2.NamedSchema{
{
Name: "count",
Value: &openapi_v2.Schema{
Type: &openapi_v2.TypeItem{
Value: []string{"integer"},
},
},
},
},
},
},
{
Name: "fake.type.2",
Value: &openapi_v2.Schema{
Properties: &openapi_v2.Properties{
AdditionalProperties: []*openapi_v2.NamedSchema{
{
Name: "count",
Value: &openapi_v2.Schema{
Type: &openapi_v2.TypeItem{
Value: []string{"array"},
},
Items: &openapi_v2.ItemsItem{
Schema: []*openapi_v2.Schema{
{
Type: &openapi_v2.TypeItem{
Value: []string{"string"},
},
},
{
Name: "fake.type.2",
Value: &openapi_v2.Schema{
Properties: &openapi_v2.Properties{
AdditionalProperties: []*openapi_v2.NamedSchema{
{
Name: "count",
Value: &openapi_v2.Schema{
Type: &openapi_v2.TypeItem{
Value: []string{"array"},
},
Items: &openapi_v2.ItemsItem{
Schema: []*openapi_v2.Schema{
{
Type: &openapi_v2.TypeItem{
Value: []string{"string"},
},
},
},
@@ -451,10 +341,11 @@ func returnedOpenAPI() *openapi_v2.Document {
},
},
},
}
},
}
func openapiSchemaDeprecatedFakeServer(status int, t *testing.T) (*httptest.Server, error) {
func openapiSchemaDeprecatedFakeServer(status int) (*httptest.Server, error) {
var sErr error
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if req.URL.Path == "/openapi/v2" {
// write the error status for the new endpoint request
@@ -462,81 +353,54 @@ func openapiSchemaDeprecatedFakeServer(status int, t *testing.T) (*httptest.Serv
return
}
if req.URL.Path != "/swagger-2.0.0.pb-v1" {
errMsg := fmt.Sprintf("Unexpected url %v", req.URL)
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(errMsg))
t.Errorf("testing should fail as %s", errMsg)
return
sErr = fmt.Errorf("Unexpected url %v", req.URL)
}
if req.Method != "GET" {
errMsg := fmt.Sprintf("Unexpected method %v", req.Method)
w.WriteHeader(http.StatusMethodNotAllowed)
w.Write([]byte(errMsg))
t.Errorf("testing should fail as %s", errMsg)
return
sErr = fmt.Errorf("Unexpected method %v", req.Method)
}
mime.AddExtensionType(".pb-v1", "application/com.github.googleapis.gnostic.OpenAPIv2@68f4ded+protobuf")
output, err := proto.Marshal(returnedOpenAPI())
output, err := proto.Marshal(&returnedOpenAPI)
if err != nil {
errMsg := fmt.Sprintf("Unexpected marshal error: %v", err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(errMsg))
t.Errorf("testing should fail as %s", errMsg)
sErr = err
return
}
w.WriteHeader(http.StatusOK)
w.Write(output)
}))
return server, nil
return server, sErr
}
func openapiSchemaFakeServer(t *testing.T) (*httptest.Server, error) {
func openapiSchemaFakeServer() (*httptest.Server, error) {
var sErr error
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if req.URL.Path != "/openapi/v2" {
errMsg := fmt.Sprintf("Unexpected url %v", req.URL)
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(errMsg))
t.Errorf("testing should fail as %s", errMsg)
return
sErr = fmt.Errorf("Unexpected url %v", req.URL)
}
if req.Method != "GET" {
errMsg := fmt.Sprintf("Unexpected method %v", req.Method)
w.WriteHeader(http.StatusMethodNotAllowed)
w.Write([]byte(errMsg))
t.Errorf("testing should fail as %s", errMsg)
return
sErr = fmt.Errorf("Unexpected method %v", req.Method)
}
decipherableFormat := req.Header.Get("Accept")
if decipherableFormat != "application/com.github.proto-openapi.spec.v2@v1.0+protobuf" {
errMsg := fmt.Sprintf("Unexpected accept mime type %v", decipherableFormat)
w.WriteHeader(http.StatusUnsupportedMediaType)
w.Write([]byte(errMsg))
t.Errorf("testing should fail as %s", errMsg)
return
sErr = fmt.Errorf("Unexpected accept mime type %v", decipherableFormat)
}
mime.AddExtensionType(".pb-v1", "application/com.github.googleapis.gnostic.OpenAPIv2@68f4ded+protobuf")
output, err := proto.Marshal(returnedOpenAPI())
output, err := proto.Marshal(&returnedOpenAPI)
if err != nil {
errMsg := fmt.Sprintf("Unexpected marshal error: %v", err)
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(errMsg))
t.Errorf("testing should fail as %s", errMsg)
sErr = err
return
}
w.WriteHeader(http.StatusOK)
w.Write(output)
}))
return server, nil
return server, sErr
}
func TestGetOpenAPISchema(t *testing.T) {
server, err := openapiSchemaFakeServer(t)
server, err := openapiSchemaFakeServer()
if err != nil {
t.Errorf("unexpected error starting fake server: %v", err)
}
@@ -547,13 +411,13 @@ func TestGetOpenAPISchema(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error getting openapi: %v", err)
}
if e, a := returnedOpenAPI(), got; !reflect.DeepEqual(e, a) {
if e, a := returnedOpenAPI, *got; !reflect.DeepEqual(e, a) {
t.Errorf("expected %v, got %v", e, a)
}
}
func TestGetOpenAPISchemaForbiddenFallback(t *testing.T) {
server, err := openapiSchemaDeprecatedFakeServer(http.StatusForbidden, t)
server, err := openapiSchemaDeprecatedFakeServer(http.StatusForbidden)
if err != nil {
t.Errorf("unexpected error starting fake server: %v", err)
}
@@ -564,13 +428,13 @@ func TestGetOpenAPISchemaForbiddenFallback(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error getting openapi: %v", err)
}
if e, a := returnedOpenAPI(), got; !reflect.DeepEqual(e, a) {
if e, a := returnedOpenAPI, *got; !reflect.DeepEqual(e, a) {
t.Errorf("expected %v, got %v", e, a)
}
}
func TestGetOpenAPISchemaNotFoundFallback(t *testing.T) {
server, err := openapiSchemaDeprecatedFakeServer(http.StatusNotFound, t)
server, err := openapiSchemaDeprecatedFakeServer(http.StatusNotFound)
if err != nil {
t.Errorf("unexpected error starting fake server: %v", err)
}
@@ -581,13 +445,13 @@ func TestGetOpenAPISchemaNotFoundFallback(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error getting openapi: %v", err)
}
if e, a := returnedOpenAPI(), got; !reflect.DeepEqual(e, a) {
if e, a := returnedOpenAPI, *got; !reflect.DeepEqual(e, a) {
t.Errorf("expected %v, got %v", e, a)
}
}
func TestGetOpenAPISchemaNotAcceptableFallback(t *testing.T) {
server, err := openapiSchemaDeprecatedFakeServer(http.StatusNotAcceptable, t)
server, err := openapiSchemaDeprecatedFakeServer(http.StatusNotAcceptable)
if err != nil {
t.Errorf("unexpected error starting fake server: %v", err)
}
@@ -598,7 +462,7 @@ func TestGetOpenAPISchemaNotAcceptableFallback(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error getting openapi: %v", err)
}
if e, a := returnedOpenAPI(), got; !reflect.DeepEqual(e, a) {
if e, a := returnedOpenAPI, *got; !reflect.DeepEqual(e, a) {
t.Errorf("expected %v, got %v", e, a)
}
}

View File

@@ -16,4 +16,4 @@ limitations under the License.
// Package discovery provides ways to discover server-supported
// API groups, versions and resources.
package discovery // import "k8s.io/client-go/discovery"
package discovery

View File

@@ -19,7 +19,7 @@ package fake
import (
"fmt"
openapi_v2 "github.com/googleapis/gnostic/openapiv2"
"github.com/googleapis/gnostic/OpenAPIv2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"

View File

@@ -26,12 +26,13 @@ import (
"strings"
"testing"
v1 "k8s.io/api/core/v1"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/discovery"
"k8s.io/client-go/kubernetes/scheme"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake"
)
@@ -81,16 +82,23 @@ func TestServerSupportsVersion(t *testing.T) {
}
for _, test := range tests {
fakeClient := fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
if test.sendErr != nil {
return nil, test.sendErr
}
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
return &http.Response{StatusCode: test.statusCode, Header: header, Body: objBody(&metav1.APIVersions{Versions: test.serverVersions})}, nil
})
fakeClient := &fake.RESTClient{
NegotiatedSerializer: scheme.Codecs,
Resp: &http.Response{
StatusCode: test.statusCode,
Body: objBody(&metav1.APIVersions{Versions: test.serverVersions}),
},
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
if test.sendErr != nil {
return nil, test.sendErr
}
header := http.Header{}
header.Set("Content-Type", runtime.ContentTypeJSON)
return &http.Response{StatusCode: test.statusCode, Header: header, Body: objBody(&metav1.APIVersions{Versions: test.serverVersions})}, nil
}),
}
c := discovery.NewDiscoveryClientForConfigOrDie(&restclient.Config{})
c.RESTClient().(*restclient.RESTClient).Client = fakeClient
c.RESTClient().(*restclient.RESTClient).Client = fakeClient.Client
err := discovery.ServerSupportsVersion(c, test.requiredVersion)
if err == nil && test.expectErr != nil {
t.Errorf("expected error, got nil for [%s].", test.name)

View File

@@ -18,7 +18,6 @@ package dynamic
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"net/http"
@@ -135,7 +134,7 @@ func TestList(t *testing.T) {
}
defer srv.Close()
got, err := cl.Resource(resource).Namespace(tc.namespace).List(context.TODO(), metav1.ListOptions{})
got, err := cl.Resource(resource).Namespace(tc.namespace).List(metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when listing %q: %v", tc.name, err)
continue
@@ -210,7 +209,7 @@ func TestGet(t *testing.T) {
}
defer srv.Close()
got, err := cl.Resource(resource).Namespace(tc.namespace).Get(context.TODO(), tc.name, metav1.GetOptions{}, tc.subresource...)
got, err := cl.Resource(resource).Namespace(tc.namespace).Get(tc.name, metav1.GetOptions{}, tc.subresource...)
if err != nil {
t.Errorf("unexpected error when getting %q: %v", tc.name, err)
continue
@@ -235,7 +234,7 @@ func TestDelete(t *testing.T) {
namespace string
name string
path string
deleteOptions metav1.DeleteOptions
deleteOptions *metav1.DeleteOptions
}{
{
name: "normal_delete",
@@ -261,7 +260,7 @@ func TestDelete(t *testing.T) {
namespace: "nstest",
name: "namespaced_delete_with_options",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete_with_options",
deleteOptions: metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}, PropagationPolicy: &background},
deleteOptions: &metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}, PropagationPolicy: &background},
},
}
for _, tc := range tcs {
@@ -284,7 +283,7 @@ func TestDelete(t *testing.T) {
}
defer srv.Close()
err = cl.Resource(resource).Namespace(tc.namespace).Delete(context.TODO(), tc.name, tc.deleteOptions, tc.subresource...)
err = cl.Resource(resource).Namespace(tc.namespace).Delete(tc.name, tc.deleteOptions, tc.subresource...)
if err != nil {
t.Errorf("unexpected error when deleting %q: %v", tc.name, err)
continue
@@ -332,7 +331,7 @@ func TestDeleteCollection(t *testing.T) {
}
defer srv.Close()
err = cl.Resource(resource).Namespace(tc.namespace).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, metav1.ListOptions{})
err = cl.Resource(resource).Namespace(tc.namespace).DeleteCollection(nil, metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err)
continue
@@ -405,7 +404,7 @@ func TestCreate(t *testing.T) {
}
defer srv.Close()
got, err := cl.Resource(resource).Namespace(tc.namespace).Create(context.TODO(), tc.obj, metav1.CreateOptions{}, tc.subresource...)
got, err := cl.Resource(resource).Namespace(tc.namespace).Create(tc.obj, metav1.CreateOptions{}, tc.subresource...)
if err != nil {
t.Errorf("unexpected error when creating %q: %v", tc.name, err)
continue
@@ -482,7 +481,7 @@ func TestUpdate(t *testing.T) {
}
defer srv.Close()
got, err := cl.Resource(resource).Namespace(tc.namespace).Update(context.TODO(), tc.obj, metav1.UpdateOptions{}, tc.subresource...)
got, err := cl.Resource(resource).Namespace(tc.namespace).Update(tc.obj, metav1.UpdateOptions{}, tc.subresource...)
if err != nil {
t.Errorf("unexpected error when updating %q: %v", tc.name, err)
continue
@@ -538,8 +537,6 @@ func TestWatch(t *testing.T) {
t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query)
}
w.Header().Set("Content-Type", "application/json")
enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, unstructured.UnstructuredJSONScheme), unstructured.UnstructuredJSONScheme)
for _, e := range tc.events {
enc.Encode(&e)
@@ -551,7 +548,7 @@ func TestWatch(t *testing.T) {
}
defer srv.Close()
watcher, err := cl.Resource(resource).Namespace(tc.namespace).Watch(context.TODO(), metav1.ListOptions{})
watcher, err := cl.Resource(resource).Namespace(tc.namespace).Watch(metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when watching %q: %v", tc.name, err)
continue
@@ -641,7 +638,7 @@ func TestPatch(t *testing.T) {
}
defer srv.Close()
got, err := cl.Resource(resource).Namespace(tc.namespace).Patch(context.TODO(), tc.name, types.StrategicMergePatchType, tc.patch, metav1.PatchOptions{}, tc.subresource...)
got, err := cl.Resource(resource).Namespace(tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch, metav1.PatchOptions{}, tc.subresource...)
if err != nil {
t.Errorf("unexpected error when patching %q: %v", tc.name, err)
continue

View File

@@ -17,7 +17,6 @@ limitations under the License.
package dynamicinformer
import (
"context"
"sync"
"time"
@@ -126,13 +125,13 @@ func NewFilteredDynamicInformer(client dynamic.Interface, gvr schema.GroupVersio
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.Resource(gvr).Namespace(namespace).List(context.TODO(), options)
return client.Resource(gvr).Namespace(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.Resource(gvr).Namespace(namespace).Watch(context.TODO(), options)
return client.Resource(gvr).Namespace(namespace).Watch(options)
},
},
&unstructured.Unstructured{},

View File

@@ -32,104 +32,6 @@ import (
"k8s.io/client-go/tools/cache"
)
type triggerFunc func(gvr schema.GroupVersionResource, ns string, fakeClient *fake.FakeDynamicClient, testObject *unstructured.Unstructured) *unstructured.Unstructured
func triggerFactory(t *testing.T) triggerFunc {
return func(gvr schema.GroupVersionResource, ns string, fakeClient *fake.FakeDynamicClient, _ *unstructured.Unstructured) *unstructured.Unstructured {
testObject := newUnstructured("apps/v1", "Deployment", "ns-foo", "name-foo")
createdObj, err := fakeClient.Resource(gvr).Namespace(ns).Create(context.TODO(), testObject, metav1.CreateOptions{})
if err != nil {
t.Error(err)
}
return createdObj
}
}
func handler(rcvCh chan<- *unstructured.Unstructured) *cache.ResourceEventHandlerFuncs {
return &cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
rcvCh <- obj.(*unstructured.Unstructured)
},
}
}
func TestFilteredDynamicSharedInformerFactory(t *testing.T) {
scenarios := []struct {
name string
existingObj *unstructured.Unstructured
gvr schema.GroupVersionResource
informNS string
ns string
trigger func(gvr schema.GroupVersionResource, ns string, fakeClient *fake.FakeDynamicClient, testObject *unstructured.Unstructured) *unstructured.Unstructured
handler func(rcvCh chan<- *unstructured.Unstructured) *cache.ResourceEventHandlerFuncs
}{
// scenario 1
{
name: "scenario 1: test adding an object in different namespace should not trigger AddFunc",
informNS: "ns-bar",
ns: "ns-foo",
gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
trigger: triggerFactory(t),
handler: handler,
},
// scenario 2
{
name: "scenario 2: test adding an object should trigger AddFunc",
informNS: "ns-foo",
ns: "ns-foo",
gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
trigger: triggerFactory(t),
handler: handler,
},
}
for _, ts := range scenarios {
t.Run(ts.name, func(t *testing.T) {
// test data
timeout := time.Duration(3 * time.Second)
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
scheme := runtime.NewScheme()
informerReciveObjectCh := make(chan *unstructured.Unstructured, 1)
objs := []runtime.Object{}
if ts.existingObj != nil {
objs = append(objs, ts.existingObj)
}
// don't adjust the scheme to include deploymentlist. This is testing whether an informer can be created against using
// a client that doesn't have a type registered in the scheme.
gvrToListKind := map[schema.GroupVersionResource]string{
{Group: "apps", Version: "v1", Resource: "deployments"}: "DeploymentList",
}
fakeClient := fake.NewSimpleDynamicClientWithCustomListKinds(scheme, gvrToListKind, objs...)
target := dynamicinformer.NewFilteredDynamicSharedInformerFactory(fakeClient, 0, ts.informNS, nil)
// act
informerListerForGvr := target.ForResource(ts.gvr)
informerListerForGvr.Informer().AddEventHandler(ts.handler(informerReciveObjectCh))
target.Start(ctx.Done())
if synced := target.WaitForCacheSync(ctx.Done()); !synced[ts.gvr] {
t.Errorf("informer for %s hasn't synced", ts.gvr)
}
testObject := ts.trigger(ts.gvr, ts.ns, fakeClient, ts.existingObj)
select {
case objFromInformer := <-informerReciveObjectCh:
if ts.ns != ts.informNS {
t.Errorf("informer received an object for namespace %s when watching namespace %s", ts.ns, ts.informNS)
}
if !equality.Semantic.DeepEqual(testObject, objFromInformer) {
t.Fatalf("%v", diff.ObjectDiff(testObject, objFromInformer))
}
case <-ctx.Done():
if ts.ns == ts.informNS {
t.Errorf("tested informer haven't received an object, waited %v", timeout)
}
}
})
}
}
func TestDynamicSharedInformerFactory(t *testing.T) {
scenarios := []struct {
name string
@@ -146,7 +48,7 @@ func TestDynamicSharedInformerFactory(t *testing.T) {
gvr: schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"},
trigger: func(gvr schema.GroupVersionResource, ns string, fakeClient *fake.FakeDynamicClient, _ *unstructured.Unstructured) *unstructured.Unstructured {
testObject := newUnstructured("extensions/v1beta1", "Deployment", "ns-foo", "name-foo")
createdObj, err := fakeClient.Resource(gvr).Namespace(ns).Create(context.TODO(), testObject, metav1.CreateOptions{})
createdObj, err := fakeClient.Resource(gvr).Namespace(ns).Create(testObject, metav1.CreateOptions{})
if err != nil {
t.Error(err)
}
@@ -169,7 +71,7 @@ func TestDynamicSharedInformerFactory(t *testing.T) {
existingObj: newUnstructured("extensions/v1beta1", "Deployment", "ns-foo", "name-foo"),
trigger: func(gvr schema.GroupVersionResource, ns string, fakeClient *fake.FakeDynamicClient, testObject *unstructured.Unstructured) *unstructured.Unstructured {
testObject.Object["spec"] = "updatedName"
updatedObj, err := fakeClient.Resource(gvr).Namespace(ns).Update(context.TODO(), testObject, metav1.UpdateOptions{})
updatedObj, err := fakeClient.Resource(gvr).Namespace(ns).Update(testObject, metav1.UpdateOptions{})
if err != nil {
t.Error(err)
}
@@ -191,7 +93,7 @@ func TestDynamicSharedInformerFactory(t *testing.T) {
gvr: schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"},
existingObj: newUnstructured("extensions/v1beta1", "Deployment", "ns-foo", "name-foo"),
trigger: func(gvr schema.GroupVersionResource, ns string, fakeClient *fake.FakeDynamicClient, testObject *unstructured.Unstructured) *unstructured.Unstructured {
err := fakeClient.Resource(gvr).Namespace(ns).Delete(context.TODO(), testObject.GetName(), metav1.DeleteOptions{})
err := fakeClient.Resource(gvr).Namespace(ns).Delete(testObject.GetName(), &metav1.DeleteOptions{})
if err != nil {
t.Error(err)
}
@@ -219,12 +121,7 @@ func TestDynamicSharedInformerFactory(t *testing.T) {
if ts.existingObj != nil {
objs = append(objs, ts.existingObj)
}
// don't adjust the scheme to include deploymentlist. This is testing whether an informer can be created against using
// a client that doesn't have a type registered in the scheme.
gvrToListKind := map[schema.GroupVersionResource]string{
{Group: "extensions", Version: "v1beta1", Resource: "deployments"}: "DeploymentList",
}
fakeClient := fake.NewSimpleDynamicClientWithCustomListKinds(scheme, gvrToListKind, objs...)
fakeClient := fake.NewSimpleDynamicClient(scheme, objs...)
target := dynamicinformer.NewDynamicSharedInformerFactory(fakeClient, 0)
// act

View File

@@ -17,8 +17,6 @@ limitations under the License.
package fake
import (
"context"
"fmt"
"strings"
"k8s.io/apimachinery/pkg/api/meta"
@@ -35,45 +33,9 @@ import (
)
func NewSimpleDynamicClient(scheme *runtime.Scheme, objects ...runtime.Object) *FakeDynamicClient {
return NewSimpleDynamicClientWithCustomListKinds(scheme, nil, objects...)
}
// NewSimpleDynamicClientWithCustomListKinds try not to use this. In general you want to have the scheme have the List types registered
// and allow the default guessing for resources match. Sometimes that doesn't work, so you can specify a custom mapping here.
func NewSimpleDynamicClientWithCustomListKinds(scheme *runtime.Scheme, gvrToListKind map[schema.GroupVersionResource]string, objects ...runtime.Object) *FakeDynamicClient {
// In order to use List with this client, you have to have your lists registered so that the object tracker will find them
// in the scheme to support the t.scheme.New(listGVK) call when it's building the return value.
// Since the base fake client needs the listGVK passed through the action (in cases where there are no instances, it
// cannot look up the actual hits), we need to know a mapping of GVR to listGVK here. For GETs and other types of calls,
// there is no return value that contains a GVK, so it doesn't have to know the mapping in advance.
// first we attempt to invert known List types from the scheme to auto guess the resource with unsafe guesses
// this covers common usage of registering types in scheme and passing them
completeGVRToListKind := map[schema.GroupVersionResource]string{}
for listGVK := range scheme.AllKnownTypes() {
if !strings.HasSuffix(listGVK.Kind, "List") {
continue
}
nonListGVK := listGVK.GroupVersion().WithKind(listGVK.Kind[:len(listGVK.Kind)-4])
plural, _ := meta.UnsafeGuessKindToResource(nonListGVK)
completeGVRToListKind[plural] = listGVK.Kind
}
for gvr, listKind := range gvrToListKind {
if !strings.HasSuffix(listKind, "List") {
panic("coding error, listGVK must end in List or this fake client doesn't work right")
}
listGVK := gvr.GroupVersion().WithKind(listKind)
// if we already have this type registered, just skip it
if _, err := scheme.New(listGVK); err == nil {
completeGVRToListKind[gvr] = listKind
continue
}
scheme.AddKnownTypeWithName(listGVK, &unstructured.UnstructuredList{})
completeGVRToListKind[gvr] = listKind
}
// In order to use List with this client, you have to have the v1.List registered in your scheme. Neat thing though
// it does NOT have to be the *same* list
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "fake-dynamic-client-group", Version: "v1", Kind: "List"}, &unstructured.UnstructuredList{})
codecs := serializer.NewCodecFactory(scheme)
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
@@ -83,7 +45,7 @@ func NewSimpleDynamicClientWithCustomListKinds(scheme *runtime.Scheme, gvrToList
}
}
cs := &FakeDynamicClient{scheme: scheme, gvrToListKind: completeGVRToListKind}
cs := &FakeDynamicClient{scheme: scheme}
cs.AddReactor("*", "*", testing.ObjectReaction(o))
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
gvr := action.GetResource()
@@ -103,21 +65,19 @@ func NewSimpleDynamicClientWithCustomListKinds(scheme *runtime.Scheme, gvrToList
// you want to test easier.
type FakeDynamicClient struct {
testing.Fake
scheme *runtime.Scheme
gvrToListKind map[schema.GroupVersionResource]string
scheme *runtime.Scheme
}
type dynamicResourceClient struct {
client *FakeDynamicClient
namespace string
resource schema.GroupVersionResource
listKind string
}
var _ dynamic.Interface = &FakeDynamicClient{}
func (c *FakeDynamicClient) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableResourceInterface {
return &dynamicResourceClient{client: c, resource: resource, listKind: c.gvrToListKind[resource]}
return &dynamicResourceClient{client: c, resource: resource}
}
func (c *dynamicResourceClient) Namespace(ns string) dynamic.ResourceInterface {
@@ -126,7 +86,7 @@ func (c *dynamicResourceClient) Namespace(ns string) dynamic.ResourceInterface {
return &ret
}
func (c *dynamicResourceClient) Create(ctx context.Context, obj *unstructured.Unstructured, opts metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, opts metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
var uncastRet runtime.Object
var err error
switch {
@@ -135,8 +95,7 @@ func (c *dynamicResourceClient) Create(ctx context.Context, obj *unstructured.Un
Invokes(testing.NewRootCreateAction(c.resource, obj), obj)
case len(c.namespace) == 0 && len(subresources) > 0:
var accessor metav1.Object // avoid shadowing err
accessor, err = meta.Accessor(obj)
accessor, err := meta.Accessor(obj)
if err != nil {
return nil, err
}
@@ -149,8 +108,7 @@ func (c *dynamicResourceClient) Create(ctx context.Context, obj *unstructured.Un
Invokes(testing.NewCreateAction(c.resource, c.namespace, obj), obj)
case len(c.namespace) > 0 && len(subresources) > 0:
var accessor metav1.Object // avoid shadowing err
accessor, err = meta.Accessor(obj)
accessor, err := meta.Accessor(obj)
if err != nil {
return nil, err
}
@@ -174,7 +132,7 @@ func (c *dynamicResourceClient) Create(ctx context.Context, obj *unstructured.Un
return ret, err
}
func (c *dynamicResourceClient) Update(ctx context.Context, obj *unstructured.Unstructured, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
var uncastRet runtime.Object
var err error
switch {
@@ -210,7 +168,7 @@ func (c *dynamicResourceClient) Update(ctx context.Context, obj *unstructured.Un
return ret, err
}
func (c *dynamicResourceClient) UpdateStatus(ctx context.Context, obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) {
var uncastRet runtime.Object
var err error
switch {
@@ -238,7 +196,7 @@ func (c *dynamicResourceClient) UpdateStatus(ctx context.Context, obj *unstructu
return ret, err
}
func (c *dynamicResourceClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions, subresources ...string) error {
func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
var err error
switch {
case len(c.namespace) == 0 && len(subresources) == 0:
@@ -261,7 +219,7 @@ func (c *dynamicResourceClient) Delete(ctx context.Context, name string, opts me
return err
}
func (c *dynamicResourceClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOptions metav1.ListOptions) error {
func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
var err error
switch {
case len(c.namespace) == 0:
@@ -277,7 +235,7 @@ func (c *dynamicResourceClient) DeleteCollection(ctx context.Context, opts metav
return err
}
func (c *dynamicResourceClient) Get(ctx context.Context, name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
var uncastRet runtime.Object
var err error
switch {
@@ -312,23 +270,17 @@ func (c *dynamicResourceClient) Get(ctx context.Context, name string, opts metav
return ret, err
}
func (c *dynamicResourceClient) List(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
if len(c.listKind) == 0 {
panic(fmt.Sprintf("coding error: you must register resource to list kind for every resource you're going to LIST when creating the client. See NewSimpleDynamicClientWithCustomListKinds or register the list into the scheme: %v out of %v", c.resource, c.client.gvrToListKind))
}
listGVK := c.resource.GroupVersion().WithKind(c.listKind)
listForFakeClientGVK := c.resource.GroupVersion().WithKind(c.listKind[:len(c.listKind)-4]) /*base library appends List*/
func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
var obj runtime.Object
var err error
switch {
case len(c.namespace) == 0:
obj, err = c.client.Fake.
Invokes(testing.NewRootListAction(c.resource, listForFakeClientGVK, opts), &metav1.Status{Status: "dynamic list fail"})
Invokes(testing.NewRootListAction(c.resource, schema.GroupVersionKind{Group: "fake-dynamic-client-group", Version: "v1", Kind: "" /*List is appended by the tracker automatically*/}, opts), &metav1.Status{Status: "dynamic list fail"})
case len(c.namespace) > 0:
obj, err = c.client.Fake.
Invokes(testing.NewListAction(c.resource, listForFakeClientGVK, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"})
Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Group: "fake-dynamic-client-group", Version: "v1", Kind: "" /*List is appended by the tracker automatically*/}, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"})
}
@@ -352,7 +304,6 @@ func (c *dynamicResourceClient) List(ctx context.Context, opts metav1.ListOption
list := &unstructured.UnstructuredList{}
list.SetResourceVersion(entireList.GetResourceVersion())
list.GetObjectKind().SetGroupVersionKind(listGVK)
for i := range entireList.Items {
item := &entireList.Items[i]
metadata, err := meta.Accessor(item)
@@ -366,7 +317,7 @@ func (c *dynamicResourceClient) List(ctx context.Context, opts metav1.ListOption
return list, nil
}
func (c *dynamicResourceClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
switch {
case len(c.namespace) == 0:
return c.client.Fake.
@@ -382,7 +333,7 @@ func (c *dynamicResourceClient) Watch(ctx context.Context, opts metav1.ListOptio
}
// TODO: opts are currently ignored.
func (c *dynamicResourceClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error) {
var uncastRet runtime.Object
var err error
switch {

View File

@@ -17,7 +17,6 @@ limitations under the License.
package fake
import (
"context"
"fmt"
"testing"
@@ -59,138 +58,31 @@ func newUnstructuredWithSpec(spec map[string]interface{}) *unstructured.Unstruct
return u
}
func TestGet(t *testing.T) {
scheme := runtime.NewScheme()
client := NewSimpleDynamicClient(scheme, newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"))
get, err := client.Resource(schema.GroupVersionResource{Group: "group", Version: "version", Resource: "thekinds"}).Namespace("ns-foo").Get(context.TODO(), "name-foo", metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}
expected := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "group/version",
"kind": "TheKind",
"metadata": map[string]interface{}{
"name": "name-foo",
"namespace": "ns-foo",
},
},
}
if !equality.Semantic.DeepEqual(get, expected) {
t.Fatal(diff.ObjectGoPrintDiff(expected, get))
}
}
func TestListDecoding(t *testing.T) {
// this the duplication of logic from the real List API. This will prove that our dynamic client actually returns the gvk
uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, []byte(`{"apiVersion": "group/version", "kind": "TheKindList", "items":[]}`))
if err != nil {
t.Fatal(err)
}
list := uncastObj.(*unstructured.UnstructuredList)
expectedList := &unstructured.UnstructuredList{
Object: map[string]interface{}{
"apiVersion": "group/version",
"kind": "TheKindList",
},
Items: []unstructured.Unstructured{},
}
if !equality.Semantic.DeepEqual(list, expectedList) {
t.Fatal(diff.ObjectGoPrintDiff(expectedList, list))
}
}
func TestGetDecoding(t *testing.T) {
// this the duplication of logic from the real Get API. This will prove that our dynamic client actually returns the gvk
uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, []byte(`{"apiVersion": "group/version", "kind": "TheKind"}`))
if err != nil {
t.Fatal(err)
}
get := uncastObj.(*unstructured.Unstructured)
expectedObj := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "group/version",
"kind": "TheKind",
},
}
if !equality.Semantic.DeepEqual(get, expectedObj) {
t.Fatal(diff.ObjectGoPrintDiff(expectedObj, get))
}
}
func TestList(t *testing.T) {
scheme := runtime.NewScheme()
client := NewSimpleDynamicClientWithCustomListKinds(scheme,
map[schema.GroupVersionResource]string{
{Group: "group", Version: "version", Resource: "thekinds"}: "TheKindList",
},
client := NewSimpleDynamicClient(scheme,
newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
newUnstructured("group2/version", "TheKind", "ns-foo", "name2-foo"),
newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"),
newUnstructured("group/version", "TheKind", "ns-foo", "name-baz"),
newUnstructured("group2/version", "TheKind", "ns-foo", "name2-baz"),
)
listFirst, err := client.Resource(schema.GroupVersionResource{Group: "group", Version: "version", Resource: "thekinds"}).List(context.TODO(), metav1.ListOptions{})
listFirst, err := client.Resource(schema.GroupVersionResource{Group: "group", Version: "version", Resource: "thekinds"}).List(metav1.ListOptions{})
if err != nil {
t.Fatal(err)
}
expected := []unstructured.Unstructured{
*newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
*newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"),
*newUnstructured("group/version", "TheKind", "ns-foo", "name-baz"),
*newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
}
if !equality.Semantic.DeepEqual(listFirst.Items, expected) {
t.Fatal(diff.ObjectGoPrintDiff(expected, listFirst.Items))
}
}
func Test_ListKind(t *testing.T) {
scheme := runtime.NewScheme()
client := NewSimpleDynamicClientWithCustomListKinds(scheme,
map[schema.GroupVersionResource]string{
{Group: "group", Version: "version", Resource: "thekinds"}: "TheKindList",
},
&unstructured.UnstructuredList{
Object: map[string]interface{}{
"apiVersion": "group/version",
"kind": "TheKindList",
},
Items: []unstructured.Unstructured{
*newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
*newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"),
*newUnstructured("group/version", "TheKind", "ns-foo", "name-baz"),
},
},
)
listFirst, err := client.Resource(schema.GroupVersionResource{Group: "group", Version: "version", Resource: "thekinds"}).List(context.TODO(), metav1.ListOptions{})
if err != nil {
t.Fatal(err)
}
expectedList := &unstructured.UnstructuredList{
Object: map[string]interface{}{
"apiVersion": "group/version",
"kind": "TheKindList",
"metadata": map[string]interface{}{
"resourceVersion": "",
},
},
Items: []unstructured.Unstructured{
*newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"),
*newUnstructured("group/version", "TheKind", "ns-foo", "name-baz"),
*newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
},
}
if !equality.Semantic.DeepEqual(listFirst, expectedList) {
t.Fatal(diff.ObjectGoPrintDiff(expectedList, listFirst))
}
}
type patchTestCase struct {
name string
object runtime.Object
@@ -204,7 +96,7 @@ func (tc *patchTestCase) runner(t *testing.T) {
client := NewSimpleDynamicClient(runtime.NewScheme(), tc.object)
resourceInterface := client.Resource(schema.GroupVersionResource{Group: testGroup, Version: testVersion, Resource: testResource}).Namespace(testNamespace)
got, recErr := resourceInterface.Patch(context.TODO(), testName, tc.patchType, tc.patchBytes, metav1.PatchOptions{})
got, recErr := resourceInterface.Patch(testName, tc.patchType, tc.patchBytes, metav1.PatchOptions{})
if err := tc.verifyErr(recErr); err != nil {
t.Error(err)

View File

@@ -17,8 +17,6 @@ limitations under the License.
package dynamic
import (
"context"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -31,15 +29,15 @@ type Interface interface {
}
type ResourceInterface interface {
Create(ctx context.Context, obj *unstructured.Unstructured, options metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error)
Update(ctx context.Context, obj *unstructured.Unstructured, options metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error)
UpdateStatus(ctx context.Context, obj *unstructured.Unstructured, options metav1.UpdateOptions) (*unstructured.Unstructured, error)
Delete(ctx context.Context, name string, options metav1.DeleteOptions, subresources ...string) error
DeleteCollection(ctx context.Context, options metav1.DeleteOptions, listOptions metav1.ListOptions) error
Get(ctx context.Context, name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error)
List(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, options metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error)
Create(obj *unstructured.Unstructured, options metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error)
Update(obj *unstructured.Unstructured, options metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error)
UpdateStatus(obj *unstructured.Unstructured, options metav1.UpdateOptions) (*unstructured.Unstructured, error)
Delete(name string, options *metav1.DeleteOptions, subresources ...string) error
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
Get(name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error)
List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
Watch(opts metav1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, options metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error)
}
type NamespaceableResourceInterface interface {

View File

@@ -18,11 +18,11 @@ package dynamic
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/runtime/serializer/versioning"
)
var watchScheme = runtime.NewScheme()
@@ -41,6 +41,37 @@ func init() {
metav1.AddToGroupVersion(deleteScheme, versionV1)
}
var watchJsonSerializerInfo = runtime.SerializerInfo{
MediaType: "application/json",
MediaTypeType: "application",
MediaTypeSubType: "json",
EncodesAsText: true,
Serializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, false),
PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, true),
StreamSerializer: &runtime.StreamSerializerInfo{
EncodesAsText: true,
Serializer: json.NewSerializer(json.DefaultMetaFactory, watchScheme, watchScheme, false),
Framer: json.Framer,
},
}
// watchNegotiatedSerializer is used to read the wrapper of the watch stream
type watchNegotiatedSerializer struct{}
var watchNegotiatedSerializerInstance = watchNegotiatedSerializer{}
func (s watchNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo {
return []runtime.SerializerInfo{watchJsonSerializerInfo}
}
func (s watchNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
return versioning.NewDefaultingCodecForScheme(watchScheme, encoder, nil, gv, nil)
}
func (s watchNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
return versioning.NewDefaultingCodecForScheme(watchScheme, nil, decoder, nil, gv)
}
// basicNegotiatedSerializer is used to handle discovery and error handling serialization
type basicNegotiatedSerializer struct{}
@@ -51,8 +82,8 @@ func (s basicNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInf
MediaTypeType: "application",
MediaTypeSubType: "json",
EncodesAsText: true,
Serializer: json.NewSerializer(json.DefaultMetaFactory, unstructuredCreater{basicScheme}, unstructuredTyper{basicScheme}, false),
PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, unstructuredCreater{basicScheme}, unstructuredTyper{basicScheme}, true),
Serializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, false),
PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, true),
StreamSerializer: &runtime.StreamSerializerInfo{
EncodesAsText: true,
Serializer: json.NewSerializer(json.DefaultMetaFactory, basicScheme, basicScheme, false),
@@ -63,46 +94,9 @@ func (s basicNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInf
}
func (s basicNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
return runtime.WithVersionEncoder{
Version: gv,
Encoder: encoder,
ObjectTyper: unstructuredTyper{basicScheme},
}
return versioning.NewDefaultingCodecForScheme(watchScheme, encoder, nil, gv, nil)
}
func (s basicNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
return decoder
}
type unstructuredCreater struct {
nested runtime.ObjectCreater
}
func (c unstructuredCreater) New(kind schema.GroupVersionKind) (runtime.Object, error) {
out, err := c.nested.New(kind)
if err == nil {
return out, nil
}
out = &unstructured.Unstructured{}
out.GetObjectKind().SetGroupVersionKind(kind)
return out, nil
}
type unstructuredTyper struct {
nested runtime.ObjectTyper
}
func (t unstructuredTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
kinds, unversioned, err := t.nested.ObjectKinds(obj)
if err == nil {
return kinds, unversioned, nil
}
if _, ok := obj.(runtime.Unstructured); ok && !obj.GetObjectKind().GroupVersionKind().Empty() {
return []schema.GroupVersionKind{obj.GetObjectKind().GroupVersionKind()}, false, nil
}
return nil, false, err
}
func (t unstructuredTyper) Recognizes(gvk schema.GroupVersionKind) bool {
return true
return versioning.NewDefaultingCodecForScheme(watchScheme, nil, decoder, nil, gv)
}

View File

@@ -17,14 +17,15 @@ limitations under the License.
package dynamic
import (
"context"
"fmt"
"io"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/rest"
@@ -90,7 +91,7 @@ func (c *dynamicResourceClient) Namespace(ns string) ResourceInterface {
return &ret
}
func (c *dynamicResourceClient) Create(ctx context.Context, obj *unstructured.Unstructured, opts metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, opts metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
if err != nil {
return nil, err
@@ -112,7 +113,7 @@ func (c *dynamicResourceClient) Create(ctx context.Context, obj *unstructured.Un
AbsPath(append(c.makeURLSegments(name), subresources...)...).
Body(outBytes).
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
Do(ctx)
Do()
if err := result.Error(); err != nil {
return nil, err
}
@@ -128,7 +129,7 @@ func (c *dynamicResourceClient) Create(ctx context.Context, obj *unstructured.Un
return uncastObj.(*unstructured.Unstructured), nil
}
func (c *dynamicResourceClient) Update(ctx context.Context, obj *unstructured.Unstructured, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
accessor, err := meta.Accessor(obj)
if err != nil {
return nil, err
@@ -147,7 +148,7 @@ func (c *dynamicResourceClient) Update(ctx context.Context, obj *unstructured.Un
AbsPath(append(c.makeURLSegments(name), subresources...)...).
Body(outBytes).
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
Do(ctx)
Do()
if err := result.Error(); err != nil {
return nil, err
}
@@ -163,7 +164,7 @@ func (c *dynamicResourceClient) Update(ctx context.Context, obj *unstructured.Un
return uncastObj.(*unstructured.Unstructured), nil
}
func (c *dynamicResourceClient) UpdateStatus(ctx context.Context, obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) {
accessor, err := meta.Accessor(obj)
if err != nil {
return nil, err
@@ -183,7 +184,7 @@ func (c *dynamicResourceClient) UpdateStatus(ctx context.Context, obj *unstructu
AbsPath(append(c.makeURLSegments(name), "status")...).
Body(outBytes).
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
Do(ctx)
Do()
if err := result.Error(); err != nil {
return nil, err
}
@@ -199,11 +200,14 @@ func (c *dynamicResourceClient) UpdateStatus(ctx context.Context, obj *unstructu
return uncastObj.(*unstructured.Unstructured), nil
}
func (c *dynamicResourceClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions, subresources ...string) error {
func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
if len(name) == 0 {
return fmt.Errorf("name is required")
}
deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), &opts)
if opts == nil {
opts = &metav1.DeleteOptions{}
}
deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts)
if err != nil {
return err
}
@@ -212,12 +216,15 @@ func (c *dynamicResourceClient) Delete(ctx context.Context, name string, opts me
Delete().
AbsPath(append(c.makeURLSegments(name), subresources...)...).
Body(deleteOptionsByte).
Do(ctx)
Do()
return result.Error()
}
func (c *dynamicResourceClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOptions metav1.ListOptions) error {
deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), &opts)
func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
if opts == nil {
opts = &metav1.DeleteOptions{}
}
deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts)
if err != nil {
return err
}
@@ -227,15 +234,15 @@ func (c *dynamicResourceClient) DeleteCollection(ctx context.Context, opts metav
AbsPath(c.makeURLSegments("")...).
Body(deleteOptionsByte).
SpecificallyVersionedParams(&listOptions, dynamicParameterCodec, versionV1).
Do(ctx)
Do()
return result.Error()
}
func (c *dynamicResourceClient) Get(ctx context.Context, name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
if len(name) == 0 {
return nil, fmt.Errorf("name is required")
}
result := c.client.client.Get().AbsPath(append(c.makeURLSegments(name), subresources...)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do(ctx)
result := c.client.client.Get().AbsPath(append(c.makeURLSegments(name), subresources...)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
if err := result.Error(); err != nil {
return nil, err
}
@@ -250,8 +257,8 @@ func (c *dynamicResourceClient) Get(ctx context.Context, name string, opts metav
return uncastObj.(*unstructured.Unstructured), nil
}
func (c *dynamicResourceClient) List(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do(ctx)
func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
if err := result.Error(); err != nil {
return nil, err
}
@@ -274,14 +281,35 @@ func (c *dynamicResourceClient) List(ctx context.Context, opts metav1.ListOption
return list, nil
}
func (c *dynamicResourceClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
internalGV := schema.GroupVersions{
{Group: c.resource.Group, Version: runtime.APIVersionInternal},
// always include the legacy group as a decoding target to handle non-error `Status` return types
{Group: "", Version: runtime.APIVersionInternal},
}
s := &rest.Serializers{
Encoder: watchNegotiatedSerializerInstance.EncoderForVersion(watchJsonSerializerInfo.Serializer, c.resource.GroupVersion()),
Decoder: watchNegotiatedSerializerInstance.DecoderToVersion(watchJsonSerializerInfo.Serializer, internalGV),
RenegotiatedDecoder: func(contentType string, params map[string]string) (runtime.Decoder, error) {
return watchNegotiatedSerializerInstance.DecoderToVersion(watchJsonSerializerInfo.Serializer, internalGV), nil
},
StreamingSerializer: watchJsonSerializerInfo.StreamSerializer.Serializer,
Framer: watchJsonSerializerInfo.StreamSerializer.Framer,
}
wrappedDecoderFn := func(body io.ReadCloser) streaming.Decoder {
framer := s.Framer.NewFrameReader(body)
return streaming.NewDecoder(framer, s.StreamingSerializer)
}
opts.Watch = true
return c.client.client.Get().AbsPath(c.makeURLSegments("")...).
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
Watch(ctx)
WatchWithSpecificDecoders(wrappedDecoderFn, unstructured.UnstructuredJSONScheme)
}
func (c *dynamicResourceClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error) {
if len(name) == 0 {
return nil, fmt.Errorf("name is required")
}
@@ -290,7 +318,7 @@ func (c *dynamicResourceClient) Patch(ctx context.Context, name string, pt types
AbsPath(append(c.makeURLSegments(name), subresources...)...).
Body(data).
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
Do(ctx)
Do()
if err := result.Error(); err != nil {
return nil, err
}

View File

@@ -19,7 +19,6 @@ package main
import (
"bufio"
"context"
"flag"
"fmt"
"os"
@@ -34,7 +33,7 @@ import (
"k8s.io/client-go/util/retry"
//
// Uncomment to load all auth plugins
// _ "k8s.io/client-go/plugin/pkg/client/auth"
// _ "k8s.io/client-go/plugin/pkg/client/auth
//
// Or uncomment to load specific auth plugins
// _ "k8s.io/client-go/plugin/pkg/client/auth/azure"
@@ -101,7 +100,7 @@ func main() {
// Create Deployment
fmt.Println("Creating deployment...")
result, err := deploymentsClient.Create(context.TODO(), deployment, metav1.CreateOptions{})
result, err := deploymentsClient.Create(deployment)
if err != nil {
panic(err)
}
@@ -126,14 +125,14 @@ func main() {
retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
// Retrieve the latest version of Deployment before attempting update
// RetryOnConflict uses exponential backoff to avoid exhausting the apiserver
result, getErr := deploymentsClient.Get(context.TODO(), "demo-deployment", metav1.GetOptions{})
result, getErr := deploymentsClient.Get("demo-deployment", metav1.GetOptions{})
if getErr != nil {
panic(fmt.Errorf("Failed to get latest version of Deployment: %v", getErr))
}
result.Spec.Replicas = int32Ptr(1) // reduce replica count
result.Spec.Template.Spec.Containers[0].Image = "nginx:1.13" // change nginx version
_, updateErr := deploymentsClient.Update(context.TODO(), result, metav1.UpdateOptions{})
_, updateErr := deploymentsClient.Update(result)
return updateErr
})
if retryErr != nil {
@@ -144,7 +143,7 @@ func main() {
// List Deployments
prompt()
fmt.Printf("Listing deployments in namespace %q:\n", apiv1.NamespaceDefault)
list, err := deploymentsClient.List(context.TODO(), metav1.ListOptions{})
list, err := deploymentsClient.List(metav1.ListOptions{})
if err != nil {
panic(err)
}
@@ -156,7 +155,7 @@ func main() {
prompt()
fmt.Println("Deleting deployment...")
deletePolicy := metav1.DeletePropagationForeground
if err := deploymentsClient.Delete(context.TODO(), "demo-deployment", metav1.DeleteOptions{
if err := deploymentsClient.Delete("demo-deployment", &metav1.DeleteOptions{
PropagationPolicy: &deletePolicy,
}); err != nil {
panic(err)

View File

@@ -1,93 +0,0 @@
# Create, Update & Delete Deployment with the Dynamic Package
This example program demonstrates the fundamental operations for managing on
[Deployment][1] resources, such as `Create`, `List`, `Update` and `Delete` using client-go's `dynamic` package.
## Typed Vs. Dynamic
The code in this directory is based on a similar [example that uses Kubernetes typed client sets][2]. The typed client sets make it simple to communicate with the API server using pre-generated local API objects to achieve an RPC-like programming experience. Typed clients uses program compilations to enforce data safety and some validation. However, when using typed clients, programs are forced to be tightly coupled with the version and the types used.
The `dynamic` package on the other hand, uses a simple type, `unstructured.Unstructured`, to represent all object values from the API server. Type `Unstructured` uses a collection of nested `map[string]interface{}` values to create an internal structure that closely resemble the REST payload from the server.
The dynamic package defers all data bindings until runtime. This means programs that use the dynamic client will not get any of the benefits of type validation until the program is running. This may be a problem for certain types of applications that require strong data type check and validation.
Being loosely coupled, however, means that programs that uses the `dynamic` package do not require recompilation when the client API changes. The client program has more flexibility in handling updates to the API surface without knowing ahead of time what those changes are.
## Running this example
Make sure you have a Kubernetes cluster and `kubectl` is configured:
```
kubectl get nodes
```
Compile this example on your workstation:
```
cd dynamic-create-update-delete-deployment
go build -o ./app
```
Now, run this application on your workstation with your local kubeconfig file:
```
./app
# or specify a kubeconfig file with flag
./app -kubeconfig=$HOME/.kube/config
```
Running this command will execute the following operations on your cluster:
1. **Create Deployment:** This will create a 2 replica Deployment. Verify with
`kubectl get pods`.
2. **Update Deployment:** This will update the Deployment resource created in
previous step by setting the replica count to 1 and changing the container
image to `nginx:1.13`. You are encouraged to inspect the retry loop that
handles conflicts. Verify the new replica count and container image with
`kubectl describe deployment demo`.
3. **List Deployments:** This will retrieve Deployments in the `default`
namespace and print their names and replica counts.
4. **Delete Deployment:** This will delete the Deployment object and its
dependent ReplicaSet resource. Verify with `kubectl get deployments`.
Each step is separated by an interactive prompt. You must hit the
<kbd>Return</kbd> key to proceed to the next step. You can use these prompts as
a break to take time to run `kubectl` and inspect the result of the operations
executed.
You should see an output like the following:
```
Creating deployment...
Created deployment "demo-deployment".
-> Press Return key to continue.
Updating deployment...
Updated deployment...
-> Press Return key to continue.
Listing deployments in namespace "default":
* demo-deployment (1 replicas)
-> Press Return key to continue.
Deleting deployment...
Deleted deployment.
```
## Cleanup
Successfully running this program will clean the created artifacts. If you
terminate the program without completing, you can clean up the created
deployment with:
kubectl delete deploy demo-deployment
## Troubleshooting
If you are getting the following error, make sure Kubernetes version of your
cluster is v1.13 or higher in `kubectl version`:
panic: the server could not find the requested resource
[1]: https://kubernetes.io/docs/user-guide/deployments/
[2]: ../create-update-delete-deployment

View File

@@ -1,209 +0,0 @@
/*
Copyright 2019 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.
*/
// Note: the example only works with the code within the same release/branch.
package main
import (
"bufio"
"context"
"flag"
"fmt"
"os"
"path/filepath"
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
"k8s.io/client-go/util/retry"
//
// Uncomment to load all auth plugins
// _ "k8s.io/client-go/plugin/pkg/client/auth"
//
// Or uncomment to load specific auth plugins
// _ "k8s.io/client-go/plugin/pkg/client/auth/azure"
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
// _ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
// _ "k8s.io/client-go/plugin/pkg/client/auth/openstack"
)
func main() {
var kubeconfig *string
if home := homedir.HomeDir(); home != "" {
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
}
flag.Parse()
namespace := "default"
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
panic(err)
}
client, err := dynamic.NewForConfig(config)
if err != nil {
panic(err)
}
deploymentRes := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}
deployment := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "demo-deployment",
},
"spec": map[string]interface{}{
"replicas": 2,
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app": "demo",
},
},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app": "demo",
},
},
"spec": map[string]interface{}{
"containers": []map[string]interface{}{
{
"name": "web",
"image": "nginx:1.12",
"ports": []map[string]interface{}{
{
"name": "http",
"protocol": "TCP",
"containerPort": 80,
},
},
},
},
},
},
},
},
}
// Create Deployment
fmt.Println("Creating deployment...")
result, err := client.Resource(deploymentRes).Namespace(namespace).Create(context.TODO(), deployment, metav1.CreateOptions{})
if err != nil {
panic(err)
}
fmt.Printf("Created deployment %q.\n", result.GetName())
// Update Deployment
prompt()
fmt.Println("Updating deployment...")
// You have two options to Update() this Deployment:
//
// 1. Modify the "deployment" variable and call: Update(deployment).
// This works like the "kubectl replace" command and it overwrites/loses changes
// made by other clients between you Create() and Update() the object.
// 2. Modify the "result" returned by Get() and retry Update(result) until
// you no longer get a conflict error. This way, you can preserve changes made
// by other clients between Create() and Update(). This is implemented below
// using the retry utility package included with client-go. (RECOMMENDED)
//
// More Info:
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
// Retrieve the latest version of Deployment before attempting update
// RetryOnConflict uses exponential backoff to avoid exhausting the apiserver
result, getErr := client.Resource(deploymentRes).Namespace(namespace).Get(context.TODO(), "demo-deployment", metav1.GetOptions{})
if getErr != nil {
panic(fmt.Errorf("failed to get latest version of Deployment: %v", getErr))
}
// update replicas to 1
if err := unstructured.SetNestedField(result.Object, int64(1), "spec", "replicas"); err != nil {
panic(fmt.Errorf("failed to set replica value: %v", err))
}
// extract spec containers
containers, found, err := unstructured.NestedSlice(result.Object, "spec", "template", "spec", "containers")
if err != nil || !found || containers == nil {
panic(fmt.Errorf("deployment containers not found or error in spec: %v", err))
}
// update container[0] image
if err := unstructured.SetNestedField(containers[0].(map[string]interface{}), "nginx:1.13", "image"); err != nil {
panic(err)
}
if err := unstructured.SetNestedField(result.Object, containers, "spec", "template", "spec", "containers"); err != nil {
panic(err)
}
_, updateErr := client.Resource(deploymentRes).Namespace(namespace).Update(context.TODO(), result, metav1.UpdateOptions{})
return updateErr
})
if retryErr != nil {
panic(fmt.Errorf("update failed: %v", retryErr))
}
fmt.Println("Updated deployment...")
// List Deployments
prompt()
fmt.Printf("Listing deployments in namespace %q:\n", apiv1.NamespaceDefault)
list, err := client.Resource(deploymentRes).Namespace(namespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err)
}
for _, d := range list.Items {
replicas, found, err := unstructured.NestedInt64(d.Object, "spec", "replicas")
if err != nil || !found {
fmt.Printf("Replicas not found for deployment %s: error=%s", d.GetName(), err)
continue
}
fmt.Printf(" * %s (%d replicas)\n", d.GetName(), replicas)
}
// Delete Deployment
prompt()
fmt.Println("Deleting deployment...")
deletePolicy := metav1.DeletePropagationForeground
deleteOptions := metav1.DeleteOptions{
PropagationPolicy: &deletePolicy,
}
if err := client.Resource(deploymentRes).Namespace(namespace).Delete(context.TODO(), "demo-deployment", deleteOptions); err != nil {
panic(err)
}
fmt.Println("Deleted deployment.")
}
func prompt() {
fmt.Printf("-> Press Return key to continue.")
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
break
}
if err := scanner.Err(); err != nil {
panic(err)
}
fmt.Println()
}

View File

@@ -59,7 +59,7 @@ func TestFakeClient(t *testing.T) {
// Inject an event into the fake client.
p := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "my-pod"}}
_, err := client.CoreV1().Pods("test-ns").Create(context.TODO(), p, metav1.CreateOptions{})
_, err := client.CoreV1().Pods("test-ns").Create(p)
if err != nil {
t.Fatalf("error injecting pod add: %v", err)
}

View File

@@ -37,7 +37,7 @@ kubectl create clusterrolebinding default-view --clusterrole=view --serviceaccou
Then, run the image in a Pod with a single instance Deployment:
kubectl run --rm -i demo --image=in-cluster
kubectl run --rm -i demo --image=in-cluster --image-pull-policy=Never
There are 4 pods in the cluster
There are 4 pods in the cluster

View File

@@ -18,7 +18,6 @@ limitations under the License.
package main
import (
"context"
"fmt"
"time"
@@ -28,7 +27,7 @@ import (
"k8s.io/client-go/rest"
//
// Uncomment to load all auth plugins
// _ "k8s.io/client-go/plugin/pkg/client/auth"
// _ "k8s.io/client-go/plugin/pkg/client/auth
//
// Or uncomment to load specific auth plugins
// _ "k8s.io/client-go/plugin/pkg/client/auth/azure"
@@ -49,26 +48,24 @@ func main() {
panic(err.Error())
}
for {
// get pods in all the namespaces by omitting namespace
// Or specify namespace to get pods in particular namespace
pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{})
if err != nil {
panic(err.Error())
}
fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))
// Examples for error handling:
// - Use helper functions e.g. errors.IsNotFound()
// - Use helper functions like e.g. errors.IsNotFound()
// - And/or cast to StatusError and use its properties like e.g. ErrStatus.Message
_, err = clientset.CoreV1().Pods("default").Get(context.TODO(), "example-xxxxx", metav1.GetOptions{})
_, err = clientset.CoreV1().Pods("default").Get("example-xxxxx", metav1.GetOptions{})
if errors.IsNotFound(err) {
fmt.Printf("Pod example-xxxxx not found in default namespace\n")
fmt.Printf("Pod not found\n")
} else if statusError, isStatus := err.(*errors.StatusError); isStatus {
fmt.Printf("Error getting pod %v\n", statusError.ErrStatus.Message)
} else if err != nil {
panic(err.Error())
} else {
fmt.Printf("Found example-xxxxx pod in default namespace\n")
fmt.Printf("Found pod\n")
}
time.Sleep(10 * time.Second)

View File

@@ -7,16 +7,15 @@ This example demonstrates how to use the leader election package.
Run the following three commands in separate terminals. Each terminal needs a unique `id`.
```bash
# first terminal
go run main.go -kubeconfig=/path/to/kubeconfig -logtostderr=true -lease-lock-name=example -lease-lock-namespace=default -id=1
# first terminal
go run *.go -kubeconfig=/my/config -logtostderr=true -id=1
# second terminal
go run main.go -kubeconfig=/path/to/kubeconfig -logtostderr=true -lease-lock-name=example -lease-lock-namespace=default -id=2
# second terminal
go run *.go -kubeconfig=/my/config -logtostderr=true -id=2
# third terminal
go run main.go -kubeconfig=/path/to/kubeconfig -logtostderr=true -lease-lock-name=example -lease-lock-namespace=default -id=3
go run *.go -kubeconfig=/my/config -logtostderr=true -id=3
```
> You can ignore the `-kubeconfig` flag if you are running these commands in the Kubernetes cluster.
Now kill the existing leader. You will see from the terminal outputs that one of the remaining two processes will be elected as the new leader.

View File

@@ -19,19 +19,22 @@ package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"os/signal"
"strings"
"syscall"
"time"
"github.com/google/uuid"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/leaderelection"
"k8s.io/client-go/tools/leaderelection/resourcelock"
"k8s.io/klog/v2"
"k8s.io/client-go/transport"
"k8s.io/klog"
)
func buildConfig(kubeconfig string) (*rest.Config, error) {
@@ -59,16 +62,13 @@ func main() {
var id string
flag.StringVar(&kubeconfig, "kubeconfig", "", "absolute path to the kubeconfig file")
flag.StringVar(&id, "id", uuid.New().String(), "the holder identity name")
flag.StringVar(&leaseLockName, "lease-lock-name", "", "the lease lock resource name")
flag.StringVar(&leaseLockNamespace, "lease-lock-namespace", "", "the lease lock resource namespace")
flag.StringVar(&id, "id", "", "the holder identity name")
flag.StringVar(&leaseLockName, "lease-lock-name", "example", "the lease lock resource name")
flag.StringVar(&leaseLockNamespace, "lease-lock-namespace", "default", "the lease lock resource namespace")
flag.Parse()
if leaseLockName == "" {
klog.Fatal("unable to get lease lock resource name (missing lease-lock-name flag).")
}
if leaseLockNamespace == "" {
klog.Fatal("unable to get lease lock resource namespace (missing lease-lock-namespace flag).")
if id == "" {
klog.Fatal("unable to get id (missing id flag).")
}
// leader election uses the Kubernetes API by writing to a
@@ -82,29 +82,6 @@ func main() {
}
client := clientset.NewForConfigOrDie(config)
run := func(ctx context.Context) {
// complete your controller loop here
klog.Info("Controller loop...")
select {}
}
// use a Go context so we can tell the leaderelection code when we
// want to step down
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// listen for interrupts or the Linux SIGTERM signal and cancel
// our context, which the leader election code will observe and
// step down
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
go func() {
<-ch
klog.Info("Received termination, signaling shutdown")
cancel()
}()
// we use the Lease lock type since edits to Leases are less common
// and fewer objects in the cluster watch "all Leases".
lock := &resourcelock.LeaseLock{
@@ -118,6 +95,25 @@ func main() {
},
}
// use a Go context so we can tell the leaderelection code when we
// want to step down
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// use a client that will stop allowing new requests once the context ends
config.Wrap(transport.ContextCanceller(ctx, fmt.Errorf("the leader is shutting down")))
// listen for interrupts or the Linux SIGTERM signal and cancel
// our context, which the leader election code will observe and
// step down
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
go func() {
<-ch
log.Printf("Received termination, signaling shutdown")
cancel()
}()
// start the leader election code loop
leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{
Lock: lock,
@@ -135,12 +131,12 @@ func main() {
OnStartedLeading: func(ctx context.Context) {
// we're notified when we start - this is where you would
// usually put your code
run(ctx)
klog.Infof("%s: leading", id)
},
OnStoppedLeading: func() {
// we can do cleanup here
klog.Infof("leader lost: %s", id)
os.Exit(0)
// we can do cleanup here, or after the RunOrDie method
// returns
klog.Infof("%s: lost", id)
},
OnNewLeader: func(identity string) {
// we're notified when new leader elected
@@ -148,8 +144,18 @@ func main() {
// I just got the lock
return
}
klog.Infof("new leader elected: %s", identity)
klog.Infof("new leader elected: %v", identity)
},
},
})
// because the context is closed, the client should report errors
_, err = client.CoordinationV1().Leases(leaseLockNamespace).Get(leaseLockName, metav1.GetOptions{})
if err == nil || !strings.Contains(err.Error(), "the leader is shutting down") {
log.Fatalf("%s: expected to get an error when trying to make a client call: %v", id, err)
}
// we no longer hold the lease, so perform any cleanup and then
// exit
log.Printf("%s: done", id)
}

View File

@@ -18,9 +18,9 @@ limitations under the License.
package main
import (
"context"
"flag"
"fmt"
"os"
"path/filepath"
"time"
@@ -28,7 +28,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
//
// Uncomment to load all auth plugins
// _ "k8s.io/client-go/plugin/pkg/client/auth"
@@ -42,7 +41,7 @@ import (
func main() {
var kubeconfig *string
if home := homedir.HomeDir(); home != "" {
if home := homeDir(); home != "" {
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
@@ -61,7 +60,7 @@ func main() {
panic(err.Error())
}
for {
pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{})
if err != nil {
panic(err.Error())
}
@@ -72,7 +71,7 @@ func main() {
// - And/or cast to StatusError and use its properties like e.g. ErrStatus.Message
namespace := "default"
pod := "example-xxxxx"
_, err = clientset.CoreV1().Pods(namespace).Get(context.TODO(), pod, metav1.GetOptions{})
_, err = clientset.CoreV1().Pods(namespace).Get(pod, metav1.GetOptions{})
if errors.IsNotFound(err) {
fmt.Printf("Pod %s in namespace %s not found\n", pod, namespace)
} else if statusError, isStatus := err.(*errors.StatusError); isStatus {
@@ -87,3 +86,10 @@ func main() {
time.Sleep(10 * time.Second)
}
}
func homeDir() string {
if h := os.Getenv("HOME"); h != "" {
return h
}
return os.Getenv("USERPROFILE") // windows
}

View File

@@ -21,9 +21,9 @@ import (
"fmt"
"time"
"k8s.io/klog/v2"
"k8s.io/klog"
v1 "k8s.io/api/core/v1"
"k8s.io/api/core/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/runtime"
@@ -34,14 +34,12 @@ import (
"k8s.io/client-go/util/workqueue"
)
// Controller demonstrates how to implement a controller with client-go.
type Controller struct {
indexer cache.Indexer
queue workqueue.RateLimitingInterface
informer cache.Controller
}
// NewController creates a new Controller.
func NewController(queue workqueue.RateLimitingInterface, indexer cache.Indexer, informer cache.Controller) *Controller {
return &Controller{
informer: informer,
@@ -115,7 +113,6 @@ func (c *Controller) handleErr(err error, key interface{}) {
klog.Infof("Dropping pod %q out of the queue: %v", key, err)
}
// Run begins watching and syncing.
func (c *Controller) Run(threadiness int, stopCh chan struct{}) {
defer runtime.HandleCrash()

55
go.mod
View File

@@ -2,38 +2,41 @@
module k8s.io/client-go
go 1.15
go 1.12
require (
cloud.google.com/go v0.54.0 // indirect
github.com/Azure/go-autorest/autorest v0.11.1
github.com/Azure/go-autorest/autorest/adal v0.9.5
github.com/Azure/go-autorest v11.1.2+incompatible
github.com/davecgh/go-spew v1.1.1
github.com/evanphx/json-patch v4.9.0+incompatible
github.com/gogo/protobuf v1.3.2
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e
github.com/golang/protobuf v1.4.3
github.com/google/go-cmp v0.5.2
github.com/google/gofuzz v1.1.0
github.com/google/uuid v1.1.2
github.com/googleapis/gnostic v0.4.1
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda // indirect
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903
github.com/golang/protobuf v1.2.0
github.com/google/btree v0.0.0-20160524151835-7d79101e329e // indirect
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7
github.com/imdario/mergo v0.3.5
github.com/peterbourgon/diskv v2.0.1+incompatible
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.6.1
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
k8s.io/api v0.20.6
k8s.io/apimachinery v0.20.6
k8s.io/klog/v2 v2.4.0
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
sigs.k8s.io/yaml v1.2.0
github.com/spf13/pflag v1.0.1
github.com/stretchr/testify v1.2.2
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d
google.golang.org/appengine v1.5.0 // indirect
k8s.io/api v0.15.8-beta.1
k8s.io/apimachinery v0.15.8-beta.1
k8s.io/klog v0.3.1
k8s.io/utils v0.0.0-20190221042446-c2654d5206da
sigs.k8s.io/yaml v1.1.0
)
replace (
k8s.io/api => k8s.io/api v0.20.6
k8s.io/apimachinery => k8s.io/apimachinery v0.20.6
golang.org/x/sync => golang.org/x/sync v0.0.0-20181108010431-42b317875d0f
golang.org/x/sys => golang.org/x/sys v0.0.0-20190209173611-3b5209105503
golang.org/x/tools => golang.org/x/tools v0.0.0-20190313210603-aa82965741a9
k8s.io/api => k8s.io/api v0.15.8-beta.1
k8s.io/apimachinery => k8s.io/apimachinery v0.15.8-beta.1
)

477
go.sum
View File

@@ -1,446 +1,105 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.1 h1:eVvIXUKiTgv++6YnWb42DUA1YL7qDugnKP0HljexdnQ=
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE=
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/Azure/go-autorest v11.1.2+incompatible h1:viZ3tV5l4gE2Sw0xrasFHytCGtzYCrT+um/rrSQ1BfA=
github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY=
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e h1:p1yVGRW3nmb85p1Sh1ZJSDm4A4iKLS5QNbvUHMgGu/M=
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550 h1:mV9jbLoSW/8m4VK16ZkHTozJa8sesK5u5kTMFysTYac=
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415 h1:WSBJMqJbLxsn+bTCPyPYZfqHdJmc8MK4wrBjMft6BAM=
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/btree v0.0.0-20160524151835-7d79101e329e h1:JHB7F/4TJCrYBW8+GZO8VkWDj1jxcWuCl6uxKODiyi4=
github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8 h1:L9JPKrtsHMQ4VCRQfHvbbHBfB2Urn8xf6QZeXZ+OrN4=
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be h1:AHimNtVIpiBjPUhEF5KNCkrUyqTSA5zWUl8sQ2bfGBE=
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3 h1:EooPXg51Tn+xmWPXJUGCnJhJSpeuMlBmfJVcqIRmmv8=
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774 h1:a4tQYYYuK9QdeO/+kEvNYyuR21S+7ve5EANok6hABhI=
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68=
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7vhXAZQ9hiP+1Q/DMrWg=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wktg7Jn/a/fNmr33HSj8g=
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20190313210603-aa82965741a9/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o=
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.0.3 h1:4oyYo8NREp49LBBhKxEqCulFjg26rawYKrnCmg+Sr6c=
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
k8s.io/api v0.15.8-beta.1/go.mod h1:PxbEZx5EcvbplexI7Fab+UfpaHM6NZ+FkHMkxxTr7is=
k8s.io/apimachinery v0.15.8-beta.1/go.mod h1:Xc10RHc1U+F/e9GCloJ8QAeCGevSVP5xhOhqlE+e1kM=
k8s.io/klog v0.3.1 h1:RVgyDHY/kFKtLqh67NvEWIgkMneNoIrdkN0CxDSQc68=
k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30 h1:TRb4wNWoBVrH9plmkp2q86FIDppkbrEXdXlxU3a3BMI=
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
k8s.io/utils v0.0.0-20190221042446-c2654d5206da h1:ElyM7RPonbKnQqOcw7dG2IK5uvQQn3b/WPHqD5mBvP4=
k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -19,15 +19,12 @@ limitations under the License.
package admissionregistration
import (
v1 "k8s.io/client-go/informers/admissionregistration/v1"
v1beta1 "k8s.io/client-go/informers/admissionregistration/v1beta1"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1 provides access to shared informers for resources in V1.
V1() v1.Interface
// V1beta1 provides access to shared informers for resources in V1beta1.
V1beta1() v1beta1.Interface
}
@@ -43,11 +40,6 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1 returns a new v1.Interface.
func (g *group) V1() v1.Interface {
return v1.New(g.factory, g.namespace, g.tweakListOptions)
}
// V1beta1 returns a new v1beta1.Interface.
func (g *group) V1beta1() v1beta1.Interface {
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)

View File

@@ -1,52 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1
import (
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// MutatingWebhookConfigurations returns a MutatingWebhookConfigurationInformer.
MutatingWebhookConfigurations() MutatingWebhookConfigurationInformer
// ValidatingWebhookConfigurations returns a ValidatingWebhookConfigurationInformer.
ValidatingWebhookConfigurations() ValidatingWebhookConfigurationInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// MutatingWebhookConfigurations returns a MutatingWebhookConfigurationInformer.
func (v *version) MutatingWebhookConfigurations() MutatingWebhookConfigurationInformer {
return &mutatingWebhookConfigurationInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}
// ValidatingWebhookConfigurations returns a ValidatingWebhookConfigurationInformer.
func (v *version) ValidatingWebhookConfigurations() ValidatingWebhookConfigurationInformer {
return &validatingWebhookConfigurationInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}

View File

@@ -1,89 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1
import (
"context"
time "time"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
kubernetes "k8s.io/client-go/kubernetes"
v1 "k8s.io/client-go/listers/admissionregistration/v1"
cache "k8s.io/client-go/tools/cache"
)
// MutatingWebhookConfigurationInformer provides access to a shared informer and lister for
// MutatingWebhookConfigurations.
type MutatingWebhookConfigurationInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1.MutatingWebhookConfigurationLister
}
type mutatingWebhookConfigurationInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewMutatingWebhookConfigurationInformer constructs a new informer for MutatingWebhookConfiguration type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewMutatingWebhookConfigurationInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredMutatingWebhookConfigurationInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredMutatingWebhookConfigurationInformer constructs a new informer for MutatingWebhookConfiguration type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredMutatingWebhookConfigurationInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AdmissionregistrationV1().MutatingWebhookConfigurations().List(context.TODO(), options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AdmissionregistrationV1().MutatingWebhookConfigurations().Watch(context.TODO(), options)
},
},
&admissionregistrationv1.MutatingWebhookConfiguration{},
resyncPeriod,
indexers,
)
}
func (f *mutatingWebhookConfigurationInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredMutatingWebhookConfigurationInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *mutatingWebhookConfigurationInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&admissionregistrationv1.MutatingWebhookConfiguration{}, f.defaultInformer)
}
func (f *mutatingWebhookConfigurationInformer) Lister() v1.MutatingWebhookConfigurationLister {
return v1.NewMutatingWebhookConfigurationLister(f.Informer().GetIndexer())
}

View File

@@ -1,89 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1
import (
"context"
time "time"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
kubernetes "k8s.io/client-go/kubernetes"
v1 "k8s.io/client-go/listers/admissionregistration/v1"
cache "k8s.io/client-go/tools/cache"
)
// ValidatingWebhookConfigurationInformer provides access to a shared informer and lister for
// ValidatingWebhookConfigurations.
type ValidatingWebhookConfigurationInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1.ValidatingWebhookConfigurationLister
}
type validatingWebhookConfigurationInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewValidatingWebhookConfigurationInformer constructs a new informer for ValidatingWebhookConfiguration type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewValidatingWebhookConfigurationInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredValidatingWebhookConfigurationInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredValidatingWebhookConfigurationInformer constructs a new informer for ValidatingWebhookConfiguration type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredValidatingWebhookConfigurationInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AdmissionregistrationV1().ValidatingWebhookConfigurations().List(context.TODO(), options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Watch(context.TODO(), options)
},
},
&admissionregistrationv1.ValidatingWebhookConfiguration{},
resyncPeriod,
indexers,
)
}
func (f *validatingWebhookConfigurationInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredValidatingWebhookConfigurationInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *validatingWebhookConfigurationInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&admissionregistrationv1.ValidatingWebhookConfiguration{}, f.defaultInformer)
}
func (f *validatingWebhookConfigurationInformer) Lister() v1.ValidatingWebhookConfigurationLister {
return v1.NewValidatingWebhookConfigurationLister(f.Informer().GetIndexer())
}

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
@@ -61,13 +60,13 @@ func NewFilteredMutatingWebhookConfigurationInformer(client kubernetes.Interface
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().List(context.TODO(), options)
return client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Watch(context.TODO(), options)
return client.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Watch(options)
},
},
&admissionregistrationv1beta1.MutatingWebhookConfiguration{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
@@ -61,13 +60,13 @@ func NewFilteredValidatingWebhookConfigurationInformer(client kubernetes.Interfa
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().List(context.TODO(), options)
return client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Watch(context.TODO(), options)
return client.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Watch(options)
},
},
&admissionregistrationv1beta1.ValidatingWebhookConfiguration{},

View File

@@ -1,89 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
time "time"
apiserverinternalv1alpha1 "k8s.io/api/apiserverinternal/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
kubernetes "k8s.io/client-go/kubernetes"
v1alpha1 "k8s.io/client-go/listers/apiserverinternal/v1alpha1"
cache "k8s.io/client-go/tools/cache"
)
// StorageVersionInformer provides access to a shared informer and lister for
// StorageVersions.
type StorageVersionInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha1.StorageVersionLister
}
type storageVersionInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewStorageVersionInformer constructs a new informer for StorageVersion type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewStorageVersionInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredStorageVersionInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredStorageVersionInformer constructs a new informer for StorageVersion type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredStorageVersionInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.InternalV1alpha1().StorageVersions().List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.InternalV1alpha1().StorageVersions().Watch(context.TODO(), options)
},
},
&apiserverinternalv1alpha1.StorageVersion{},
resyncPeriod,
indexers,
)
}
func (f *storageVersionInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredStorageVersionInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *storageVersionInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&apiserverinternalv1alpha1.StorageVersion{}, f.defaultInformer)
}
func (f *storageVersionInformer) Lister() v1alpha1.StorageVersionLister {
return v1alpha1.NewStorageVersionLister(f.Informer().GetIndexer())
}

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
appsv1 "k8s.io/api/apps/v1"
@@ -62,13 +61,13 @@ func NewFilteredControllerRevisionInformer(client kubernetes.Interface, namespac
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1().ControllerRevisions(namespace).List(context.TODO(), options)
return client.AppsV1().ControllerRevisions(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1().ControllerRevisions(namespace).Watch(context.TODO(), options)
return client.AppsV1().ControllerRevisions(namespace).Watch(options)
},
},
&appsv1.ControllerRevision{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
appsv1 "k8s.io/api/apps/v1"
@@ -62,13 +61,13 @@ func NewFilteredDaemonSetInformer(client kubernetes.Interface, namespace string,
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1().DaemonSets(namespace).List(context.TODO(), options)
return client.AppsV1().DaemonSets(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1().DaemonSets(namespace).Watch(context.TODO(), options)
return client.AppsV1().DaemonSets(namespace).Watch(options)
},
},
&appsv1.DaemonSet{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
appsv1 "k8s.io/api/apps/v1"
@@ -62,13 +61,13 @@ func NewFilteredDeploymentInformer(client kubernetes.Interface, namespace string
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1().Deployments(namespace).List(context.TODO(), options)
return client.AppsV1().Deployments(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1().Deployments(namespace).Watch(context.TODO(), options)
return client.AppsV1().Deployments(namespace).Watch(options)
},
},
&appsv1.Deployment{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
appsv1 "k8s.io/api/apps/v1"
@@ -62,13 +61,13 @@ func NewFilteredReplicaSetInformer(client kubernetes.Interface, namespace string
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1().ReplicaSets(namespace).List(context.TODO(), options)
return client.AppsV1().ReplicaSets(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1().ReplicaSets(namespace).Watch(context.TODO(), options)
return client.AppsV1().ReplicaSets(namespace).Watch(options)
},
},
&appsv1.ReplicaSet{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
appsv1 "k8s.io/api/apps/v1"
@@ -62,13 +61,13 @@ func NewFilteredStatefulSetInformer(client kubernetes.Interface, namespace strin
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1().StatefulSets(namespace).List(context.TODO(), options)
return client.AppsV1().StatefulSets(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1().StatefulSets(namespace).Watch(context.TODO(), options)
return client.AppsV1().StatefulSets(namespace).Watch(options)
},
},
&appsv1.StatefulSet{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
appsv1beta1 "k8s.io/api/apps/v1beta1"
@@ -62,13 +61,13 @@ func NewFilteredControllerRevisionInformer(client kubernetes.Interface, namespac
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta1().ControllerRevisions(namespace).List(context.TODO(), options)
return client.AppsV1beta1().ControllerRevisions(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta1().ControllerRevisions(namespace).Watch(context.TODO(), options)
return client.AppsV1beta1().ControllerRevisions(namespace).Watch(options)
},
},
&appsv1beta1.ControllerRevision{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
appsv1beta1 "k8s.io/api/apps/v1beta1"
@@ -62,13 +61,13 @@ func NewFilteredDeploymentInformer(client kubernetes.Interface, namespace string
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta1().Deployments(namespace).List(context.TODO(), options)
return client.AppsV1beta1().Deployments(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta1().Deployments(namespace).Watch(context.TODO(), options)
return client.AppsV1beta1().Deployments(namespace).Watch(options)
},
},
&appsv1beta1.Deployment{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
appsv1beta1 "k8s.io/api/apps/v1beta1"
@@ -62,13 +61,13 @@ func NewFilteredStatefulSetInformer(client kubernetes.Interface, namespace strin
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta1().StatefulSets(namespace).List(context.TODO(), options)
return client.AppsV1beta1().StatefulSets(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta1().StatefulSets(namespace).Watch(context.TODO(), options)
return client.AppsV1beta1().StatefulSets(namespace).Watch(options)
},
},
&appsv1beta1.StatefulSet{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta2
import (
"context"
time "time"
appsv1beta2 "k8s.io/api/apps/v1beta2"
@@ -62,13 +61,13 @@ func NewFilteredControllerRevisionInformer(client kubernetes.Interface, namespac
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta2().ControllerRevisions(namespace).List(context.TODO(), options)
return client.AppsV1beta2().ControllerRevisions(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta2().ControllerRevisions(namespace).Watch(context.TODO(), options)
return client.AppsV1beta2().ControllerRevisions(namespace).Watch(options)
},
},
&appsv1beta2.ControllerRevision{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta2
import (
"context"
time "time"
appsv1beta2 "k8s.io/api/apps/v1beta2"
@@ -62,13 +61,13 @@ func NewFilteredDaemonSetInformer(client kubernetes.Interface, namespace string,
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta2().DaemonSets(namespace).List(context.TODO(), options)
return client.AppsV1beta2().DaemonSets(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta2().DaemonSets(namespace).Watch(context.TODO(), options)
return client.AppsV1beta2().DaemonSets(namespace).Watch(options)
},
},
&appsv1beta2.DaemonSet{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta2
import (
"context"
time "time"
appsv1beta2 "k8s.io/api/apps/v1beta2"
@@ -62,13 +61,13 @@ func NewFilteredDeploymentInformer(client kubernetes.Interface, namespace string
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta2().Deployments(namespace).List(context.TODO(), options)
return client.AppsV1beta2().Deployments(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta2().Deployments(namespace).Watch(context.TODO(), options)
return client.AppsV1beta2().Deployments(namespace).Watch(options)
},
},
&appsv1beta2.Deployment{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta2
import (
"context"
time "time"
appsv1beta2 "k8s.io/api/apps/v1beta2"
@@ -62,13 +61,13 @@ func NewFilteredReplicaSetInformer(client kubernetes.Interface, namespace string
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta2().ReplicaSets(namespace).List(context.TODO(), options)
return client.AppsV1beta2().ReplicaSets(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta2().ReplicaSets(namespace).Watch(context.TODO(), options)
return client.AppsV1beta2().ReplicaSets(namespace).Watch(options)
},
},
&appsv1beta2.ReplicaSet{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta2
import (
"context"
time "time"
appsv1beta2 "k8s.io/api/apps/v1beta2"
@@ -62,13 +61,13 @@ func NewFilteredStatefulSetInformer(client kubernetes.Interface, namespace strin
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta2().StatefulSets(namespace).List(context.TODO(), options)
return client.AppsV1beta2().StatefulSets(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AppsV1beta2().StatefulSets(namespace).Watch(context.TODO(), options)
return client.AppsV1beta2().StatefulSets(namespace).Watch(options)
},
},
&appsv1beta2.StatefulSet{},

View File

@@ -16,10 +16,10 @@ limitations under the License.
// Code generated by informer-gen. DO NOT EDIT.
package apiserverinternal
package auditregistration
import (
v1alpha1 "k8s.io/client-go/informers/apiserverinternal/v1alpha1"
v1alpha1 "k8s.io/client-go/informers/auditregistration/v1alpha1"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)

View File

@@ -16,74 +16,73 @@ limitations under the License.
// Code generated by informer-gen. DO NOT EDIT.
package v1
package v1alpha1
import (
"context"
time "time"
storagev1 "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
auditregistrationv1alpha1 "k8s.io/api/auditregistration/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
kubernetes "k8s.io/client-go/kubernetes"
v1 "k8s.io/client-go/listers/storage/v1"
v1alpha1 "k8s.io/client-go/listers/auditregistration/v1alpha1"
cache "k8s.io/client-go/tools/cache"
)
// CSIDriverInformer provides access to a shared informer and lister for
// CSIDrivers.
type CSIDriverInformer interface {
// AuditSinkInformer provides access to a shared informer and lister for
// AuditSinks.
type AuditSinkInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1.CSIDriverLister
Lister() v1alpha1.AuditSinkLister
}
type cSIDriverInformer struct {
type auditSinkInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewCSIDriverInformer constructs a new informer for CSIDriver type.
// NewAuditSinkInformer constructs a new informer for AuditSink type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewCSIDriverInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredCSIDriverInformer(client, resyncPeriod, indexers, nil)
func NewAuditSinkInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredAuditSinkInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredCSIDriverInformer constructs a new informer for CSIDriver type.
// NewFilteredAuditSinkInformer constructs a new informer for AuditSink type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredCSIDriverInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
func NewFilteredAuditSinkInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.StorageV1().CSIDrivers().List(context.TODO(), options)
return client.AuditregistrationV1alpha1().AuditSinks().List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.StorageV1().CSIDrivers().Watch(context.TODO(), options)
return client.AuditregistrationV1alpha1().AuditSinks().Watch(options)
},
},
&storagev1.CSIDriver{},
&auditregistrationv1alpha1.AuditSink{},
resyncPeriod,
indexers,
)
}
func (f *cSIDriverInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredCSIDriverInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
func (f *auditSinkInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredAuditSinkInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *cSIDriverInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&storagev1.CSIDriver{}, f.defaultInformer)
func (f *auditSinkInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&auditregistrationv1alpha1.AuditSink{}, f.defaultInformer)
}
func (f *cSIDriverInformer) Lister() v1.CSIDriverLister {
return v1.NewCSIDriverLister(f.Informer().GetIndexer())
func (f *auditSinkInformer) Lister() v1alpha1.AuditSinkLister {
return v1alpha1.NewAuditSinkLister(f.Informer().GetIndexer())
}

View File

@@ -16,7 +16,7 @@ limitations under the License.
// Code generated by informer-gen. DO NOT EDIT.
package v1
package v1alpha1
import (
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
@@ -24,8 +24,8 @@ import (
// Interface provides access to all the informers in this group version.
type Interface interface {
// Events returns a EventInformer.
Events() EventInformer
// AuditSinks returns a AuditSinkInformer.
AuditSinks() AuditSinkInformer
}
type version struct {
@@ -39,7 +39,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// Events returns a EventInformer.
func (v *version) Events() EventInformer {
return &eventInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
// AuditSinks returns a AuditSinkInformer.
func (v *version) AuditSinks() AuditSinkInformer {
return &auditSinkInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
autoscalingv1 "k8s.io/api/autoscaling/v1"
@@ -62,13 +61,13 @@ func NewFilteredHorizontalPodAutoscalerInformer(client kubernetes.Interface, nam
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AutoscalingV1().HorizontalPodAutoscalers(namespace).List(context.TODO(), options)
return client.AutoscalingV1().HorizontalPodAutoscalers(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AutoscalingV1().HorizontalPodAutoscalers(namespace).Watch(context.TODO(), options)
return client.AutoscalingV1().HorizontalPodAutoscalers(namespace).Watch(options)
},
},
&autoscalingv1.HorizontalPodAutoscaler{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v2beta1
import (
"context"
time "time"
autoscalingv2beta1 "k8s.io/api/autoscaling/v2beta1"
@@ -62,13 +61,13 @@ func NewFilteredHorizontalPodAutoscalerInformer(client kubernetes.Interface, nam
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AutoscalingV2beta1().HorizontalPodAutoscalers(namespace).List(context.TODO(), options)
return client.AutoscalingV2beta1().HorizontalPodAutoscalers(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AutoscalingV2beta1().HorizontalPodAutoscalers(namespace).Watch(context.TODO(), options)
return client.AutoscalingV2beta1().HorizontalPodAutoscalers(namespace).Watch(options)
},
},
&autoscalingv2beta1.HorizontalPodAutoscaler{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v2beta2
import (
"context"
time "time"
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
@@ -62,13 +61,13 @@ func NewFilteredHorizontalPodAutoscalerInformer(client kubernetes.Interface, nam
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AutoscalingV2beta2().HorizontalPodAutoscalers(namespace).List(context.TODO(), options)
return client.AutoscalingV2beta2().HorizontalPodAutoscalers(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AutoscalingV2beta2().HorizontalPodAutoscalers(namespace).Watch(context.TODO(), options)
return client.AutoscalingV2beta2().HorizontalPodAutoscalers(namespace).Watch(options)
},
},
&autoscalingv2beta2.HorizontalPodAutoscaler{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
batchv1 "k8s.io/api/batch/v1"
@@ -62,13 +61,13 @@ func NewFilteredJobInformer(client kubernetes.Interface, namespace string, resyn
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.BatchV1().Jobs(namespace).List(context.TODO(), options)
return client.BatchV1().Jobs(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.BatchV1().Jobs(namespace).Watch(context.TODO(), options)
return client.BatchV1().Jobs(namespace).Watch(options)
},
},
&batchv1.Job{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
batchv1beta1 "k8s.io/api/batch/v1beta1"
@@ -62,13 +61,13 @@ func NewFilteredCronJobInformer(client kubernetes.Interface, namespace string, r
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.BatchV1beta1().CronJobs(namespace).List(context.TODO(), options)
return client.BatchV1beta1().CronJobs(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.BatchV1beta1().CronJobs(namespace).Watch(context.TODO(), options)
return client.BatchV1beta1().CronJobs(namespace).Watch(options)
},
},
&batchv1beta1.CronJob{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v2alpha1
import (
"context"
time "time"
batchv2alpha1 "k8s.io/api/batch/v2alpha1"
@@ -62,13 +61,13 @@ func NewFilteredCronJobInformer(client kubernetes.Interface, namespace string, r
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.BatchV2alpha1().CronJobs(namespace).List(context.TODO(), options)
return client.BatchV2alpha1().CronJobs(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.BatchV2alpha1().CronJobs(namespace).Watch(context.TODO(), options)
return client.BatchV2alpha1().CronJobs(namespace).Watch(options)
},
},
&batchv2alpha1.CronJob{},

View File

@@ -19,15 +19,12 @@ limitations under the License.
package certificates
import (
v1 "k8s.io/client-go/informers/certificates/v1"
v1beta1 "k8s.io/client-go/informers/certificates/v1beta1"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1 provides access to shared informers for resources in V1.
V1() v1.Interface
// V1beta1 provides access to shared informers for resources in V1beta1.
V1beta1() v1beta1.Interface
}
@@ -43,11 +40,6 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1 returns a new v1.Interface.
func (g *group) V1() v1.Interface {
return v1.New(g.factory, g.namespace, g.tweakListOptions)
}
// V1beta1 returns a new v1beta1.Interface.
func (g *group) V1beta1() v1beta1.Interface {
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)

View File

@@ -1,89 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1
import (
"context"
time "time"
certificatesv1 "k8s.io/api/certificates/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
kubernetes "k8s.io/client-go/kubernetes"
v1 "k8s.io/client-go/listers/certificates/v1"
cache "k8s.io/client-go/tools/cache"
)
// CertificateSigningRequestInformer provides access to a shared informer and lister for
// CertificateSigningRequests.
type CertificateSigningRequestInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1.CertificateSigningRequestLister
}
type certificateSigningRequestInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewCertificateSigningRequestInformer constructs a new informer for CertificateSigningRequest type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewCertificateSigningRequestInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredCertificateSigningRequestInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredCertificateSigningRequestInformer constructs a new informer for CertificateSigningRequest type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredCertificateSigningRequestInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CertificatesV1().CertificateSigningRequests().List(context.TODO(), options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CertificatesV1().CertificateSigningRequests().Watch(context.TODO(), options)
},
},
&certificatesv1.CertificateSigningRequest{},
resyncPeriod,
indexers,
)
}
func (f *certificateSigningRequestInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredCertificateSigningRequestInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *certificateSigningRequestInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&certificatesv1.CertificateSigningRequest{}, f.defaultInformer)
}
func (f *certificateSigningRequestInformer) Lister() v1.CertificateSigningRequestLister {
return v1.NewCertificateSigningRequestLister(f.Informer().GetIndexer())
}

View File

@@ -1,45 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1
import (
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// CertificateSigningRequests returns a CertificateSigningRequestInformer.
CertificateSigningRequests() CertificateSigningRequestInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// CertificateSigningRequests returns a CertificateSigningRequestInformer.
func (v *version) CertificateSigningRequests() CertificateSigningRequestInformer {
return &certificateSigningRequestInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
@@ -61,13 +60,13 @@ func NewFilteredCertificateSigningRequestInformer(client kubernetes.Interface, r
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CertificatesV1beta1().CertificateSigningRequests().List(context.TODO(), options)
return client.CertificatesV1beta1().CertificateSigningRequests().List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CertificatesV1beta1().CertificateSigningRequests().Watch(context.TODO(), options)
return client.CertificatesV1beta1().CertificateSigningRequests().Watch(options)
},
},
&certificatesv1beta1.CertificateSigningRequest{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
coordinationv1 "k8s.io/api/coordination/v1"
@@ -62,13 +61,13 @@ func NewFilteredLeaseInformer(client kubernetes.Interface, namespace string, res
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoordinationV1().Leases(namespace).List(context.TODO(), options)
return client.CoordinationV1().Leases(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoordinationV1().Leases(namespace).Watch(context.TODO(), options)
return client.CoordinationV1().Leases(namespace).Watch(options)
},
},
&coordinationv1.Lease{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
coordinationv1beta1 "k8s.io/api/coordination/v1beta1"
@@ -62,13 +61,13 @@ func NewFilteredLeaseInformer(client kubernetes.Interface, namespace string, res
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoordinationV1beta1().Leases(namespace).List(context.TODO(), options)
return client.CoordinationV1beta1().Leases(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoordinationV1beta1().Leases(namespace).Watch(context.TODO(), options)
return client.CoordinationV1beta1().Leases(namespace).Watch(options)
},
},
&coordinationv1beta1.Lease{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -61,13 +60,13 @@ func NewFilteredComponentStatusInformer(client kubernetes.Interface, resyncPerio
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().ComponentStatuses().List(context.TODO(), options)
return client.CoreV1().ComponentStatuses().List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().ComponentStatuses().Watch(context.TODO(), options)
return client.CoreV1().ComponentStatuses().Watch(options)
},
},
&corev1.ComponentStatus{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredConfigMapInformer(client kubernetes.Interface, namespace string,
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().ConfigMaps(namespace).List(context.TODO(), options)
return client.CoreV1().ConfigMaps(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().ConfigMaps(namespace).Watch(context.TODO(), options)
return client.CoreV1().ConfigMaps(namespace).Watch(options)
},
},
&corev1.ConfigMap{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredEndpointsInformer(client kubernetes.Interface, namespace string,
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Endpoints(namespace).List(context.TODO(), options)
return client.CoreV1().Endpoints(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Endpoints(namespace).Watch(context.TODO(), options)
return client.CoreV1().Endpoints(namespace).Watch(options)
},
},
&corev1.Endpoints{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredEventInformer(client kubernetes.Interface, namespace string, res
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Events(namespace).List(context.TODO(), options)
return client.CoreV1().Events(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Events(namespace).Watch(context.TODO(), options)
return client.CoreV1().Events(namespace).Watch(options)
},
},
&corev1.Event{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredLimitRangeInformer(client kubernetes.Interface, namespace string
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().LimitRanges(namespace).List(context.TODO(), options)
return client.CoreV1().LimitRanges(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().LimitRanges(namespace).Watch(context.TODO(), options)
return client.CoreV1().LimitRanges(namespace).Watch(options)
},
},
&corev1.LimitRange{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -61,13 +60,13 @@ func NewFilteredNamespaceInformer(client kubernetes.Interface, resyncPeriod time
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Namespaces().List(context.TODO(), options)
return client.CoreV1().Namespaces().List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Namespaces().Watch(context.TODO(), options)
return client.CoreV1().Namespaces().Watch(options)
},
},
&corev1.Namespace{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -61,13 +60,13 @@ func NewFilteredNodeInformer(client kubernetes.Interface, resyncPeriod time.Dura
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Nodes().List(context.TODO(), options)
return client.CoreV1().Nodes().List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Nodes().Watch(context.TODO(), options)
return client.CoreV1().Nodes().Watch(options)
},
},
&corev1.Node{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -61,13 +60,13 @@ func NewFilteredPersistentVolumeInformer(client kubernetes.Interface, resyncPeri
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().PersistentVolumes().List(context.TODO(), options)
return client.CoreV1().PersistentVolumes().List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().PersistentVolumes().Watch(context.TODO(), options)
return client.CoreV1().PersistentVolumes().Watch(options)
},
},
&corev1.PersistentVolume{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredPersistentVolumeClaimInformer(client kubernetes.Interface, names
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().PersistentVolumeClaims(namespace).List(context.TODO(), options)
return client.CoreV1().PersistentVolumeClaims(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().PersistentVolumeClaims(namespace).Watch(context.TODO(), options)
return client.CoreV1().PersistentVolumeClaims(namespace).Watch(options)
},
},
&corev1.PersistentVolumeClaim{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredPodInformer(client kubernetes.Interface, namespace string, resyn
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Pods(namespace).List(context.TODO(), options)
return client.CoreV1().Pods(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Pods(namespace).Watch(context.TODO(), options)
return client.CoreV1().Pods(namespace).Watch(options)
},
},
&corev1.Pod{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredPodTemplateInformer(client kubernetes.Interface, namespace strin
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().PodTemplates(namespace).List(context.TODO(), options)
return client.CoreV1().PodTemplates(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().PodTemplates(namespace).Watch(context.TODO(), options)
return client.CoreV1().PodTemplates(namespace).Watch(options)
},
},
&corev1.PodTemplate{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredReplicationControllerInformer(client kubernetes.Interface, names
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().ReplicationControllers(namespace).List(context.TODO(), options)
return client.CoreV1().ReplicationControllers(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().ReplicationControllers(namespace).Watch(context.TODO(), options)
return client.CoreV1().ReplicationControllers(namespace).Watch(options)
},
},
&corev1.ReplicationController{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredResourceQuotaInformer(client kubernetes.Interface, namespace str
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().ResourceQuotas(namespace).List(context.TODO(), options)
return client.CoreV1().ResourceQuotas(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().ResourceQuotas(namespace).Watch(context.TODO(), options)
return client.CoreV1().ResourceQuotas(namespace).Watch(options)
},
},
&corev1.ResourceQuota{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredSecretInformer(client kubernetes.Interface, namespace string, re
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Secrets(namespace).List(context.TODO(), options)
return client.CoreV1().Secrets(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Secrets(namespace).Watch(context.TODO(), options)
return client.CoreV1().Secrets(namespace).Watch(options)
},
},
&corev1.Secret{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredServiceInformer(client kubernetes.Interface, namespace string, r
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Services(namespace).List(context.TODO(), options)
return client.CoreV1().Services(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().Services(namespace).Watch(context.TODO(), options)
return client.CoreV1().Services(namespace).Watch(options)
},
},
&corev1.Service{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1
import (
"context"
time "time"
corev1 "k8s.io/api/core/v1"
@@ -62,13 +61,13 @@ func NewFilteredServiceAccountInformer(client kubernetes.Interface, namespace st
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().ServiceAccounts(namespace).List(context.TODO(), options)
return client.CoreV1().ServiceAccounts(namespace).List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.CoreV1().ServiceAccounts(namespace).Watch(context.TODO(), options)
return client.CoreV1().ServiceAccounts(namespace).Watch(options)
},
},
&corev1.ServiceAccount{},

View File

@@ -1,90 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
"context"
time "time"
discoveryv1alpha1 "k8s.io/api/discovery/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
kubernetes "k8s.io/client-go/kubernetes"
v1alpha1 "k8s.io/client-go/listers/discovery/v1alpha1"
cache "k8s.io/client-go/tools/cache"
)
// EndpointSliceInformer provides access to a shared informer and lister for
// EndpointSlices.
type EndpointSliceInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha1.EndpointSliceLister
}
type endpointSliceInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewEndpointSliceInformer constructs a new informer for EndpointSlice type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewEndpointSliceInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredEndpointSliceInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredEndpointSliceInformer constructs a new informer for EndpointSlice type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredEndpointSliceInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.DiscoveryV1alpha1().EndpointSlices(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.DiscoveryV1alpha1().EndpointSlices(namespace).Watch(context.TODO(), options)
},
},
&discoveryv1alpha1.EndpointSlice{},
resyncPeriod,
indexers,
)
}
func (f *endpointSliceInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredEndpointSliceInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *endpointSliceInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&discoveryv1alpha1.EndpointSlice{}, f.defaultInformer)
}
func (f *endpointSliceInformer) Lister() v1alpha1.EndpointSliceLister {
return v1alpha1.NewEndpointSliceLister(f.Informer().GetIndexer())
}

View File

@@ -1,45 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// EndpointSlices returns a EndpointSliceInformer.
EndpointSlices() EndpointSliceInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// EndpointSlices returns a EndpointSliceInformer.
func (v *version) EndpointSlices() EndpointSliceInformer {
return &endpointSliceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}

View File

@@ -1,90 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1beta1
import (
"context"
time "time"
discoveryv1beta1 "k8s.io/api/discovery/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
kubernetes "k8s.io/client-go/kubernetes"
v1beta1 "k8s.io/client-go/listers/discovery/v1beta1"
cache "k8s.io/client-go/tools/cache"
)
// EndpointSliceInformer provides access to a shared informer and lister for
// EndpointSlices.
type EndpointSliceInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1beta1.EndpointSliceLister
}
type endpointSliceInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewEndpointSliceInformer constructs a new informer for EndpointSlice type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewEndpointSliceInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredEndpointSliceInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredEndpointSliceInformer constructs a new informer for EndpointSlice type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredEndpointSliceInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.DiscoveryV1beta1().EndpointSlices(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.DiscoveryV1beta1().EndpointSlices(namespace).Watch(context.TODO(), options)
},
},
&discoveryv1beta1.EndpointSlice{},
resyncPeriod,
indexers,
)
}
func (f *endpointSliceInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredEndpointSliceInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *endpointSliceInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&discoveryv1beta1.EndpointSlice{}, f.defaultInformer)
}
func (f *endpointSliceInformer) Lister() v1beta1.EndpointSliceLister {
return v1beta1.NewEndpointSliceLister(f.Informer().GetIndexer())
}

View File

@@ -1,45 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1beta1
import (
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// EndpointSlices returns a EndpointSliceInformer.
EndpointSlices() EndpointSliceInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// EndpointSlices returns a EndpointSliceInformer.
func (v *version) EndpointSlices() EndpointSliceInformer {
return &endpointSliceInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}

View File

@@ -19,15 +19,12 @@ limitations under the License.
package events
import (
v1 "k8s.io/client-go/informers/events/v1"
v1beta1 "k8s.io/client-go/informers/events/v1beta1"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1 provides access to shared informers for resources in V1.
V1() v1.Interface
// V1beta1 provides access to shared informers for resources in V1beta1.
V1beta1() v1beta1.Interface
}
@@ -43,11 +40,6 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1 returns a new v1.Interface.
func (g *group) V1() v1.Interface {
return v1.New(g.factory, g.namespace, g.tweakListOptions)
}
// V1beta1 returns a new v1beta1.Interface.
func (g *group) V1beta1() v1beta1.Interface {
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)

View File

@@ -1,90 +0,0 @@
/*
Copyright 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.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1
import (
"context"
time "time"
eventsv1 "k8s.io/api/events/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
kubernetes "k8s.io/client-go/kubernetes"
v1 "k8s.io/client-go/listers/events/v1"
cache "k8s.io/client-go/tools/cache"
)
// EventInformer provides access to a shared informer and lister for
// Events.
type EventInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1.EventLister
}
type eventInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewEventInformer constructs a new informer for Event type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewEventInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredEventInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredEventInformer constructs a new informer for Event type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredEventInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.EventsV1().Events(namespace).List(context.TODO(), options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.EventsV1().Events(namespace).Watch(context.TODO(), options)
},
},
&eventsv1.Event{},
resyncPeriod,
indexers,
)
}
func (f *eventInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredEventInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *eventInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&eventsv1.Event{}, f.defaultInformer)
}
func (f *eventInformer) Lister() v1.EventLister {
return v1.NewEventLister(f.Informer().GetIndexer())
}

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
eventsv1beta1 "k8s.io/api/events/v1beta1"
@@ -62,13 +61,13 @@ func NewFilteredEventInformer(client kubernetes.Interface, namespace string, res
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.EventsV1beta1().Events(namespace).List(context.TODO(), options)
return client.EventsV1beta1().Events(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.EventsV1beta1().Events(namespace).Watch(context.TODO(), options)
return client.EventsV1beta1().Events(namespace).Watch(options)
},
},
&eventsv1beta1.Event{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
@@ -62,13 +61,13 @@ func NewFilteredDaemonSetInformer(client kubernetes.Interface, namespace string,
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.ExtensionsV1beta1().DaemonSets(namespace).List(context.TODO(), options)
return client.ExtensionsV1beta1().DaemonSets(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.ExtensionsV1beta1().DaemonSets(namespace).Watch(context.TODO(), options)
return client.ExtensionsV1beta1().DaemonSets(namespace).Watch(options)
},
},
&extensionsv1beta1.DaemonSet{},

View File

@@ -19,7 +19,6 @@ limitations under the License.
package v1beta1
import (
"context"
time "time"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
@@ -62,13 +61,13 @@ func NewFilteredDeploymentInformer(client kubernetes.Interface, namespace string
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.ExtensionsV1beta1().Deployments(namespace).List(context.TODO(), options)
return client.ExtensionsV1beta1().Deployments(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.ExtensionsV1beta1().Deployments(namespace).Watch(context.TODO(), options)
return client.ExtensionsV1beta1().Deployments(namespace).Watch(options)
},
},
&extensionsv1beta1.Deployment{},

Some files were not shown because too many files have changed in this diff Show More