vendor: update kubernetes v1.18.0-beta.1
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
105
vendor/k8s.io/client-go/README.md
generated
vendored
105
vendor/k8s.io/client-go/README.md
generated
vendored
@@ -2,7 +2,8 @@
|
||||
|
||||
Go clients for talking to a [kubernetes](http://kubernetes.io/) cluster.
|
||||
|
||||
We recommend using the `kubernetes-1.x.y` tag matching the current Kubernetes release (`kubernetes-1.15.3` at the time this was written).
|
||||
We recommend using the `v0.x.y` tags for Kubernetes releases >= `v1.17.0` and
|
||||
`kubernetes-1.x.y` tags for Kubernetes releases < `v1.17.0`.
|
||||
See [INSTALL.md](/INSTALL.md) for detailed installation instructions.
|
||||
`go get k8s.io/client-go@master` works, but will fetch `master`, which may be less stable than a tagged release.
|
||||
|
||||
@@ -44,42 +45,31 @@ See [INSTALL.md](/INSTALL.md) for detailed installation instructions.
|
||||
|
||||
### Versioning
|
||||
|
||||
`client-go` follows [semver](http://semver.org/). We will not make
|
||||
backwards-incompatible changes without incrementing the major version number. A
|
||||
change is backwards-incompatible either if it *i)* changes the public interfaces
|
||||
of `client-go`, or *ii)* makes `client-go` incompatible with otherwise supported
|
||||
versions of Kubernetes clusters.
|
||||
- For each `v1.x.y` Kubernetes release, the major version (first digit)
|
||||
would remain `0`.
|
||||
|
||||
Changes that add features in a backwards-compatible way will result in bumping
|
||||
the minor version (second digit) number.
|
||||
|
||||
Bugfixes will result in the patch version (third digit) changing. PRs that are
|
||||
- Bugfixes will result in the patch version (third digit) changing. PRs that are
|
||||
cherry-picked into an older Kubernetes release branch will result in an update
|
||||
to the corresponding branch in `client-go`, with a corresponding new tag
|
||||
changing the patch version.
|
||||
|
||||
A consequence of this is that `client-go` version numbers will be unrelated to
|
||||
Kubernetes version numbers.
|
||||
|
||||
#### Branches and tags.
|
||||
|
||||
We will create a new branch and tag for each increment in the major version number or
|
||||
minor version number. We will create only a new tag for each increment in the patch
|
||||
We will create a new branch and tag for each increment in the minor version
|
||||
number. We will create only a new tag for each increment in the patch
|
||||
version number. See [semver](http://semver.org/) for definitions of major,
|
||||
minor, and patch.
|
||||
|
||||
The master branch will track HEAD in the main Kubernetes repo and
|
||||
accumulate changes. Consider HEAD to have the version `x.(y+1).0-alpha` or
|
||||
`(x+1).0.0-alpha` (depending on whether it has accumulated a breaking change or
|
||||
not), where `x` and `y` are the current major and minor versions.
|
||||
The HEAD of the master branch in client-go will track the HEAD of the master
|
||||
branch in the main Kubernetes repo.
|
||||
|
||||
#### Compatibility: your code <-> client-go
|
||||
|
||||
`client-go` follows [semver](http://semver.org/), so until the major version of
|
||||
client-go gets increased, your code will compile and will continue to work with
|
||||
explicitly supported versions of Kubernetes clusters. You must use a dependency
|
||||
management system and pin a specific major version of `client-go` to get this
|
||||
benefit, as HEAD follows the upstream Kubernetes repo.
|
||||
The `v0.x.y` tags indicate that go APIs may change in incompatible ways in
|
||||
different versions.
|
||||
|
||||
See [INSTALL.md](INSTALL.md) for guidelines on requiring a specific
|
||||
version of client-go.
|
||||
|
||||
#### Compatibility: client-go <-> Kubernetes clusters
|
||||
|
||||
@@ -92,16 +82,12 @@ We will backport bugfixes--but not new features--into older versions of
|
||||
|
||||
#### Compatibility matrix
|
||||
|
||||
| | Kubernetes 1.9 | Kubernetes 1.10 | Kubernetes 1.11 | Kubernetes 1.12 | Kubernetes 1.13 | Kubernetes 1.14 | Kubernetes 1.15 |
|
||||
|---------------------|----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
|
||||
| client-go 6.0 | ✓ | +- | +- | +- | +- | +- | +- |
|
||||
| client-go 7.0 | +- | ✓ | +- | +- | +- | +- | +- |
|
||||
| client-go 8.0 | +- | +- | ✓ | +- | +- | +- | +- |
|
||||
| client-go 9.0 | +- | +- | +- | ✓ | +- | +- | +- |
|
||||
| client-go 10.0 | +- | +- | +- | +- | ✓ | +- | +- |
|
||||
| client-go 11.0 | +- | +- | +- | +- | +- | ✓ | +- |
|
||||
| client-go 12.0 | +- | +- | +- | +- | +- | +- | ✓ |
|
||||
| client-go HEAD | +- | +- | +- | +- | +- | +- | +- |
|
||||
| | Kubernetes 1.15 | Kubernetes 1.16 | Kubernetes 1.17 |
|
||||
|-------------------------------|-----------------|-----------------|-----------------|
|
||||
| `kubernetes-1.15.0` | ✓ | +- | +- |
|
||||
| `kubernetes-1.16.0` | +- | ✓ | +- |
|
||||
| `kubernetes-1.17.0`/`v0.17.0` | +- | +- | ✓ |
|
||||
| `HEAD` | +- | +- | +- |
|
||||
|
||||
Key:
|
||||
|
||||
@@ -122,19 +108,21 @@ between client-go versions.
|
||||
|
||||
| Branch | Canonical source code location | Maintenance status |
|
||||
|----------------|--------------------------------------|-------------------------------|
|
||||
| client-go 1.4 | Kubernetes main repo, 1.4 branch | = - |
|
||||
| client-go 1.5 | Kubernetes main repo, 1.5 branch | = - |
|
||||
| client-go 2.0 | Kubernetes main repo, 1.5 branch | = - |
|
||||
| client-go 3.0 | Kubernetes main repo, 1.6 branch | = - |
|
||||
| client-go 4.0 | Kubernetes main repo, 1.7 branch | = - |
|
||||
| client-go 5.0 | Kubernetes main repo, 1.8 branch | = - |
|
||||
| client-go 6.0 | Kubernetes main repo, 1.9 branch | = - |
|
||||
| client-go 7.0 | Kubernetes main repo, 1.10 branch | = - |
|
||||
| client-go 8.0 | Kubernetes main repo, 1.11 branch | =- |
|
||||
| client-go 9.0 | Kubernetes main repo, 1.12 branch | =- |
|
||||
| client-go 10.0 | Kubernetes main repo, 1.13 branch | ✓ |
|
||||
| client-go 11.0 | Kubernetes main repo, 1.14 branch | ✓ |
|
||||
| client-go 12.0 | Kubernetes main repo, 1.15 branch | ✓ |
|
||||
| `release-1.4` | Kubernetes main repo, 1.4 branch | = - |
|
||||
| `release-1.5` | Kubernetes main repo, 1.5 branch | = - |
|
||||
| `release-2.0` | Kubernetes main repo, 1.5 branch | = - |
|
||||
| `release-3.0` | Kubernetes main repo, 1.6 branch | = - |
|
||||
| `release-4.0` | Kubernetes main repo, 1.7 branch | = - |
|
||||
| `release-5.0` | Kubernetes main repo, 1.8 branch | = - |
|
||||
| `release-6.0` | Kubernetes main repo, 1.9 branch | = - |
|
||||
| `release-7.0` | Kubernetes main repo, 1.10 branch | = - |
|
||||
| `release-8.0` | Kubernetes main repo, 1.11 branch | =- |
|
||||
| `release-9.0` | Kubernetes main repo, 1.12 branch | =- |
|
||||
| `release-10.0` | Kubernetes main repo, 1.13 branch | =- |
|
||||
| `release-11.0` | Kubernetes main repo, 1.14 branch | ✓ |
|
||||
| `release-12.0` | Kubernetes main repo, 1.15 branch | ✓ |
|
||||
| `release-13.0` | Kubernetes main repo, 1.16 branch | ✓ |
|
||||
| `release-14.0` | Kubernetes main repo, 1.17 branch | ✓ |
|
||||
| client-go HEAD | Kubernetes main repo, master branch | ✓ |
|
||||
|
||||
Key:
|
||||
@@ -161,14 +149,19 @@ existing users won't be broken.
|
||||
|
||||
This repository is still a mirror of
|
||||
[k8s.io/kubernetes/staging/src/client-go](https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/client-go),
|
||||
the code development is still done in the staging area. Since Kubernetes 1.8
|
||||
release, when syncing the code from the staging area, we also sync the Kubernetes
|
||||
version tags to client-go, prefixed with "kubernetes-". For example, if you check
|
||||
out the `kubernetes-1.15.3` tag in client-go, the code you get is exactly the
|
||||
same as if you check out the `v1.15.3` tag in Kubernetes, and change directory to
|
||||
`staging/src/k8s.io/client-go`. The purpose is to let users quickly find matching
|
||||
commits among published repos, like
|
||||
[sample-apiserver](https://github.com/kubernetes/sample-apiserver),
|
||||
the code development is still done in the staging area.
|
||||
|
||||
Since Kubernetes `v1.8.0`, when syncing the code from the staging area,
|
||||
we also sync the Kubernetes version tags to client-go, prefixed with
|
||||
`kubernetes-`. From Kubernetes `v1.17.0`, we also create matching semver
|
||||
`v0.x.y` tags for each `v1.x.y` Kubernetes release.
|
||||
|
||||
For example, if you check out the `kubernetes-1.17.0` or the `v0.17.0` tag in
|
||||
client-go, the code you get is exactly the same as if you check out the `v1.17.0`
|
||||
tag in Kubernetes, and change directory to `staging/src/k8s.io/client-go`.
|
||||
|
||||
The purpose is to let users quickly find matching commits among published repos,
|
||||
like [sample-apiserver](https://github.com/kubernetes/sample-apiserver),
|
||||
[apiextension-apiserver](https://github.com/kubernetes/apiextensions-apiserver),
|
||||
etc. The Kubernetes version tag does NOT claim any backwards compatibility
|
||||
guarantees for client-go. Please check the [semantic versions](#versioning) if
|
||||
@@ -179,7 +172,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@kubernetes-1.15.3
|
||||
go get k8s.io/client-go@v0.17.0
|
||||
```
|
||||
|
||||
See [INSTALL.md](/INSTALL.md) for detailed instructions.
|
||||
|
||||
22
vendor/k8s.io/client-go/go.mod
generated
vendored
22
vendor/k8s.io/client-go/go.mod
generated
vendored
@@ -2,7 +2,7 @@
|
||||
|
||||
module k8s.io/client-go
|
||||
|
||||
go 1.12
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.38.0 // indirect
|
||||
@@ -10,34 +10,34 @@ require (
|
||||
github.com/Azure/go-autorest/autorest/adal v0.5.0
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d
|
||||
github.com/gogo/protobuf v1.3.1
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903
|
||||
github.com/golang/protobuf v1.3.2
|
||||
github.com/google/btree v1.0.0 // indirect
|
||||
github.com/google/gofuzz v1.0.0
|
||||
github.com/google/gofuzz v1.1.0
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d
|
||||
github.com/googleapis/gnostic v0.1.0
|
||||
github.com/gophercloud/gophercloud v0.1.0
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7
|
||||
github.com/imdario/mergo v0.3.5
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.4.0
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586
|
||||
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
|
||||
google.golang.org/appengine v1.5.0 // indirect
|
||||
k8s.io/api v0.17.1
|
||||
k8s.io/apimachinery v0.17.1
|
||||
k8s.io/api v0.18.0-beta.1
|
||||
k8s.io/apimachinery v0.18.0-beta.1
|
||||
k8s.io/klog v1.0.0
|
||||
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f
|
||||
sigs.k8s.io/yaml v1.1.0
|
||||
k8s.io/utils v0.0.0-20200117235808-5f6fbceb4c31
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
)
|
||||
|
||||
replace (
|
||||
golang.org/x/sys => golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a // pinned to release-branch.go1.13
|
||||
golang.org/x/tools => golang.org/x/tools v0.0.0-20190821162956-65e3620a7ae7 // pinned to release-branch.go1.13
|
||||
k8s.io/api => k8s.io/api v0.17.1
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.17.1
|
||||
k8s.io/api => k8s.io/api v0.18.0-beta.1
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.18.0-beta.1
|
||||
)
|
||||
|
||||
27
vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go
generated
vendored
27
vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/exec.go
generated
vendored
@@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -42,6 +43,7 @@ import (
|
||||
"k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1"
|
||||
"k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||
"k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/client-go/tools/metrics"
|
||||
"k8s.io/client-go/transport"
|
||||
"k8s.io/client-go/util/connrotation"
|
||||
"k8s.io/klog"
|
||||
@@ -260,6 +262,7 @@ func (a *Authenticator) cert() (*tls.Certificate, error) {
|
||||
func (a *Authenticator) getCreds() (*credentials, error) {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
if a.cachedCreds != nil && !a.credsExpired() {
|
||||
return a.cachedCreds, nil
|
||||
}
|
||||
@@ -267,6 +270,7 @@ func (a *Authenticator) getCreds() (*credentials, error) {
|
||||
if err := a.refreshCredsLocked(nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return a.cachedCreds, nil
|
||||
}
|
||||
|
||||
@@ -355,6 +359,17 @@ func (a *Authenticator) refreshCredsLocked(r *clientauthentication.Response) err
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed parsing client key/certificate: %v", err)
|
||||
}
|
||||
|
||||
// Leaf is initialized to be nil:
|
||||
// https://golang.org/pkg/crypto/tls/#X509KeyPair
|
||||
// Leaf certificate is the first certificate:
|
||||
// https://golang.org/pkg/crypto/tls/#Certificate
|
||||
// Populating leaf is useful for quickly accessing the underlying x509
|
||||
// certificate values.
|
||||
cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed parsing client leaf certificate: %v", err)
|
||||
}
|
||||
newCreds.cert = &cert
|
||||
}
|
||||
|
||||
@@ -362,10 +377,20 @@ func (a *Authenticator) refreshCredsLocked(r *clientauthentication.Response) err
|
||||
a.cachedCreds = newCreds
|
||||
// Only close all connections when TLS cert rotates. Token rotation doesn't
|
||||
// need the extra noise.
|
||||
if len(a.onRotateList) > 0 && oldCreds != nil && !reflect.DeepEqual(oldCreds.cert, a.cachedCreds.cert) {
|
||||
if oldCreds != nil && !reflect.DeepEqual(oldCreds.cert, a.cachedCreds.cert) {
|
||||
// Can be nil if the exec auth plugin only returned token auth.
|
||||
if oldCreds.cert != nil && oldCreds.cert.Leaf != nil {
|
||||
metrics.ClientCertRotationAge.Observe(time.Now().Sub(oldCreds.cert.Leaf.NotBefore))
|
||||
}
|
||||
for _, onRotate := range a.onRotateList {
|
||||
onRotate()
|
||||
}
|
||||
}
|
||||
|
||||
expiry := time.Time{}
|
||||
if a.cachedCreds.cert != nil && a.cachedCreds.cert.Leaf != nil {
|
||||
expiry = a.cachedCreds.cert.Leaf.NotAfter
|
||||
}
|
||||
expirationMetrics.set(a, expiry)
|
||||
return nil
|
||||
}
|
||||
|
||||
60
vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/metrics.go
generated
vendored
Normal file
60
vendor/k8s.io/client-go/plugin/pkg/client/auth/exec/metrics.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package exec
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/client-go/tools/metrics"
|
||||
)
|
||||
|
||||
type certificateExpirationTracker struct {
|
||||
mu sync.RWMutex
|
||||
m map[*Authenticator]time.Time
|
||||
metricSet func(*time.Time)
|
||||
}
|
||||
|
||||
var expirationMetrics = &certificateExpirationTracker{
|
||||
m: map[*Authenticator]time.Time{},
|
||||
metricSet: func(e *time.Time) {
|
||||
metrics.ClientCertExpiry.Set(e)
|
||||
},
|
||||
}
|
||||
|
||||
// set stores the given expiration time and updates the updates the certificate
|
||||
// expiry metric to the earliest expiration time.
|
||||
func (c *certificateExpirationTracker) set(a *Authenticator, t time.Time) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.m[a] = t
|
||||
|
||||
earliest := time.Time{}
|
||||
for _, t := range c.m {
|
||||
if t.IsZero() {
|
||||
continue
|
||||
}
|
||||
if earliest.IsZero() || earliest.After(t) {
|
||||
earliest = t
|
||||
}
|
||||
}
|
||||
if earliest.IsZero() {
|
||||
c.metricSet(nil)
|
||||
} else {
|
||||
c.metricSet(&earliest)
|
||||
}
|
||||
}
|
||||
144
vendor/k8s.io/client-go/rest/request.go
generated
vendored
144
vendor/k8s.io/client-go/rest/request.go
generated
vendored
@@ -30,6 +30,7 @@ import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
@@ -51,6 +52,9 @@ var (
|
||||
// throttled (via the provided rateLimiter) for more than longThrottleLatency will
|
||||
// be logged.
|
||||
longThrottleLatency = 50 * time.Millisecond
|
||||
|
||||
// extraLongThrottleLatency defines the threshold for logging requests at log level 2.
|
||||
extraLongThrottleLatency = 1 * time.Second
|
||||
)
|
||||
|
||||
// HTTPClient is an interface for testing a request object.
|
||||
@@ -61,8 +65,8 @@ type HTTPClient interface {
|
||||
// ResponseWrapper is an interface for getting a response.
|
||||
// The response may be either accessed as a raw data (the whole output is put into memory) or as a stream.
|
||||
type ResponseWrapper interface {
|
||||
DoRaw() ([]byte, error)
|
||||
Stream() (io.ReadCloser, error)
|
||||
DoRaw(context.Context) ([]byte, error)
|
||||
Stream(context.Context) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
// RequestConstructionError is returned when there's an error assembling a request.
|
||||
@@ -104,9 +108,6 @@ type Request struct {
|
||||
// output
|
||||
err error
|
||||
body io.Reader
|
||||
|
||||
// This is only used for per-request timeouts, deadlines, and cancellations.
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// NewRequest creates a new request helper object for accessing runtime.Objects on a server.
|
||||
@@ -438,13 +439,6 @@ func (r *Request) Body(obj interface{}) *Request {
|
||||
return r
|
||||
}
|
||||
|
||||
// Context adds a context to the request. Contexts are only used for
|
||||
// timeouts, deadlines, and cancellations.
|
||||
func (r *Request) Context(ctx context.Context) *Request {
|
||||
r.ctx = ctx
|
||||
return r
|
||||
}
|
||||
|
||||
// URL returns the current working URL.
|
||||
func (r *Request) URL() *url.URL {
|
||||
p := r.pathPrefix
|
||||
@@ -548,29 +542,56 @@ func (r Request) finalURLTemplate() url.URL {
|
||||
return *url
|
||||
}
|
||||
|
||||
func (r *Request) tryThrottle() error {
|
||||
func (r *Request) tryThrottle(ctx context.Context) error {
|
||||
if r.rateLimiter == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
var err error
|
||||
if r.ctx != nil {
|
||||
err = r.rateLimiter.Wait(r.ctx)
|
||||
} else {
|
||||
r.rateLimiter.Accept()
|
||||
}
|
||||
|
||||
if latency := time.Since(now); latency > longThrottleLatency {
|
||||
klog.V(4).Infof("Throttling request took %v, request: %s:%s", latency, r.verb, r.URL().String())
|
||||
err := r.rateLimiter.Wait(ctx)
|
||||
|
||||
latency := time.Since(now)
|
||||
if latency > longThrottleLatency {
|
||||
klog.V(3).Infof("Throttling request took %v, request: %s:%s", latency, r.verb, r.URL().String())
|
||||
}
|
||||
if latency > extraLongThrottleLatency {
|
||||
globalThrottledLogger.Log(2, fmt.Sprintf("Throttling request took %v, request: %s:%s", latency, r.verb, r.URL().String()))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
type throttledLogger struct {
|
||||
logTimeLock sync.RWMutex
|
||||
lastLogTime time.Time
|
||||
minLogInterval time.Duration
|
||||
}
|
||||
|
||||
var globalThrottledLogger = &throttledLogger{
|
||||
minLogInterval: 1 * time.Second,
|
||||
}
|
||||
|
||||
func (b *throttledLogger) Log(level klog.Level, message string) {
|
||||
if bool(klog.V(level)) {
|
||||
if func() bool {
|
||||
b.logTimeLock.RLock()
|
||||
defer b.logTimeLock.RUnlock()
|
||||
return time.Since(b.lastLogTime) > b.minLogInterval
|
||||
}() {
|
||||
b.logTimeLock.Lock()
|
||||
defer b.logTimeLock.Unlock()
|
||||
if time.Since(b.lastLogTime) > b.minLogInterval {
|
||||
klog.V(level).Info(message)
|
||||
b.lastLogTime = time.Now()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Watch attempts to begin watching the requested location.
|
||||
// Returns a watch.Interface, or an error.
|
||||
func (r *Request) Watch() (watch.Interface, error) {
|
||||
func (r *Request) Watch(ctx context.Context) (watch.Interface, error) {
|
||||
// We specifically don't want to rate limit watches, so we
|
||||
// don't use r.rateLimiter here.
|
||||
if r.err != nil {
|
||||
@@ -582,9 +603,7 @@ func (r *Request) Watch() (watch.Interface, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.ctx != nil {
|
||||
req = req.WithContext(r.ctx)
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
req.Header = r.headers
|
||||
client := r.c.Client
|
||||
if client == nil {
|
||||
@@ -659,12 +678,12 @@ func updateURLMetrics(req *Request, resp *http.Response, err error) {
|
||||
// Returns io.ReadCloser which could be used for streaming of the response, or an error
|
||||
// Any non-2xx http status code causes an error. If we get a non-2xx code, we try to convert the body into an APIStatus object.
|
||||
// If we can, we return that as an error. Otherwise, we create an error that lists the http status and the content of the response.
|
||||
func (r *Request) Stream() (io.ReadCloser, error) {
|
||||
func (r *Request) Stream(ctx context.Context) (io.ReadCloser, error) {
|
||||
if r.err != nil {
|
||||
return nil, r.err
|
||||
}
|
||||
|
||||
if err := r.tryThrottle(); err != nil {
|
||||
if err := r.tryThrottle(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -676,9 +695,7 @@ func (r *Request) Stream() (io.ReadCloser, error) {
|
||||
if r.body != nil {
|
||||
req.Body = ioutil.NopCloser(r.body)
|
||||
}
|
||||
if r.ctx != nil {
|
||||
req = req.WithContext(r.ctx)
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
req.Header = r.headers
|
||||
client := r.c.Client
|
||||
if client == nil {
|
||||
@@ -746,7 +763,7 @@ func (r *Request) requestPreflightCheck() error {
|
||||
// received. It handles retry behavior and up front validation of requests. It will invoke
|
||||
// fn at most once. It will return an error if a problem occurred prior to connecting to the
|
||||
// server - the provided function is responsible for handling server errors.
|
||||
func (r *Request) request(fn func(*http.Request, *http.Response)) error {
|
||||
func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Response)) error {
|
||||
//Metrics for total request latency
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
@@ -767,26 +784,30 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
|
||||
client = http.DefaultClient
|
||||
}
|
||||
|
||||
// Throttle the first try before setting up the timeout configured on the
|
||||
// client. We don't want a throttled client to return timeouts to callers
|
||||
// before it makes a single request.
|
||||
if err := r.tryThrottle(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.timeout > 0 {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, r.timeout)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
// Right now we make about ten retry attempts if we get a Retry-After response.
|
||||
maxRetries := 10
|
||||
retries := 0
|
||||
for {
|
||||
|
||||
url := r.URL().String()
|
||||
req, err := http.NewRequest(r.verb, url, r.body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if r.timeout > 0 {
|
||||
if r.ctx == nil {
|
||||
r.ctx = context.Background()
|
||||
}
|
||||
var cancelFn context.CancelFunc
|
||||
r.ctx, cancelFn = context.WithTimeout(r.ctx, r.timeout)
|
||||
defer cancelFn()
|
||||
}
|
||||
if r.ctx != nil {
|
||||
req = req.WithContext(r.ctx)
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
req.Header = r.headers
|
||||
|
||||
r.backoff.Sleep(r.backoff.CalculateBackoff(r.URL()))
|
||||
@@ -794,7 +815,7 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
|
||||
// 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(); err != nil {
|
||||
if err := r.tryThrottle(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -806,19 +827,24 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
|
||||
r.backoff.UpdateBackoff(r.URL(), err, resp.StatusCode)
|
||||
}
|
||||
if err != nil {
|
||||
// "Connection reset by peer" is usually a transient error.
|
||||
// "Connection reset by peer" or "apiserver is shutting down" are usually a transient errors.
|
||||
// Thus in case of "GET" operations, we simply retry it.
|
||||
// We are not automatically retrying "write" operations, as
|
||||
// they are not idempotent.
|
||||
if !net.IsConnectionReset(err) || r.verb != "GET" {
|
||||
if r.verb != "GET" {
|
||||
return err
|
||||
}
|
||||
// For the purpose of retry, we set the artificial "retry-after" response.
|
||||
// TODO: Should we clean the original response if it exists?
|
||||
resp = &http.Response{
|
||||
StatusCode: http.StatusInternalServerError,
|
||||
Header: http.Header{"Retry-After": []string{"1"}},
|
||||
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
|
||||
// For connection errors and apiserver shutdown errors retry.
|
||||
if net.IsConnectionReset(err) {
|
||||
// For the purpose of retry, we set the artificial "retry-after" response.
|
||||
// TODO: Should we clean the original response if it exists?
|
||||
resp = &http.Response{
|
||||
StatusCode: http.StatusInternalServerError,
|
||||
Header: http.Header{"Retry-After": []string{"1"}},
|
||||
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,13 +890,9 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
|
||||
// Error type:
|
||||
// * If the server responds with a status: *errors.StatusError or *errors.UnexpectedObjectError
|
||||
// * http.Client.Do errors are returned directly.
|
||||
func (r *Request) Do() Result {
|
||||
if err := r.tryThrottle(); err != nil {
|
||||
return Result{err: err}
|
||||
}
|
||||
|
||||
func (r *Request) Do(ctx context.Context) Result {
|
||||
var result Result
|
||||
err := r.request(func(req *http.Request, resp *http.Response) {
|
||||
err := r.request(ctx, func(req *http.Request, resp *http.Response) {
|
||||
result = r.transformResponse(resp, req)
|
||||
})
|
||||
if err != nil {
|
||||
@@ -880,13 +902,9 @@ func (r *Request) Do() Result {
|
||||
}
|
||||
|
||||
// DoRaw executes the request but does not process the response body.
|
||||
func (r *Request) DoRaw() ([]byte, error) {
|
||||
if err := r.tryThrottle(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (r *Request) DoRaw(ctx context.Context) ([]byte, error) {
|
||||
var result Result
|
||||
err := r.request(func(req *http.Request, resp *http.Response) {
|
||||
err := r.request(ctx, func(req *http.Request, resp *http.Response) {
|
||||
result.body, result.err = ioutil.ReadAll(resp.Body)
|
||||
glogBody("Response Body", result.body)
|
||||
if resp.StatusCode < http.StatusOK || resp.StatusCode > http.StatusPartialContent {
|
||||
|
||||
46
vendor/k8s.io/client-go/tools/metrics/metrics.go
generated
vendored
46
vendor/k8s.io/client-go/tools/metrics/metrics.go
generated
vendored
@@ -26,6 +26,16 @@ import (
|
||||
|
||||
var registerMetrics sync.Once
|
||||
|
||||
// DurationMetric is a measurement of some amount of time.
|
||||
type DurationMetric interface {
|
||||
Observe(duration time.Duration)
|
||||
}
|
||||
|
||||
// ExpiryMetric sets some time of expiry. If nil, assume not relevant.
|
||||
type ExpiryMetric interface {
|
||||
Set(expiry *time.Time)
|
||||
}
|
||||
|
||||
// LatencyMetric observes client latency partitioned by verb and url.
|
||||
type LatencyMetric interface {
|
||||
Observe(verb string, u url.URL, latency time.Duration)
|
||||
@@ -37,21 +47,51 @@ type ResultMetric interface {
|
||||
}
|
||||
|
||||
var (
|
||||
// ClientCertExpiry is the expiry time of a client certificate
|
||||
ClientCertExpiry ExpiryMetric = noopExpiry{}
|
||||
// ClientCertRotationAge is the age of a certificate that has just been rotated.
|
||||
ClientCertRotationAge DurationMetric = noopDuration{}
|
||||
// RequestLatency is the latency metric that rest clients will update.
|
||||
RequestLatency LatencyMetric = noopLatency{}
|
||||
// RequestResult is the result metric that rest clients will update.
|
||||
RequestResult ResultMetric = noopResult{}
|
||||
)
|
||||
|
||||
// RegisterOpts contains all the metrics to register. Metrics may be nil.
|
||||
type RegisterOpts struct {
|
||||
ClientCertExpiry ExpiryMetric
|
||||
ClientCertRotationAge DurationMetric
|
||||
RequestLatency LatencyMetric
|
||||
RequestResult ResultMetric
|
||||
}
|
||||
|
||||
// Register registers metrics for the rest client to use. This can
|
||||
// only be called once.
|
||||
func Register(lm LatencyMetric, rm ResultMetric) {
|
||||
func Register(opts RegisterOpts) {
|
||||
registerMetrics.Do(func() {
|
||||
RequestLatency = lm
|
||||
RequestResult = rm
|
||||
if opts.ClientCertExpiry != nil {
|
||||
ClientCertExpiry = opts.ClientCertExpiry
|
||||
}
|
||||
if opts.ClientCertRotationAge != nil {
|
||||
ClientCertRotationAge = opts.ClientCertRotationAge
|
||||
}
|
||||
if opts.RequestLatency != nil {
|
||||
RequestLatency = opts.RequestLatency
|
||||
}
|
||||
if opts.RequestResult != nil {
|
||||
RequestResult = opts.RequestResult
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type noopDuration struct{}
|
||||
|
||||
func (noopDuration) Observe(time.Duration) {}
|
||||
|
||||
type noopExpiry struct{}
|
||||
|
||||
func (noopExpiry) Set(*time.Time) {}
|
||||
|
||||
type noopLatency struct{}
|
||||
|
||||
func (noopLatency) Observe(string, url.URL, time.Duration) {}
|
||||
|
||||
10
vendor/k8s.io/client-go/util/connrotation/connrotation.go
generated
vendored
10
vendor/k8s.io/client-go/util/connrotation/connrotation.go
generated
vendored
@@ -77,11 +77,6 @@ func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.
|
||||
|
||||
closable := &closableConn{Conn: conn}
|
||||
|
||||
// Start tracking the connection
|
||||
d.mu.Lock()
|
||||
d.conns[closable] = struct{}{}
|
||||
d.mu.Unlock()
|
||||
|
||||
// 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.
|
||||
@@ -91,6 +86,11 @@ func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.
|
||||
d.mu.Unlock()
|
||||
}
|
||||
|
||||
// Start tracking the connection
|
||||
d.mu.Lock()
|
||||
d.conns[closable] = struct{}{}
|
||||
d.mu.Unlock()
|
||||
|
||||
return closable, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user