summaryrefslogtreecommitdiff
path: root/vendor/k8s.io/apimachinery/pkg/util
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/k8s.io/apimachinery/pkg/util')
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/clock/clock.go18
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/errors/errors.go2
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/framer/framer.go3
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection.go50
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go49
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade.go17
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto2
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go42
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/intstr/intstr.go70
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/json/json.go33
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/net/http.go51
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/net/port_range.go2
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go4
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/validation/field/path.go3
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/validation/validation.go6
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/yaml/decoder.go31
16 files changed, 329 insertions, 54 deletions
diff --git a/vendor/k8s.io/apimachinery/pkg/util/clock/clock.go b/vendor/k8s.io/apimachinery/pkg/util/clock/clock.go
index 6cf13d83d..3e1e2517b 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/clock/clock.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/clock/clock.go
@@ -348,7 +348,13 @@ func (f *fakeTimer) Stop() bool {
// Reset conditionally updates the firing time of the timer. If the
// timer has neither fired nor been stopped then this call resets the
// timer to the fake clock's "now" + d and returns true, otherwise
-// this call returns false. This is like time.Timer::Reset.
+// it creates a new waiter, adds it to the clock, and returns true.
+//
+// It is not possible to return false, because a fake timer can be reset
+// from any state (waiting to fire, already fired, and stopped).
+//
+// See the GoDoc for time.Timer::Reset for more context on why
+// the return value of Reset() is not useful.
func (f *fakeTimer) Reset(d time.Duration) bool {
f.fakeClock.lock.Lock()
defer f.fakeClock.lock.Unlock()
@@ -360,7 +366,15 @@ func (f *fakeTimer) Reset(d time.Duration) bool {
return true
}
}
- return false
+ // No existing waiter, timer has already fired or been reset.
+ // We should still enable Reset() to succeed by creating a
+ // new waiter and adding it to the clock's waiters.
+ newWaiter := fakeClockWaiter{
+ targetTime: f.fakeClock.time.Add(d),
+ destChan: seekChan,
+ }
+ f.fakeClock.waiters = append(f.fakeClock.waiters, newWaiter)
+ return true
}
// Ticker defines the Ticker interface
diff --git a/vendor/k8s.io/apimachinery/pkg/util/errors/errors.go b/vendor/k8s.io/apimachinery/pkg/util/errors/errors.go
index 5bafc218e..1f5a04fd4 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/errors/errors.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/errors/errors.go
@@ -163,7 +163,7 @@ func matchesError(err error, fns ...Matcher) bool {
// filterErrors returns any errors (or nested errors, if the list contains
// nested Errors) for which all fns return false. If no errors
-// remain a nil list is returned. The resulting silec will have all
+// remain a nil list is returned. The resulting slice will have all
// nested slices flattened as a side effect.
func filterErrors(list []error, fns ...Matcher) []error {
result := []error{}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/framer/framer.go b/vendor/k8s.io/apimachinery/pkg/util/framer/framer.go
index 066680f44..45aa74bf5 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/framer/framer.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/framer/framer.go
@@ -132,12 +132,14 @@ func (r *jsonFrameReader) Read(data []byte) (int, error) {
// Return whatever remaining data exists from an in progress frame
if n := len(r.remaining); n > 0 {
if n <= len(data) {
+ //lint:ignore SA4006,SA4010 underlying array of data is modified here.
data = append(data[0:0], r.remaining...)
r.remaining = nil
return n, nil
}
n = len(data)
+ //lint:ignore SA4006,SA4010 underlying array of data is modified here.
data = append(data[0:0], r.remaining[:n]...)
r.remaining = r.remaining[n:]
return n, io.ErrShortBuffer
@@ -155,6 +157,7 @@ func (r *jsonFrameReader) Read(data []byte) (int, error) {
// and set m to it, which means we need to copy the partial result back into data and preserve
// the remaining result for subsequent reads.
if len(m) > n {
+ //lint:ignore SA4006,SA4010 underlying array of data is modified here.
data = append(data[0:0], m[:n]...)
r.remaining = m[n:]
return n, io.ErrShortBuffer
diff --git a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection.go b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection.go
index 7a6881250..336b4908b 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/connection.go
@@ -34,38 +34,62 @@ type connection struct {
streams []httpstream.Stream
streamLock sync.Mutex
newStreamHandler httpstream.NewStreamHandler
+ ping func() (time.Duration, error)
}
// NewClientConnection creates a new SPDY client connection.
func NewClientConnection(conn net.Conn) (httpstream.Connection, error) {
+ return NewClientConnectionWithPings(conn, 0)
+}
+
+// NewClientConnectionWithPings creates a new SPDY client connection.
+//
+// If pingPeriod is non-zero, a background goroutine will send periodic Ping
+// frames to the server. Use this to keep idle connections through certain load
+// balancers alive longer.
+func NewClientConnectionWithPings(conn net.Conn, pingPeriod time.Duration) (httpstream.Connection, error) {
spdyConn, err := spdystream.NewConnection(conn, false)
if err != nil {
defer conn.Close()
return nil, err
}
- return newConnection(spdyConn, httpstream.NoOpNewStreamHandler), nil
+ return newConnection(spdyConn, httpstream.NoOpNewStreamHandler, pingPeriod, spdyConn.Ping), nil
}
// NewServerConnection creates a new SPDY server connection. newStreamHandler
// will be invoked when the server receives a newly created stream from the
// client.
func NewServerConnection(conn net.Conn, newStreamHandler httpstream.NewStreamHandler) (httpstream.Connection, error) {
+ return NewServerConnectionWithPings(conn, newStreamHandler, 0)
+}
+
+// NewServerConnectionWithPings creates a new SPDY server connection.
+// newStreamHandler will be invoked when the server receives a newly created
+// stream from the client.
+//
+// If pingPeriod is non-zero, a background goroutine will send periodic Ping
+// frames to the server. Use this to keep idle connections through certain load
+// balancers alive longer.
+func NewServerConnectionWithPings(conn net.Conn, newStreamHandler httpstream.NewStreamHandler, pingPeriod time.Duration) (httpstream.Connection, error) {
spdyConn, err := spdystream.NewConnection(conn, true)
if err != nil {
defer conn.Close()
return nil, err
}
- return newConnection(spdyConn, newStreamHandler), nil
+ return newConnection(spdyConn, newStreamHandler, pingPeriod, spdyConn.Ping), nil
}
// newConnection returns a new connection wrapping conn. newStreamHandler
// will be invoked when the server receives a newly created stream from the
// client.
-func newConnection(conn *spdystream.Connection, newStreamHandler httpstream.NewStreamHandler) httpstream.Connection {
- c := &connection{conn: conn, newStreamHandler: newStreamHandler}
+func newConnection(conn *spdystream.Connection, newStreamHandler httpstream.NewStreamHandler, pingPeriod time.Duration, pingFn func() (time.Duration, error)) httpstream.Connection {
+ c := &connection{conn: conn, newStreamHandler: newStreamHandler, ping: pingFn}
go conn.Serve(c.newSpdyStream)
+ if pingPeriod > 0 && pingFn != nil {
+ go c.sendPings(pingPeriod)
+ }
return c
}
@@ -143,3 +167,21 @@ func (c *connection) newSpdyStream(stream *spdystream.Stream) {
func (c *connection) SetIdleTimeout(timeout time.Duration) {
c.conn.SetIdleTimeout(timeout)
}
+
+func (c *connection) sendPings(period time.Duration) {
+ t := time.NewTicker(period)
+ defer t.Stop()
+ for {
+ select {
+ case <-c.conn.CloseChan():
+ return
+ case <-t.C:
+ }
+ if _, err := c.ping(); err != nil {
+ klog.V(3).Infof("SPDY Ping failed: %v", err)
+ // Continue, in case this is a transient failure.
+ // c.conn.CloseChan above will tell us when the connection is
+ // actually closed.
+ }
+ }
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go
index 6309fbc26..4cb1cfadc 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/roundtripper.go
@@ -30,6 +30,7 @@ import (
"net/http/httputil"
"net/url"
"strings"
+ "time"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -70,6 +71,9 @@ type SpdyRoundTripper struct {
// requireSameHostRedirects restricts redirect following to only follow redirects to the same host
// as the original request.
requireSameHostRedirects bool
+ // pingPeriod is a period for sending Ping frames over established
+ // connections.
+ pingPeriod time.Duration
}
var _ utilnet.TLSClientConfigHolder = &SpdyRoundTripper{}
@@ -79,20 +83,53 @@ var _ utilnet.Dialer = &SpdyRoundTripper{}
// NewRoundTripper creates a new SpdyRoundTripper that will use the specified
// tlsConfig.
func NewRoundTripper(tlsConfig *tls.Config, followRedirects, requireSameHostRedirects bool) *SpdyRoundTripper {
- return NewRoundTripperWithProxy(tlsConfig, followRedirects, requireSameHostRedirects, utilnet.NewProxierWithNoProxyCIDR(http.ProxyFromEnvironment))
+ return NewRoundTripperWithConfig(RoundTripperConfig{
+ TLS: tlsConfig,
+ FollowRedirects: followRedirects,
+ RequireSameHostRedirects: requireSameHostRedirects,
+ })
}
// NewRoundTripperWithProxy creates a new SpdyRoundTripper that will use the
// specified tlsConfig and proxy func.
func NewRoundTripperWithProxy(tlsConfig *tls.Config, followRedirects, requireSameHostRedirects bool, proxier func(*http.Request) (*url.URL, error)) *SpdyRoundTripper {
+ return NewRoundTripperWithConfig(RoundTripperConfig{
+ TLS: tlsConfig,
+ FollowRedirects: followRedirects,
+ RequireSameHostRedirects: requireSameHostRedirects,
+ Proxier: proxier,
+ })
+}
+
+// NewRoundTripperWithProxy creates a new SpdyRoundTripper with the specified
+// configuration.
+func NewRoundTripperWithConfig(cfg RoundTripperConfig) *SpdyRoundTripper {
+ if cfg.Proxier == nil {
+ cfg.Proxier = utilnet.NewProxierWithNoProxyCIDR(http.ProxyFromEnvironment)
+ }
return &SpdyRoundTripper{
- tlsConfig: tlsConfig,
- followRedirects: followRedirects,
- requireSameHostRedirects: requireSameHostRedirects,
- proxier: proxier,
+ tlsConfig: cfg.TLS,
+ followRedirects: cfg.FollowRedirects,
+ requireSameHostRedirects: cfg.RequireSameHostRedirects,
+ proxier: cfg.Proxier,
+ pingPeriod: cfg.PingPeriod,
}
}
+// RoundTripperConfig is a set of options for an SpdyRoundTripper.
+type RoundTripperConfig struct {
+ // TLS configuration used by the round tripper.
+ TLS *tls.Config
+ // Proxier is a proxy function invoked on each request. Optional.
+ Proxier func(*http.Request) (*url.URL, error)
+ // PingPeriod is a period for sending SPDY Pings on the connection.
+ // Optional.
+ PingPeriod time.Duration
+
+ FollowRedirects bool
+ RequireSameHostRedirects bool
+}
+
// TLSClientConfig implements pkg/util/net.TLSClientConfigHolder for proper TLS checking during
// proxying with a spdy roundtripper.
func (s *SpdyRoundTripper) TLSClientConfig() *tls.Config {
@@ -316,7 +353,7 @@ func (s *SpdyRoundTripper) NewConnection(resp *http.Response) (httpstream.Connec
return nil, fmt.Errorf("unable to upgrade connection: %s", responseError)
}
- return NewClientConnection(s.conn)
+ return NewClientConnectionWithPings(s.conn, s.pingPeriod)
}
// statusScheme is private scheme for the decoding here until someone fixes the TODO in NewConnection
diff --git a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade.go b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade.go
index 045d214d2..f17eb09e9 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/httpstream/spdy/upgrade.go
@@ -24,6 +24,7 @@ import (
"net/http"
"strings"
"sync/atomic"
+ "time"
"k8s.io/apimachinery/pkg/util/httpstream"
"k8s.io/apimachinery/pkg/util/runtime"
@@ -34,6 +35,7 @@ const HeaderSpdy31 = "SPDY/3.1"
// responseUpgrader knows how to upgrade HTTP responses. It
// implements the httpstream.ResponseUpgrader interface.
type responseUpgrader struct {
+ pingPeriod time.Duration
}
// connWrapper is used to wrap a hijacked connection and its bufio.Reader. All
@@ -64,7 +66,18 @@ func (w *connWrapper) Close() error {
// capable of upgrading HTTP responses using SPDY/3.1 via the
// spdystream package.
func NewResponseUpgrader() httpstream.ResponseUpgrader {
- return responseUpgrader{}
+ return NewResponseUpgraderWithPings(0)
+}
+
+// NewResponseUpgraderWithPings returns a new httpstream.ResponseUpgrader that
+// is capable of upgrading HTTP responses using SPDY/3.1 via the spdystream
+// package.
+//
+// If pingPeriod is non-zero, for each incoming connection a background
+// goroutine will send periodic Ping frames to the server. Use this to keep
+// idle connections through certain load balancers alive longer.
+func NewResponseUpgraderWithPings(pingPeriod time.Duration) httpstream.ResponseUpgrader {
+ return responseUpgrader{pingPeriod: pingPeriod}
}
// UpgradeResponse upgrades an HTTP response to one that supports multiplexed
@@ -97,7 +110,7 @@ func (u responseUpgrader) UpgradeResponse(w http.ResponseWriter, req *http.Reque
}
connWithBuf := &connWrapper{Conn: conn, bufReader: bufrw.Reader}
- spdyConn, err := NewServerConnection(connWithBuf, newStreamHandler)
+ spdyConn, err := NewServerConnectionWithPings(connWithBuf, newStreamHandler, u.pingPeriod)
if err != nil {
runtime.HandleError(fmt.Errorf("unable to upgrade: error creating SPDY server connection: %v", err))
return nil
diff --git a/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto b/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto
index e79fb9e57..a76f79851 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto
+++ b/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto
@@ -17,7 +17,7 @@ limitations under the License.
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
-syntax = 'proto2';
+syntax = "proto2";
package k8s.io.apimachinery.pkg.util.intstr;
diff --git a/vendor/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go b/vendor/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go
new file mode 100644
index 000000000..2501d5516
--- /dev/null
+++ b/vendor/k8s.io/apimachinery/pkg/util/intstr/instr_fuzz.go
@@ -0,0 +1,42 @@
+// +build !notest
+
+/*
+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 intstr
+
+import (
+ fuzz "github.com/google/gofuzz"
+)
+
+// Fuzz satisfies fuzz.Interface
+func (intstr *IntOrString) Fuzz(c fuzz.Continue) {
+ if intstr == nil {
+ return
+ }
+ if c.RandBool() {
+ intstr.Type = Int
+ c.Fuzz(&intstr.IntVal)
+ intstr.StrVal = ""
+ } else {
+ intstr.Type = String
+ intstr.IntVal = 0
+ c.Fuzz(&intstr.StrVal)
+ }
+}
+
+// ensure IntOrString implements fuzz.Interface
+var _ fuzz.Interface = &IntOrString{}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/intstr/intstr.go b/vendor/k8s.io/apimachinery/pkg/util/intstr/intstr.go
index 6576def82..c0e8927fe 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/intstr/intstr.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/intstr/intstr.go
@@ -25,7 +25,6 @@ import (
"strconv"
"strings"
- "github.com/google/gofuzz"
"k8s.io/klog/v2"
)
@@ -90,6 +89,9 @@ func (intstr *IntOrString) UnmarshalJSON(value []byte) error {
// String returns the string value, or the Itoa of the int value.
func (intstr *IntOrString) String() string {
+ if intstr == nil {
+ return "<nil>"
+ }
if intstr.Type == String {
return intstr.StrVal
}
@@ -129,21 +131,6 @@ func (IntOrString) OpenAPISchemaType() []string { return []string{"string"} }
// the OpenAPI spec of this type.
func (IntOrString) OpenAPISchemaFormat() string { return "int-or-string" }
-func (intstr *IntOrString) Fuzz(c fuzz.Continue) {
- if intstr == nil {
- return
- }
- if c.RandBool() {
- intstr.Type = Int
- c.Fuzz(&intstr.IntVal)
- intstr.StrVal = ""
- } else {
- intstr.Type = String
- intstr.IntVal = 0
- c.Fuzz(&intstr.StrVal)
- }
-}
-
func ValueOrDefault(intOrPercent *IntOrString, defaultValue IntOrString) *IntOrString {
if intOrPercent == nil {
return &defaultValue
@@ -151,6 +138,33 @@ func ValueOrDefault(intOrPercent *IntOrString, defaultValue IntOrString) *IntOrS
return intOrPercent
}
+// GetScaledValueFromIntOrPercent is meant to replace GetValueFromIntOrPercent.
+// This method returns a scaled value from an IntOrString type. If the IntOrString
+// is a percentage string value it's treated as a percentage and scaled appropriately
+// in accordance to the total, if it's an int value it's treated as a a simple value and
+// if it is a string value which is either non-numeric or numeric but lacking a trailing '%' it returns an error.
+func GetScaledValueFromIntOrPercent(intOrPercent *IntOrString, total int, roundUp bool) (int, error) {
+ if intOrPercent == nil {
+ return 0, errors.New("nil value for IntOrString")
+ }
+ value, isPercent, err := getIntOrPercentValueSafely(intOrPercent)
+ if err != nil {
+ return 0, fmt.Errorf("invalid value for IntOrString: %v", err)
+ }
+ if isPercent {
+ if roundUp {
+ value = int(math.Ceil(float64(value) * (float64(total)) / 100))
+ } else {
+ value = int(math.Floor(float64(value) * (float64(total)) / 100))
+ }
+ }
+ return value, nil
+}
+
+// GetValueFromIntOrPercent was deprecated in favor of
+// GetScaledValueFromIntOrPercent. This method was treating all int as a numeric value and all
+// strings with or without a percent symbol as a percentage value.
+// Deprecated
func GetValueFromIntOrPercent(intOrPercent *IntOrString, total int, roundUp bool) (int, error) {
if intOrPercent == nil {
return 0, errors.New("nil value for IntOrString")
@@ -169,6 +183,8 @@ func GetValueFromIntOrPercent(intOrPercent *IntOrString, total int, roundUp bool
return value, nil
}
+// getIntOrPercentValue is a legacy function and only meant to be called by GetValueFromIntOrPercent
+// For a more correct implementation call getIntOrPercentSafely
func getIntOrPercentValue(intOrStr *IntOrString) (int, bool, error) {
switch intOrStr.Type {
case Int:
@@ -183,3 +199,25 @@ func getIntOrPercentValue(intOrStr *IntOrString) (int, bool, error) {
}
return 0, false, fmt.Errorf("invalid type: neither int nor percentage")
}
+
+func getIntOrPercentValueSafely(intOrStr *IntOrString) (int, bool, error) {
+ switch intOrStr.Type {
+ case Int:
+ return intOrStr.IntValue(), false, nil
+ case String:
+ isPercent := false
+ s := intOrStr.StrVal
+ if strings.HasSuffix(s, "%") {
+ isPercent = true
+ s = strings.TrimSuffix(intOrStr.StrVal, "%")
+ } else {
+ return 0, false, fmt.Errorf("invalid type: string is not a percentage")
+ }
+ v, err := strconv.Atoi(s)
+ if err != nil {
+ return 0, false, fmt.Errorf("invalid value %q: %v", intOrStr.StrVal, err)
+ }
+ return int(v), isPercent, nil
+ }
+ return 0, false, fmt.Errorf("invalid type: neither int nor percentage")
+}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/json/json.go b/vendor/k8s.io/apimachinery/pkg/util/json/json.go
index 204834883..778e58f70 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/json/json.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/json/json.go
@@ -39,7 +39,8 @@ func Marshal(v interface{}) ([]byte, error) {
const maxDepth = 10000
// Unmarshal unmarshals the given data
-// If v is a *map[string]interface{}, numbers are converted to int64 or float64
+// If v is a *map[string]interface{}, *[]interface{}, or *interface{} numbers
+// are converted to int64 or float64
func Unmarshal(data []byte, v interface{}) error {
switch v := v.(type) {
case *map[string]interface{}:
@@ -52,7 +53,7 @@ func Unmarshal(data []byte, v interface{}) error {
return err
}
// If the decode succeeds, post-process the map to convert json.Number objects to int64 or float64
- return convertMapNumbers(*v, 0)
+ return ConvertMapNumbers(*v, 0)
case *[]interface{}:
// Build a decoder from the given data
@@ -64,7 +65,7 @@ func Unmarshal(data []byte, v interface{}) error {
return err
}
// If the decode succeeds, post-process the map to convert json.Number objects to int64 or float64
- return convertSliceNumbers(*v, 0)
+ return ConvertSliceNumbers(*v, 0)
case *interface{}:
// Build a decoder from the given data
@@ -76,29 +77,31 @@ func Unmarshal(data []byte, v interface{}) error {
return err
}
// If the decode succeeds, post-process the map to convert json.Number objects to int64 or float64
- return convertInterfaceNumbers(v, 0)
+ return ConvertInterfaceNumbers(v, 0)
default:
return json.Unmarshal(data, v)
}
}
-func convertInterfaceNumbers(v *interface{}, depth int) error {
+// ConvertInterfaceNumbers converts any json.Number values to int64 or float64.
+// Values which are map[string]interface{} or []interface{} are recursively visited
+func ConvertInterfaceNumbers(v *interface{}, depth int) error {
var err error
switch v2 := (*v).(type) {
case json.Number:
*v, err = convertNumber(v2)
case map[string]interface{}:
- err = convertMapNumbers(v2, depth+1)
+ err = ConvertMapNumbers(v2, depth+1)
case []interface{}:
- err = convertSliceNumbers(v2, depth+1)
+ err = ConvertSliceNumbers(v2, depth+1)
}
return err
}
-// convertMapNumbers traverses the map, converting any json.Number values to int64 or float64.
+// ConvertMapNumbers traverses the map, converting any json.Number values to int64 or float64.
// values which are map[string]interface{} or []interface{} are recursively visited
-func convertMapNumbers(m map[string]interface{}, depth int) error {
+func ConvertMapNumbers(m map[string]interface{}, depth int) error {
if depth > maxDepth {
return fmt.Errorf("exceeded max depth of %d", maxDepth)
}
@@ -109,9 +112,9 @@ func convertMapNumbers(m map[string]interface{}, depth int) error {
case json.Number:
m[k], err = convertNumber(v)
case map[string]interface{}:
- err = convertMapNumbers(v, depth+1)
+ err = ConvertMapNumbers(v, depth+1)
case []interface{}:
- err = convertSliceNumbers(v, depth+1)
+ err = ConvertSliceNumbers(v, depth+1)
}
if err != nil {
return err
@@ -120,9 +123,9 @@ func convertMapNumbers(m map[string]interface{}, depth int) error {
return nil
}
-// convertSliceNumbers traverses the slice, converting any json.Number values to int64 or float64.
+// ConvertSliceNumbers traverses the slice, converting any json.Number values to int64 or float64.
// values which are map[string]interface{} or []interface{} are recursively visited
-func convertSliceNumbers(s []interface{}, depth int) error {
+func ConvertSliceNumbers(s []interface{}, depth int) error {
if depth > maxDepth {
return fmt.Errorf("exceeded max depth of %d", maxDepth)
}
@@ -133,9 +136,9 @@ func convertSliceNumbers(s []interface{}, depth int) error {
case json.Number:
s[i], err = convertNumber(v)
case map[string]interface{}:
- err = convertMapNumbers(v, depth+1)
+ err = ConvertMapNumbers(v, depth+1)
case []interface{}:
- err = convertSliceNumbers(v, depth+1)
+ err = ConvertSliceNumbers(v, depth+1)
}
if err != nil {
return err
diff --git a/vendor/k8s.io/apimachinery/pkg/util/net/http.go b/vendor/k8s.io/apimachinery/pkg/util/net/http.go
index 945886c43..ba63d02df 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/net/http.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/net/http.go
@@ -33,6 +33,7 @@ import (
"regexp"
"strconv"
"strings"
+ "time"
"unicode"
"unicode/utf8"
@@ -132,13 +133,61 @@ func SetTransportDefaults(t *http.Transport) *http.Transport {
if s := os.Getenv("DISABLE_HTTP2"); len(s) > 0 {
klog.Infof("HTTP2 has been explicitly disabled")
} else if allowsHTTP2(t) {
- if err := http2.ConfigureTransport(t); err != nil {
+ if err := configureHTTP2Transport(t); err != nil {
klog.Warningf("Transport failed http2 configuration: %v", err)
}
}
return t
}
+func readIdleTimeoutSeconds() int {
+ ret := 30
+ // User can set the readIdleTimeout to 0 to disable the HTTP/2
+ // connection health check.
+ if s := os.Getenv("HTTP2_READ_IDLE_TIMEOUT_SECONDS"); len(s) > 0 {
+ i, err := strconv.Atoi(s)
+ if err != nil {
+ klog.Warningf("Illegal HTTP2_READ_IDLE_TIMEOUT_SECONDS(%q): %v."+
+ " Default value %d is used", s, err, ret)
+ return ret
+ }
+ ret = i
+ }
+ return ret
+}
+
+func pingTimeoutSeconds() int {
+ ret := 15
+ if s := os.Getenv("HTTP2_PING_TIMEOUT_SECONDS"); len(s) > 0 {
+ i, err := strconv.Atoi(s)
+ if err != nil {
+ klog.Warningf("Illegal HTTP2_PING_TIMEOUT_SECONDS(%q): %v."+
+ " Default value %d is used", s, err, ret)
+ return ret
+ }
+ ret = i
+ }
+ return ret
+}
+
+func configureHTTP2Transport(t *http.Transport) error {
+ t2, err := http2.ConfigureTransports(t)
+ if err != nil {
+ return err
+ }
+ // The following enables the HTTP/2 connection health check added in
+ // https://github.com/golang/net/pull/55. The health check detects and
+ // closes broken transport layer connections. Without the health check,
+ // a broken connection can linger too long, e.g., a broken TCP
+ // connection will be closed by the Linux kernel after 13 to 30 minutes
+ // by default, which caused
+ // https://github.com/kubernetes/client-go/issues/374 and
+ // https://github.com/kubernetes/kubernetes/issues/87615.
+ t2.ReadIdleTimeout = time.Duration(readIdleTimeoutSeconds()) * time.Second
+ t2.PingTimeout = time.Duration(pingTimeoutSeconds()) * time.Second
+ return nil
+}
+
func allowsHTTP2(t *http.Transport) bool {
if t.TLSClientConfig == nil || len(t.TLSClientConfig.NextProtos) == 0 {
// the transport expressed no NextProto preference, allow
diff --git a/vendor/k8s.io/apimachinery/pkg/util/net/port_range.go b/vendor/k8s.io/apimachinery/pkg/util/net/port_range.go
index 7b6eca893..42ecffcca 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/net/port_range.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/net/port_range.go
@@ -130,7 +130,7 @@ func (*PortRange) Type() string {
}
// ParsePortRange parses a string of the form "min-max", inclusive at both
-// ends, and initializs a new PortRange from it.
+// ends, and initializes a new PortRange from it.
func ParsePortRange(value string) (*PortRange, error) {
pr := &PortRange{}
err := pr.Set(value)
diff --git a/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go b/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go
index e8a9f609f..035c52811 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/runtime/runtime.go
@@ -79,7 +79,7 @@ func logPanic(r interface{}) {
}
}
-// ErrorHandlers is a list of functions which will be invoked when an unreturnable
+// ErrorHandlers is a list of functions which will be invoked when a nonreturnable
// error occurs.
// TODO(lavalamp): for testability, this and the below HandleError function
// should be packaged up into a testable and reusable object.
@@ -165,7 +165,7 @@ func RecoverFromPanic(err *error) {
}
}
-// Must panics on non-nil errors. Useful to handling programmer level errors.
+// Must panics on non-nil errors. Useful to handling programmer level errors.
func Must(err error) {
if err != nil {
panic(err)
diff --git a/vendor/k8s.io/apimachinery/pkg/util/validation/field/path.go b/vendor/k8s.io/apimachinery/pkg/util/validation/field/path.go
index 2efc8eec7..f9be7ac33 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/validation/field/path.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/validation/field/path.go
@@ -67,6 +67,9 @@ func (p *Path) Key(key string) *Path {
// String produces a string representation of the Path.
func (p *Path) String() string {
+ if p == nil {
+ return "<nil>"
+ }
// make a slice to iterate
elems := []*Path{}
for ; p != nil; p = p.parent {
diff --git a/vendor/k8s.io/apimachinery/pkg/util/validation/validation.go b/vendor/k8s.io/apimachinery/pkg/util/validation/validation.go
index 4752b29a9..c8b419984 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/validation/validation.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/validation/validation.go
@@ -175,7 +175,7 @@ func IsValidLabelValue(value string) []string {
}
const dns1123LabelFmt string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?"
-const dns1123LabelErrMsg string = "a DNS-1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character"
+const dns1123LabelErrMsg string = "a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character"
// DNS1123LabelMaxLength is a label's max length in DNS (RFC 1123)
const DNS1123LabelMaxLength int = 63
@@ -196,7 +196,7 @@ func IsDNS1123Label(value string) []string {
}
const dns1123SubdomainFmt string = dns1123LabelFmt + "(\\." + dns1123LabelFmt + ")*"
-const dns1123SubdomainErrorMsg string = "a DNS-1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character"
+const dns1123SubdomainErrorMsg string = "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character"
// DNS1123SubdomainMaxLength is a subdomain's max length in DNS (RFC 1123)
const DNS1123SubdomainMaxLength int = 253
@@ -347,7 +347,7 @@ func IsValidPortName(port string) []string {
// IsValidIP tests that the argument is a valid IP address.
func IsValidIP(value string) []string {
if net.ParseIP(value) == nil {
- return []string{"must be a valid IP address, (e.g. 10.9.8.7)"}
+ return []string{"must be a valid IP address, (e.g. 10.9.8.7 or 2001:db8::ffff)"}
}
return nil
}
diff --git a/vendor/k8s.io/apimachinery/pkg/util/yaml/decoder.go b/vendor/k8s.io/apimachinery/pkg/util/yaml/decoder.go
index 492171faf..7fe706467 100644
--- a/vendor/k8s.io/apimachinery/pkg/util/yaml/decoder.go
+++ b/vendor/k8s.io/apimachinery/pkg/util/yaml/decoder.go
@@ -26,10 +26,41 @@ import (
"strings"
"unicode"
+ jsonutil "k8s.io/apimachinery/pkg/util/json"
+
"k8s.io/klog/v2"
"sigs.k8s.io/yaml"
)
+// Unmarshal unmarshals the given data
+// If v is a *map[string]interface{}, *[]interface{}, or *interface{} numbers
+// are converted to int64 or float64
+func Unmarshal(data []byte, v interface{}) error {
+ preserveIntFloat := func(d *json.Decoder) *json.Decoder {
+ d.UseNumber()
+ return d
+ }
+ switch v := v.(type) {
+ case *map[string]interface{}:
+ if err := yaml.Unmarshal(data, v, preserveIntFloat); err != nil {
+ return err
+ }
+ return jsonutil.ConvertMapNumbers(*v, 0)
+ case *[]interface{}:
+ if err := yaml.Unmarshal(data, v, preserveIntFloat); err != nil {
+ return err
+ }
+ return jsonutil.ConvertSliceNumbers(*v, 0)
+ case *interface{}:
+ if err := yaml.Unmarshal(data, v, preserveIntFloat); err != nil {
+ return err
+ }
+ return jsonutil.ConvertInterfaceNumbers(v, 0)
+ default:
+ return yaml.Unmarshal(data, v)
+ }
+}
+
// ToJSON converts a single YAML document into a JSON document
// or returns an error. If the document appears to be JSON the
// YAML decoding path is not used (so that error messages are