* plugin/kubernetes: copy Labels in Pod.DeepCopyObject
Pod.DeepCopyObject built the copy field by field and left Labels out, so
every copy came back unlabelled. Every other object in this package copies
all of its fields; Pod was the only one missing any.
Labels feeds the kubernetes/client-label/<key> metadata, so anything that
reached a pod through a deep copy would see no labels at all rather than an
error. Nothing does today - DefaultProcessor stores the converted object
straight into the indexer without copying it, which is why this has not
surfaced - so this is a latent bug rather than a live one.
Clone the map instead of assigning it, so the copy does not alias the
original. maps.Clone returns nil for a nil map, so an unlabelled pod stays
unlabelled and a round trip does not turn a nil map into an empty one.
The test covers every runtime.Object in the package rather than just Pod,
and refuses to pass if a fixture leaves a field at its zero value. Adding a
field to any of these types therefore fails the test until the fixture sets
it, which is what makes the round-trip assertion cover the new field too.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
* plugin/kubernetes/object: deep copy the Service and ServiceImport ports
The deepcopy tests claimed a package-wide guarantee that a copy shares nothing
with its original, but only checked it for Pod and a hand-written Endpoints
value. Both api.ServicePort and mcs.ServicePort hold an AppProtocol *string, so
the elementwise copy(s1.Ports, s.Ports) in Service.DeepCopyObject and
ServiceImport.DeepCopyObject left the copy pointing at the original's string.
Mutating it through either side was visible from the other, and the tests still
passed.
Copy the ports with the generated DeepCopyInto so the copy owns everything it
can reach, and make the guarantee real: TestDeepCopyObjectIsDeep now runs over
every case in deepCopyCases, mutates every value reachable through a pointer,
slice, or map, and requires the copy to still equal a pristine fixture. A type
that gains a reference-bearing field is covered as soon as assertAllFieldsSet
forces the fixture to populate it, rather than needing a new hand-written case.
Failure messages render as JSON, because %+v prints an aliased pointer field as
an address and hides the value that actually differs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
---------
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* plugin/kubernetes: skip zone serial bump on DNS neutral pod updates
In pods verified mode every pod update event bumped the zone modified
timestamp, even when the pod IP did not change. Pod records only depend
on the pod IP, so routine status churn (conditions, container statuses,
labels) caused spurious SOA serial changes and needless zone transfer
activity, even though pod records are not part of transfers at all.
Only bump the modified timestamp when the pod IP changes, mirroring how
service and endpoint updates are already filtered. Also update the pods
verified documentation to describe the actual overhead: modest memory
for a stripped down pod object, plus watch load on the API server.
Ref #8043
Signed-off-by: Karan V <karanvknarayanan@gmail.com>
* plugin/kubernetes: keep pods verified cost description neutral
Avoid characterizing the memory overhead as modest until benchmark
data quantifies it. State only what the code does: the watch requires
additional memory in CoreDNS and adds load to the API server.
Signed-off-by: Karan V <karanvknarayanan@gmail.com>
---------
Signed-off-by: Karan V <karanvknarayanan@gmail.com>
* test: add benchmark cases for Request IP/Port and parseRequest
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
* test(kubernetes): add BenchmarkServices and BenchmarkServicesHeadless
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
* perf(forward): fast-path string comparison in isAllowedDomain
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
---------
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
- Added nolint to plugin/auto/walk.go to avoid a symlink/TOCTOU
warning, as it needs to follow symlink.
- Replaced a few flagged integer conversions with safe equivalents in
cache hashing, reuseport socket setup, and TLS arg handling
- Preallocated response rule slices in plugin/rewrite/name.go
- Replaced WriteString(fmt.Sprintf/Sprintln(...)) with direct
fmt.Fprint* calls
- Removed stale nolint directives from code and tests that are no
longer needed
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
The plugin dropped the actual error message from the log, so the log
becomes completely useless.
Before:
```
[ERROR] plugin/kubernetes: error Failed to watch
```
After:
```
[ERROR] plugin/kubernetes: Failed to watch: failed to list *v1.Namespace: Get "https://10.96.0.1:443/api/v1/namespaces?limit=500&resourceVersion=0": tls: failed to parse certificate from server: x509: SAN dNSName is malformed
```
Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
Enable intrange linter to enforce modern Go range syntax over
traditional for loops, by converting:
for i := 0; i < n; i++
to:
for i := range n
Adding type conversions where needed for compatibility
with existing uint64 parameters.
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
Enable copyloopvar linter and remove redundant variable
shadowing in Kubernetes plugin metadata handling. This pattern is
no longer needed in Go 1.22+ where loop variables are automatically
captured correctly in closures.
Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
* kubernetes: add multicluster support
Add multicluster support via Multi-Cluster Services API (MCS-API) via a
new option `multiclusterZones` in the kubernetes plugin.
When some multicluster zones are passed to the kubernetes plugin, it
will start watching the ServiceImport objects and its associated
EndpointSlices.
Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr>
* kubernetes: implement xfr support for multicluster zones
Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr>
---------
Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr>
Don't explicitly set `RetryOnError` to `false`. It won't exist in the
next version of the k8s api and it won't make a difference in this code
since the struct would default to that.
Signed-off-by: Kevin Lyda <kevin@lyda.ie>
In kubernetes' audit logs you'll see:
"userAgent":"coredns/v0.0.0 (linux/amd64) kubernetes/$Format"
This change adds a userAgent to the requests made by CoreDNS against the kubernetes API:
"userAgent":"CoreDNS/v1.11.1 git_commit:ae2bbc29be1aaae0b3ded5d188968a6c97bb3144 (linux/amd64/go1.22)"
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
Add a NativeHistogramBucketFactor parameter to the use of
`NewHistogramVec` in order to enable use of Prometheus Native
Histograms.
This will store automatically computed sparse buckets in CoreDNS.
If a compatible Prometeus requests native histograms this data will
returned instead of the static buckets.
The default factor of 1.05 should provide high quality resolution data.
Signed-off-by: SuperQ <superq@gmail.com>