The API for the package already had a context, so all that was missing was to
extract and use the logger from that.
Kubernetes-commit: 0690af4710a5b322163564d82b95b90417ae3644
The only log output is for error messages which should normally not occur. It's
also likely that users expect to see exactly those messages, so it's better to
not touch them.
Kubernetes-commit: 1ec1248a6555be7ca7a0827061cdd3ef162f6c45
When debugging, it helps to keep output from different connections
separate. This can be done with contextual logging and using different loggers
for each connection.
Cancellation is handled separately for requests. Therefore the new APIs only
add support for passing a logger instance.
Kubernetes-commit: dfdf07bb531aa8a397f3c74e5eec851130325971
The main purpose is to replace context.TODO with a context provided by the
caller. A secondary purpose is to enable contextual logging.
Modifying the existing interfaces and APIs would have a big impact on the
ecosystem. This is a no-go. Instead, the following approach was taken:
- All interfaces get duplicated in a *WithContext variant where the methods
also have a *WithContext suffix and the ctx parameter. All methods are
treated this way except for obvious local get methods (like RESTClient)
because it cannot be ruled out entirely that some implementation may
need a context.
- Implementations of these interfaces implement both method variants
which is possible because the method names are different.
The old methods are implemented as thin wrappers around the updated
code which is now the body of the new methods or shared helpers.
In some cases there is additional overhead (type checks, potentially
additional allocations) when using the old methods.
- To*WithContext helpers bridge from the old to the new interfaces. They
try a type cast first. Because the in-tree implementations implement
both, they can be used directly. For other implementations wrappers
are used.
- All old APIs and interfaces are marked as deprecated. There is no
intent to ever remove them, but consumers should be made aware
that there are now better alternatives. Implementations also
get marked this way even if nothing ever calls them directly
because it shows which code, at least theoretically, could get
removed.
- Existing unit tests do not get updated to the new APIs. This gives
us unit test coverage of the old and new API because the old
APIs call the new ones.
- In-tree consumers will be updated in follow-up PRs. This is likely
to be a longer process. Because of the deprecation comment,
`hack/golangci-lint.sh -n` can be used to find code which needs
to be updated.
Kubernetes-commit: 025b844bcabe0212c4dd56395ee18481602d7c65
I wasn't entirely sure whether this should return a value or a pointer to
satisfy the interface. Both works, so I benchmarked it elsewhere (REST
mapper). Mem allocs are the same (one alloc/call), but returning a value is 10%
slower when calling one method.
What I then benchmarked is whether pointer vs value receiver in the wrapper
makes a difference. Converting from value receiver (what I had before) to
pointer receiver reduced call overhead by 6%. That's because with a value
receiver, Go has to auto-generate a variant with pointer receiver and calls the
value receiver through that.
That can be seen in a debugger (call stack) and when setting breakpoints:
(dlv) b restMapperWrapper.KindForWithContext
Command failed: Location "restMapperWrapper.KindForWithContext" ambiguous: k8s.io/apimachinery/pkg/api/meta.restMapperWrapper.KindForWithContext, k8s.io/apimachinery/pkg/api/meta.(*restMapperWrapper).KindForWithContext…
Conventional wisdom is to define types with value receiver because those can be
called also on unmutable instances, making them more flexible.
But for types which will only ever be used via a pointer, I think pointer
receiver is better for the reasons above (small performance difference, easier
to debug).
Kubernetes-commit: b21dcbcaa1ccf4995bf486afc37dc0321c5bdf0b
Latest release of both. The CurrentTreeConstructionNodeReport fix
is needed before being able to use it in the E2E framework.
Kubernetes-commit: f8a0c80ed81711f6add7a765d22b56d2d41ac522
We need to lock on observedTime reads to avoid races, before we were
only locking to read the observed record.
Use a RW lock since there are much more reads that writes.
Kubernetes-commit: d5ac0e408a0a1e50197e1b599b9b8b2e505bfe46
Quite a lot of unit tests set up informers with a fake client, do
informerFactory.WaitForCacheSync, then create or modify objects. Such tests
suffered from a race: because the fake client only delivered objects to the
watch after the watch has been created, creating an object too early caused
that object to not get delivered to the informer.
Usually the timing worked out okay because WaitForCacheSync typically slept a
bit while polling, giving the Watch call time to complete, but this race has
also gone wrong occasionally. Now with WaitForCacheSync returning more promptly
without polling (work in progress), the race goes wrong more often.
Instead of working around this in unit tests it's better to improve the fake
client such that List+Watch works reliably, regardless of the timing. The fake
client has traditionally not touched ResourceVersion in stored objects and
doing so now might break unit tests, so the added support for ResourceVersion
is intentionally limited to List+Watch.
The test simulates "real" usage of informers. It runs in a synctest bubble and
completes quickly:
go test -v .
=== RUN TestListAndWatch
listandwatch_test.go:67: I0101 01:00:00.000000] Listed configMaps="&ConfigMapList{ListMeta:{ 1 <nil>},Items:[]ConfigMap{ConfigMap{ObjectMeta:{cm1 default 0 0001-01-01 00:00:00 +0000 UTC <nil> <nil> map[] map[] [] [] []},Data:map[string]string{},BinaryData:map[string][]byte{},Immutable:nil,},},}" err=null
listandwatch_test.go:79: I0101 01:00:00.000000] Delaying Watch...
listandwatch_test.go:90: I0101 01:00:00.100000] Caches synced
listandwatch_test.go:107: I0101 01:00:00.100000] Created second ConfigMap
listandwatch_test.go:81: I0101 01:00:00.100000] Continuing Watch...
--- PASS: TestListAndWatch (0.00s)
PASS
ok k8s.io/client-go/testing/internal 0.009s
Some users of the fake client need to be updated to avoid test failures:
- ListMeta comparisons have to be updated.
- Optional: pass ListOptions into tracker.Watch. It's optional because
the implementation behaves as before when options are missing,
but the List+Watch race fix only works when options are passed.
Kubernetes-commit: 56448506075c3db1d16b5bbf0c581b833a4646f1
This uses the new generic fixed ring implementation in k8s.io/utils.
Signed-off-by: Stephen Kitt <skitt@redhat.com>
Kubernetes-commit: 3653ae2b9a7768da89e47ef84d503ae9cf0b910b
This fixes some issues found in Kubernetes (data race in ginkgo CLI, gomega
formatting) and helps with diagnosing OOM killing in CI jobs (exit status of
processes).
The modified gomega formatting shows up in some of the output tests for the E2E
framework. They get updated accordingly.
Kubernetes-commit: db841afdbb193ea7d612472c7cc4c7b3f58eb676
Embed proper interface in TransformingStore to ensure DeltaFIFO and RealFIFO are implementing it
Kubernetes-commit: 04e8064bccebd04981ee0094457550c9de4f92e3
Update leaderelection package to use contextual logging variants:
- Replace wait.JitterUntil with wait.JitterUntilWithContext
- Replace wait.Until with wait.UntilWithContext
This enables proper contextual logging support as part of the
structured logging migration.
Ref #126379
Kubernetes-commit: c5b64ebf2ef8619fb96c35f3a613b1b945ebe0f2