Compare commits

..

81 Commits

Author SHA1 Message Date
Kubernetes Publisher
f0b343266d Update dependencies to v0.21.0-beta.0 tag 2021-02-24 01:22:48 +00:00
Kubernetes Publisher
12449b5492 Merge pull request #99193 from zhijianli88/subresource
request.go: correct subresource referencing

Kubernetes-commit: e16c6cc3483989899961c623518a1150e9078495
2021-02-19 05:21:55 +00:00
Kubernetes Publisher
fa31d62bd0 Merge pull request #99111 from databus23/patch-5
Return error when persister fails to modify config

Kubernetes-commit: a4f412dc769643723f42aa78dcea60b827d7bf55
2021-02-19 01:21:56 +00:00
Li Zhijian
bb1d67da92 request.go: correct subresource referencing
Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>

Kubernetes-commit: 678e4ebaf6534e9b15fc4cc8602caadbead2e40e
2021-02-18 17:51:55 +08:00
Kubernetes Publisher
21dd7eaeef Merge pull request #99079 from tkashem/throttle-message
add more context to client-go request throttling message

Kubernetes-commit: 83e140125c96bf9dbde46f4c13ebccb3909951cc
2021-02-17 21:33:28 +00:00
Kubernetes Publisher
10def0e245 Merge pull request #99063 from ZxYuan/patch-1
Fix typo in client-go/rest/client.go

Kubernetes-commit: 7e2e928f3920825f17096c959500f7b72dc51f8e
2021-02-17 21:33:27 +00:00
Kubernetes Publisher
7279fc64d8 Merge pull request #96987 from soltysh/drop_batch-alpha
Drop batch/v2alpha1

Kubernetes-commit: 4f1dd5d2fbe42f39a841016796c5646711946ad1
2021-02-17 17:21:42 +00:00
Kubernetes Publisher
df50762b9f Merge pull request #99014 from apelisse/update-smd
Update sigs.k8s.io/structured-merge-diff to v4.0.3

Kubernetes-commit: 93252fa433214462e61495a63e792b756fd6777a
2021-02-17 01:23:14 +00:00
Kubernetes Publisher
39da007993 Merge pull request #99110 from nikhita/clean-up-owners-jan-2021
Remove inactive members from OWNERS - Jan 2021

Kubernetes-commit: 47d076610681d027c9c7e28ca08e29e6dd49a138
2021-02-16 17:27:02 +00:00
Fabian Ruff
a125444d4d Return error when persister fails to modify config
Kubernetes-commit: 9efd1fd12f646b0a328702cca4c52fdf0966212d
2021-02-16 08:45:59 +01:00
Nikhita Raghunath
1d0cb03f5a *: remove nikhiljindal from OWNERS
Kubernetes-commit: 6cef3a4e33c10c27bb301a1070ea3ff4cdad0c39
2021-02-16 10:50:50 +05:30
Nikhita Raghunath
e8ab2528ca *: remove madhusudancs from reviewers
Kubernetes-commit: 6b12c96a9b7fe4d7c03d0dfed447edd6b1055067
2021-02-16 10:40:42 +05:30
Nikhita Raghunath
4c4207ac6f *: move gmarek to emeritus_approvers
Kubernetes-commit: b11516d69f2131327931a2cf7452d5e891d7e520
2021-02-16 10:31:19 +05:30
ZxYuan
a9fe1e1ae9 Fix typo in client-go/rest/client.go
Kubernetes-commit: cd63fd4543b99a45d0920421d0bd23af6f762dc8
2021-02-14 00:18:41 +08:00
Abu Kashem
d1fdbcd4dc client-go: add more context to request throttle message
Kubernetes-commit: bc66d3d137d3600b117be390ccb253a9dbcde25e
2021-02-12 14:39:44 -05:00
Antoine Pelisse
508a193d5a Update sigs.k8s.io/structured-merge-diff to v4.0.3
Kubernetes-commit: 707612732a7b43aa12e329b0cd6308116ff4af4d
2021-02-11 17:01:23 -08:00
Kubernetes Publisher
20732a1bc1 Merge pull request #98889 from jkaniuk/leaderelection-simplify
Simplify leader election code

Kubernetes-commit: 93d288e2a47fa6d497b50d37c8b3a04e91da4228
2021-02-09 07:50:49 -08:00
Jacek Kaniuk
0eaf14c16e Simplify leader election code
Kubernetes-commit: c891207ab7c9e8e2ffb75edf41e6525d57543773
2021-02-08 19:28:55 +01:00
Kubernetes Publisher
100613764a Merge pull request #98790 from jkh52/master
Bump konnectivity-client to v0.0.15

Kubernetes-commit: 96a98e50afa7641d6f0e4fb324041126ff5a4ec2
2021-02-06 01:11:12 +00:00
Joseph Anttila Hall
bf60d3faed Bump konnectivity-client to v0.0.15
$ ./hack/pin-dependency.sh \
  sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15
$ ./hack/update-vendor.sh

Kubernetes-commit: 6499d4a730f8e6159da3e6c43f8ea6b13c5f46e5
2021-02-04 19:42:20 -08:00
Kubernetes Publisher
93ce9718ff Merge pull request #98671 from liggitt/kubeconfig-env
Isolate TestModifyContext from $KUBECONFIG

Kubernetes-commit: edd4576510445fae06cab29ba6dbd286a99987fd
2021-02-03 04:12:31 +00:00
Kubernetes Publisher
3c12da5d77 Merge pull request #98324 from atosatto/export-debug-roundripper
client-go: export NewDebuggingRoundTripper function and DebugLevel

Kubernetes-commit: 27104f159557da6bec20cf8227b468b1f22cd884
2021-02-03 00:20:23 +00:00
Kubernetes Publisher
3147a30d7b Merge pull request #98477 from palnabarun/update-gogo/protobuf
Update gogo/protobuf to v1.3.2

Kubernetes-commit: 4d3ed163a0ed45e8790801d74503fe300d05daa0
2021-02-02 20:12:39 +00:00
Jordan Liggitt
b620e827ab Isolate TestModifyContext from $KUBECONFIG
Kubernetes-commit: ce7e1e214a9b690f2222397c82c14c0d10905940
2021-02-01 14:03:07 -05:00
Kubernetes Publisher
ab82d40f6e Merge pull request #98488 from pohly/klog-2.5.0
klog 2.5.0 + logr 0.4.0 update

Kubernetes-commit: 76ead99a5601d89ac83a6a633cd2f828145adbff
2021-01-30 04:12:07 +00:00
Kubernetes Publisher
c8e0107904 Merge pull request #98565 from adisky/move-spdystream
Move dependency docker/spdystream to moby/spdystream

Kubernetes-commit: 64a6ee4321d37740b84a5c5c7aaa67e0bf6b6508
2021-01-29 20:12:47 +00:00
Aditi Sharma
b8b770f6b7 Update dependency docker/spdystream to moby/spdystream
docker/spdystream has been moved to moby/spdystream.

Signed-off-by: Aditi Sharma <adi.sky17@gmail.com>

Kubernetes-commit: c5c938a056abdf9961962554013632d6cfd3bbd4
2021-01-29 12:03:46 +05:30
Kubernetes Publisher
6329432013 Merge pull request #98496 from lavalamp/connrotation
Remove unbounded connection creation; also change worst case delay from 50s to 5s

Kubernetes-commit: 9f2f1b8c460b4b5ec8bfcd34490fb259ebad65b0
2021-01-28 08:12:11 +00:00
Daniel Smith
5985bbb560 Fix unbounded connection creation & 50s of delay
Kubernetes-commit: 80c3ec4c6a62486b0993b2e2f51c3e6f9bd6413a
2021-01-27 16:47:04 -08:00
Patrick Ohly
362c4854a6 logging: support call depth via logr, structured logging
The new releases of klog (via klogr) and logr expose support for call
traces via a new WithCallDepth API in logr.

The new klogr can be configured to pass structured log entries into
klog instead of turning them into a single text message.

Kubernetes-commit: 562a39a2e1e26854c06ac2b317f6f8a4ebb23ac1
2021-01-27 20:36:56 +01:00
Nabarun Pal
28611520a9 update gogo/protobuf to v1.3.2
gogo/protobuf@v1.3.2 fixes https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3121

Ref: https://github.com/kubernetes/client-go/issues/927

Signed-off-by: Nabarun Pal <pal.nabarun95@gmail.com>

Kubernetes-commit: 9cada2ec3ba793597606a1df1375ff8e8311ccf3
2021-01-27 18:01:27 +05:30
Andrea Tosatto
ef84e47785 Re-run gofmt against staging/src/k8s.io/client-go/transport/
Kubernetes-commit: 1449af17555eb5148d11556ee205c42b83821af0
2021-01-27 00:08:07 +00:00
Andrea Tosatto
e87f4d8d19 Remove unexpected updates to go.mod and go.sum
Kubernetes-commit: 961fa25dd4468cad40274258c701e5d48fa02c5e
2021-01-26 23:49:25 +00:00
Andrea Tosatto
9d369ea084 Update bazel BUILD file
Kubernetes-commit: bdd2da5c7eb98e4f7ce02977793b7268c717d98a
2021-01-26 23:31:42 +00:00
Andrea Tosatto
84db31c178 Address golint warnings
Kubernetes-commit: 675cefa1d15cadc5d1772d0ced16a3e843488347
2021-01-26 23:29:32 +00:00
Andrea Tosatto
8d3dc9e9ef Run gofmt against staging/src/k8s.io/client-go/transport/round_trippers_test.go
Kubernetes-commit: e87349f3caa810b96ed86fac7aec6bd0e73dacb1
2021-01-26 23:14:56 +00:00
Andrea Tosatto
2bce1731eb Run gofmt against staging/src/k8s.io/client-go/transport/round_trippers.go
Kubernetes-commit: 9cb5580ac6584cc787a2b2061c6c61656d065392
2021-01-26 22:04:52 +00:00
Andrea Tosatto
5c01a03456 client-go: export NewDebuggingRoundTripper function and DebugLevel
`debuggingRoundTripper` is a useful throbleshooting tool to debug of Kubernetes API requests and their timing.

Unfortunately, as of today, it can only be used via the `DebugWrappers` function, which automatically adjust the amount of debug information exposed by the roundTripper based on the configured `klog` verbosity.

While `DebugWrappers` definitely fits the purpose for clients using `klog`, this is currently hard to be used for controllers using `controller-runtime`, which uses `github.com/go-logr/logr` for logging.

In this PR we change the visibility of `newDebuggingRoundTripper` and `debugLevel` in order to be directly accessible from users of the `k8s.io/client-go/transport` package.

In particular, the changes proposed in this PR allow users of `controller-runtime` to use the `debuggingRoundTripper` to intercept Kubernetes API requests as follows

```go
import (
        ctrl "sigs.k8s.io/controller-runtime"
)

func init() {
	ctrl.SetLogger(zap.New())
}

func main() {
        // wrap the http transport used by the Kubernetes client
	restConfig, err := ctrl.GetConfig()
	checkError(setupLog, err, "unable to get kubernetes client config")

        restConfig.Wrap(func(rt http.RoundTripper) http.RoundTripper {
		return transport.NewDebuggingRoundTripper(rt, transport.DebugJustURL)
	})

        ...
}
```

Kubernetes-commit: 8de53ce96cb58d56fd00e91d8bcf7761ab498b83
2021-01-22 14:57:14 +01:00
Kubernetes Publisher
b72204b244 Merge pull request #95664 from DirectXMan12/bug/non-racy-recorder-shutdown
Don't spawn a goroutine for every event recording

Kubernetes-commit: 9d99dbc357ed85bcc963fc4bab8a4a3089c910b2
2021-01-21 07:15:29 +00:00
Kubernetes Publisher
fc034b4b76 Merge pull request #96552 from pandaamanda/klog_fmt
use klog.Info and klog.Warning when had no format

Kubernetes-commit: 8bf42039e62d001f5d0331753bd99790b70d51eb
2021-01-16 05:01:05 +00:00
Kubernetes Publisher
537eda74d8 Merge pull request #98058 from jprzychodzen/le-comment
[Leader election] Add documentation to function

Kubernetes-commit: a16df75344c6036730e1fba42b25c64c704b1494
2021-01-14 13:04:07 +00:00
Kubernetes Publisher
25e8b5f54c Merge pull request #97083 from knight42/feat/enable-spdy-ping
feat: enable SPDY pings on connections

Kubernetes-commit: a3bf53a0a5031f69389a835a8e13e783090b35a7
2021-01-14 01:01:00 +00:00
Jakub Przychodzeń
eae461ddf8 [Leader election] Add documentation to function
Kubernetes-commit: 852075b23c1854d538582e3940dff36947de2907
2021-01-13 17:34:07 +01:00
Jian Zeng
479dd01de2 feat: enable SPDY pings on connections
Signed-off-by: Jian Zeng <zengjian.zj@bytedance.com>

Kubernetes-commit: d0dce7035832f0673d87ae44503560204f3d3d46
2020-12-05 22:31:52 +08:00
Kubernetes Publisher
623741e9c1 Merge pull request #97909 from adamzhoul/fix-chan-bug
fix unit test "TestSPDYExecutorStream" flaking problem

Kubernetes-commit: 9caf675ed1a055ebce18cf34e8284028a729fd00
2021-01-12 05:01:01 +00:00
Kubernetes Publisher
2192138125 Merge pull request #97095 from sabbox/fix-panic-azure-oidc-auth-plugins
fix: Azure/OIDC auth panics when no AuthProviderConfigPersister is nil

Kubernetes-commit: 31e89372716a1414495594ce1a65368e4124db26
2021-01-12 05:00:59 +00:00
Andrey Viktorov
b804f9f657 add noop persister to plugin loader
Kubernetes-commit: 2dd86fe8c2cc7b655085b773bd1a06bc2ab54bbd
2021-01-12 00:08:42 +02:00
Kubernetes Publisher
f80da32721 Merge pull request #97255 from chotiwat/patch-1
Fix stale object causing a panic on DELETE event

Kubernetes-commit: d2575b7ddb374d8ce915fe095fa5b7a5b3df138e
2021-01-11 21:01:20 +00:00
Kubernetes Publisher
224c1c6ff4 Merge pull request #97857 from liggitt/exec-auth-reuse-dialer
Track opened connections with a single tracker per authenticator

Kubernetes-commit: e9dba7a627520f89778b367fc0d955776f220638
2021-01-11 17:01:11 +00:00
adamzhoul
5c32e970ce fix replyChan block
Kubernetes-commit: 314a9c4a6215b7e57944c86acacc5c75ab55121f
2021-01-11 08:36:27 +00:00
Jordan Liggitt
0c5bab64fe Track opened connections with a single tracker per authenticator
Kubernetes-commit: ecbff22ca134bd802127aab2be165d2770a9262a
2021-01-08 12:13:19 -05:00
Chotiwat Chawannakul
a35bc8fe7a Fix stale object causing a panic on DELETE event
Kubernetes-commit: 1f4f78ac414b7a1666e908670c5e447015bdc6b9
2021-01-06 10:38:31 -08:00
Kubernetes Publisher
9761a13537 Merge pull request #96906 from Rajalakshmi-Girish/issue-96853
Fixes the unit tests to be more tolerant with error messages

Kubernetes-commit: 10c1c3acf65cfb00de7fa28f784865bd42ab4872
2021-01-06 05:04:32 +00:00
Kubernetes Prow Robot
0d3f257a17 Merge pull request #907 from munnerz/patch-1
README: add 1.20 in compatibility matrix
2021-01-05 02:33:59 -08:00
Kubernetes Publisher
e9d996dae2 Merge pull request #97326 from victor-timofei/deltafifo-doc
Update DeltaFIFO documentation and group Delta definitions to the top of the file

Kubernetes-commit: 9406e145c25e4c3041ec82529176957f164fdb08
2020-12-29 09:00:12 +00:00
Victor Timofei
53a09c71a4 Update the wording of the DeltaFIFO
Kubernetes-commit: 3a107951f0bf16a022b70a667c98833e4ac1d540
2020-12-24 16:33:04 +02:00
Kubernetes Publisher
0964d4be75 Merge pull request #97033 from patrickshan/pshan/bump/Azure/go-autorest/autorest
Bump github.com/Azure/go-autorest/autorest to v0.11.12

Kubernetes-commit: e11e9d4c6c3f522ed398748a11cc5dd1f8949c2b
2020-12-17 08:59:40 +00:00
Kubernetes Publisher
2b31242e93 Merge pull request #94813 from dramich/nometrics
Don't start goroutine for noMetrics

Kubernetes-commit: c4aca30005dacca3f768e511f3e424893161558d
2020-12-17 01:02:20 +00:00
James Munnelly
efbc7082a8 README: add 1.20 in compatibility matrix 2020-12-16 15:26:15 +00:00
Kubernetes Publisher
cc9d424da8 Merge pull request #96883 from pacoxu/fix/96862
fix index test: multi index check for empty list

Kubernetes-commit: 46d481b4556e3328758eeb851920e2536a488658
2020-12-16 04:59:30 +00:00
Victor Timofei
710a222444 Move Delta definitions to the top
Kubernetes-commit: bcc1c9a387c898478ed47c629864418be89bf518
2020-12-15 22:07:33 +02:00
Victor Timofei
09cf7147ab Update DeltaFIFO Documentation
Kubernetes-commit: 1a4ed5ea57ac4d562311d2b2852dcc59b78725da
2020-12-15 21:31:30 +02:00
Kubernetes Publisher
77dfe4dff7 Merge pull request #92138 from ash2k/ash2k/client-cleanups
Client library cleanups

Kubernetes-commit: 667deec758fbbd9576df1c5f081a4e239996b074
2020-12-10 21:00:11 +00:00
Kubernetes Publisher
62f63bbbfe Merge pull request #96837 from adamzhoul/master
fix  remotecommand stream blocked forever problems.

Kubernetes-commit: ccd29ea264535fa2ef36cf4dfb004fed99c99fbf
2020-12-10 05:00:18 +00:00
Patrick Shan
01fbb1db89 Bump github.com/Azure/go-autorest/autorest to v0.11.12
Kubernetes-commit: c75d9906587a8b174338e0ffe725759f68c0be56
2020-12-03 15:38:17 +11:00
Maciej Szulik
61675820ec Generated changes
Kubernetes-commit: 7d9f36cd850cfc080d8598ff4eac7b6fa3efc27d
2020-12-01 16:34:55 +01:00
Maciej Szulik
d6cefbd7a0 Drop batch/v2alpha1 API
Kubernetes-commit: 3dab7462d1ff6e20f7efe38249dd9958e4e32c89
2020-12-01 16:33:47 +01:00
Rajalakshmi-Girish
cb8d3d1111 fixes the unit tests to be more tolerant with error messages
Kubernetes-commit: 98948ad8092b41ebc08d50aa557b2d7ba5496e7d
2020-11-27 08:21:56 +00:00
pacoxu
8031d76bd6 fix index test: multi index check for empty list
Signed-off-by: pacoxu <paco.xu@daocloud.io>

Kubernetes-commit: ae6360f6c732d554c332a0bc1b99808149d8376e
2020-11-26 18:23:57 +08:00
adamzhoul
04adad44d6 fix spdy stream, conn deadlock.
Kubernetes-commit: 94a297485bf39a6d69f316c257d351e9432b8cb5
2020-11-15 17:06:34 +08:00
Kubernetes Publisher
e24efdc77f Merge pull request #96797 from jqmichael/initialCountLength
Fixed a bug where initialPopulationCount should be based on the key length not list size in DeltaFIFO#Replace()

Kubernetes-commit: 7d8587c4cc3529dc9065c1536071ea382e6c725c
2020-12-09 05:00:23 +00:00
Kubernetes Publisher
50c086135a Merge pull request #96643 from bboreham/lose-timestamp
Remove unused argument from generateEvent

Kubernetes-commit: e3bf0cc4ae836dd27bb01a5e426cb50721f63211
2020-12-09 05:00:20 +00:00
Qing Ju
1d175299a2 Fixed a harmless bug where initialPopulationCount should be based on the key length not list size in DeltaFIFO#Replace()
Kubernetes-commit: bc39672c0638426979feef95baeff39d170161eb
2020-11-22 16:35:19 -08:00
Bryan Boreham
5d2c89de53 Remove unused argument from generateEvent
Kubernetes-commit: beceee68156dff8b10123a37bb4645941b7df0c2
2020-11-17 16:51:10 +00:00
xiongzhongliang
d7ba1f2e01 use klog.Info and klog.Warning when had no format
Kubernetes-commit: 90f4aeeea4cc5f96caa6ed87c67ca7e62d1ba21c
2020-11-14 00:55:06 +08:00
Solly Ross
726d27fe7a Don't record events in goroutines
This changes the event recorder to use the equivalent of a select
statement instead of a goroutine to record events.

Previously, we used a goroutine to make event recording non-blocking.
Unfortunately, this writes to a channel, and during shutdown we then
race to write to a closed channel, panicing (caught by the error
handler, but still) and making the race detector unhappy.

Instead, we now use the select statement to make event emitting
non-blocking, and if we'd block, we just drop the event.  We already
drop events if a particular sink is overloaded, so this just moves the
incoming event queue to match that behavior (and makes the incoming
event queue much longer).

This means that, if the user uses `Eventf` and friends correctly (i.e.
ensure they've returned by the time we call `Shutdown`), it's
now safe to call Shutdown.  This matches the conventional go guidance on
channels: the writer should call close.

Kubernetes-commit: e90e67bd002e70a525d3ee9045b213a5d826074d
2020-10-16 15:05:00 -07:00
Dan Ramich
f39ca994bd Don't start goroutine for noMetrics
Problem:
When calling newQueue metrics can be of type noMetrics when just calling
New. When doing this a new goroutine is created to update the metrics
but in this case there are no metrics so it's just creating goroutines
that don't do anything but consume resources.

Solution:
If the incoming metrics is of type noMetrics, don't start the goroutine

Kubernetes-commit: de021396f81ff438899297a6f464c70113b58475
2020-09-15 16:21:48 -06:00
Mikhail Mazurskiy
29b07456f5 Check errors of the Close call
Error from out.Close() was not checked

Kubernetes-commit: f9b928f1f13821b65ea4ef783f847993c51fb4dd
2020-06-15 21:47:08 +10:00
Mikhail Mazurskiy
6cc39819fd Make inClusterConfigProvider thread safe
If configuration object is used concurrently
it is not safe to mutate self.
There is no need for mutation so avoid it
just in case.

Kubernetes-commit: 9e360eb05efafd0fcabd5a065b62cb8226da94c2
2020-06-15 21:17:45 +10:00
Mikhail Mazurskiy
6d09f8e62e Stop using mergo.MergeWithOverwrite
Use the recommended replacement instead.

Kubernetes-commit: 243a9b204e14dc9c92f08cd3252c31731b9532fd
2020-06-15 21:11:27 +10:00
Mikhail Mazurskiy
277eea62aa Cleanup currentMigrationRules
1. Use filepath for filename manipulations
2. Restructure method logic

Kubernetes-commit: 11800147f51e85b9a4fb7eb2654cae3ded9d8cf0
2020-06-15 20:59:21 +10:00
51 changed files with 964 additions and 1154 deletions

42
Godeps/Godeps.json generated
View File

@@ -36,7 +36,7 @@
},
{
"ImportPath": "github.com/Azure/go-autorest/autorest",
"Rev": "v0.11.1"
"Rev": "v0.11.12"
},
{
"ImportPath": "github.com/Azure/go-autorest/autorest/adal",
@@ -106,14 +106,6 @@
"ImportPath": "github.com/davecgh/go-spew",
"Rev": "v1.1.1"
},
{
"ImportPath": "github.com/dgrijalva/jwt-go",
"Rev": "v3.2.0"
},
{
"ImportPath": "github.com/docker/spdystream",
"Rev": "449fdfce4d96"
},
{
"ImportPath": "github.com/docopt/docopt-go",
"Rev": "ee0de3bc6815"
@@ -160,7 +152,7 @@
},
{
"ImportPath": "github.com/go-logr/logr",
"Rev": "v0.2.0"
"Rev": "v0.4.0"
},
{
"ImportPath": "github.com/go-openapi/jsonpointer",
@@ -180,7 +172,7 @@
},
{
"ImportPath": "github.com/gogo/protobuf",
"Rev": "v1.3.1"
"Rev": "v1.3.2"
},
{
"ImportPath": "github.com/golang/glog",
@@ -234,6 +226,10 @@
"ImportPath": "github.com/googleapis/gnostic",
"Rev": "v0.4.1"
},
{
"ImportPath": "github.com/gorilla/websocket",
"Rev": "v1.4.2"
},
{
"ImportPath": "github.com/gregjones/httpcache",
"Rev": "9cad4c3443a7"
@@ -264,7 +260,7 @@
},
{
"ImportPath": "github.com/kisielk/errcheck",
"Rev": "v1.2.0"
"Rev": "v1.5.0"
},
{
"ImportPath": "github.com/kisielk/gotool",
@@ -290,6 +286,10 @@
"ImportPath": "github.com/mitchellh/mapstructure",
"Rev": "v1.1.2"
},
{
"ImportPath": "github.com/moby/spdystream",
"Rev": "v0.2.0"
},
{
"ImportPath": "github.com/modern-go/concurrent",
"Rev": "bacd9c7ef1dd"
@@ -350,6 +350,10 @@
"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"
@@ -376,7 +380,7 @@
},
{
"ImportPath": "golang.org/x/mod",
"Rev": "v0.2.0"
"Rev": "v0.3.0"
},
{
"ImportPath": "golang.org/x/net",
@@ -388,7 +392,7 @@
},
{
"ImportPath": "golang.org/x/sync",
"Rev": "cd5d95a43a6e"
"Rev": "67f06af15bc9"
},
{
"ImportPath": "golang.org/x/sys",
@@ -404,7 +408,7 @@
},
{
"ImportPath": "golang.org/x/tools",
"Rev": "95d2e580d8eb"
"Rev": "113979e3529a"
},
{
"ImportPath": "golang.org/x/xerrors",
@@ -464,11 +468,11 @@
},
{
"ImportPath": "k8s.io/api",
"Rev": "v0.21.0-alpha.0"
"Rev": "v0.21.0-beta.0"
},
{
"ImportPath": "k8s.io/apimachinery",
"Rev": "v0.21.0-alpha.0"
"Rev": "v0.21.0-beta.0"
},
{
"ImportPath": "k8s.io/gengo",
@@ -476,7 +480,7 @@
},
{
"ImportPath": "k8s.io/klog/v2",
"Rev": "v2.4.0"
"Rev": "v2.5.0"
},
{
"ImportPath": "k8s.io/kube-openapi",
@@ -500,7 +504,7 @@
},
{
"ImportPath": "sigs.k8s.io/structured-merge-diff/v4",
"Rev": "v4.0.2"
"Rev": "v4.0.3"
},
{
"ImportPath": "sigs.k8s.io/yaml",

View File

@@ -82,14 +82,15 @@ 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.15 | Kubernetes 1.16 | Kubernetes 1.17 | Kubernetes 1.18 | Kubernetes 1.19 | Kubernetes 1.20 |
|-------------------------------|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
| `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` | +- | +- | +- | +- | ✓ | +- |
| `kubernetes-1.20.0`/`v0.20.0` | +- | +- | +- | +- | +- | |
| `HEAD` | +- | +- | +- | +- | +- | +- |
Key:
@@ -123,10 +124,11 @@ between client-go versions.
| `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-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 | ✓ |
| `release-1.20` | Kubernetes main repo, 1.20 branch | ✓ |
| client-go HEAD | Kubernetes main repo, master branch | ✓ |
Key:
@@ -176,7 +178,7 @@ you care about backwards compatibility.
Use go1.11+ and fetch the desired version using the `go get` command. For example:
```
go get k8s.io/client-go@v0.19.0
go get k8s.io/client-go@v0.20.0
```
See [INSTALL.md](/INSTALL.md) for detailed instructions.

14
go.mod
View File

@@ -6,11 +6,11 @@ go 1.15
require (
cloud.google.com/go v0.54.0 // indirect
github.com/Azure/go-autorest/autorest v0.11.1
github.com/Azure/go-autorest/autorest v0.11.12
github.com/Azure/go-autorest/autorest/adal v0.9.5
github.com/davecgh/go-spew v1.1.1
github.com/evanphx/json-patch v4.9.0+incompatible
github.com/gogo/protobuf v1.3.1
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
@@ -26,14 +26,14 @@ require (
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.21.0-alpha.0
k8s.io/apimachinery v0.21.0-alpha.0
k8s.io/klog/v2 v2.4.0
k8s.io/api v0.21.0-beta.0
k8s.io/apimachinery v0.21.0-beta.0
k8s.io/klog/v2 v2.5.0
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
sigs.k8s.io/yaml v1.2.0
)
replace (
k8s.io/api => k8s.io/api v0.21.0-alpha.0
k8s.io/apimachinery => k8s.io/apimachinery v0.21.0-alpha.0
k8s.io/api => k8s.io/api v0.21.0-beta.0
k8s.io/apimachinery => k8s.io/apimachinery v0.21.0-beta.0
)

54
go.sum
View File

@@ -24,16 +24,12 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
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 h1:SigMbuFNuKgc1xcGhaeapbh+8fgsu+GxgDRFyg7f5lM=
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
github.com/Azure/go-autorest/autorest v0.11.12 h1:gI8ytXbxMfI+IVbI9mP2JGCTXIuhHLgRlvQ9X4PsnHE=
github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
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 h1:z20OWOSG5aCye0HEkDp6TPmP17ZcfeMxPi6HnSALa8c=
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=
@@ -54,10 +50,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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 h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/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=
@@ -68,7 +60,6 @@ github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQo
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/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=
@@ -76,10 +67,9 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H
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 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg=
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-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
github.com/go-logr/logr v0.4.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=
@@ -87,11 +77,10 @@ github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL9
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.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
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 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA=
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=
@@ -119,7 +108,6 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
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 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
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=
@@ -134,7 +122,6 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf
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 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
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=
@@ -142,6 +129,7 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
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/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
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/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@@ -157,7 +145,7 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr
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.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
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=
@@ -169,6 +157,8 @@ 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/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
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=
@@ -199,10 +189,11 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
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=
@@ -212,7 +203,6 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
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 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
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=
@@ -245,6 +235,7 @@ 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=
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=
@@ -265,14 +256,13 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
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 h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
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 h1:pE8b58s1HRDMi8RDc79m0HISf9D4TzseP40cEA6IGfs=
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=
@@ -282,6 +272,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
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=
@@ -311,7 +302,6 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fq
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 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
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=
@@ -321,7 +311,6 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb
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-20181030221726-6c7e314b6563/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=
@@ -352,9 +341,10 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK
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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
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=
@@ -433,12 +423,12 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
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.21.0-alpha.0/go.mod h1:DOT/fV/LCjexRJsUibhQWInU+3bnYnj1IO21JwG8SC0=
k8s.io/apimachinery v0.21.0-alpha.0/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/api v0.21.0-beta.0/go.mod h1:3WblMF9mf/mKU1KxrpPzzNy8NKsVBaeTEnLWd2mdNho=
k8s.io/apimachinery v0.21.0-beta.0/go.mod h1:Z7ps/g0rjlTeMstYrMOUttJfT2Gg34DEaG/f2PYLCWY=
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/klog/v2 v2.5.0 h1:8mOnjf1RmUPW6KRqQCfYSZq/K20Unmp3IhuZUhxl8KI=
k8s.io/klog/v2 v2.5.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
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=
@@ -448,6 +438,8 @@ 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 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8=
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=
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

@@ -21,7 +21,6 @@ package batch
import (
v1 "k8s.io/client-go/informers/batch/v1"
v1beta1 "k8s.io/client-go/informers/batch/v1beta1"
v2alpha1 "k8s.io/client-go/informers/batch/v2alpha1"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)
@@ -31,8 +30,6 @@ type Interface interface {
V1() v1.Interface
// V1beta1 provides access to shared informers for resources in V1beta1.
V1beta1() v1beta1.Interface
// V2alpha1 provides access to shared informers for resources in V2alpha1.
V2alpha1() v2alpha1.Interface
}
type group struct {
@@ -55,8 +52,3 @@ func (g *group) V1() v1.Interface {
func (g *group) V1beta1() v1beta1.Interface {
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)
}
// V2alpha1 returns a new v2alpha1.Interface.
func (g *group) V2alpha1() v2alpha1.Interface {
return v2alpha1.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 v2alpha1
import (
"context"
time "time"
batchv2alpha1 "k8s.io/api/batch/v2alpha1"
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"
v2alpha1 "k8s.io/client-go/listers/batch/v2alpha1"
cache "k8s.io/client-go/tools/cache"
)
// CronJobInformer provides access to a shared informer and lister for
// CronJobs.
type CronJobInformer interface {
Informer() cache.SharedIndexInformer
Lister() v2alpha1.CronJobLister
}
type cronJobInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewCronJobInformer constructs a new informer for CronJob 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 NewCronJobInformer(client kubernetes.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredCronJobInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredCronJobInformer constructs a new informer for CronJob 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 NewFilteredCronJobInformer(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.BatchV2alpha1().CronJobs(namespace).List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.BatchV2alpha1().CronJobs(namespace).Watch(context.TODO(), options)
},
},
&batchv2alpha1.CronJob{},
resyncPeriod,
indexers,
)
}
func (f *cronJobInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredCronJobInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *cronJobInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&batchv2alpha1.CronJob{}, f.defaultInformer)
}
func (f *cronJobInformer) Lister() v2alpha1.CronJobLister {
return v2alpha1.NewCronJobLister(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 v2alpha1
import (
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// CronJobs returns a CronJobInformer.
CronJobs() CronJobInformer
}
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}
}
// CronJobs returns a CronJobInformer.
func (v *version) CronJobs() CronJobInformer {
return &cronJobInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}

View File

@@ -32,7 +32,6 @@ import (
v2beta2 "k8s.io/api/autoscaling/v2beta2"
batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
v2alpha1 "k8s.io/api/batch/v2alpha1"
certificatesv1 "k8s.io/api/certificates/v1"
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
coordinationv1 "k8s.io/api/coordination/v1"
@@ -154,10 +153,6 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
case batchv1beta1.SchemeGroupVersion.WithResource("cronjobs"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Batch().V1beta1().CronJobs().Informer()}, nil
// Group=batch, Version=v2alpha1
case v2alpha1.SchemeGroupVersion.WithResource("cronjobs"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Batch().V2alpha1().CronJobs().Informer()}, nil
// Group=certificates.k8s.io, Version=v1
case certificatesv1.SchemeGroupVersion.WithResource("certificatesigningrequests"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Certificates().V1().CertificateSigningRequests().Informer()}, nil

View File

@@ -37,7 +37,6 @@ import (
autoscalingv2beta2 "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2"
batchv1 "k8s.io/client-go/kubernetes/typed/batch/v1"
batchv1beta1 "k8s.io/client-go/kubernetes/typed/batch/v1beta1"
batchv2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1"
certificatesv1 "k8s.io/client-go/kubernetes/typed/certificates/v1"
certificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1"
@@ -86,7 +85,6 @@ type Interface interface {
AutoscalingV2beta2() autoscalingv2beta2.AutoscalingV2beta2Interface
BatchV1() batchv1.BatchV1Interface
BatchV1beta1() batchv1beta1.BatchV1beta1Interface
BatchV2alpha1() batchv2alpha1.BatchV2alpha1Interface
CertificatesV1() certificatesv1.CertificatesV1Interface
CertificatesV1beta1() certificatesv1beta1.CertificatesV1beta1Interface
CoordinationV1beta1() coordinationv1beta1.CoordinationV1beta1Interface
@@ -135,7 +133,6 @@ type Clientset struct {
autoscalingV2beta2 *autoscalingv2beta2.AutoscalingV2beta2Client
batchV1 *batchv1.BatchV1Client
batchV1beta1 *batchv1beta1.BatchV1beta1Client
batchV2alpha1 *batchv2alpha1.BatchV2alpha1Client
certificatesV1 *certificatesv1.CertificatesV1Client
certificatesV1beta1 *certificatesv1beta1.CertificatesV1beta1Client
coordinationV1beta1 *coordinationv1beta1.CoordinationV1beta1Client
@@ -240,11 +237,6 @@ func (c *Clientset) BatchV1beta1() batchv1beta1.BatchV1beta1Interface {
return c.batchV1beta1
}
// BatchV2alpha1 retrieves the BatchV2alpha1Client
func (c *Clientset) BatchV2alpha1() batchv2alpha1.BatchV2alpha1Interface {
return c.batchV2alpha1
}
// CertificatesV1 retrieves the CertificatesV1Client
func (c *Clientset) CertificatesV1() certificatesv1.CertificatesV1Interface {
return c.certificatesV1
@@ -461,10 +453,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
if err != nil {
return nil, err
}
cs.batchV2alpha1, err = batchv2alpha1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.certificatesV1, err = certificatesv1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
@@ -600,7 +588,6 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
cs.autoscalingV2beta2 = autoscalingv2beta2.NewForConfigOrDie(c)
cs.batchV1 = batchv1.NewForConfigOrDie(c)
cs.batchV1beta1 = batchv1beta1.NewForConfigOrDie(c)
cs.batchV2alpha1 = batchv2alpha1.NewForConfigOrDie(c)
cs.certificatesV1 = certificatesv1.NewForConfigOrDie(c)
cs.certificatesV1beta1 = certificatesv1beta1.NewForConfigOrDie(c)
cs.coordinationV1beta1 = coordinationv1beta1.NewForConfigOrDie(c)
@@ -651,7 +638,6 @@ func New(c rest.Interface) *Clientset {
cs.autoscalingV2beta2 = autoscalingv2beta2.New(c)
cs.batchV1 = batchv1.New(c)
cs.batchV1beta1 = batchv1beta1.New(c)
cs.batchV2alpha1 = batchv2alpha1.New(c)
cs.certificatesV1 = certificatesv1.New(c)
cs.certificatesV1beta1 = certificatesv1beta1.New(c)
cs.coordinationV1beta1 = coordinationv1beta1.New(c)

View File

@@ -54,8 +54,6 @@ import (
fakebatchv1 "k8s.io/client-go/kubernetes/typed/batch/v1/fake"
batchv1beta1 "k8s.io/client-go/kubernetes/typed/batch/v1beta1"
fakebatchv1beta1 "k8s.io/client-go/kubernetes/typed/batch/v1beta1/fake"
batchv2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1"
fakebatchv2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1/fake"
certificatesv1 "k8s.io/client-go/kubernetes/typed/certificates/v1"
fakecertificatesv1 "k8s.io/client-go/kubernetes/typed/certificates/v1/fake"
certificatesv1beta1 "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
@@ -235,11 +233,6 @@ func (c *Clientset) BatchV1beta1() batchv1beta1.BatchV1beta1Interface {
return &fakebatchv1beta1.FakeBatchV1beta1{Fake: &c.Fake}
}
// BatchV2alpha1 retrieves the BatchV2alpha1Client
func (c *Clientset) BatchV2alpha1() batchv2alpha1.BatchV2alpha1Interface {
return &fakebatchv2alpha1.FakeBatchV2alpha1{Fake: &c.Fake}
}
// CertificatesV1 retrieves the CertificatesV1Client
func (c *Clientset) CertificatesV1() certificatesv1.CertificatesV1Interface {
return &fakecertificatesv1.FakeCertificatesV1{Fake: &c.Fake}

View File

@@ -34,7 +34,6 @@ import (
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
batchv2alpha1 "k8s.io/api/batch/v2alpha1"
certificatesv1 "k8s.io/api/certificates/v1"
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
coordinationv1 "k8s.io/api/coordination/v1"
@@ -88,7 +87,6 @@ var localSchemeBuilder = runtime.SchemeBuilder{
autoscalingv2beta2.AddToScheme,
batchv1.AddToScheme,
batchv1beta1.AddToScheme,
batchv2alpha1.AddToScheme,
certificatesv1.AddToScheme,
certificatesv1beta1.AddToScheme,
coordinationv1beta1.AddToScheme,

View File

@@ -34,7 +34,6 @@ import (
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
batchv1 "k8s.io/api/batch/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
batchv2alpha1 "k8s.io/api/batch/v2alpha1"
certificatesv1 "k8s.io/api/certificates/v1"
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
coordinationv1 "k8s.io/api/coordination/v1"
@@ -88,7 +87,6 @@ var localSchemeBuilder = runtime.SchemeBuilder{
autoscalingv2beta2.AddToScheme,
batchv1.AddToScheme,
batchv1beta1.AddToScheme,
batchv2alpha1.AddToScheme,
certificatesv1.AddToScheme,
certificatesv1beta1.AddToScheme,
coordinationv1beta1.AddToScheme,

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 client-gen. DO NOT EDIT.
package v2alpha1
import (
v2alpha1 "k8s.io/api/batch/v2alpha1"
"k8s.io/client-go/kubernetes/scheme"
rest "k8s.io/client-go/rest"
)
type BatchV2alpha1Interface interface {
RESTClient() rest.Interface
CronJobsGetter
}
// BatchV2alpha1Client is used to interact with features provided by the batch group.
type BatchV2alpha1Client struct {
restClient rest.Interface
}
func (c *BatchV2alpha1Client) CronJobs(namespace string) CronJobInterface {
return newCronJobs(c, namespace)
}
// NewForConfig creates a new BatchV2alpha1Client for the given config.
func NewForConfig(c *rest.Config) (*BatchV2alpha1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &BatchV2alpha1Client{client}, nil
}
// NewForConfigOrDie creates a new BatchV2alpha1Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *BatchV2alpha1Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new BatchV2alpha1Client for the given RESTClient.
func New(c rest.Interface) *BatchV2alpha1Client {
return &BatchV2alpha1Client{c}
}
func setConfigDefaults(config *rest.Config) error {
gv := v2alpha1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *BatchV2alpha1Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

View File

@@ -1,195 +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 client-gen. DO NOT EDIT.
package v2alpha1
import (
"context"
"time"
v2alpha1 "k8s.io/api/batch/v2alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
scheme "k8s.io/client-go/kubernetes/scheme"
rest "k8s.io/client-go/rest"
)
// CronJobsGetter has a method to return a CronJobInterface.
// A group's client should implement this interface.
type CronJobsGetter interface {
CronJobs(namespace string) CronJobInterface
}
// CronJobInterface has methods to work with CronJob resources.
type CronJobInterface interface {
Create(ctx context.Context, cronJob *v2alpha1.CronJob, opts v1.CreateOptions) (*v2alpha1.CronJob, error)
Update(ctx context.Context, cronJob *v2alpha1.CronJob, opts v1.UpdateOptions) (*v2alpha1.CronJob, error)
UpdateStatus(ctx context.Context, cronJob *v2alpha1.CronJob, opts v1.UpdateOptions) (*v2alpha1.CronJob, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*v2alpha1.CronJob, error)
List(ctx context.Context, opts v1.ListOptions) (*v2alpha1.CronJobList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2alpha1.CronJob, err error)
CronJobExpansion
}
// cronJobs implements CronJobInterface
type cronJobs struct {
client rest.Interface
ns string
}
// newCronJobs returns a CronJobs
func newCronJobs(c *BatchV2alpha1Client, namespace string) *cronJobs {
return &cronJobs{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the cronJob, and returns the corresponding cronJob object, and an error if there is any.
func (c *cronJobs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2alpha1.CronJob, err error) {
result = &v2alpha1.CronJob{}
err = c.client.Get().
Namespace(c.ns).
Resource("cronjobs").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do(ctx).
Into(result)
return
}
// List takes label and field selectors, and returns the list of CronJobs that match those selectors.
func (c *cronJobs) List(ctx context.Context, opts v1.ListOptions) (result *v2alpha1.CronJobList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v2alpha1.CronJobList{}
err = c.client.Get().
Namespace(c.ns).
Resource("cronjobs").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do(ctx).
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested cronJobs.
func (c *cronJobs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("cronjobs").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch(ctx)
}
// Create takes the representation of a cronJob and creates it. Returns the server's representation of the cronJob, and an error, if there is any.
func (c *cronJobs) Create(ctx context.Context, cronJob *v2alpha1.CronJob, opts v1.CreateOptions) (result *v2alpha1.CronJob, err error) {
result = &v2alpha1.CronJob{}
err = c.client.Post().
Namespace(c.ns).
Resource("cronjobs").
VersionedParams(&opts, scheme.ParameterCodec).
Body(cronJob).
Do(ctx).
Into(result)
return
}
// Update takes the representation of a cronJob and updates it. Returns the server's representation of the cronJob, and an error, if there is any.
func (c *cronJobs) Update(ctx context.Context, cronJob *v2alpha1.CronJob, opts v1.UpdateOptions) (result *v2alpha1.CronJob, err error) {
result = &v2alpha1.CronJob{}
err = c.client.Put().
Namespace(c.ns).
Resource("cronjobs").
Name(cronJob.Name).
VersionedParams(&opts, scheme.ParameterCodec).
Body(cronJob).
Do(ctx).
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *cronJobs) UpdateStatus(ctx context.Context, cronJob *v2alpha1.CronJob, opts v1.UpdateOptions) (result *v2alpha1.CronJob, err error) {
result = &v2alpha1.CronJob{}
err = c.client.Put().
Namespace(c.ns).
Resource("cronjobs").
Name(cronJob.Name).
SubResource("status").
VersionedParams(&opts, scheme.ParameterCodec).
Body(cronJob).
Do(ctx).
Into(result)
return
}
// Delete takes name of the cronJob and deletes it. Returns an error if one occurs.
func (c *cronJobs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("cronjobs").
Name(name).
Body(&opts).
Do(ctx).
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *cronJobs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
var timeout time.Duration
if listOpts.TimeoutSeconds != nil {
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("cronjobs").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
Body(&opts).
Do(ctx).
Error()
}
// Patch applies the patch and returns the patched cronJob.
func (c *cronJobs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2alpha1.CronJob, err error) {
result = &v2alpha1.CronJob{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("cronjobs").
Name(name).
SubResource(subresources...).
VersionedParams(&opts, scheme.ParameterCodec).
Body(data).
Do(ctx).
Into(result)
return
}

View File

@@ -1,20 +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 client-gen. DO NOT EDIT.
// This package has the automatically generated typed clients.
package v2alpha1

View File

@@ -1,20 +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 client-gen. DO NOT EDIT.
// Package fake has the automatically generated clients.
package fake

View File

@@ -1,40 +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 client-gen. DO NOT EDIT.
package fake
import (
v2alpha1 "k8s.io/client-go/kubernetes/typed/batch/v2alpha1"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeBatchV2alpha1 struct {
*testing.Fake
}
func (c *FakeBatchV2alpha1) CronJobs(namespace string) v2alpha1.CronJobInterface {
return &FakeCronJobs{c, namespace}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeBatchV2alpha1) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}

View File

@@ -1,142 +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 client-gen. DO NOT EDIT.
package fake
import (
"context"
v2alpha1 "k8s.io/api/batch/v2alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
)
// FakeCronJobs implements CronJobInterface
type FakeCronJobs struct {
Fake *FakeBatchV2alpha1
ns string
}
var cronjobsResource = schema.GroupVersionResource{Group: "batch", Version: "v2alpha1", Resource: "cronjobs"}
var cronjobsKind = schema.GroupVersionKind{Group: "batch", Version: "v2alpha1", Kind: "CronJob"}
// Get takes name of the cronJob, and returns the corresponding cronJob object, and an error if there is any.
func (c *FakeCronJobs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v2alpha1.CronJob, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(cronjobsResource, c.ns, name), &v2alpha1.CronJob{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.CronJob), err
}
// List takes label and field selectors, and returns the list of CronJobs that match those selectors.
func (c *FakeCronJobs) List(ctx context.Context, opts v1.ListOptions) (result *v2alpha1.CronJobList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(cronjobsResource, cronjobsKind, c.ns, opts), &v2alpha1.CronJobList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v2alpha1.CronJobList{ListMeta: obj.(*v2alpha1.CronJobList).ListMeta}
for _, item := range obj.(*v2alpha1.CronJobList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested cronJobs.
func (c *FakeCronJobs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(cronjobsResource, c.ns, opts))
}
// Create takes the representation of a cronJob and creates it. Returns the server's representation of the cronJob, and an error, if there is any.
func (c *FakeCronJobs) Create(ctx context.Context, cronJob *v2alpha1.CronJob, opts v1.CreateOptions) (result *v2alpha1.CronJob, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(cronjobsResource, c.ns, cronJob), &v2alpha1.CronJob{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.CronJob), err
}
// Update takes the representation of a cronJob and updates it. Returns the server's representation of the cronJob, and an error, if there is any.
func (c *FakeCronJobs) Update(ctx context.Context, cronJob *v2alpha1.CronJob, opts v1.UpdateOptions) (result *v2alpha1.CronJob, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(cronjobsResource, c.ns, cronJob), &v2alpha1.CronJob{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.CronJob), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeCronJobs) UpdateStatus(ctx context.Context, cronJob *v2alpha1.CronJob, opts v1.UpdateOptions) (*v2alpha1.CronJob, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(cronjobsResource, "status", c.ns, cronJob), &v2alpha1.CronJob{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.CronJob), err
}
// Delete takes name of the cronJob and deletes it. Returns an error if one occurs.
func (c *FakeCronJobs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(cronjobsResource, c.ns, name), &v2alpha1.CronJob{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeCronJobs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(cronjobsResource, c.ns, listOpts)
_, err := c.Fake.Invokes(action, &v2alpha1.CronJobList{})
return err
}
// Patch applies the patch and returns the patched cronJob.
func (c *FakeCronJobs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v2alpha1.CronJob, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(cronjobsResource, c.ns, name, pt, data, subresources...), &v2alpha1.CronJob{})
if obj == nil {
return nil, err
}
return obj.(*v2alpha1.CronJob), err
}

View File

@@ -1,99 +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 lister-gen. DO NOT EDIT.
package v2alpha1
import (
v2alpha1 "k8s.io/api/batch/v2alpha1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
)
// CronJobLister helps list CronJobs.
// All objects returned here must be treated as read-only.
type CronJobLister interface {
// List lists all CronJobs in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v2alpha1.CronJob, err error)
// CronJobs returns an object that can list and get CronJobs.
CronJobs(namespace string) CronJobNamespaceLister
CronJobListerExpansion
}
// cronJobLister implements the CronJobLister interface.
type cronJobLister struct {
indexer cache.Indexer
}
// NewCronJobLister returns a new CronJobLister.
func NewCronJobLister(indexer cache.Indexer) CronJobLister {
return &cronJobLister{indexer: indexer}
}
// List lists all CronJobs in the indexer.
func (s *cronJobLister) List(selector labels.Selector) (ret []*v2alpha1.CronJob, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v2alpha1.CronJob))
})
return ret, err
}
// CronJobs returns an object that can list and get CronJobs.
func (s *cronJobLister) CronJobs(namespace string) CronJobNamespaceLister {
return cronJobNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// CronJobNamespaceLister helps list and get CronJobs.
// All objects returned here must be treated as read-only.
type CronJobNamespaceLister interface {
// List lists all CronJobs in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v2alpha1.CronJob, err error)
// Get retrieves the CronJob from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*v2alpha1.CronJob, error)
CronJobNamespaceListerExpansion
}
// cronJobNamespaceLister implements the CronJobNamespaceLister
// interface.
type cronJobNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all CronJobs in the indexer for a given namespace.
func (s cronJobNamespaceLister) List(selector labels.Selector) (ret []*v2alpha1.CronJob, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v2alpha1.CronJob))
})
return ret, err
}
// Get retrieves the CronJob from the indexer for a given namespace and name.
func (s cronJobNamespaceLister) Get(name string) (*v2alpha1.CronJob, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v2alpha1.Resource("cronjob"), name)
}
return obj.(*v2alpha1.CronJob), nil
}

View File

@@ -1,27 +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 lister-gen. DO NOT EDIT.
package v2alpha1
// CronJobListerExpansion allows custom methods to be added to
// CronJobLister.
type CronJobListerExpansion interface{}
// CronJobNamespaceListerExpansion allows custom methods to be added to
// CronJobNamespaceLister.
type CronJobNamespaceListerExpansion interface{}

View File

@@ -18,7 +18,6 @@ package exec
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"errors"
@@ -52,7 +51,6 @@ import (
)
const execInfoEnv = "KUBERNETES_EXEC_INFO"
const onRotateListWarningLength = 1000
const installHintVerboseHelp = `
It looks like you are trying to use a client-go credential plugin that is not installed.
@@ -177,6 +175,12 @@ func newAuthenticator(c *cache, config *api.ExecConfig, cluster *clientauthentic
return nil, fmt.Errorf("exec plugin: invalid apiVersion %q", config.APIVersion)
}
connTracker := connrotation.NewConnectionTracker()
defaultDialer := connrotation.NewDialerWithTracker(
(&net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}).DialContext,
connTracker,
)
a := &Authenticator{
cmd: config.Command,
args: config.Args,
@@ -196,6 +200,9 @@ func newAuthenticator(c *cache, config *api.ExecConfig, cluster *clientauthentic
interactive: terminal.IsTerminal(int(os.Stdout.Fd())),
now: time.Now,
environ: os.Environ,
defaultDialer: defaultDialer,
connTracker: connTracker,
}
for _, env := range config.Env {
@@ -229,6 +236,11 @@ type Authenticator struct {
now func() time.Time
environ func() []string
// defaultDialer is used for clients which don't specify a custom dialer
defaultDialer *connrotation.Dialer
// connTracker tracks all connections opened that we need to close when rotating a client certificate
connTracker *connrotation.ConnectionTracker
// Cached results.
//
// The mutex also guards calling the plugin. Since the plugin could be
@@ -236,8 +248,6 @@ type Authenticator struct {
mu sync.Mutex
cachedCreds *credentials
exp time.Time
onRotateList []func()
}
type credentials struct {
@@ -266,20 +276,12 @@ func (a *Authenticator) UpdateTransportConfig(c *transport.Config) error {
}
c.TLS.GetCert = a.cert
var dial func(ctx context.Context, network, addr string) (net.Conn, error)
var d *connrotation.Dialer
if c.Dial != nil {
dial = c.Dial
// if c has a custom dialer, we have to wrap it
d = connrotation.NewDialerWithTracker(c.Dial, a.connTracker)
} else {
dial = (&net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}).DialContext
}
d := connrotation.NewDialer(dial)
a.mu.Lock()
defer a.mu.Unlock()
a.onRotateList = append(a.onRotateList, d.CloseAll)
onRotateListLength := len(a.onRotateList)
if onRotateListLength > onRotateListWarningLength {
klog.Warningf("constructing many client instances from the same exec auth config can cause performance problems during cert rotation and can exhaust available network connections; %d clients constructed calling %q", onRotateListLength, a.cmd)
d = a.defaultDialer
}
c.Dial = d.DialContext
@@ -458,9 +460,7 @@ func (a *Authenticator) refreshCredsLocked(r *clientauthentication.Response) err
if oldCreds.cert != nil && oldCreds.cert.Leaf != nil {
metrics.ClientCertRotationAge.Observe(time.Now().Sub(oldCreds.cert.Leaf.NotBefore))
}
for _, onRotate := range a.onRotateList {
onRotate()
}
a.connTracker.CloseAll()
}
expiry := time.Time{}

View File

@@ -8,8 +8,6 @@ reviewers:
- deads2k
- brendandburns
- liggitt
- nikhiljindal
- gmarek
- erictune
- sttts
- luxas

View File

@@ -127,7 +127,7 @@ func NewRESTClient(baseURL *url.URL, versionedAPIPath string, config ClientConte
}, nil
}
// GetRateLimiter returns rate limier for a given client, or nil if it's called on a nil client
// GetRateLimiter returns rate limiter for a given client, or nil if it's called on a nil client
func (c *RESTClient) GetRateLimiter() flowcontrol.RateLimiter {
if c == nil {
return nil

View File

@@ -47,6 +47,13 @@ type AuthProviderConfigPersister interface {
Persist(map[string]string) error
}
type noopPersister struct{}
func (n *noopPersister) Persist(_ map[string]string) error {
// no operation persister
return nil
}
// All registered auth provider plugins.
var pluginsLock sync.Mutex
var plugins = make(map[string]Factory)
@@ -69,5 +76,8 @@ func GetAuthProvider(clusterAddress string, apc *clientcmdapi.AuthProviderConfig
if !ok {
return nil, fmt.Errorf("no Auth Provider found for name %q", apc.Name)
}
if persister == nil {
persister = &noopPersister{}
}
return p(clusterAddress, apc.Config, persister)
}

View File

@@ -171,6 +171,28 @@ func TestAuthPluginPersist(t *testing.T) {
}
func Test_WhenNilPersister_NoOpPersisterIsAssigned(t *testing.T) {
if err := RegisterAuthProviderPlugin("anyPlugin", pluginPersistProvider); err != nil {
t.Errorf("unexpected error: failed to register 'anyPlugin': %v", err)
}
cfg := &clientcmdapi.AuthProviderConfig{
Name: "anyPlugin",
Config: nil,
}
plugin, err := GetAuthProvider("127.0.0.1", cfg, nil)
if err != nil {
t.Errorf("unexpected error: failed to get 'anyPlugin': %v", err)
}
anyPlugin := plugin.(*pluginPersist)
if _, ok := anyPlugin.persister.(*noopPersister); !ok {
t.Errorf("expected to be No Operation persister")
}
}
// emptyTransport provides an empty http.Response with an initialized header
// to allow wrapping RoundTrippers to set header values.
type emptyTransport struct{}

View File

@@ -242,7 +242,7 @@ func (r *Request) SubResource(subresources ...string) *Request {
}
subresource := path.Join(subresources...)
if len(r.subresource) != 0 {
r.err = fmt.Errorf("subresource already set to %q, cannot change to %q", r.resource, subresource)
r.err = fmt.Errorf("subresource already set to %q, cannot change to %q", r.subresource, subresource)
return r
}
for _, s := range subresources {
@@ -577,7 +577,7 @@ func (r Request) finalURLTemplate() url.URL {
return *url
}
func (r *Request) tryThrottle(ctx context.Context) error {
func (r *Request) tryThrottleWithInfo(ctx context.Context, retryInfo string) error {
if r.rateLimiter == nil {
return nil
}
@@ -587,19 +587,32 @@ func (r *Request) tryThrottle(ctx context.Context) error {
err := r.rateLimiter.Wait(ctx)
latency := time.Since(now)
var message string
switch {
case len(retryInfo) > 0:
message = fmt.Sprintf("Waited for %v, %s - request: %s:%s", latency, retryInfo, r.verb, r.URL().String())
default:
message = fmt.Sprintf("Waited for %v due to client-side throttling, not priority and fairness, request: %s:%s", latency, r.verb, r.URL().String())
}
if latency > longThrottleLatency {
klog.V(3).Infof("Throttling request took %v, request: %s:%s", latency, r.verb, r.URL().String())
klog.V(3).Info(message)
}
if latency > extraLongThrottleLatency {
// If the rate limiter latency is very high, the log message should be printed at a higher log level,
// but we use a throttled logger to prevent spamming.
globalThrottledLogger.Infof("Throttling request took %v, request: %s:%s", latency, r.verb, r.URL().String())
globalThrottledLogger.Infof(message)
}
metrics.RateLimiterLatency.Observe(r.verb, r.finalURLTemplate(), latency)
return err
}
func (r *Request) tryThrottle(ctx context.Context) error {
return r.tryThrottleWithInfo(ctx, "")
}
type throttleSettings struct {
logLevel klog.Level
minLogInterval time.Duration
@@ -869,6 +882,7 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp
// Right now we make about ten retry attempts if we get a Retry-After response.
retries := 0
var retryInfo string
for {
url := r.URL().String()
@@ -884,9 +898,10 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp
// We are retrying the request that we already send to apiserver
// at least once before.
// This request should also be throttled with the client-internal rate limiter.
if err := r.tryThrottle(ctx); err != nil {
if err := r.tryThrottleWithInfo(ctx, retryInfo); err != nil {
return err
}
retryInfo = ""
}
resp, err := client.Do(req)
updateURLMetrics(r, resp, err)
@@ -931,6 +946,7 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp
retries++
if seconds, wait := checkWait(resp); wait && retries <= r.maxRetries {
retryInfo = getRetryReason(retries, seconds, resp, err)
if seeker, ok := r.body.(io.Seeker); ok && r.body != nil {
_, err := seeker.Seek(0, 0)
if err != nil {
@@ -1204,6 +1220,26 @@ func retryAfterSeconds(resp *http.Response) (int, bool) {
return 0, false
}
func getRetryReason(retries, seconds int, resp *http.Response, err error) string {
// priority and fairness sets the UID of the FlowSchema associated with a request
// in the following response Header.
const responseHeaderMatchedFlowSchemaUID = "X-Kubernetes-PF-FlowSchema-UID"
message := fmt.Sprintf("retries: %d, retry-after: %ds", retries, seconds)
switch {
case resp.StatusCode == http.StatusTooManyRequests:
// it is server-side throttling from priority and fairness
flowSchemaUID := resp.Header.Get(responseHeaderMatchedFlowSchemaUID)
return fmt.Sprintf("%s - retry-reason: due to server-side throttling, FlowSchema UID: %q", message, flowSchemaUID)
case err != nil:
// it's a retriable error
return fmt.Sprintf("%s - retry-reason: due to retriable error, error: %v", message, err)
default:
return fmt.Sprintf("%s - retry-reason: %d", message, resp.StatusCode)
}
}
// Result contains the result of calling Request.Do().
type Result struct {
body []byte

2
tools/cache/OWNERS vendored
View File

@@ -20,7 +20,6 @@ reviewers:
- caesarxuchao
- mikedanese
- liggitt
- nikhiljindal
- erictune
- davidopp
- pmorie
@@ -29,7 +28,6 @@ reviewers:
- soltysh
- jsafrane
- dims
- madhusudancs
- hongchaodeng
- krousey
- xiang90

View File

@@ -26,54 +26,6 @@ import (
"k8s.io/klog/v2"
)
// NewDeltaFIFO returns a Queue which can be used to process changes to items.
//
// keyFunc is used to figure out what key an object should have. (It is
// exposed in the returned DeltaFIFO's KeyOf() method, with additional handling
// around deleted objects and queue state).
//
// 'knownObjects' may be supplied to modify the behavior of Delete,
// Replace, and Resync. It may be nil if you do not need those
// modifications.
//
// TODO: consider merging keyLister with this object, tracking a list of
// "known" keys when Pop() is called. Have to think about how that
// affects error retrying.
// NOTE: It is possible to misuse this and cause a race when using an
// external known object source.
// Whether there is a potential race depends on how the consumer
// modifies knownObjects. In Pop(), process function is called under
// lock, so it is safe to update data structures in it that need to be
// in sync with the queue (e.g. knownObjects).
//
// Example:
// In case of sharedIndexInformer being a consumer
// (https://github.com/kubernetes/kubernetes/blob/0cdd940f/staging/
// src/k8s.io/client-go/tools/cache/shared_informer.go#L192),
// there is no race as knownObjects (s.indexer) is modified safely
// under DeltaFIFO's lock. The only exceptions are GetStore() and
// GetIndexer() methods, which expose ways to modify the underlying
// storage. Currently these two methods are used for creating Lister
// and internal tests.
//
// Also see the comment on DeltaFIFO.
//
// Warning: This constructs a DeltaFIFO that does not differentiate between
// events caused by a call to Replace (e.g., from a relist, which may
// contain object updates), and synthetic events caused by a periodic resync
// (which just emit the existing object). See https://issue.k8s.io/86015 for details.
//
// Use `NewDeltaFIFOWithOptions(DeltaFIFOOptions{..., EmitDeltaTypeReplaced: true})`
// instead to receive a `Replaced` event depending on the type.
//
// Deprecated: Equivalent to NewDeltaFIFOWithOptions(DeltaFIFOOptions{KeyFunction: keyFunc, KnownObjects: knownObjects})
func NewDeltaFIFO(keyFunc KeyFunc, knownObjects KeyListerGetter) *DeltaFIFO {
return NewDeltaFIFOWithOptions(DeltaFIFOOptions{
KeyFunction: keyFunc,
KnownObjects: knownObjects,
})
}
// DeltaFIFOOptions is the configuration parameters for DeltaFIFO. All are
// optional.
type DeltaFIFOOptions struct {
@@ -99,25 +51,6 @@ type DeltaFIFOOptions struct {
EmitDeltaTypeReplaced bool
}
// NewDeltaFIFOWithOptions returns a Queue which can be used to process changes to
// items. See also the comment on DeltaFIFO.
func NewDeltaFIFOWithOptions(opts DeltaFIFOOptions) *DeltaFIFO {
if opts.KeyFunction == nil {
opts.KeyFunction = MetaNamespaceKeyFunc
}
f := &DeltaFIFO{
items: map[string]Deltas{},
queue: []string{},
keyFunc: opts.KeyFunction,
knownObjects: opts.KnownObjects,
emitDeltaTypeReplaced: opts.EmitDeltaTypeReplaced,
}
f.cond.L = &f.lock
return f
}
// DeltaFIFO is like FIFO, but differs in two ways. One is that the
// accumulator associated with a given object's key is not that object
// but rather a Deltas, which is a slice of Delta values for that
@@ -128,8 +61,11 @@ func NewDeltaFIFOWithOptions(opts DeltaFIFOOptions) *DeltaFIFO {
// Deleted if the older Deleted's object is a
// DeletedFinalStateUnknown.
//
// The other difference is that DeltaFIFO has an additional way that
// an object can be applied to an accumulator, called Sync.
// The other difference is that DeltaFIFO has two additional ways that
// an object can be applied to an accumulator: Replaced and Sync.
// If EmitDeltaTypeReplaced is not set to true, Sync will be used in
// replace events for backwards compatibility. Sync is used for periodic
// resync events.
//
// DeltaFIFO is a producer-consumer queue, where a Reflector is
// intended to be the producer, and the consumer is whatever calls
@@ -193,6 +129,107 @@ type DeltaFIFO struct {
emitDeltaTypeReplaced bool
}
// DeltaType is the type of a change (addition, deletion, etc)
type DeltaType string
// Change type definition
const (
Added DeltaType = "Added"
Updated DeltaType = "Updated"
Deleted DeltaType = "Deleted"
// Replaced is emitted when we encountered watch errors and had to do a
// relist. We don't know if the replaced object has changed.
//
// NOTE: Previous versions of DeltaFIFO would use Sync for Replace events
// as well. Hence, Replaced is only emitted when the option
// EmitDeltaTypeReplaced is true.
Replaced DeltaType = "Replaced"
// Sync is for synthetic events during a periodic resync.
Sync DeltaType = "Sync"
)
// Delta is a member of Deltas (a list of Delta objects) which
// in its turn is the type stored by a DeltaFIFO. It tells you what
// change happened, and the object's state after* that change.
//
// [*] Unless the change is a deletion, and then you'll get the final
// state of the object before it was deleted.
type Delta struct {
Type DeltaType
Object interface{}
}
// Deltas is a list of one or more 'Delta's to an individual object.
// The oldest delta is at index 0, the newest delta is the last one.
type Deltas []Delta
// NewDeltaFIFO returns a Queue which can be used to process changes to items.
//
// keyFunc is used to figure out what key an object should have. (It is
// exposed in the returned DeltaFIFO's KeyOf() method, with additional handling
// around deleted objects and queue state).
//
// 'knownObjects' may be supplied to modify the behavior of Delete,
// Replace, and Resync. It may be nil if you do not need those
// modifications.
//
// TODO: consider merging keyLister with this object, tracking a list of
// "known" keys when Pop() is called. Have to think about how that
// affects error retrying.
// NOTE: It is possible to misuse this and cause a race when using an
// external known object source.
// Whether there is a potential race depends on how the consumer
// modifies knownObjects. In Pop(), process function is called under
// lock, so it is safe to update data structures in it that need to be
// in sync with the queue (e.g. knownObjects).
//
// Example:
// In case of sharedIndexInformer being a consumer
// (https://github.com/kubernetes/kubernetes/blob/0cdd940f/staging/
// src/k8s.io/client-go/tools/cache/shared_informer.go#L192),
// there is no race as knownObjects (s.indexer) is modified safely
// under DeltaFIFO's lock. The only exceptions are GetStore() and
// GetIndexer() methods, which expose ways to modify the underlying
// storage. Currently these two methods are used for creating Lister
// and internal tests.
//
// Also see the comment on DeltaFIFO.
//
// Warning: This constructs a DeltaFIFO that does not differentiate between
// events caused by a call to Replace (e.g., from a relist, which may
// contain object updates), and synthetic events caused by a periodic resync
// (which just emit the existing object). See https://issue.k8s.io/86015 for details.
//
// Use `NewDeltaFIFOWithOptions(DeltaFIFOOptions{..., EmitDeltaTypeReplaced: true})`
// instead to receive a `Replaced` event depending on the type.
//
// Deprecated: Equivalent to NewDeltaFIFOWithOptions(DeltaFIFOOptions{KeyFunction: keyFunc, KnownObjects: knownObjects})
func NewDeltaFIFO(keyFunc KeyFunc, knownObjects KeyListerGetter) *DeltaFIFO {
return NewDeltaFIFOWithOptions(DeltaFIFOOptions{
KeyFunction: keyFunc,
KnownObjects: knownObjects,
})
}
// NewDeltaFIFOWithOptions returns a Queue which can be used to process changes to
// items. See also the comment on DeltaFIFO.
func NewDeltaFIFOWithOptions(opts DeltaFIFOOptions) *DeltaFIFO {
if opts.KeyFunction == nil {
opts.KeyFunction = MetaNamespaceKeyFunc
}
f := &DeltaFIFO{
items: map[string]Deltas{},
queue: []string{},
keyFunc: opts.KeyFunction,
knownObjects: opts.KnownObjects,
emitDeltaTypeReplaced: opts.EmitDeltaTypeReplaced,
}
f.cond.L = &f.lock
return f
}
var (
_ = Queue(&DeltaFIFO{}) // DeltaFIFO is a Queue
)
@@ -572,7 +609,7 @@ func (f *DeltaFIFO) Replace(list []interface{}, resourceVersion string) error {
f.populated = true
// While there shouldn't be any queued deletions in the initial
// population of the queue, it's better to be on the safe side.
f.initialPopulationCount = len(list) + queuedDeletions
f.initialPopulationCount = keys.Len() + queuedDeletions
}
return nil
@@ -602,7 +639,7 @@ func (f *DeltaFIFO) Replace(list []interface{}, resourceVersion string) error {
if !f.populated {
f.populated = true
f.initialPopulationCount = len(list) + queuedDeletions
f.initialPopulationCount = keys.Len() + queuedDeletions
}
return nil
@@ -673,39 +710,6 @@ type KeyGetter interface {
GetByKey(key string) (value interface{}, exists bool, err error)
}
// DeltaType is the type of a change (addition, deletion, etc)
type DeltaType string
// Change type definition
const (
Added DeltaType = "Added"
Updated DeltaType = "Updated"
Deleted DeltaType = "Deleted"
// Replaced is emitted when we encountered watch errors and had to do a
// relist. We don't know if the replaced object has changed.
//
// NOTE: Previous versions of DeltaFIFO would use Sync for Replace events
// as well. Hence, Replaced is only emitted when the option
// EmitDeltaTypeReplaced is true.
Replaced DeltaType = "Replaced"
// Sync is for synthetic events during a periodic resync.
Sync DeltaType = "Sync"
)
// Delta is the type stored by a DeltaFIFO. It tells you what change
// happened, and the object's state after* that change.
//
// [*] Unless the change is a deletion, and then you'll get the final
// state of the object before it was deleted.
type Delta struct {
Type DeltaType
Object interface{}
}
// Deltas is a list of one or more 'Delta's to an individual object.
// The oldest delta is at index 0, the newest delta is the last one.
type Deltas []Delta
// Oldest is a convenience function that returns the oldest delta, or
// nil if there are no deltas.
func (d Deltas) Oldest() *Delta {

View File

@@ -633,6 +633,15 @@ func TestDeltaFIFO_HasSynced(t *testing.T) {
},
expectedSynced: true,
},
{
// This test case won't happen in practice since a Reflector, the only producer for delta_fifo today, always passes a complete snapshot consistent in time;
// there cannot be duplicate keys in the list or apiserver is broken.
actions: []func(f *DeltaFIFO){
func(f *DeltaFIFO) { f.Replace([]interface{}{mkFifoObj("a", 1), mkFifoObj("a", 2)}, "0") },
func(f *DeltaFIFO) { Pop(f) },
},
expectedSynced: true,
},
}
for i, test := range tests {

View File

@@ -76,7 +76,7 @@ func TestMultiIndexKeys(t *testing.T) {
expected["bert"] = sets.NewString("one", "two")
expected["elmo"] = sets.NewString("tre")
expected["oscar"] = sets.NewString("two")
expected["elmo"] = sets.NewString() // let's just make sure we don't get anything back in this case
expected["elmo1"] = sets.NewString()
{
for k, v := range expected {
found := sets.String{}
@@ -87,9 +87,8 @@ func TestMultiIndexKeys(t *testing.T) {
for _, item := range indexResults {
found.Insert(item.(*v1.Pod).Name)
}
items := v.List()
if !found.HasAll(items...) {
t.Errorf("missing items, index %s, expected %v but found %v", k, items, found.List())
if !found.Equal(v) {
t.Errorf("missing items, index %s, expected %v but found %v", k, v.List(), found.List())
}
}
}

View File

@@ -198,13 +198,13 @@ func (config *DirectClientConfig) ClientConfig() (*restclient.Config, error) {
if err != nil {
return nil, err
}
mergo.MergeWithOverwrite(clientConfig, userAuthPartialConfig)
mergo.Merge(clientConfig, userAuthPartialConfig, mergo.WithOverride)
serverAuthPartialConfig, err := getServerIdentificationPartialConfig(configAuthInfo, configClusterInfo)
if err != nil {
return nil, err
}
mergo.MergeWithOverwrite(clientConfig, serverAuthPartialConfig)
mergo.Merge(clientConfig, serverAuthPartialConfig, mergo.WithOverride)
}
return clientConfig, nil
@@ -225,7 +225,7 @@ func getServerIdentificationPartialConfig(configAuthInfo clientcmdapi.AuthInfo,
configClientConfig.CAData = configClusterInfo.CertificateAuthorityData
configClientConfig.Insecure = configClusterInfo.InsecureSkipTLSVerify
configClientConfig.ServerName = configClusterInfo.TLSServerName
mergo.MergeWithOverwrite(mergedConfig, configClientConfig)
mergo.Merge(mergedConfig, configClientConfig, mergo.WithOverride)
return mergedConfig, nil
}
@@ -294,8 +294,8 @@ func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthI
promptedConfig := makeUserIdentificationConfig(*promptedAuthInfo)
previouslyMergedConfig := mergedConfig
mergedConfig = &restclient.Config{}
mergo.MergeWithOverwrite(mergedConfig, promptedConfig)
mergo.MergeWithOverwrite(mergedConfig, previouslyMergedConfig)
mergo.Merge(mergedConfig, promptedConfig, mergo.WithOverride)
mergo.Merge(mergedConfig, previouslyMergedConfig, mergo.WithOverride)
config.promptedCredentials.username = mergedConfig.Username
config.promptedCredentials.password = mergedConfig.Password
}
@@ -463,12 +463,12 @@ func (config *DirectClientConfig) getContext() (clientcmdapi.Context, error) {
mergedContext := clientcmdapi.NewContext()
if configContext, exists := contexts[contextName]; exists {
mergo.MergeWithOverwrite(mergedContext, configContext)
mergo.Merge(mergedContext, configContext, mergo.WithOverride)
} else if required {
return clientcmdapi.Context{}, fmt.Errorf("context %q does not exist", contextName)
}
if config.overrides != nil {
mergo.MergeWithOverwrite(mergedContext, config.overrides.Context)
mergo.Merge(mergedContext, config.overrides.Context, mergo.WithOverride)
}
return *mergedContext, nil
@@ -481,12 +481,12 @@ func (config *DirectClientConfig) getAuthInfo() (clientcmdapi.AuthInfo, error) {
mergedAuthInfo := clientcmdapi.NewAuthInfo()
if configAuthInfo, exists := authInfos[authInfoName]; exists {
mergo.MergeWithOverwrite(mergedAuthInfo, configAuthInfo)
mergo.Merge(mergedAuthInfo, configAuthInfo, mergo.WithOverride)
} else if required {
return clientcmdapi.AuthInfo{}, fmt.Errorf("auth info %q does not exist", authInfoName)
}
if config.overrides != nil {
mergo.MergeWithOverwrite(mergedAuthInfo, config.overrides.AuthInfo)
mergo.Merge(mergedAuthInfo, config.overrides.AuthInfo, mergo.WithOverride)
}
return *mergedAuthInfo, nil
@@ -499,15 +499,15 @@ func (config *DirectClientConfig) getCluster() (clientcmdapi.Cluster, error) {
mergedClusterInfo := clientcmdapi.NewCluster()
if config.overrides != nil {
mergo.MergeWithOverwrite(mergedClusterInfo, config.overrides.ClusterDefaults)
mergo.Merge(mergedClusterInfo, config.overrides.ClusterDefaults, mergo.WithOverride)
}
if configClusterInfo, exists := clusterInfos[clusterInfoName]; exists {
mergo.MergeWithOverwrite(mergedClusterInfo, configClusterInfo)
mergo.Merge(mergedClusterInfo, configClusterInfo, mergo.WithOverride)
} else if required {
return clientcmdapi.Cluster{}, fmt.Errorf("cluster %q does not exist", clusterInfoName)
}
if config.overrides != nil {
mergo.MergeWithOverwrite(mergedClusterInfo, config.overrides.ClusterInfo)
mergo.Merge(mergedClusterInfo, config.overrides.ClusterInfo, mergo.WithOverride)
}
// * An override of --insecure-skip-tls-verify=true and no accompanying CA/CA data should clear already-set CA/CA data
@@ -548,11 +548,12 @@ func (config *inClusterClientConfig) RawConfig() (clientcmdapi.Config, error) {
}
func (config *inClusterClientConfig) ClientConfig() (*restclient.Config, error) {
if config.inClusterConfigProvider == nil {
config.inClusterConfigProvider = restclient.InClusterConfig
inClusterConfigProvider := config.inClusterConfigProvider
if inClusterConfigProvider == nil {
inClusterConfigProvider = restclient.InClusterConfig
}
icc, err := config.inClusterConfigProvider()
icc, err := inClusterConfigProvider()
if err != nil {
return nil, err
}
@@ -572,7 +573,7 @@ func (config *inClusterClientConfig) ClientConfig() (*restclient.Config, error)
}
}
return icc, err
return icc, nil
}
func (config *inClusterClientConfig) Namespace() (string, bool, error) {
@@ -611,7 +612,7 @@ func (config *inClusterClientConfig) Possible() bool {
// to the default config.
func BuildConfigFromFlags(masterUrl, kubeconfigPath string) (*restclient.Config, error) {
if kubeconfigPath == "" && masterUrl == "" {
klog.Warningf("Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.")
klog.Warning("Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.")
kubeconfig, err := restclient.InClusterConfig()
if err == nil {
return kubeconfig, nil

View File

@@ -63,7 +63,7 @@ func TestMergoSemantics(t *testing.T) {
},
}
for _, data := range testDataStruct {
err := mergo.MergeWithOverwrite(&data.dst, &data.src)
err := mergo.Merge(&data.dst, &data.src, mergo.WithOverride)
if err != nil {
t.Errorf("error while merging: %s", err)
}
@@ -92,7 +92,7 @@ func TestMergoSemantics(t *testing.T) {
},
}
for _, data := range testDataMap {
err := mergo.MergeWithOverwrite(&data.dst, &data.src)
err := mergo.Merge(&data.dst, &data.src, mergo.WithOverride)
if err != nil {
t.Errorf("error while merging: %s", err)
}

View File

@@ -374,7 +374,7 @@ func (p *persister) Persist(config map[string]string) error {
authInfo, ok := newConfig.AuthInfos[p.user]
if ok && authInfo.AuthProvider != nil {
authInfo.AuthProvider.Config = config
ModifyConfig(p.configAccess, *newConfig, false)
return ModifyConfig(p.configAccess, *newConfig, false)
}
return nil
}

View File

@@ -18,10 +18,8 @@ package clientcmd
import (
"fmt"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
"reflect"
goruntime "runtime"
@@ -48,24 +46,24 @@ const (
)
var (
RecommendedConfigDir = path.Join(homedir.HomeDir(), RecommendedHomeDir)
RecommendedHomeFile = path.Join(RecommendedConfigDir, RecommendedFileName)
RecommendedSchemaFile = path.Join(RecommendedConfigDir, RecommendedSchemaName)
RecommendedConfigDir = filepath.Join(homedir.HomeDir(), RecommendedHomeDir)
RecommendedHomeFile = filepath.Join(RecommendedConfigDir, RecommendedFileName)
RecommendedSchemaFile = filepath.Join(RecommendedConfigDir, RecommendedSchemaName)
)
// currentMigrationRules returns a map that holds the history of recommended home directories used in previous versions.
// Any future changes to RecommendedHomeFile and related are expected to add a migration rule here, in order to make
// sure existing config files are migrated to their new locations properly.
func currentMigrationRules() map[string]string {
oldRecommendedHomeFile := path.Join(os.Getenv("HOME"), "/.kube/.kubeconfig")
oldRecommendedWindowsHomeFile := path.Join(os.Getenv("HOME"), RecommendedHomeDir, RecommendedFileName)
migrationRules := map[string]string{}
migrationRules[RecommendedHomeFile] = oldRecommendedHomeFile
var oldRecommendedHomeFileName string
if goruntime.GOOS == "windows" {
migrationRules[RecommendedHomeFile] = oldRecommendedWindowsHomeFile
oldRecommendedHomeFileName = RecommendedFileName
} else {
oldRecommendedHomeFileName = ".kubeconfig"
}
return map[string]string{
RecommendedHomeFile: filepath.Join(os.Getenv("HOME"), RecommendedHomeDir, oldRecommendedHomeFileName),
}
return migrationRules
}
type ClientConfigLoader interface {
@@ -227,7 +225,7 @@ func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
mapConfig := clientcmdapi.NewConfig()
for _, kubeconfig := range kubeconfigs {
mergo.MergeWithOverwrite(mapConfig, kubeconfig)
mergo.Merge(mapConfig, kubeconfig, mergo.WithOverride)
}
// merge all of the struct values in the reverse order so that priority is given correctly
@@ -235,14 +233,14 @@ func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
nonMapConfig := clientcmdapi.NewConfig()
for i := len(kubeconfigs) - 1; i >= 0; i-- {
kubeconfig := kubeconfigs[i]
mergo.MergeWithOverwrite(nonMapConfig, kubeconfig)
mergo.Merge(nonMapConfig, kubeconfig, mergo.WithOverride)
}
// since values are overwritten, but maps values are not, we can merge the non-map config on top of the map config and
// get the values we expect.
config := clientcmdapi.NewConfig()
mergo.MergeWithOverwrite(config, mapConfig)
mergo.MergeWithOverwrite(config, nonMapConfig)
mergo.Merge(config, mapConfig, mergo.WithOverride)
mergo.Merge(config, nonMapConfig, mergo.WithOverride)
if rules.ResolvePaths() {
if err := ResolveLocalPaths(config); err != nil {
@@ -283,20 +281,15 @@ func (rules *ClientConfigLoadingRules) Migrate() error {
return fmt.Errorf("cannot migrate %v to %v because it is a directory", source, destination)
}
in, err := os.Open(source)
data, err := ioutil.ReadFile(source)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(destination)
// destination is created with mode 0666 before umask
err = ioutil.WriteFile(destination, data, 0666)
if err != nil {
return err
}
defer out.Close()
if _, err = io.Copy(out, in); err != nil {
return err
}
}
return nil

View File

@@ -1,5 +1,5 @@
/*
Copyright The Kubernetes Authors.
Copyright 2021 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.
@@ -14,8 +14,21 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package clientcmd
package v2alpha1
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
)
type CronJobExpansion interface{}
func TestMain(m *testing.M) {
tmp, err := ioutil.TempDir("", "testkubeconfig")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmp)
os.Setenv("KUBECONFIG", filepath.Join(tmp, "dummy-nonexistent-kubeconfig"))
os.Exit(m.Run())
}

View File

@@ -7,7 +7,6 @@ reviewers:
- wojtek-t
- deads2k
- mikedanese
- gmarek
- timothysc
- ingvagabund
- resouer

View File

@@ -145,10 +145,13 @@ func New(lockType string, ns string, name string, coreClient corev1.CoreV1Interf
}
// NewFromKubeconfig will create a lock of a given type according to the input parameters.
// Timeout set for a client used to contact to Kubernetes should be lower than
// RenewDeadline to keep a single hung request from forcing a leader loss.
// Setting it to max(time.Second, RenewDeadline/2) as a reasonable heuristic.
func NewFromKubeconfig(lockType string, ns string, name string, rlc ResourceLockConfig, kubeconfig *restclient.Config, renewDeadline time.Duration) (Interface, error) {
// shallow copy, do not modify the kubeconfig
config := *kubeconfig
timeout := ((renewDeadline / time.Millisecond) / 2) * time.Millisecond
timeout := renewDeadline / 2
if timeout < time.Second {
timeout = time.Second
}

View File

@@ -10,7 +10,6 @@ reviewers:
- vishh
- mikedanese
- liggitt
- nikhiljindal
- erictune
- pmorie
- dchen1107

View File

@@ -155,21 +155,21 @@ func (a *EventRecorderAdapter) Eventf(regarding, _ runtime.Object, eventtype, re
// Creates a new event broadcaster.
func NewBroadcaster() EventBroadcaster {
return &eventBroadcasterImpl{
Broadcaster: watch.NewBroadcaster(maxQueuedEvents, watch.DropIfChannelFull),
Broadcaster: watch.NewLongQueueBroadcaster(maxQueuedEvents, watch.DropIfChannelFull),
sleepDuration: defaultSleepDuration,
}
}
func NewBroadcasterForTests(sleepDuration time.Duration) EventBroadcaster {
return &eventBroadcasterImpl{
Broadcaster: watch.NewBroadcaster(maxQueuedEvents, watch.DropIfChannelFull),
Broadcaster: watch.NewLongQueueBroadcaster(maxQueuedEvents, watch.DropIfChannelFull),
sleepDuration: sleepDuration,
}
}
func NewBroadcasterWithCorrelatorOptions(options CorrelatorOptions) EventBroadcaster {
return &eventBroadcasterImpl{
Broadcaster: watch.NewBroadcaster(maxQueuedEvents, watch.DropIfChannelFull),
Broadcaster: watch.NewLongQueueBroadcaster(maxQueuedEvents, watch.DropIfChannelFull),
sleepDuration: defaultSleepDuration,
options: options,
}
@@ -323,7 +323,7 @@ type recorderImpl struct {
clock clock.Clock
}
func (recorder *recorderImpl) generateEvent(object runtime.Object, annotations map[string]string, timestamp metav1.Time, eventtype, reason, message string) {
func (recorder *recorderImpl) generateEvent(object runtime.Object, annotations map[string]string, eventtype, reason, message string) {
ref, err := ref.GetReference(recorder.scheme, object)
if err != nil {
klog.Errorf("Could not construct reference to: '%#v' due to: '%v'. Will not report event: '%v' '%v' '%v'", object, err, eventtype, reason, message)
@@ -338,15 +338,18 @@ func (recorder *recorderImpl) generateEvent(object runtime.Object, annotations m
event := recorder.makeEvent(ref, annotations, eventtype, reason, message)
event.Source = recorder.source
go func() {
// NOTE: events should be a non-blocking operation
defer utilruntime.HandleCrash()
recorder.Action(watch.Added, event)
}()
// NOTE: events should be a non-blocking operation, but we also need to not
// put this in a goroutine, otherwise we'll race to write to a closed channel
// when we go to shut down this broadcaster. Just drop events if we get overloaded,
// and log an error if that happens (we've configured the broadcaster to drop
// outgoing events anyway).
if sent := recorder.ActionOrDrop(watch.Added, event); !sent {
klog.Errorf("unable to record event: too many queued events, dropped event %#v", event)
}
}
func (recorder *recorderImpl) Event(object runtime.Object, eventtype, reason, message string) {
recorder.generateEvent(object, nil, metav1.Now(), eventtype, reason, message)
recorder.generateEvent(object, nil, eventtype, reason, message)
}
func (recorder *recorderImpl) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) {
@@ -354,7 +357,7 @@ func (recorder *recorderImpl) Eventf(object runtime.Object, eventtype, reason, m
}
func (recorder *recorderImpl) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) {
recorder.generateEvent(object, annotations, metav1.Now(), eventtype, reason, fmt.Sprintf(messageFmt, args...))
recorder.generateEvent(object, annotations, eventtype, reason, fmt.Sprintf(messageFmt, args...))
}
func (recorder *recorderImpl) makeEvent(ref *v1.ObjectReference, annotations map[string]string, eventtype, reason, message string) *v1.Event {

View File

@@ -21,6 +21,7 @@ import (
"fmt"
"net/http"
"strconv"
"sync"
"testing"
"time"
@@ -101,6 +102,29 @@ func OnPatchFactory(testCache map[string]*v1.Event, patchEvent chan<- *v1.Event)
}
}
func TestNonRacyShutdown(t *testing.T) {
// Attempt to simulate previously racy conditions, and ensure that no race
// occurs: Nominally, calling "Eventf" *followed by* shutdown from the same
// thread should be a safe operation, but it's not if we launch recorder.Action
// in a goroutine.
caster := NewBroadcasterForTests(0)
clock := clock.NewFakeClock(time.Now())
recorder := recorderWithFakeClock(v1.EventSource{Component: "eventTest"}, caster, clock)
var wg sync.WaitGroup
wg.Add(100)
for i := 0; i < 100; i++ {
go func() {
defer wg.Done()
recorder.Eventf(&v1.ObjectReference{}, v1.EventTypeNormal, "Started", "blah")
}()
}
wg.Wait()
caster.Shutdown()
}
func TestEventf(t *testing.T) {
testPod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{

View File

@@ -0,0 +1,266 @@
/*
Copyright 2020 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 remotecommand
import (
"encoding/json"
"errors"
"io"
"io/ioutil"
v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/httpstream"
"k8s.io/apimachinery/pkg/util/httpstream/spdy"
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/rest"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"time"
)
type AttachFunc func(in io.Reader, out, err io.WriteCloser, tty bool, resize <-chan TerminalSize) error
type streamContext struct {
conn io.Closer
stdinStream io.ReadCloser
stdoutStream io.WriteCloser
stderrStream io.WriteCloser
writeStatus func(status *apierrors.StatusError) error
}
type streamAndReply struct {
httpstream.Stream
replySent <-chan struct{}
}
type fakeMassiveDataPty struct{}
func (s *fakeMassiveDataPty) Read(p []byte) (int, error) {
time.Sleep(time.Duration(1) * time.Second)
return copy(p, []byte{}), errors.New("client crashed after 1 second")
}
func (s *fakeMassiveDataPty) Write(p []byte) (int, error) {
time.Sleep(time.Duration(1) * time.Second)
return len(p), errors.New("return err")
}
func fakeMassiveDataAttacher(stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan TerminalSize) error {
copyDone := make(chan struct{}, 3)
if stdin == nil {
return errors.New("stdin is requested") // we need stdin to notice the conn break
}
go func() {
io.Copy(ioutil.Discard, stdin)
copyDone <- struct{}{}
}()
go func() {
if stdout == nil {
return
}
copyDone <- writeMassiveData(stdout)
}()
go func() {
if stderr == nil {
return
}
copyDone <- writeMassiveData(stderr)
}()
select {
case <-copyDone:
return nil
}
}
func writeMassiveData(stdStream io.Writer) struct{} { // write to stdin or stdout
for {
_, err := io.Copy(stdStream, strings.NewReader("something"))
if err != nil && err.Error() != "EOF" {
break
}
}
return struct{}{}
}
func TestSPDYExecutorStream(t *testing.T) {
tests := []struct {
name string
options StreamOptions
expectError string
attacher AttachFunc
}{
{
name: "stdoutBlockTest",
options: StreamOptions{
Stdin: &fakeMassiveDataPty{},
Stdout: &fakeMassiveDataPty{},
},
expectError: "",
attacher: fakeMassiveDataAttacher,
},
{
name: "stderrBlockTest",
options: StreamOptions{
Stdin: &fakeMassiveDataPty{},
Stderr: &fakeMassiveDataPty{},
},
expectError: "",
attacher: fakeMassiveDataAttacher,
},
}
for _, test := range tests {
server := newTestHTTPServer(test.attacher, &test.options)
err := attach2Server(server.URL, test.options)
gotError := ""
if err != nil {
gotError = err.Error()
}
if test.expectError != gotError {
t.Errorf("%s: expected [%v], got [%v]", test.name, test.expectError, gotError)
}
server.Close()
}
}
func newTestHTTPServer(f AttachFunc, options *StreamOptions) *httptest.Server {
server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
ctx, err := createHTTPStreams(writer, request, options)
if err != nil {
return
}
defer ctx.conn.Close()
// handle input output
err = f(ctx.stdinStream, ctx.stdoutStream, ctx.stderrStream, false, nil)
if err != nil {
ctx.writeStatus(apierrors.NewInternalError(err))
} else {
ctx.writeStatus(&apierrors.StatusError{ErrStatus: metav1.Status{
Status: metav1.StatusSuccess,
}})
}
}))
return server
}
func attach2Server(rawURL string, options StreamOptions) error {
uri, _ := url.Parse(rawURL)
exec, err := NewSPDYExecutor(&rest.Config{Host: uri.Host}, "POST", uri)
if err != nil {
return err
}
e := make(chan error)
go func(e chan error) {
e <- exec.Stream(options)
}(e)
select {
case err := <-e:
return err
case <-time.After(wait.ForeverTestTimeout):
return errors.New("execute timeout")
}
}
// simplify createHttpStreams , only support StreamProtocolV4Name
func createHTTPStreams(w http.ResponseWriter, req *http.Request, opts *StreamOptions) (*streamContext, error) {
_, err := httpstream.Handshake(req, w, []string{remotecommandconsts.StreamProtocolV4Name})
if err != nil {
return nil, err
}
upgrader := spdy.NewResponseUpgrader()
streamCh := make(chan streamAndReply)
conn := upgrader.UpgradeResponse(w, req, func(stream httpstream.Stream, replySent <-chan struct{}) error {
streamCh <- streamAndReply{Stream: stream, replySent: replySent}
return nil
})
ctx := &streamContext{
conn: conn,
}
// wait for stream
replyChan := make(chan struct{}, 4)
defer close(replyChan)
receivedStreams := 0
expectedStreams := 1
if opts.Stdout != nil {
expectedStreams++
}
if opts.Stdin != nil {
expectedStreams++
}
if opts.Stderr != nil {
expectedStreams++
}
WaitForStreams:
for {
select {
case stream := <-streamCh:
streamType := stream.Headers().Get(v1.StreamType)
switch streamType {
case v1.StreamTypeError:
replyChan <- struct{}{}
ctx.writeStatus = v4WriteStatusFunc(stream)
case v1.StreamTypeStdout:
replyChan <- struct{}{}
ctx.stdoutStream = stream
case v1.StreamTypeStdin:
replyChan <- struct{}{}
ctx.stdinStream = stream
case v1.StreamTypeStderr:
replyChan <- struct{}{}
ctx.stderrStream = stream
default:
// add other stream ...
return nil, errors.New("unimplemented stream type")
}
case <-replyChan:
receivedStreams++
if receivedStreams == expectedStreams {
break WaitForStreams
}
}
}
return ctx, nil
}
func v4WriteStatusFunc(stream io.Writer) func(status *apierrors.StatusError) error {
return func(status *apierrors.StatusError) error {
bs, err := json.Marshal(status.Status())
if err != nil {
return err
}
_, err = stream.Write(bs)
return err
}
}

View File

@@ -142,6 +142,10 @@ func (p *streamProtocolV2) copyStdout(wg *sync.WaitGroup) {
go func() {
defer runtime.HandleCrash()
defer wg.Done()
// make sure, packet in queue can be consumed.
// block in queue may lead to deadlock in conn.server
// issue: https://github.com/kubernetes/kubernetes/issues/96339
defer io.Copy(ioutil.Discard, p.remoteStdout)
if _, err := io.Copy(p.Stdout, p.remoteStdout); err != nil {
runtime.HandleError(err)
@@ -158,6 +162,7 @@ func (p *streamProtocolV2) copyStderr(wg *sync.WaitGroup) {
go func() {
defer runtime.HandleCrash()
defer wg.Done()
defer io.Copy(ioutil.Discard, p.remoteStderr)
if _, err := io.Copy(p.Stderr, p.remoteStderr); err != nil {
runtime.HandleError(err)

View File

@@ -18,6 +18,7 @@ package remotecommand
import (
"fmt"
"strings"
"testing"
)
@@ -36,7 +37,7 @@ func TestV4ErrorDecoder(t *testing.T) {
},
{
message: "{",
err: "error stream protocol error: unexpected end of JSON input in \"{\"",
err: "unexpected end of JSON input in \"{\"",
},
{
message: `{"status": "Success" }`,
@@ -64,7 +65,7 @@ func TestV4ErrorDecoder(t *testing.T) {
if want == "" {
want = "<nil>"
}
if got := fmt.Sprintf("%v", err); got != want {
if got := fmt.Sprintf("%v", err); !strings.Contains(got, want) {
t.Errorf("wrong error for message %q: want=%q, got=%q", test.message, want, got)
}
}

View File

@@ -127,7 +127,7 @@ func NewIndexerInformerWatcher(lw cache.ListerWatcher, objType runtime.Object) (
// We have no means of passing the additional information down using
// watch API based on watch.Event but the caller can filter such
// objects by checking if metadata.deletionTimestamp is set
obj = staleObj
obj = staleObj.Obj
}
e.push(watch.Event{

View File

@@ -27,6 +27,7 @@ import (
"github.com/davecgh/go-spew/spew"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -276,3 +277,88 @@ func TestNewInformerWatcher(t *testing.T) {
}
}
// TestInformerWatcherDeletedFinalStateUnknown tests the code path when `DeleteFunc`
// in `NewIndexerInformerWatcher` receives a `cache.DeletedFinalStateUnknown`
// object from the underlying `DeltaFIFO`. The triggering condition is described
// at https://github.com/kubernetes/kubernetes/blob/dc39ab2417bfddcec37be4011131c59921fdbe98/staging/src/k8s.io/client-go/tools/cache/delta_fifo.go#L736-L739.
//
// Code from @liggitt
func TestInformerWatcherDeletedFinalStateUnknown(t *testing.T) {
listCalls := 0
watchCalls := 0
lw := &cache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
retval := &corev1.SecretList{}
if listCalls == 0 {
// Return a list with items in it
retval.ResourceVersion = "1"
retval.Items = []corev1.Secret{{ObjectMeta: metav1.ObjectMeta{Name: "secret1", Namespace: "ns1", ResourceVersion: "123"}}}
} else {
// Return empty lists after the first call
retval.ResourceVersion = "2"
}
listCalls++
return retval, nil
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
w := watch.NewFake()
if options.ResourceVersion == "1" {
go func() {
// Close with a "Gone" error when trying to start a watch from the first list
w.Error(&apierrors.NewGone("gone").ErrStatus)
w.Stop()
}()
}
watchCalls++
return w, nil
},
}
_, _, w, done := NewIndexerInformerWatcher(lw, &corev1.Secret{})
// Expect secret add
select {
case event, ok := <-w.ResultChan():
if !ok {
t.Fatal("unexpected close")
}
if event.Type != watch.Added {
t.Fatalf("expected Added event, got %#v", event)
}
if event.Object.(*corev1.Secret).ResourceVersion != "123" {
t.Fatalf("expected added Secret with rv=123, got %#v", event.Object)
}
case <-time.After(time.Second * 10):
t.Fatal("timeout")
}
// Expect secret delete because the relist was missing the secret
select {
case event, ok := <-w.ResultChan():
if !ok {
t.Fatal("unexpected close")
}
if event.Type != watch.Deleted {
t.Fatalf("expected Deleted event, got %#v", event)
}
if event.Object.(*corev1.Secret).ResourceVersion != "123" {
t.Fatalf("expected deleted Secret with rv=123, got %#v", event.Object)
}
case <-time.After(time.Second * 10):
t.Fatal("timeout")
}
w.Stop()
select {
case <-done:
case <-time.After(time.Second * 10):
t.Fatal("timeout")
}
if listCalls < 2 {
t.Fatalf("expected at least 2 list calls, got %d", listCalls)
}
if watchCalls < 1 {
t.Fatalf("expected at least 1 watch call, got %d", watchCalls)
}
}

View File

@@ -23,9 +23,9 @@ import (
"time"
"golang.org/x/oauth2"
"k8s.io/klog/v2"
utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/klog/v2"
)
// HTTPWrappersForConfig wraps a round tripper with any relevant layered
@@ -68,13 +68,13 @@ func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTrip
func DebugWrappers(rt http.RoundTripper) http.RoundTripper {
switch {
case bool(klog.V(9).Enabled()):
rt = newDebuggingRoundTripper(rt, debugCurlCommand, debugURLTiming, debugResponseHeaders)
rt = NewDebuggingRoundTripper(rt, DebugCurlCommand, DebugURLTiming, DebugResponseHeaders)
case bool(klog.V(8).Enabled()):
rt = newDebuggingRoundTripper(rt, debugJustURL, debugRequestHeaders, debugResponseStatus, debugResponseHeaders)
rt = NewDebuggingRoundTripper(rt, DebugJustURL, DebugRequestHeaders, DebugResponseStatus, DebugResponseHeaders)
case bool(klog.V(7).Enabled()):
rt = newDebuggingRoundTripper(rt, debugJustURL, debugRequestHeaders, debugResponseStatus)
rt = NewDebuggingRoundTripper(rt, DebugJustURL, DebugRequestHeaders, DebugResponseStatus)
case bool(klog.V(6).Enabled()):
rt = newDebuggingRoundTripper(rt, debugURLTiming)
rt = NewDebuggingRoundTripper(rt, DebugURLTiming)
}
return rt
@@ -353,25 +353,35 @@ func (r *requestInfo) toCurl() string {
// through it based on what is configured
type debuggingRoundTripper struct {
delegatedRoundTripper http.RoundTripper
levels map[debugLevel]bool
levels map[DebugLevel]bool
}
type debugLevel int
// DebugLevel is used to enable debugging of certain
// HTTP requests and responses fields via the debuggingRoundTripper.
type DebugLevel int
const (
debugJustURL debugLevel = iota
debugURLTiming
debugCurlCommand
debugRequestHeaders
debugResponseStatus
debugResponseHeaders
// DebugJustURL will add to the debug output HTTP requests method and url.
DebugJustURL DebugLevel = iota
// DebugURLTiming will add to the debug output the duration of HTTP requests.
DebugURLTiming
// DebugCurlCommand will add to the debug output the curl command equivalent to the
// HTTP request.
DebugCurlCommand
// DebugRequestHeaders will add to the debug output the HTTP requests headers.
DebugRequestHeaders
// DebugResponseStatus will add to the debug output the HTTP response status.
DebugResponseStatus
// DebugResponseHeaders will add to the debug output the HTTP response headers.
DebugResponseHeaders
)
func newDebuggingRoundTripper(rt http.RoundTripper, levels ...debugLevel) *debuggingRoundTripper {
// NewDebuggingRoundTripper allows to display in the logs output debug information
// on the API requests performed by the client.
func NewDebuggingRoundTripper(rt http.RoundTripper, levels ...DebugLevel) http.RoundTripper {
drt := &debuggingRoundTripper{
delegatedRoundTripper: rt,
levels: make(map[debugLevel]bool, len(levels)),
levels: make(map[DebugLevel]bool, len(levels)),
}
for _, v := range levels {
drt.levels[v] = true
@@ -418,15 +428,14 @@ func maskValue(key string, value string) string {
func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
reqInfo := newRequestInfo(req)
if rt.levels[debugJustURL] {
if rt.levels[DebugJustURL] {
klog.Infof("%s %s", reqInfo.RequestVerb, reqInfo.RequestURL)
}
if rt.levels[debugCurlCommand] {
if rt.levels[DebugCurlCommand] {
klog.Infof("%s", reqInfo.toCurl())
}
if rt.levels[debugRequestHeaders] {
klog.Infof("Request Headers:")
if rt.levels[DebugRequestHeaders] {
klog.Info("Request Headers:")
for key, values := range reqInfo.RequestHeaders {
for _, value := range values {
value = maskValue(key, value)
@@ -441,14 +450,14 @@ func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, e
reqInfo.complete(response, err)
if rt.levels[debugURLTiming] {
if rt.levels[DebugURLTiming] {
klog.Infof("%s %s %s in %d milliseconds", reqInfo.RequestVerb, reqInfo.RequestURL, reqInfo.ResponseStatus, reqInfo.Duration.Nanoseconds()/int64(time.Millisecond))
}
if rt.levels[debugResponseStatus] {
if rt.levels[DebugResponseStatus] {
klog.Infof("Response Status: %s in %d milliseconds", reqInfo.ResponseStatus, reqInfo.Duration.Nanoseconds()/int64(time.Millisecond))
}
if rt.levels[debugResponseHeaders] {
klog.Infof("Response Headers:")
if rt.levels[DebugResponseHeaders] {
klog.Info("Response Headers:")
for key, values := range reqInfo.ResponseHeaders {
for _, value := range values {
klog.Infof(" %s: %s", key, value)

View File

@@ -17,11 +17,15 @@ limitations under the License.
package transport
import (
"bytes"
"fmt"
"net/http"
"net/url"
"reflect"
"strings"
"testing"
"k8s.io/klog/v2"
)
type testRoundTripper struct {
@@ -412,3 +416,102 @@ func TestHeaderEscapeRoundTrip(t *testing.T) {
})
}
}
func TestDebuggingRoundTripper(t *testing.T) {
t.Parallel()
rawURL := "https://127.0.0.1:12345/api/v1/pods?limit=500"
req := &http.Request{
Method: http.MethodGet,
Header: map[string][]string{
"Authorization": {"bearer secretauthtoken"},
"X-Test-Request": {"test"},
},
}
res := &http.Response{
Status: "OK",
StatusCode: http.StatusOK,
Header: map[string][]string{
"X-Test-Response": {"test"},
},
}
tcs := []struct {
levels []DebugLevel
expectedOutputLines []string
}{
{
levels: []DebugLevel{DebugJustURL},
expectedOutputLines: []string{fmt.Sprintf("%s %s", req.Method, rawURL)},
},
{
levels: []DebugLevel{DebugRequestHeaders},
expectedOutputLines: func() []string {
lines := []string{fmt.Sprintf("Request Headers:\n")}
for key, values := range req.Header {
for _, value := range values {
if key == "Authorization" {
value = "bearer <masked>"
}
lines = append(lines, fmt.Sprintf(" %s: %s\n", key, value))
}
}
return lines
}(),
},
{
levels: []DebugLevel{DebugResponseHeaders},
expectedOutputLines: func() []string {
lines := []string{fmt.Sprintf("Response Headers:\n")}
for key, values := range res.Header {
for _, value := range values {
lines = append(lines, fmt.Sprintf(" %s: %s\n", key, value))
}
}
return lines
}(),
},
{
levels: []DebugLevel{DebugURLTiming},
expectedOutputLines: []string{fmt.Sprintf("%s %s %s", req.Method, rawURL, res.Status)},
},
{
levels: []DebugLevel{DebugResponseStatus},
expectedOutputLines: []string{fmt.Sprintf("Response Status: %s", res.Status)},
},
{
levels: []DebugLevel{DebugCurlCommand},
expectedOutputLines: []string{fmt.Sprintf("curl -k -v -X")},
},
}
for _, tc := range tcs {
// hijack the klog output
tmpWriteBuffer := bytes.NewBuffer(nil)
klog.SetOutput(tmpWriteBuffer)
klog.LogToStderr(false)
// parse rawURL
parsedURL, err := url.Parse(rawURL)
if err != nil {
t.Fatalf("url.Parse(%q) returned error: %v", rawURL, err)
}
req.URL = parsedURL
// execute the round tripper
rt := &testRoundTripper{
Response: res,
}
NewDebuggingRoundTripper(rt, tc.levels...).RoundTrip(req)
// call Flush to ensure the text isn't still buffered
klog.Flush()
// check if klog's output contains the expected lines
actual := tmpWriteBuffer.String()
for _, expected := range tc.expectedOutputLines {
if !strings.Contains(actual, expected) {
t.Errorf("%q does not contain expected output %q", actual, expected)
}
}
}
}

View File

@@ -20,6 +20,7 @@ import (
"fmt"
"net/http"
"net/url"
"time"
"k8s.io/apimachinery/pkg/util/httpstream"
"k8s.io/apimachinery/pkg/util/httpstream/spdy"
@@ -42,7 +43,13 @@ func RoundTripperFor(config *restclient.Config) (http.RoundTripper, Upgrader, er
if config.Proxy != nil {
proxy = config.Proxy
}
upgradeRoundTripper := spdy.NewRoundTripperWithProxy(tlsConfig, true, false, proxy)
upgradeRoundTripper := spdy.NewRoundTripperWithConfig(spdy.RoundTripperConfig{
TLS: tlsConfig,
FollowRedirects: true,
RequireSameHostRedirects: false,
Proxier: proxy,
PingPeriod: time.Second * 5,
})
wrapper, err := restclient.HTTPWrappersForConfig(config, upgradeRoundTripper)
if err != nil {
return nil, nil, err

View File

@@ -33,18 +33,40 @@ type DialFunc func(ctx context.Context, network, address string) (net.Conn, erro
// Dialer opens connections through Dial and tracks them.
type Dialer struct {
dial DialFunc
*ConnectionTracker
}
// NewDialer creates a new Dialer instance.
// Equivalent to NewDialerWithTracker(dial, nil).
func NewDialer(dial DialFunc) *Dialer {
return NewDialerWithTracker(dial, nil)
}
// NewDialerWithTracker creates a new Dialer instance.
//
// If dial is not nil, it will be used to create new underlying connections.
// Otherwise net.DialContext is used.
// If tracker is not nil, it will be used to track new underlying connections.
// Otherwise NewConnectionTracker() is used.
func NewDialerWithTracker(dial DialFunc, tracker *ConnectionTracker) *Dialer {
if tracker == nil {
tracker = NewConnectionTracker()
}
return &Dialer{
dial: dial,
ConnectionTracker: tracker,
}
}
// ConnectionTracker keeps track of opened connections
type ConnectionTracker struct {
mu sync.Mutex
conns map[*closableConn]struct{}
}
// NewDialer creates a new Dialer instance.
//
// If dial is not nil, it will be used to create new underlying connections.
// Otherwise net.DialContext is used.
func NewDialer(dial DialFunc) *Dialer {
return &Dialer{
dial: dial,
// NewConnectionTracker returns a connection tracker for use with NewDialerWithTracker
func NewConnectionTracker() *ConnectionTracker {
return &ConnectionTracker{
conns: make(map[*closableConn]struct{}),
}
}
@@ -52,17 +74,40 @@ func NewDialer(dial DialFunc) *Dialer {
// CloseAll forcibly closes all tracked connections.
//
// Note: new connections may get created before CloseAll returns.
func (d *Dialer) CloseAll() {
d.mu.Lock()
conns := d.conns
d.conns = make(map[*closableConn]struct{})
d.mu.Unlock()
func (c *ConnectionTracker) CloseAll() {
c.mu.Lock()
conns := c.conns
c.conns = make(map[*closableConn]struct{})
c.mu.Unlock()
for conn := range conns {
conn.Close()
}
}
// Track adds the connection to the list of tracked connections,
// and returns a wrapped copy of the connection that stops tracking the connection
// when it is closed.
func (c *ConnectionTracker) Track(conn net.Conn) net.Conn {
closable := &closableConn{Conn: conn}
// When the connection is closed, remove it from the map. This will
// be no-op if the connection isn't in the map, e.g. if CloseAll()
// is called.
closable.onClose = func() {
c.mu.Lock()
delete(c.conns, closable)
c.mu.Unlock()
}
// Start tracking the connection
c.mu.Lock()
c.conns[closable] = struct{}{}
c.mu.Unlock()
return closable
}
// Dial creates a new tracked connection.
func (d *Dialer) Dial(network, address string) (net.Conn, error) {
return d.DialContext(context.Background(), network, address)
@@ -74,24 +119,7 @@ func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.
if err != nil {
return nil, err
}
closable := &closableConn{Conn: conn}
// When the connection is closed, remove it from the map. This will
// be no-op if the connection isn't in the map, e.g. if CloseAll()
// is called.
closable.onClose = func() {
d.mu.Lock()
delete(d.conns, closable)
d.mu.Unlock()
}
// Start tracking the connection
d.mu.Lock()
d.conns[closable] = struct{}{}
d.mu.Unlock()
return closable, nil
return d.ConnectionTracker.Track(conn), nil
}
type closableConn struct {

View File

@@ -26,7 +26,7 @@ import (
)
func TestCloseAll(t *testing.T) {
closed := make(chan struct{})
closed := make(chan struct{}, 50)
dialFn := func(ctx context.Context, network, address string) (net.Conn, error) {
return closeOnlyConn{onClose: func() { closed <- struct{}{} }}, nil
}
@@ -42,10 +42,11 @@ func TestCloseAll(t *testing.T) {
}
}
dialer.CloseAll()
deadline := time.After(time.Second)
for j := 0; j < numConns; j++ {
select {
case <-closed:
case <-time.After(time.Second):
case <-deadline:
t.Fatalf("iteration %d: 1s after CloseAll only %d/%d connections closed", i, j, numConns)
}
}
@@ -59,48 +60,42 @@ func TestCloseAllRace(t *testing.T) {
return closeOnlyConn{onClose: func() { atomic.AddInt64(&conns, -1) }}, nil
})
done := make(chan struct{})
const raceCount = 5000
begin := &sync.WaitGroup{}
begin.Add(1)
wg := &sync.WaitGroup{}
// Close all as fast as we can
wg.Add(1)
go func() {
begin.Wait()
defer wg.Done()
for {
select {
case <-done:
return
default:
dialer.CloseAll()
}
for i := 0; i < raceCount; i++ {
dialer.CloseAll()
}
}()
// Dial as fast as we can
wg.Add(1)
go func() {
begin.Wait()
defer wg.Done()
for {
select {
case <-done:
for i := 0; i < raceCount; i++ {
if _, err := dialer.Dial("", ""); err != nil {
t.Error(err)
return
default:
if _, err := dialer.Dial("", ""); err != nil {
t.Error(err)
return
}
atomic.AddInt64(&conns, 1)
}
atomic.AddInt64(&conns, 1)
}
}()
// Soak to ensure no races
time.Sleep(time.Second)
// Trigger both goroutines as close to the same time as possible
begin.Done()
// Signal completion
close(done)
// Wait for goroutines
wg.Wait()
// Ensure CloseAll ran after all dials
dialer.CloseAll()

View File

@@ -55,7 +55,13 @@ func newQueue(c clock.Clock, metrics queueMetrics, updatePeriod time.Duration) *
metrics: metrics,
unfinishedWorkUpdatePeriod: updatePeriod,
}
go t.updateUnfinishedWorkLoop()
// Don't start the goroutine for a type of noMetrics so we don't consume
// resources unnecessarily
if _, ok := metrics.(noMetrics); !ok {
go t.updateUnfinishedWorkLoop()
}
return t
}