Merge pull request #62733 from soltysh/discovery_timeout

Automatic merge from submit-queue (batch tested with PRs 62876, 62733, 62827). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Set a default request timeout for discovery client

Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1546117

Adds a default request timeout to requests made by the discovery client.
This prevents a command from hanging indefinitely due to one or multiple calls
to the apiserver taking longer than usual when when a --request-timeout flag value
has not been set.

/assign @deads2k @juanvallejo

**Release note**:
```release-note
NONE
```

Kubernetes-commit: 6da4355ad543411fcfef8320f4fbbc3d47bb0302
This commit is contained in:
Kubernetes Publisher 2018-04-20 13:39:11 -07:00
commit f123460f11
4 changed files with 93 additions and 59 deletions

108
Godeps/Godeps.json generated
View File

@ -1,6 +1,6 @@
{
"ImportPath": "k8s.io/client-go",
"GoVersion": "go1.9",
"GoVersion": "go1.10",
"GodepVersion": "v80",
"Packages": [
"./..."
@ -360,215 +360,215 @@
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/conversion",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/fields",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/labels",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/selection",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/types",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/cache",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/clock",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/framer",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/net",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/wait",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/version",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/watch",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
"Rev": "73aa818bbacf185a03468ddc170fb275763dec3d"
"Rev": "1c973d529bdf4c4f349357ca665fb8e1d13e2d0d"
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",

View File

@ -22,6 +22,7 @@ import (
"net/url"
"sort"
"strings"
"time"
"github.com/golang/protobuf/proto"
"github.com/googleapis/gnostic/OpenAPIv2"
@ -43,6 +44,13 @@ const (
mimePb = "application/com.github.proto-openapi.spec.v2@v1.0+protobuf"
)
var (
// defaultTimeout is the maximum amount of time per request when no timeout has been set on a RESTClient.
// Defaults to 32s in order to have a distinguishable length of time, relative to other timeouts that exist.
// It's a variable to be able to change it in tests.
defaultTimeout = 32 * time.Second
)
// DiscoveryInterface holds the methods that discover server-supported API groups,
// versions and resources.
type DiscoveryInterface interface {
@ -373,6 +381,9 @@ func withRetries(maxRetries int, f func() ([]*metav1.APIResourceList, error)) ([
func setDiscoveryDefaults(config *restclient.Config) error {
config.APIPath = ""
config.GroupVersion = nil
if config.Timeout == 0 {
config.Timeout = defaultTimeout
}
codec := runtime.NoopEncoder{Decoder: scheme.Codecs.UniversalDecoder()}
config.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})
if len(config.UserAgent) == 0 {

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package discovery_test
package discovery
import (
"encoding/json"
@ -23,7 +23,9 @@ import (
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"time"
"github.com/gogo/protobuf/proto"
"github.com/googleapis/gnostic/OpenAPIv2"
@ -32,7 +34,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/version"
. "k8s.io/client-go/discovery"
restclient "k8s.io/client-go/rest"
)
@ -129,6 +130,21 @@ func TestGetServerGroupsWithBrokenServer(t *testing.T) {
}
}
}
func TestGetServerGroupsWithTimeout(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
time.Sleep(2 * time.Second)
w.WriteHeader(http.StatusOK)
}))
defer server.Close()
tmp := defaultTimeout
defaultTimeout = 1 * time.Second
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
_, err := client.ServerGroups()
if err == nil || strings.Contains(err.Error(), "deadline") {
t.Fatalf("unexpected error: %v", err)
}
defaultTimeout = tmp
}
func TestGetServerResourcesWithV1Server(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {

View File

@ -353,8 +353,8 @@ func (r *Request) SetHeader(key string, values ...string) *Request {
return r
}
// Timeout makes the request use the given duration as a timeout. Sets the "timeout"
// parameter.
// Timeout makes the request use the given duration as an overall timeout for the
// request. Additionally, if set passes the value as "timeout" parameter in URL.
func (r *Request) Timeout(d time.Duration) *Request {
if r.err != nil {
return r
@ -640,7 +640,6 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
}
// Right now we make about ten retry attempts if we get a Retry-After response.
// TODO: Change to a timeout based approach.
maxRetries := 10
retries := 0
for {
@ -649,6 +648,14 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
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)
}