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
[WIP]Migrate client-go/rest to contextual logging #122445
base: master
Are you sure you want to change the base?
Conversation
|
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the The Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Welcome @WillardHu! |
Hi @WillardHu. Thanks for your PR. I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
PTAL, thanks @pohly |
client-go is a library consumed from multiple projects , sounds weird that controller foo with its own context has /cc @liggitt |
@@ -513,6 +515,9 @@ func InClusterConfig() (*Config, error) { | |||
tokenFile = "/var/run/secrets/kubernetes.io/serviceaccount/token" | |||
rootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" | |||
) | |||
// TODO: the context parameter can be added to the method in the future |
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 goal is to convert the code now, not later... 🥵
I don't know what the right API should be. That is what we need to find out.
@WillardHu: I don't think this PR is ready for review. It's probably also not a good first issue. Are you sure that you want to continue? |
Yes, I'll follow up on the changes, and I'll think again about how to define logger instances. We can discuss in the issue first. |
5f57a7d
to
6e1cf85
Compare
6e1cf85
to
85dae87
Compare
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: WillardHu The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
25c8cff
to
1bedf91
Compare
klog.Errorf("Expected to load root CA config from %s, but got err: %v", rootCAFile, err) | ||
} else { | ||
tlsClientConfig.CAFile = rootCAFile | ||
return nil, err |
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 is a potentially breaking change: previously, the error was ignored, which might have allowed some apps to run. Now they are going to fail.
We need to research why this error was ignored and reach out to maintainers to figure out whether this can be changed.
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 original logic looks like verifying the validity of the root CA. The function NewPool() returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates. Invalid client root certificate access k8s services also return error responses.
I will try to find the author to understand why it was considered to ignore this 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.
I reverted to the original logic, but I found that error logging here was important to the caller, so I used a new function InClusterConfigWithContext() to support contextual logging.
@@ -335,36 +335,36 @@ func TestHTTPProxy(t *testing.T) { | |||
} | |||
|
|||
func TestCreateBackoffManager(t *testing.T) { | |||
|
|||
ctx := context.Background() |
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.
In tests, use _, ctx := ktesting.NewTestContext(t)
with ktesting
= k8s.io/klog/v2/ktesting
.
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.
Done, thanks.
UpdateBackoff(actualUrl *url.URL, err error, responseCode int) | ||
CalculateBackoff(actualUrl *url.URL) time.Duration | ||
UpdateBackoff(ctx context.Context, actualUrl *url.URL, err error, responseCode int) | ||
CalculateBackoff(ctx context.Context, actualUrl *url.URL) time.Duration |
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.
Changing the interface is another API break.
We have to keep BackoffManager
as it is and add a BackoffManagerContext
. Let's keep the method names the same in both, to minimize code changes.
BackoffManager
and all functions returning one must get the logcheck
remark.
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.
Done, thanks.
@@ -68,8 +69,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(context.Context) ([]byte, error) | |||
Stream(context.Context) (io.ReadCloser, error) | |||
DoRaw(...context.Context) ([]byte, 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.
Let's keep the interface as it is (API break!). Passing nil for "no context" seems fine to me.
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.
My idea is use a variable argument list for backward compatibility. In this case, the function DoRaw() can have a context paramete DoRaw(ctx)
or no paramete DoRaw()
. We can delete the context.Context paramete in the future.
But this is for the user to use, the modification behavior is not controlled. I'll modify 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.
Done, thanks.
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.
Changing an interface can also break code which implements it. This code used to work:
var r rest.Request = &myRequest{}
type myRequest struct {
...
}
func (r *myRequest) DoRaw(context.Context) ([]byte, error) { ... }
With the change to DoRaw(...context.Context) ([]byte, error)
it no longer does. Extending an interface has the same problem.
This code also breaks:
var doRaw func(context.Context) ([]byte, error)
doRaw = r.DoRaw
It's not clear whether any of this is actually going to be a problem. But it might, so let's avoid it whenever possible.
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 have reverted the interface definition. :-)
|
||
// gctx defined the global context, it's set by method chaining Context(). | ||
// We can get it using the r.ctx() member function, which ensures that returns context is always not nil | ||
gctx context.Context |
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 context isn't global? It's specific for the request. I would simply call the field ctx
.
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.
Done, thanks.
return r | ||
} | ||
|
||
// ctx returns the global context, if it is not set, we use the default context.Background() |
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.
Presumably this is needed because klog.FromContext
and logr.FromContext
crash when passed a nil context. Probably too late to change that now.
getCtx
returning r.ctx
?
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, the function returns the member field r.ctx
, but if the member field is nil, the default value context.Background()
is returned.
0a8481b
to
ddb1101
Compare
Next I'll regenerate the client code in kubernetes/typed package, and complete the performance comparison. |
Signed-off-by: WillardHu <wei.hu@daocloud.io>
ddb1101
to
6834ea7
Compare
PR needs rebase. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
What type of PR is this?
/kind cleanup
What this PR does / why we need it:
Migrate client-go/rest to contextual logging
Which issue(s) this PR fixes:
Fixes [#3077 ](kubernetes/enhancements#3077)
Special notes for your reviewer:
Check result of logcheck:
Does this PR introduce a user-facing change?
Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.: