Skip to content
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

Fixes issue #3558 kubeconfig using server paths does not work with tap #3640

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pkg/tap/tap.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
"net/http"
"net/url"
"path"
"time"

"github.com/golang/protobuf/proto"
Expand Down Expand Up @@ -37,7 +38,7 @@ func Reader(k8sAPI *k8s.KubernetesAPI, req *pb.TapByResourceRequest, timeout tim
if err != nil {
return nil, nil, err
}
url.Path = protohttp.TapReqToURL(req)
url.Path = path.Join(url.Path, protohttp.TapReqToURL(req))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good but I wonder if we're going to run into this again for any other requests we make directly to the Kubernetes API server in the future. Do you think we could have a more general solution by adding a RoundTripper to the client in k8sAPI.NewClient() which prepends url path prefix to request paths?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That already works correctly. This specific instance doesn’t work because we’re building the URL specific to tap requests and replacing the already constructed one by NewClient() wholesale here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, you're right! thanks!

Copy link
Contributor

@cpretzer cpretzer Feb 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pietervogelaar

I figured out the cause for the error, and it is not unique to rancher.

According to the url.Join docs:

Join joins any number of path elements into a single path, adding a separating slash if necessary. The result is Cleaned; in particular, all empty strings are ignored.

This is relevant because the path for the kubernetes API uses two slashes in a row when an item is "namespaced".

Here are examples of the commands that are executed and the k8s API URLs that are generated when
url.Path = path.Join(url.Path, protohttp.TapReqToURL(req)) is replaced with
url.Path = fmt.Sprintf("%s%s",url.Path, protohttp.TapReqToURL(req)):

command:
bin/go-run cli tap -n linkerd deploy/linkerd-controller --verbose
URL:
https://<rancher-url>/k8s/clusters/c-66q2l/apis/tap.linkerd.io/v1alpha1/watch/namespaces/linkerd/deployments/linkerd-controller/tap

command:
bin/go-run cli tap -n linkerd deploy --verbose
URL:
https://<rancher-url>/k8s/clusters/c-66q2l/apis/tap.linkerd.io/v1alpha1/watch/namespaces/linkerd/deployments//tap

Notice the consecutive slashes // between deployments and tap

I get the same results when running against a single node kind cluster on my local machine.

To summarize, the gotcha here is that join.Path calls join.Clean which results in consecutive slashes // being cleaned to /


httpReq, err := http.NewRequest(
http.MethodPost,
Expand Down