-
Notifications
You must be signed in to change notification settings - Fork 39.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add redirect support to SpdyRoundTripper #44451
Add redirect support to SpdyRoundTripper #44451
Conversation
I seem to have broken TestServePortForward and am looking into it |
d157bb4
to
23d8754
Compare
@@ -1552,11 +1552,20 @@ func TestServePortForward(t *testing.T) { | |||
url = fmt.Sprintf("%s/portForward/%s/%s", fw.testHTTPServer.URL, podNamespace, podName) | |||
} | |||
|
|||
upgradeRoundTripper := spdy.NewRoundTripper(nil) | |||
c := &http.Client{Transport: upgradeRoundTripper} | |||
// Don't follow redirects, since we want to inspect the redirect response. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this case was odd... it seems like it was explicitly testing a scenario the spdy round tripper wouldn't handle, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but I think it was testing to make sure that the kubelet server could return a redirect. My change here made it start breaking, because the round tripper started following the redirect, so I updated this test case to match what's done in textExecAttach.
method = "GET" | ||
} | ||
|
||
r, err := http.NewRequest(method, location.String(), req.Body) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remind me again why reusing the original req.Body doesn't do bad things if we hit this loop more than once?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The request body is never used for spdy requests, but otherwise, we'd probably need to be more careful. This appears to be what the proxy code is doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the request body isn't used, can you just pass nil? That's what the proxy code does for subsequent requests (
intermediateConn, err = h.connectBackend("GET", location, initialReq.Header, nil) |
@k8s-bot verify test this (some verify generated protobuf rsync issue) |
@k8s-bot cvm gce e2e test this |
method = "GET" | ||
} | ||
|
||
r, err := http.NewRequest(method, location.String(), req.Body) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the request body isn't used, can you just pass nil? That's what the proxy code does for subsequent requests (
intermediateConn, err = h.connectBackend("GET", location, initialReq.Header, nil) |
|
||
s.conn = intermediateConn | ||
intermediateConn = nil // Don't close the connection when we return it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix comment (not returning intermediateConn)
header.Add(httpstream.HeaderConnection, httpstream.HeaderUpgrade) | ||
header.Add(httpstream.HeaderUpgrade, HeaderSpdy31) | ||
|
||
redirectLoop: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This duplicates a lot of code from the proxy (
redirectLoop: |
connectBackend
function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will look and see what I can do.
23d8754
to
8291d8a
Compare
@timstclair @liggitt updated to extract the common logic shared between spdy and the upgrade aware proxy. PTAL. Also, naming is hard, so I'm open to any suggestions for what to call the new interface and method. |
func (s *SpdyRoundTripper) TLSClientConfig() *tls.Config { | ||
return s.tlsConfig | ||
} | ||
|
||
// SendRequest implements k8s.io/apimachinery/pkg/util/net.RequestSender. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better use an anonymous var with type cast instead of a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix
intermediateConn net.Conn | ||
rawResponse = bytes.NewBuffer(make([]byte, 0, 256)) | ||
body = originalBody | ||
err error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err can be local in the loop body.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because that would result in intermediateConn being shadowed.
Some nits. Otherwise, looks good now that the redirect loop is factored out. |
8291d8a
to
ecf3618
Compare
Updated and squashed the code review commits |
@k8s-bot gci gce e2e test this (one node didn't come up for some reason).
|
return nil, nil, fmt.Errorf("too many redirects (%d)", redirects) | ||
} | ||
if redirects != 0 { | ||
// Redirected requests switch to "GET" according to the HTTP spec: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: if you want, you can move these down to the Prepare to follow the redirect.
section and make unconditional
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point... Since you've asked for a comment for 'future us' below, I'll make the change.
if redirectStr == "" { | ||
return nil, nil, fmt.Errorf("%d response missing Location header", resp.StatusCode) | ||
} | ||
location, err = location.Parse(redirectStr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment about parsing relative to the last requested location would be helpful here for future us
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do
lgtm |
ecf3618
to
038c7ce
Compare
@timstclair @liggitt @sttts ready for final review. Any other comments? |
none from me |
Just pushed up the new changes. PTAL. I'll say it's a bit weird to have |
/lgtm |
@@ -78,7 +80,8 @@ func NewExecutor(config *restclient.Config, method string, url *url.URL) (Stream | |||
return nil, err | |||
} | |||
|
|||
upgradeRoundTripper := spdy.NewRoundTripper(tlsConfig) | |||
followRedirects := utilfeature.DefaultFeatureGate.Enabled(genericfeatures.StreamingProxyRedirects) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having feature gates in client code is awkward. Any reason to have this feature gate at all here? Why don't we enable redirection for remotecommand? If the kubelet still depends on the gate, that's fine and another topic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't actually used in client code, is it? Maybe I'm confused about how this is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be happy to remove it. Do we all agree on that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI here is where the apiserver in OpenShift is creating a spdy roundtripper and executor: https://github.com/openshift/origin/blob/aaf06ed2b62b0e06845ad804932cddeec36b686e/pkg/build/registry/buildconfiginstantiate/rest.go#L237-L238.
fe88f42
to
299e9dd
Compare
Rebased and squashed. PTAL. /release-note |
I'm ok without the gate.
…On Tue, Apr 25, 2017 at 1:00 PM, Andy Goldstein ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In pkg/client/unversioned/remotecommand/remotecommand.go
<#44451 (comment)>
:
> @@ -78,7 +80,8 @@ func NewExecutor(config *restclient.Config, method string, url *url.URL) (Stream
return nil, err
}
- upgradeRoundTripper := spdy.NewRoundTripper(tlsConfig)
+ followRedirects := utilfeature.DefaultFeatureGate.Enabled(genericfeatures.StreamingProxyRedirects)
FYI here is where the apiserver in OpenShift is creating a spdy
roundtripper and executor: https://github.com/openshift/origin/blob/
aaf06ed2b62b0e06845ad804932cddeec36b686e/pkg/build/registry/
buildconfiginstantiate/rest.go#L237-L238.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#44451 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABG_pyOs0YyefmsykTzsK_JsFKGdOG8yks5rziaugaJpZM4M83Ao>
.
|
I don't want to keep blocking this - I'm ok with or without the gate. |
I'll take it out later tonight when I'm back at a computer.
…On Tue, Apr 25, 2017 at 4:15 PM Tim St. Clair ***@***.***> wrote:
I don't want to keep blocking this - I'm ok with or without the gate.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#44451 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAABYq5gzgHhKu4xEhqxBgZx14oFEApRks5rzn6MgaJpZM4M83Ao>
.
|
Add support for following redirects to the SpdyRoundTripper. This is necessary for clients using it directly (e.g. the apiserver talking directly to the kubelet) because the CRI streaming server issues a redirect for streaming requests. Also extract common logic for following redirects.
299e9dd
to
fc2128c
Compare
Ok, removed the flag from the client code. Hopefully this is the last revision :-) |
@timstclair @sttts @smarterclayton @liggitt I think this should be good to go, if you're all ok with it |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ncdc, smarterclayton, timstclair
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
Automatic merge from submit-queue |
Add support for following redirects to the SpdyRoundTripper. This is
necessary for clients using it directly (e.g. the apiserver talking
directly to the kubelet) because the CRI streaming server issues a
redirect for streaming requests.
We need this in OpenShift because we have code that executes inside our apiserver that talks directly to the node to perform an attach request, and we need to be able to follow that redirect.
This code was adapted from the upgrade-aware proxy handler.
cc @smarterclayton @sttts @liggitt @timstclair @kubernetes/sig-api-machinery-pr-reviews