Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package coredns for openSUSE:Factory checked 
in at 2026-01-27 16:16:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/coredns (Old)
 and      /work/SRC/openSUSE:Factory/.coredns.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "coredns"

Tue Jan 27 16:16:01 2026 rev:28 rq:1329460 version:1.14.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/coredns/coredns.changes  2026-01-09 
17:04:47.711232572 +0100
+++ /work/SRC/openSUSE:Factory/.coredns.new.1928/coredns.changes        
2026-01-27 16:16:04.975458687 +0100
@@ -1,0 +2,13 @@
+Tue Jan 27 08:35:27 UTC 2026 - Andrea Manzini <[email protected]>
+
+- Update to version 1.14.1:
+  * This release primarily addresses security vulnerabilities affecting Go 
+    versions prior to Go 1.25.6 and Go 1.24.12 
+    (CVE-2025-61728, CVE-2025-61726, CVE-2025-68121, CVE-2025-61731,
+     CVE-2025-68119). 
+     It also includes performance improvements to the proxy plugin via
+     multiplexed connections, along with various documentation updates.
+
+- skip flaky tests
+
+-------------------------------------------------------------------

Old:
----
  coredns-1.14.0.tar.gz

New:
----
  coredns-1.14.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ coredns.spec ++++++
--- /var/tmp/diff_new_pack.dy5xBb/_old  2026-01-27 16:16:06.327515063 +0100
+++ /var/tmp/diff_new_pack.dy5xBb/_new  2026-01-27 16:16:06.331515230 +0100
@@ -18,7 +18,7 @@
 
 %define project github.com/coredns/coredns
 Name:           coredns
-Version:        1.14.0
+Version:        1.14.1
 Release:        0
 Summary:        DNS server written in Go
 License:        Apache-2.0
@@ -71,7 +71,23 @@
 %check
 # Too many tests fail due to the restricted permissions in the build 
enviroment.
 # Updates must be tested manually.
-go test ./... 
-skip="TestZoneExternalCNAMELookupWithProxy|TestReadme|TestCorefile1|TestView|TestMultisocket_Restart"
+
+skiplist=(
+    "TestIssue7630"
+    "TestMetricsRewriteRequestSize"
+    "TestReloadUnreadyPlugin"
+    "TestZoneExternalCNAMELookupWithProxy"
+    "TestReadme"
+    "TestCorefile1"
+    "TestView"
+    "TestMultisocket_Restart"
+    "TestFailover"
+)
+
+# Concatenate the array elements into a single regex string separated by pipes 
(|)
+# Output will look like: 
"TestIssue7630|TestMetricsRewriteRequestSize|TestReloadUnreadyPlugin"
+TEST_TO_SKIP=$(IFS="|"; echo "${skiplist[*]}")
+go test ./... -skip="$TEST_TO_SKIP"
 
 %install
 cd $HOME/go/src/%{project}

++++++ _service ++++++
--- /var/tmp/diff_new_pack.dy5xBb/_old  2026-01-27 16:16:06.431519400 +0100
+++ /var/tmp/diff_new_pack.dy5xBb/_new  2026-01-27 16:16:06.431519400 +0100
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/coredns/coredns</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v1.14.0</param>
+    <param name="revision">v1.14.1</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="changesgenerate">enable</param>
     <param name="versionrewrite-pattern">v(.*)</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.dy5xBb/_old  2026-01-27 16:16:06.475521235 +0100
+++ /var/tmp/diff_new_pack.dy5xBb/_new  2026-01-27 16:16:06.487521735 +0100
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/coredns/coredns</param>
-              <param 
name="changesrevision">1c964f2f68bd04a875a41479822ec3da1f1e76ef</param></service></servicedata>
+              <param 
name="changesrevision">80527fd389841310a728cf862491129321c8a112</param></service></servicedata>
 (No newline at EOF)
 

++++++ coredns-1.14.0.tar.gz -> coredns-1.14.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/.go-version 
new/coredns-1.14.1/.go-version
--- old/coredns-1.14.0/.go-version      2026-01-07 05:21:18.000000000 +0100
+++ new/coredns-1.14.1/.go-version      2026-01-16 05:47:07.000000000 +0100
@@ -1 +1 @@
-1.25.5
+1.25.6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/Makefile new/coredns-1.14.1/Makefile
--- old/coredns-1.14.0/Makefile 2026-01-07 05:21:18.000000000 +0100
+++ new/coredns-1.14.1/Makefile 2026-01-16 05:47:07.000000000 +0100
@@ -8,6 +8,8 @@
 MAKEPWD:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
 CGO_ENABLED?=0
 GOLANG_VERSION ?= $(shell cat .go-version)
+STRIP_FLAGS?=-s -w
+LDFLAGS?=-ldflags="$(STRIP_FLAGS) -X 
github.com/coredns/coredns/coremain.GitCommit=$(GITCOMMIT)"
 
 export GOSUMDB = sum.golang.org
 export GOTOOLCHAIN = go$(GOLANG_VERSION)
@@ -17,7 +19,7 @@
 
 .PHONY: coredns
 coredns: $(CHECKS)
-       CGO_ENABLED=$(CGO_ENABLED) $(SYSTEM) go build $(BUILDOPTS) -ldflags="-s 
-w -X github.com/coredns/coredns/coremain.GitCommit=$(GITCOMMIT)" -o $(BINARY)
+       CGO_ENABLED=$(CGO_ENABLED) $(SYSTEM) go build $(BUILDOPTS) $(LDFLAGS) 
-o $(BINARY)
 
 .PHONY: check
 check: core/plugin/zplugin.go core/dnsserver/zdirectives.go
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/README.md new/coredns-1.14.1/README.md
--- old/coredns-1.14.0/README.md        2026-01-07 05:21:18.000000000 +0100
+++ new/coredns-1.14.1/README.md        2026-01-16 05:47:07.000000000 +0100
@@ -84,6 +84,28 @@
 
 The above command alone will have `coredns` binary generated.
 
+## Quick Start
+
+Create a minimal Corefile:
+
+```bash
+cat > Corefile <<EOF
+.:53 {
+    forward . 8.8.8.8
+    log
+}
+EOF
+```
+Run CoreDNS:
+```
+$ ./coredns -conf Corefile
+```
+
+Test it:
+```
+$ dig @127.0.0.1 google.com
+```
+
 ## Examples
 
 When starting CoreDNS without any configuration, it loads the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/coremain/version.go 
new/coredns-1.14.1/coremain/version.go
--- old/coredns-1.14.0/coremain/version.go      2026-01-07 05:21:18.000000000 
+0100
+++ new/coredns-1.14.1/coremain/version.go      2026-01-16 05:47:07.000000000 
+0100
@@ -2,7 +2,7 @@
 
 // Various CoreDNS constants.
 const (
-       CoreVersion = "1.14.0"
+       CoreVersion = "1.14.1"
        CoreName    = "CoreDNS"
        serverType  = "dns"
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/go.mod new/coredns-1.14.1/go.mod
--- old/coredns-1.14.0/go.mod   2026-01-07 05:21:18.000000000 +0100
+++ new/coredns-1.14.1/go.mod   2026-01-16 05:47:07.000000000 +0100
@@ -8,14 +8,14 @@
        github.com/Azure/azure-sdk-for-go v68.0.0+incompatible
        github.com/Azure/go-autorest/autorest v0.11.30
        github.com/Azure/go-autorest/autorest/azure/auth v0.5.13
-       github.com/DataDog/dd-trace-go/v2 v2.4.1
+       github.com/DataDog/dd-trace-go/v2 v2.5.0
        github.com/apparentlymart/go-cidr v1.1.0
-       github.com/aws/aws-sdk-go-v2 v1.41.0
-       github.com/aws/aws-sdk-go-v2/config v1.32.6
-       github.com/aws/aws-sdk-go-v2/credentials v1.19.6
-       github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16
-       github.com/aws/aws-sdk-go-v2/service/route53 v1.62.0
-       github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.0
+       github.com/aws/aws-sdk-go-v2 v1.41.1
+       github.com/aws/aws-sdk-go-v2/config v1.32.7
+       github.com/aws/aws-sdk-go-v2/credentials v1.19.7
+       github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17
+       github.com/aws/aws-sdk-go-v2/service/route53 v1.62.1
+       github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.1
        github.com/coredns/caddy v1.1.4-0.20250930002214-15135a999495
        github.com/dnstap/golang-dnstap v0.4.0
        github.com/expr-lang/expr v1.17.7
@@ -25,22 +25,22 @@
        github.com/hashicorp/nomad/api v0.0.0-20250909143645-a3b86c697f38 // 
v1.10.5
        github.com/infobloxopen/go-trees v0.0.0-20200715205103-96a057b8dfb9
        github.com/matttproud/golang_protobuf_extensions v1.0.4
-       github.com/miekg/dns v1.1.69
+       github.com/miekg/dns v1.1.70
        github.com/opentracing/opentracing-go v1.2.0
        github.com/openzipkin-contrib/zipkin-go-opentracing v0.5.0
        github.com/openzipkin/zipkin-go v0.4.3
        github.com/oschwald/geoip2-golang/v2 v2.1.0
        github.com/prometheus/client_golang v1.23.0
        github.com/prometheus/client_model v0.6.2
-       github.com/prometheus/common v0.67.4
-       github.com/quic-go/quic-go v0.58.0
+       github.com/prometheus/common v0.67.5
+       github.com/quic-go/quic-go v0.59.0
        github.com/stretchr/testify v1.11.1
        go.etcd.io/etcd/api/v3 v3.6.7
        go.etcd.io/etcd/client/v3 v3.6.7
        go.uber.org/automaxprocs v1.6.0
-       golang.org/x/crypto v0.46.0
-       golang.org/x/sys v0.39.0
-       google.golang.org/api v0.258.0
+       golang.org/x/crypto v0.47.0
+       golang.org/x/sys v0.40.0
+       google.golang.org/api v0.259.0
        google.golang.org/grpc v1.78.0
        google.golang.org/protobuf v1.36.11
        k8s.io/api v0.34.3
@@ -50,10 +50,10 @@
        sigs.k8s.io/mcs-api v0.3.0
 )
 
-require golang.org/x/net v0.48.0
+require golang.org/x/net v0.49.0
 
 require (
-       cloud.google.com/go/auth v0.17.0 // indirect
+       cloud.google.com/go/auth v0.18.0 // indirect
        cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
        cloud.google.com/go/compute/metadata v0.9.0 // indirect
        github.com/Azure/go-autorest v14.2.0+incompatible // indirect
@@ -73,22 +73,21 @@
        github.com/DataDog/datadog-agent/pkg/util/scrubber v0.71.0 // indirect
        github.com/DataDog/datadog-agent/pkg/version v0.71.0 // indirect
        github.com/DataDog/datadog-go/v5 v5.6.0 // indirect
-       github.com/DataDog/go-libddwaf/v4 v4.6.1 // indirect
+       github.com/DataDog/go-libddwaf/v4 v4.8.0 // indirect
        github.com/DataDog/go-runtime-metrics-internal 
v0.0.4-0.20250721125240-fdf1ef85b633 // indirect
        github.com/DataDog/go-sqllexer v0.1.8 // indirect
        github.com/DataDog/go-tuf v1.1.1-0.5.2 // indirect
        github.com/DataDog/sketches-go v1.4.7 // indirect
-       github.com/Masterminds/semver/v3 v3.3.1 // indirect
        github.com/Microsoft/go-winio v0.6.2 // indirect
-       github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 // indirect
-       github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 // indirect
+       github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect
+       github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 // indirect
        github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
        github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 
// indirect
-       github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 // 
indirect
-       github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 // indirect
-       github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 // indirect
-       github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 // indirect
-       github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 // indirect
+       github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 // 
indirect
+       github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 // indirect
+       github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 // indirect
+       github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 // indirect
+       github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect
        github.com/aws/smithy-go v1.24.0 // indirect
        github.com/beorn7/perks v1.0.1 // indirect
        github.com/cenkalti/backoff/v5 v5.0.3 // indirect
@@ -109,7 +108,6 @@
        github.com/go-openapi/jsonpointer v0.21.0 // indirect
        github.com/go-openapi/jsonreference v0.20.2 // indirect
        github.com/go-openapi/swag v0.23.0 // indirect
-       github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
        github.com/gogo/protobuf v1.3.2 // indirect
        github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
        github.com/golang/protobuf v1.5.4 // indirect
@@ -118,9 +116,9 @@
        github.com/google/s2a-go v0.1.9 // indirect
        github.com/google/uuid v1.6.0 // indirect
        github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
-       github.com/googleapis/gax-go/v2 v2.15.0 // indirect
+       github.com/googleapis/gax-go/v2 v2.16.0 // indirect
        github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // 
indirect
-       github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
+       github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
        github.com/hashicorp/cronexpr v1.1.3 // indirect
        github.com/hashicorp/errwrap v1.1.0 // indirect
        github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
@@ -165,9 +163,10 @@
        go.etcd.io/etcd/client/pkg/v3 v3.6.7 // indirect
        go.opentelemetry.io/auto/sdk v1.2.1 // indirect
        go.opentelemetry.io/collector/component v1.39.0 // indirect
-       go.opentelemetry.io/collector/featuregate v1.39.0 // indirect
+       go.opentelemetry.io/collector/featuregate v1.46.0 // indirect
        go.opentelemetry.io/collector/internal/telemetry v0.133.0 // indirect
-       go.opentelemetry.io/collector/pdata v1.39.0 // indirect
+       go.opentelemetry.io/collector/pdata v1.46.0 // indirect
+       go.opentelemetry.io/collector/pdata/pprofile v0.140.0 // indirect
        go.opentelemetry.io/contrib/bridges/otelzap v0.12.0 // indirect
        go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 
// indirect
        go.opentelemetry.io/otel v1.38.0 // indirect
@@ -181,16 +180,16 @@
        go.yaml.in/yaml/v2 v2.4.3 // indirect
        go.yaml.in/yaml/v3 v3.0.4 // indirect
        golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
-       golang.org/x/mod v0.30.0 // indirect
+       golang.org/x/mod v0.31.0 // indirect
        golang.org/x/oauth2 v0.34.0 // indirect
        golang.org/x/sync v0.19.0 // indirect
-       golang.org/x/term v0.38.0 // indirect
-       golang.org/x/text v0.32.0 // indirect
+       golang.org/x/term v0.39.0 // indirect
+       golang.org/x/text v0.33.0 // indirect
        golang.org/x/time v0.14.0 // indirect
-       golang.org/x/tools v0.39.0 // indirect
+       golang.org/x/tools v0.40.0 // indirect
        golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
-       google.golang.org/genproto/googleapis/api 
v0.0.0-20251029180050-ab9386a59fda // indirect
-       google.golang.org/genproto/googleapis/rpc 
v0.0.0-20251213004720-97cd9d5aeac2 // indirect
+       google.golang.org/genproto/googleapis/api 
v0.0.0-20251202230838-ff82c1b0f217 // indirect
+       google.golang.org/genproto/googleapis/rpc 
v0.0.0-20251222181119-0a764e51fe1b // indirect
        gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
        gopkg.in/inf.v0 v0.9.1 // indirect
        gopkg.in/ini.v1 v1.67.0 // indirect
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/go.sum new/coredns-1.14.1/go.sum
--- old/coredns-1.14.0/go.sum   2026-01-07 05:21:18.000000000 +0100
+++ new/coredns-1.14.1/go.sum   2026-01-16 05:47:07.000000000 +0100
@@ -1,5 +1,5 @@
-cloud.google.com/go/auth v0.17.0 
h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4=
-cloud.google.com/go/auth v0.17.0/go.mod 
h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ=
+cloud.google.com/go/auth v0.18.0 
h1:wnqy5hrv7p3k7cShwAU/Br3nzod7fxoqG+k0VZ+/Pk0=
+cloud.google.com/go/auth v0.18.0/go.mod 
h1:wwkPM1AgE1f2u6dG443MiWoD8C3BtOywNsUMcUTVDRo=
 cloud.google.com/go/auth/oauth2adapt v0.2.8 
h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
 cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod 
h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
 cloud.google.com/go/compute/metadata v0.9.0 
h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
@@ -49,10 +49,10 @@
 github.com/DataDog/datadog-agent/pkg/version v0.71.0/go.mod 
h1:FYj51C1ib86rpr5tlLEep9jitqvljIJ5Uz2rrimGTeY=
 github.com/DataDog/datadog-go/v5 v5.6.0 
h1:2oCLxjF/4htd55piM75baflj/KoE6VYS7alEUqFvRDw=
 github.com/DataDog/datadog-go/v5 v5.6.0/go.mod 
h1:K9kcYBlxkcPP8tvvjZZKs/m1edNAUFzBbdpTUKfCsuw=
-github.com/DataDog/dd-trace-go/v2 v2.4.1 
h1:1WU/Kv1jPIo7QT8boObUbZMrnTlGE7346mSyq4l6aag=
-github.com/DataDog/dd-trace-go/v2 v2.4.1/go.mod 
h1:EEOkhOJlb37u+k07/9cwKCvtDC/mWjWnHrGkkk/iZCo=
-github.com/DataDog/go-libddwaf/v4 v4.6.1 
h1:wGUioRkQ2a5MYr2wTn5uZfMENbLV4uKXrkr6zCVInCs=
-github.com/DataDog/go-libddwaf/v4 v4.6.1/go.mod 
h1:/AZqP6zw3qGJK5mLrA0PkfK3UQDk1zCI2fUNCt4xftE=
+github.com/DataDog/dd-trace-go/v2 v2.5.0 
h1:Tp4McT135WhbdT/6BYcAoRvl5gH7YKzehSo6Q3uuxBM=
+github.com/DataDog/dd-trace-go/v2 v2.5.0/go.mod 
h1:A9rVmQfyzYUFCctFdKkli9us7G/YhXlMICpQ958wJUA=
+github.com/DataDog/go-libddwaf/v4 v4.8.0 
h1:m6Bl1lS2RtVN4MtdTYhR5vJ2fWQ3WmNy4FiNBpzrp6w=
+github.com/DataDog/go-libddwaf/v4 v4.8.0/go.mod 
h1:/AZqP6zw3qGJK5mLrA0PkfK3UQDk1zCI2fUNCt4xftE=
 github.com/DataDog/go-runtime-metrics-internal 
v0.0.4-0.20250721125240-fdf1ef85b633 
h1:ZRLR9Lbym748e8RznWzmSoK+OfV+8qW6SdNYA4/IqdA=
 github.com/DataDog/go-runtime-metrics-internal 
v0.0.4-0.20250721125240-fdf1ef85b633/go.mod 
h1:YFoTl1xsMzdSRFIu33oCSPS/3+HZAPGpO3oOM96wXCM=
 github.com/DataDog/go-sqllexer v0.1.8 
h1:ku9DpghFHeyyviR28W/3R4cCJwzpsuC08YIoltnx5ds=
@@ -63,43 +63,41 @@
 github.com/DataDog/gostackparse v0.7.0/go.mod 
h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM=
 github.com/DataDog/sketches-go v1.4.7 
h1:eHs5/0i2Sdf20Zkj0udVFWuCrXGRFig2Dcfm5rtcTxc=
 github.com/DataDog/sketches-go v1.4.7/go.mod 
h1:eAmQ/EBmtSO+nQp7IZMZVRPT4BQTmIc5RZQ+deGlTPM=
-github.com/Masterminds/semver/v3 v3.3.1 
h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
-github.com/Masterminds/semver/v3 v3.3.1/go.mod 
h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
 github.com/Microsoft/go-winio v0.5.0/go.mod 
h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
 github.com/Microsoft/go-winio v0.6.2 
h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
 github.com/Microsoft/go-winio v0.6.2/go.mod 
h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
 github.com/apparentlymart/go-cidr v1.1.0 
h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU=
 github.com/apparentlymart/go-cidr v1.1.0/go.mod 
h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc=
-github.com/aws/aws-sdk-go-v2 v1.41.0 
h1:tNvqh1s+v0vFYdA1xq0aOJH+Y5cRyZ5upu6roPgPKd4=
-github.com/aws/aws-sdk-go-v2 v1.41.0/go.mod 
h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0=
-github.com/aws/aws-sdk-go-v2/config v1.32.6 
h1:hFLBGUKjmLAekvi1evLi5hVvFQtSo3GYwi+Bx4lpJf8=
-github.com/aws/aws-sdk-go-v2/config v1.32.6/go.mod 
h1:lcUL/gcd8WyjCrMnxez5OXkO3/rwcNmvfno62tnXNcI=
-github.com/aws/aws-sdk-go-v2/credentials v1.19.6 
h1:F9vWao2TwjV2MyiyVS+duza0NIRtAslgLUM0vTA1ZaE=
-github.com/aws/aws-sdk-go-v2/credentials v1.19.6/go.mod 
h1:SgHzKjEVsdQr6Opor0ihgWtkWdfRAIwxYzSJ8O85VHY=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 
h1:80+uETIWS1BqjnN9uJ0dBUaETh+P1XwFy5vwHwK5r9k=
-github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16/go.mod 
h1:wOOsYuxYuB/7FlnVtzeBYRcjSRtQpAW0hCP7tIULMwo=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 
h1:rgGwPzb82iBYSvHMHXc8h9mRoOUBZIGFgKb9qniaZZc=
-github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16/go.mod 
h1:L/UxsGeKpGoIj6DxfhOWHWQ/kGKcd4I1VncE4++IyKA=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 
h1:1jtGzuV7c82xnqOVfx2F0xmJcOw5374L7N6juGW6x6U=
-github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16/go.mod 
h1:M2E5OQf+XLe+SZGmmpaI2yy+J326aFf6/+54PoxSANc=
+github.com/aws/aws-sdk-go-v2 v1.41.1 
h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU=
+github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod 
h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0=
+github.com/aws/aws-sdk-go-v2/config v1.32.7 
h1:vxUyWGUwmkQ2g19n7JY/9YL8MfAIl7bTesIUykECXmY=
+github.com/aws/aws-sdk-go-v2/config v1.32.7/go.mod 
h1:2/Qm5vKUU/r7Y+zUk/Ptt2MDAEKAfUtKc1+3U1Mo3oY=
+github.com/aws/aws-sdk-go-v2/credentials v1.19.7 
h1:tHK47VqqtJxOymRrNtUXN5SP/zUTvZKeLx4tH6PGQc8=
+github.com/aws/aws-sdk-go-v2/credentials v1.19.7/go.mod 
h1:qOZk8sPDrxhf+4Wf4oT2urYJrYt3RejHSzgAquYeppw=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 
h1:I0GyV8wiYrP8XpA70g1HBcQO1JlQxCMTW9npl5UbDHY=
+github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod 
h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 
h1:xOLELNKGp2vsiteLsvLPwxC+mYmO6OZ8PYgiuPJzF8U=
+github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17/go.mod 
h1:5M5CI3D12dNOtH3/mk6minaRwI2/37ifCURZISxA/IQ=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 
h1:WWLqlh79iO48yLkj1v3ISRNiv+3KdQoZ6JWyfcsyQik=
+github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17/go.mod 
h1:EhG22vHRrvF8oXSTYStZhJc1aUgKtnJe+aOiFEV90cM=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 
h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod 
h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 
h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E=
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod 
h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16 
h1:oHjJHeUy0ImIV0bsrX0X91GkV5nJAyv1l1CC9lnO0TI=
-github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.16/go.mod 
h1:iRSNGgOYmiYwSCXxXaKb9HfOEj40+oTKn8pTxMlYkRM=
-github.com/aws/aws-sdk-go-v2/service/route53 v1.62.0 
h1:80pDB3Tpmb2RCSZORrK9/3iQxsd+w6vSzVqpT1FGiwE=
-github.com/aws/aws-sdk-go-v2/service/route53 v1.62.0/go.mod 
h1:6EZUGGNLPLh5Unt30uEoA+KQcByERfXIkax9qrc80nA=
-github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.0 
h1:vL6rQXcGtFv9q/9eRPdI+lL+dvTm7xKGZYSHEvmrpDk=
-github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.0/go.mod 
h1:QwEDLD+7EukuEUnbWtiNE8LhgvvmhjZoi4XAppYPtyc=
-github.com/aws/aws-sdk-go-v2/service/signin v1.0.4 
h1:HpI7aMmJ+mm1wkSHIA2t5EaFFv5EFYXePW30p1EIrbQ=
-github.com/aws/aws-sdk-go-v2/service/signin v1.0.4/go.mod 
h1:C5RdGMYGlfM0gYq/tifqgn4EbyX99V15P2V3R+VHbQU=
-github.com/aws/aws-sdk-go-v2/service/sso v1.30.8 
h1:aM/Q24rIlS3bRAhTyFurowU8A0SMyGDtEOY/l/s/1Uw=
-github.com/aws/aws-sdk-go-v2/service/sso v1.30.8/go.mod 
h1:+fWt2UHSb4kS7Pu8y+BMBvJF0EWx+4H0hzNwtDNRTrg=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 
h1:AHDr0DaHIAo8c9t1emrzAlVDFp+iMMKnPdYy6XO4MCE=
-github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12/go.mod 
h1:GQ73XawFFiWxyWXMHWfhiomvP3tXtdNar/fi8z18sx0=
-github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 
h1:SciGFVNZ4mHdm7gpD1dgZYnCuVdX1s+lFTg4+4DOy70=
-github.com/aws/aws-sdk-go-v2/service/sts v1.41.5/go.mod 
h1:iW40X4QBmUxdP+fZNOpfmkdMZqsovezbAeO+Ubiv2pk=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 
h1:RuNSMoozM8oXlgLG/n6WLaFGoea7/CddrCfIiSA+xdY=
+github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17/go.mod 
h1:F2xxQ9TZz5gDWsclCtPQscGpP0VUOc8RqgFM3vDENmU=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.62.1 
h1:1jIdwWOulae7bBLIgB36OZ0DINACb1wxM6wdGlx4eHE=
+github.com/aws/aws-sdk-go-v2/service/route53 v1.62.1/go.mod 
h1:tE2zGlMIlxWv+7Otap7ctRp3qeKqtnja7DZguj3Vu/Y=
+github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.1 
h1:72DBkm/CCuWx2LMHAXvLDkZfzopT3psfAeyZDIt1/yE=
+github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.1/go.mod 
h1:A+oSJxFvzgjZWkpM0mXs3RxB5O1SD6473w3qafOC9eU=
+github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 
h1:VrhDvQib/i0lxvr3zqlUwLwJP4fpmpyD9wYG1vfSu+Y=
+github.com/aws/aws-sdk-go-v2/service/signin v1.0.5/go.mod 
h1:k029+U8SY30/3/ras4G/Fnv/b88N4mAfliNn08Dem4M=
+github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 
h1:v6EiMvhEYBoHABfbGB4alOYmCIrcgyPPiBE1wZAEbqk=
+github.com/aws/aws-sdk-go-v2/service/sso v1.30.9/go.mod 
h1:yifAsgBxgJWn3ggx70A3urX2AN49Y5sJTD1UQFlfqBw=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 
h1:gd84Omyu9JLriJVCbGApcLzVR3XtmC4ZDPcAI6Ftvds=
+github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13/go.mod 
h1:sTGThjphYE4Ohw8vJiRStAcu3rbjtXRsdNB0TvZ5wwo=
+github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 
h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/pJ1jOWYlFDJTjRQ=
+github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod 
h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ=
 github.com/aws/smithy-go v1.24.0 
h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk=
 github.com/aws/smithy-go v1.24.0/go.mod 
h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -167,8 +165,6 @@
 github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 
h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
 github.com/go-task/slim-sprig/v3 v3.0.0 
h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
 github.com/go-task/slim-sprig/v3 v3.0.0/go.mod 
h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
-github.com/go-viper/mapstructure/v2 v2.4.0 
h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
-github.com/go-viper/mapstructure/v2 v2.4.0/go.mod 
h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
 github.com/godbus/dbus/v5 v5.0.4/go.mod 
h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod 
h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@@ -207,12 +203,12 @@
 github.com/google/uuid v1.6.0/go.mod 
h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/enterprise-certificate-proxy v0.3.7 
h1:zrn2Ee/nWmHulBx5sAVrGgAa0f2/R35S4DJwfFaUPFQ=
 github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod 
h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
-github.com/googleapis/gax-go/v2 v2.15.0 
h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
-github.com/googleapis/gax-go/v2 v2.15.0/go.mod 
h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
+github.com/googleapis/gax-go/v2 v2.16.0 
h1:iHbQmKLLZrexmb0OSsNGTeSTS0HO4YvFOG8g5E4Zd0Y=
+github.com/googleapis/gax-go/v2 v2.16.0/go.mod 
h1:o1vfQjjNZn4+dPnRdl/4ZD7S9414Y4xA+a/6Icj6l14=
 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 
h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
 github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod 
h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 
h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod 
h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 
h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod 
h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
 github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 
h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU=
 github.com/grpc-ecosystem/grpc-opentracing 
v0.0.0-20180507213350-8e809c8a8645/go.mod 
h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw=
 github.com/hashicorp/cronexpr v1.1.3 
h1:rl5IkxXN2m681EfivTlccqIryzYJSXRGRNa0xeG7NA4=
@@ -258,8 +254,8 @@
 github.com/matttproud/golang_protobuf_extensions v1.0.4 
h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
 github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod 
h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
 github.com/miekg/dns v1.1.31/go.mod 
h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
-github.com/miekg/dns v1.1.69 h1:Kb7Y/1Jo+SG+a2GtfoFUfDkG//csdRPwRLkCsxDG9Sc=
-github.com/miekg/dns v1.1.69/go.mod 
h1:7OyjD9nEba5OkqQ/hB4fy3PIoxafSZJtducccIelz3g=
+github.com/miekg/dns v1.1.70 h1:DZ4u2AV35VJxdD9Fo9fIWm119BsQL5cZU1cQ9s0LkqA=
+github.com/miekg/dns v1.1.70/go.mod 
h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
 github.com/minio/simdjson-go v0.4.5 
h1:r4IQwjRGmWCQ2VeMc7fGiilu1z5du0gJ/I/FsKwgo5A=
 github.com/minio/simdjson-go v0.4.5/go.mod 
h1:eoNz0DcLQRyEDeaPr4Ru6JpjlZPzbA0IodxVJk8lO8E=
 github.com/mitchellh/go-homedir v1.1.0 
h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
@@ -313,16 +309,16 @@
 github.com/prometheus/client_golang v1.23.0/go.mod 
h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
 github.com/prometheus/client_model v0.6.2 
h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
 github.com/prometheus/client_model v0.6.2/go.mod 
h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
-github.com/prometheus/common v0.67.4 
h1:yR3NqWO1/UyO1w2PhUvXlGQs/PtFmoveVO0KZ4+Lvsc=
-github.com/prometheus/common v0.67.4/go.mod 
h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI=
+github.com/prometheus/common v0.67.5 
h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
+github.com/prometheus/common v0.67.5/go.mod 
h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
 github.com/prometheus/procfs v0.16.1 
h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
 github.com/prometheus/procfs v0.16.1/go.mod 
h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
 github.com/puzpuzpuz/xsync/v3 v3.5.1 
h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
 github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod 
h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
 github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
 github.com/quic-go/qpack v0.6.0/go.mod 
h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
-github.com/quic-go/quic-go v0.58.0 
h1:ggY2pvZaVdB9EyojxL1p+5mptkuHyX5MOSv4dgWF4Ug=
-github.com/quic-go/quic-go v0.58.0/go.mod 
h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
+github.com/quic-go/quic-go v0.59.0 
h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
+github.com/quic-go/quic-go v0.59.0/go.mod 
h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
 github.com/richardartoul/molecule v1.0.1-0.20240531184615-7ca0df43c0b3 
h1:4+LEVOB87y175cLJC/mbsgKmoDOjrBldtXvioEy96WY=
 github.com/richardartoul/molecule v1.0.1-0.20240531184615-7ca0df43c0b3/go.mod 
h1:vl5+MqJ1nBINuSsUI2mGgH79UweUT/B5Fy8857PqyyI=
 github.com/rogpeppe/go-internal v1.14.1 
h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
@@ -391,14 +387,14 @@
 go.opentelemetry.io/collector/consumer/consumertest v0.133.0/go.mod 
h1:vHGknLn/RRUcMQuuBDt+SgrpDN46DBJyqRnWXm3gLwY=
 go.opentelemetry.io/collector/consumer/xconsumer v0.133.0 
h1:Xx4Yna/We4qDlbAla1nfxgkvujzWRuR8bqqwsLLvYSg=
 go.opentelemetry.io/collector/consumer/xconsumer v0.133.0/go.mod 
h1:he874Md/0uAS2Fs+TDHAy10OBLRSw8233LdREizVvG4=
-go.opentelemetry.io/collector/featuregate v1.39.0 
h1:OlXZWW+WUP8cgKh2mnwgWXUJO/29irb0hG6jvwscRKM=
-go.opentelemetry.io/collector/featuregate v1.39.0/go.mod 
h1:A72x92glpH3zxekaUybml1vMSv94BH6jQRn5+/htcjw=
+go.opentelemetry.io/collector/featuregate v1.46.0 
h1:z3JlymFdWW6aDo9cYAJ6bCqT+OI2DlurJ9P8HqfuKWQ=
+go.opentelemetry.io/collector/featuregate v1.46.0/go.mod 
h1:d0tiRzVYrytB6LkcYgz2ESFTv7OktRPQe0QEQcPt1L4=
 go.opentelemetry.io/collector/internal/telemetry v0.133.0 
h1:YxbckZC9HniNOZgnSofTOe0AB/bEsmISNdQeS+3CU3o=
 go.opentelemetry.io/collector/internal/telemetry v0.133.0/go.mod 
h1:akUK7X6ZQ+CbbCjyXLv9y/EHt5jIy+J+nGoLvndZN14=
-go.opentelemetry.io/collector/pdata v1.39.0 
h1:jr0f033o57Hpbj2Il8M15tPbvrOgY/Aoc+/+sxzhSFU=
-go.opentelemetry.io/collector/pdata v1.39.0/go.mod 
h1:jmolu6zwqNaq8qJ4IgCpNWBEwJNPLE1qqOz9GnpqxME=
-go.opentelemetry.io/collector/pdata/pprofile v0.133.0 
h1:ewFYqV2FU4D0ixTdkJueaI2JGCoeiIJisX8EdHejDi8=
-go.opentelemetry.io/collector/pdata/pprofile v0.133.0/go.mod 
h1:5l4/B0iCxzoVkA7eOLzIHV0AUEO2IKypTHTLq9JKsHs=
+go.opentelemetry.io/collector/pdata v1.46.0 
h1:XzhnIWNtc/gbOyFiewRvybR4s3phKHrWxL3yc/wVLDo=
+go.opentelemetry.io/collector/pdata v1.46.0/go.mod 
h1:D2e3BWCUC/bUg29WNzCDVN7Ab0Gzk7hGXZL2pnrDOn0=
+go.opentelemetry.io/collector/pdata/pprofile v0.140.0 
h1:b9TZ6UnyzsT/ERQw2VKGi/NYLtKSmjG7cgQuc9wZt5s=
+go.opentelemetry.io/collector/pdata/pprofile v0.140.0/go.mod 
h1:/2s/YBWGbu+r8MuKu5zas08iSqe+3P6xnbRpfE2DWAA=
 go.opentelemetry.io/collector/pdata/testdata v0.133.0 
h1:K0q47qecWVJf0sWbeWfifbJ72TiqR+A2PCsMkCEKvus=
 go.opentelemetry.io/collector/pdata/testdata v0.133.0/go.mod 
h1:/emFpIox/mi7FucvsSn54KsiMh/iy7BUviqgURNVT6U=
 go.opentelemetry.io/collector/pipeline v1.39.0 
h1:CcEn30qdoHEzehFxgx0Ma0pWYGhrrIkRkcu218NG4V4=
@@ -429,12 +425,12 @@
 go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod 
h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
 go.opentelemetry.io/otel/trace v1.38.0 
h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
 go.opentelemetry.io/otel/trace v1.38.0/go.mod 
h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
-go.opentelemetry.io/proto/slim/otlp v1.7.1 
h1:lZ11gEokjIWYM3JWOUrIILr2wcf6RX+rq5SPObV9oyc=
-go.opentelemetry.io/proto/slim/otlp v1.7.1/go.mod 
h1:uZ6LJWa49eNM/EXnnvJGTTu8miokU8RQdnO980LJ57g=
-go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.0.1 
h1:Tr/eXq6N7ZFjN+THBF/BtGLUz8dciA7cuzGRsCEkZ88=
-go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development 
v0.0.1/go.mod h1:riqUmAOJFDFuIAzZu/3V6cOrTyfWzpgNJnG5UwrapCk=
-go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.0.1 
h1:z/oMlrCv3Kopwh/dtdRagJy+qsRRPA86/Ux3g7+zFXM=
-go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.0.1/go.mod 
h1:C7EHYSIiaALi9RnNORCVaPCQDuJgJEn/XxkctaTez1E=
+go.opentelemetry.io/proto/slim/otlp v1.9.0 
h1:fPVMv8tP3TrsqlkH1HWYUpbCY9cAIemx184VGkS6vlE=
+go.opentelemetry.io/proto/slim/otlp v1.9.0/go.mod 
h1:xXdeJJ90Gqyll+orzUkY4bOd2HECo5JofeoLpymVqdI=
+go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0 
h1:o13nadWDNkH/quoDomDUClnQBpdQQ2Qqv0lQBjIXjE8=
+go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development 
v0.2.0/go.mod h1:Gyb6Xe7FTi/6xBHwMmngGoHqL0w29Y4eW8TGFzpefGA=
+go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0 
h1:EiUYvtwu6PMrMHVjcPfnsG3v+ajPkbUeH+IL93+QYyk=
+go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0/go.mod 
h1:mUUHKFiN2SST3AhJ8XhJxEoeVW12oqfXog0Bo8W3Ec4=
 go.uber.org/atomic v1.9.0/go.mod 
h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
 go.uber.org/atomic v1.11.0/go.mod 
h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
@@ -458,8 +454,8 @@
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod 
h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod 
h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.17.0/go.mod 
h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
-golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
-golang.org/x/crypto v0.46.0/go.mod 
h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
+golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
+golang.org/x/crypto v0.47.0/go.mod 
h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
 golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 
h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
 golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod 
h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
 golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod 
h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@@ -468,8 +464,8 @@
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod 
h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
-golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
+golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
+golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod 
h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod 
h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod 
h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -481,8 +477,8 @@
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod 
h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
-golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
+golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
+golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
 golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
 golang.org/x/oauth2 v0.34.0/go.mod 
h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -515,15 +511,15 @@
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
-golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
+golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod 
h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod 
h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/term v0.15.0/go.mod 
h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
-golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
-golang.org/x/term v0.38.0/go.mod 
h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
+golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
+golang.org/x/term v0.39.0/go.mod 
h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -531,8 +527,8 @@
 golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.14.0/go.mod 
h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
-golang.org/x/text v0.32.0/go.mod 
h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
+golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
+golang.org/x/text v0.33.0/go.mod 
h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
 golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
 golang.org/x/time v0.14.0/go.mod 
h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod 
h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -543,8 +539,8 @@
 golang.org/x/tools v0.1.1/go.mod 
h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod 
h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.6.0/go.mod 
h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
-golang.org/x/tools v0.39.0/go.mod 
h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
+golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
+golang.org/x/tools v0.40.0/go.mod 
h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -553,16 +549,16 @@
 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod 
h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
 gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
 gonum.org/v1/gonum v0.16.0/go.mod 
h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
-google.golang.org/api v0.258.0 h1:IKo1j5FBlN74fe5isA2PVozN3Y5pwNKriEgAXPOkDAc=
-google.golang.org/api v0.258.0/go.mod 
h1:qhOMTQEZ6lUps63ZNq9jhODswwjkjYYguA7fA3TBFww=
+google.golang.org/api v0.259.0 h1:90TaGVIxScrh1Vn/XI2426kRpBqHwWIzVBzJsVZ5XrQ=
+google.golang.org/api v0.259.0/go.mod 
h1:LC2ISWGWbRoyQVpxGntWwLWN/vLNxxKBK9KuJRI8Te4=
 google.golang.org/appengine v1.6.8 
h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
 google.golang.org/appengine v1.6.8/go.mod 
h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
-google.golang.org/genproto v0.0.0-20250603155806-513f23925822 
h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
-google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod 
h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
-google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda 
h1:+2XxjfsAu6vqFxwGBRcHiMaDCuZiqXGDUDVWVtrFAnE=
-google.golang.org/genproto/googleapis/api 
v0.0.0-20251029180050-ab9386a59fda/go.mod 
h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20251213004720-97cd9d5aeac2 
h1:2I6GHUeJ/4shcDpoUlLs/2WPnhg7yJwvXtqcMJt9liA=
-google.golang.org/genproto/googleapis/rpc 
v0.0.0-20251213004720-97cd9d5aeac2/go.mod 
h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
+google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217 
h1:GvESR9BIyHUahIb0NcTum6itIWtdoglGX+rnGxm2934=
+google.golang.org/genproto v0.0.0-20251202230838-ff82c1b0f217/go.mod 
h1:yJ2HH4EHEDTd3JiLmhds6NkJ17ITVYOdV3m3VKOnws0=
+google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 
h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls=
+google.golang.org/genproto/googleapis/api 
v0.0.0-20251202230838-ff82c1b0f217/go.mod 
h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b 
h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=
+google.golang.org/genproto/googleapis/rpc 
v0.0.0-20251222181119-0a764e51fe1b/go.mod 
h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
 google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
 google.golang.org/grpc v1.78.0/go.mod 
h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod 
h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/notes/coredns-1.14.1.md 
new/coredns-1.14.1/notes/coredns-1.14.1.md
--- old/coredns-1.14.0/notes/coredns-1.14.1.md  1970-01-01 01:00:00.000000000 
+0100
+++ new/coredns-1.14.1/notes/coredns-1.14.1.md  2026-01-16 05:47:07.000000000 
+0100
@@ -0,0 +1,24 @@
++++
+title = "CoreDNS-1.14. Release"
+description = "CoreDNS-1.14.1 Release Notes."
+tags = ["Release", "1.14.1", "Notes"]
+release = "1.14.1"
+date = "2026-01-15T00:00:00+00:00"
+author = "coredns"
++++
+
+This release primarily addresses security vulnerabilities affecting Go 
versions prior to
+Go 1.25.6 and Go 1.24.12 (CVE-2025-61728, CVE-2025-61726, CVE-2025-68121, 
CVE-2025-61731,
+CVE-2025-68119). It also includes performance improvements to the proxy plugin 
via
+multiplexed connections, along with various documentation updates.
+
+## Brought to You By
+
+Alex Massy
+Shiv Tyagi
+Ville Vesilehto
+Yong Tang
+
+## Noteworthy Changes
+
+* plugin/proxy: Use mutex-based connection pool 
(https://github.com/coredns/coredns/pull/7790)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/plugin/forward/README.md 
new/coredns-1.14.1/plugin/forward/README.md
--- old/coredns-1.14.0/plugin/forward/README.md 2026-01-07 05:21:18.000000000 
+0100
+++ new/coredns-1.14.1/plugin/forward/README.md 2026-01-16 05:47:07.000000000 
+0100
@@ -44,6 +44,7 @@
     force_tcp
     prefer_udp
     expire DURATION
+    max_idle_conns INTEGER
     max_fails INTEGER
     max_connect_attempts INTEGER
     tls CERT KEY CA
@@ -71,6 +72,8 @@
   performed for a single incoming DNS request. Default value of 0 means no 
per-request
   cap.
 * `expire` **DURATION**, expire (cached) connections after this time, the 
default is 10s.
+* `max_idle_conns` **INTEGER**, maximum number of idle connections to cache 
per upstream for reuse.
+  Default is 0, which means unlimited.
 * `tls` **CERT** **KEY** **CA** define the TLS properties for TLS connection. 
From 0 to 3 arguments can be
   provided with the meaning as described below
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/plugin/forward/forward.go 
new/coredns-1.14.1/plugin/forward/forward.go
--- old/coredns-1.14.0/plugin/forward/forward.go        2026-01-07 
05:21:18.000000000 +0100
+++ new/coredns-1.14.1/plugin/forward/forward.go        2026-01-16 
05:47:07.000000000 +0100
@@ -49,6 +49,7 @@
        tlsServerName              string
        maxfails                   uint32
        expire                     time.Duration
+       maxIdleConns               int
        maxConcurrent              int64
        failfastUnhealthyUpstreams bool
        failoverRcodes             []int
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/plugin/forward/setup.go 
new/coredns-1.14.1/plugin/forward/setup.go
--- old/coredns-1.14.0/plugin/forward/setup.go  2026-01-07 05:21:18.000000000 
+0100
+++ new/coredns-1.14.1/plugin/forward/setup.go  2026-01-16 05:47:07.000000000 
+0100
@@ -196,6 +196,7 @@
                        }
                }
                f.proxies[i].SetExpire(f.expire)
+               f.proxies[i].SetMaxIdleConns(f.maxIdleConns)
                
f.proxies[i].GetHealthchecker().SetRecursionDesired(f.opts.HCRecursionDesired)
                // when TLS is used, checks are set to tcp-tls
                if f.opts.ForceTCP && transports[i] != transport.TLS {
@@ -311,6 +312,18 @@
                        return fmt.Errorf("expire can't be negative: %s", dur)
                }
                f.expire = dur
+       case "max_idle_conns":
+               if !c.NextArg() {
+                       return c.ArgErr()
+               }
+               n, err := strconv.Atoi(c.Val())
+               if err != nil {
+                       return err
+               }
+               if n < 0 {
+                       return fmt.Errorf("max_idle_conns can't be negative: 
%d", n)
+               }
+               f.maxIdleConns = n
        case "policy":
                if !c.NextArg() {
                        return c.ArgErr()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/plugin/forward/setup_test.go 
new/coredns-1.14.1/plugin/forward/setup_test.go
--- old/coredns-1.14.0/plugin/forward/setup_test.go     2026-01-07 
05:21:18.000000000 +0100
+++ new/coredns-1.14.1/plugin/forward/setup_test.go     2026-01-16 
05:47:07.000000000 +0100
@@ -365,6 +365,48 @@
        }
 }
 
+func TestSetupMaxIdleConns(t *testing.T) {
+       tests := []struct {
+               input       string
+               shouldErr   bool
+               expectedVal int
+               expectedErr string
+       }{
+               {"forward . 127.0.0.1\n", false, 0, ""},
+               {"forward . 127.0.0.1 {\nmax_idle_conns 10\n}\n", false, 10, 
""},
+               {"forward . 127.0.0.1 {\nmax_idle_conns 0\n}\n", false, 0, ""},
+               {"forward . 127.0.0.1 {\nmax_idle_conns many\n}\n", true, 0, 
"invalid"},
+               {"forward . 127.0.0.1 {\nmax_idle_conns -1\n}\n", true, 0, 
"negative"},
+       }
+
+       for i, test := range tests {
+               c := caddy.NewTestController("dns", test.input)
+               fs, err := parseForward(c)
+
+               if test.shouldErr && err == nil {
+                       t.Errorf("Test %d: expected error but found none for 
input %s", i, test.input)
+               }
+
+               if err != nil {
+                       if !test.shouldErr {
+                               t.Errorf("Test %d: expected no error but found 
one for input %s, got: %v", i, test.input, err)
+                       }
+
+                       if !strings.Contains(err.Error(), test.expectedErr) {
+                               t.Errorf("Test %d: expected error to contain: 
%v, found error: %v, input: %s", i, test.expectedErr, err, test.input)
+                       }
+               }
+
+               if test.shouldErr {
+                       continue
+               }
+               f := fs[0]
+               if f.maxIdleConns != test.expectedVal {
+                       t.Errorf("Test %d: expected: %d, got: %d", i, 
test.expectedVal, f.maxIdleConns)
+               }
+       }
+}
+
 func TestSetupHealthCheck(t *testing.T) {
        tests := []struct {
                input          string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/plugin/pkg/proxy/connect.go 
new/coredns-1.14.1/plugin/pkg/proxy/connect.go
--- old/coredns-1.14.0/plugin/pkg/proxy/connect.go      2026-01-07 
05:21:18.000000000 +0100
+++ new/coredns-1.14.1/plugin/pkg/proxy/connect.go      2026-01-16 
05:47:07.000000000 +0100
@@ -1,7 +1,6 @@
-// Package proxy implements a forwarding proxy. It caches an upstream net.Conn 
for some time, so if the same
-// client returns the upstream's Conn will be precached. Depending on how you 
benchmark this looks to be
-// 50% faster than just opening a new connection for every client. It works 
with UDP and TCP and uses
-// inband healthchecking.
+// Package proxy implements a forwarding proxy with connection caching.
+// It manages a pool of upstream connections (UDP and TCP) to reuse them for 
subsequent requests,
+// reducing latency and handshake overhead. It supports in-band health 
checking.
 package proxy
 
 import (
@@ -19,10 +18,7 @@
 )
 
 const (
-       ErrTransportStopped              = "proxy: transport stopped"
-       ErrTransportStoppedDuringDial    = "proxy: transport stopped during 
dial"
-       ErrTransportStoppedRetClosed     = "proxy: transport stopped, ret 
channel closed"
-       ErrTransportStoppedDuringRetWait = "proxy: transport stopped during ret 
wait"
+       ErrTransportStopped = "proxy: transport stopped"
 )
 
 // limitTimeout is a utility function to auto-tune timeout values
@@ -66,41 +62,35 @@
        default:
        }
 
-       // Use select to avoid blocking if connManager has stopped
-       select {
-       case t.dial <- proto:
-               // Successfully sent dial request
-       case <-t.stop:
-               return nil, false, errors.New(ErrTransportStoppedDuringDial)
-       }
+       transtype := stringToTransportType(proto)
 
-       // Receive response with stop awareness
-       select {
-       case pc, ok := <-t.ret:
-               if !ok {
-                       // ret channel was closed by connManager during stop
-                       return nil, false, 
errors.New(ErrTransportStoppedRetClosed)
+       t.mu.Lock()
+       // FIFO: take the oldest conn (front of slice) for source port diversity
+       for len(t.conns[transtype]) > 0 {
+               pc := t.conns[transtype][0]
+               t.conns[transtype] = t.conns[transtype][1:]
+               if time.Since(pc.used) > t.expire {
+                       pc.c.Close()
+                       continue
                }
-
-               if pc != nil {
-                       connCacheHitsCount.WithLabelValues(t.proxyName, t.addr, 
proto).Add(1)
-                       return pc, true, nil
-               }
-               connCacheMissesCount.WithLabelValues(t.proxyName, t.addr, 
proto).Add(1)
-
-               reqTime := time.Now()
-               timeout := t.dialTimeout()
-               if proto == "tcp-tls" {
-                       conn, err := dns.DialTimeoutWithTLS("tcp", t.addr, 
t.tlsConfig, timeout)
-                       t.updateDialTimeout(time.Since(reqTime))
-                       return &persistConn{c: conn}, false, err
-               }
-               conn, err := dns.DialTimeout(proto, t.addr, timeout)
+               t.mu.Unlock()
+               connCacheHitsCount.WithLabelValues(t.proxyName, t.addr, 
proto).Add(1)
+               return pc, true, nil
+       }
+       t.mu.Unlock()
+
+       connCacheMissesCount.WithLabelValues(t.proxyName, t.addr, proto).Add(1)
+
+       reqTime := time.Now()
+       timeout := t.dialTimeout()
+       if proto == "tcp-tls" {
+               conn, err := dns.DialTimeoutWithTLS("tcp", t.addr, t.tlsConfig, 
timeout)
                t.updateDialTimeout(time.Since(reqTime))
                return &persistConn{c: conn}, false, err
-       case <-t.stop:
-               return nil, false, errors.New(ErrTransportStoppedDuringRetWait)
        }
+       conn, err := dns.DialTimeout(proto, t.addr, timeout)
+       t.updateDialTimeout(time.Since(reqTime))
+       return &persistConn{c: conn}, false, err
 }
 
 // Connect selects an upstream, sends the request and waits for a response.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/plugin/pkg/proxy/connect_test.go 
new/coredns-1.14.1/plugin/pkg/proxy/connect_test.go
--- old/coredns-1.14.0/plugin/pkg/proxy/connect_test.go 2026-01-07 
05:21:18.000000000 +0100
+++ new/coredns-1.14.1/plugin/pkg/proxy/connect_test.go 2026-01-16 
05:47:07.000000000 +0100
@@ -1,7 +1,6 @@
 package proxy
 
 import (
-       "sync"
        "testing"
        "time"
 )
@@ -30,209 +29,6 @@
        }
 }
 
-// TestDial_TransportStoppedDuringDialSend tests that Dial returns 
ErrTransportStoppedDuringDial
-// if Stop() is called while Dial is attempting to send on the (blocked) 
t.dial channel.
-// This is achieved by not starting the connManager, so t.dial remains unread.
-func TestDial_TransportStoppedDuringDialSend(t *testing.T) {
-       tr := newTransport("test_during_dial_send", "127.0.0.1:0")
-       // No tr.Start() here. This ensures t.dial channel will block.
-
-       dialErrChan := make(chan error, 1)
-       go func() {
-               // Dial will pass initial stop check (t.stop is open).
-               // Then it will block on `t.dial <- proto` because no 
connManager is reading.
-               _, _, err := tr.Dial("udp")
-               dialErrChan <- err
-       }()
-
-       // Allow Dial goroutine to reach the blocking send on t.dial
-       time.Sleep(50 * time.Millisecond)
-
-       tr.Stop() // Close t.stop. Dial's select should now pick <-t.stop.
-
-       err := <-dialErrChan
-       if err == nil {
-               t.Fatalf("%s: %s", testMsgExpectedError, 
testMsgUnexpectedNilError)
-       }
-       if err.Error() != ErrTransportStoppedDuringDial {
-               t.Errorf("%s: got '%v', want '%s'", testMsgWrongError, err, 
ErrTransportStoppedDuringDial)
-       }
-}
-
-// TestDial_TransportStoppedDuringRetWait tests that Dial returns 
ErrTransportStoppedDuringRetWait
-// when the transport is stopped while Dial is waiting to receive from t.ret 
channel.
-func TestDial_TransportStoppedDuringRetWait(t *testing.T) {
-       tr := newTransport("test_during_ret_wait", "127.0.0.1:0")
-       // Replace transport's channels to control interaction precisely
-       tr.dial = make(chan string)      // Test-controlled, unbuffered
-       tr.ret = make(chan *persistConn) // Test-controlled, unbuffered
-       // tr.stop remains the original transport stop channel
-
-       // NOTE: We purposefully do not call tr.Start() here, instead we
-       // manually simulate connManager behavior below
-
-       dialErrChan := make(chan error, 1)
-       wg := sync.WaitGroup{}
-       wg.Add(1)
-
-       go func() {
-               defer wg.Done()
-               // Dial will:
-               // 1. Pass initial stop check.
-               // 2. Send on our tr.dial.
-               // 3. Block on our tr.ret in its 3rd select.
-               //    When tr.Stop() is called, this 3rd select should pick 
<-tr.stop.
-               _, _, err := tr.Dial("udp")
-               dialErrChan <- err
-       }()
-
-       // Simulate connManager reading from our tr.dial.
-       // This unblocks the Dial goroutine's send.
-       var protoFromDial string
-       select {
-       case protoFromDial = <-tr.dial:
-               t.Logf("Simulated connManager read '%s' from Dial via 
test-controlled tr.dial", protoFromDial)
-       case <-time.After(500 * time.Millisecond):
-               t.Fatal("Timeout waiting for Dial to send on test-controlled 
tr.dial")
-       }
-
-       // Stop the transport and the tr.stop channel
-       tr.Stop()
-
-       wg.Wait() // Wait for Dial goroutine to complete.
-       err := <-dialErrChan
-
-       if err == nil {
-               t.Fatalf("%s: %s", testMsgExpectedError, 
testMsgUnexpectedNilError)
-       }
-
-       // Expected error is ErrTransportStoppedDuringRetWait
-       // However, if connManager (using replaced channels) itself reacts to 
stop faster
-       // and somehow closes the test-controlled tr.ret (not its design), 
other errors are possible.
-       // But with tr.ret being ours and unwritten-to, Dial should pick 
tr.stop.
-       if err.Error() != ErrTransportStoppedDuringRetWait {
-               t.Errorf("%s: got '%v', want '%s' (or potentially '%s' if 
timing is very tight)",
-                       testMsgWrongError, err, 
ErrTransportStoppedDuringRetWait, ErrTransportStopped)
-       } else {
-               t.Logf("Dial correctly returned '%s'", 
ErrTransportStoppedDuringRetWait)
-       }
-}
-
-// TestDial_Returns_ErrTransportStoppedRetClosed tests that Dial
-// returns ErrTransportStoppedRetClosed when tr.ret is closed before Dial 
reads from it.
-func TestDial_Returns_ErrTransportStoppedRetClosed(t *testing.T) {
-       tr := newTransport("test_returns_ret_closed", "127.0.0.1:0")
-
-       // Replace transport channels with test-controlled ones
-       testDialChan := make(chan string, 1)   // Buffered to allow 
non-blocking send by Dial
-       testRetChan := make(chan *persistConn) // This will be closed by the 
test
-       tr.dial = testDialChan
-       tr.ret = testRetChan
-       // tr.stop remains the original, initially open channel.
-
-       dialErrChan := make(chan error, 1)
-       var wg sync.WaitGroup
-       wg.Add(1)
-
-       go func() {
-               defer wg.Done()
-               // Dial will:
-               // 1. Pass initial stop check (tr.stop is open).
-               // 2. Send "udp" on tr.dial (which is testDialChan).
-               // 3. Block on <-tr.ret (which is testRetChan) in its 3rd 
select.
-               //    When testRetChan is closed, it will read (nil, false), 
hitting the target error.
-               _, _, err := tr.Dial("udp")
-               dialErrChan <- err
-       }()
-
-       // Step 1: Simulate connManager reading the dial request from Dial.
-       // Read from testDialChan. This unblocks the Dial goroutine's send to 
testDialChan.
-       select {
-       case proto := <-testDialChan:
-               if proto != "udp" {
-                       wg.Done()
-                       t.Fatalf("Dial sent wrong proto on testDialChan: got 
%s, want udp", proto)
-               }
-               t.Logf("Simulated connManager received '%s' from Dial via 
testDialChan.", proto)
-       case <-time.After(500 * time.Millisecond):
-               // If Dial didn't send, the test is flawed or Dial is stuck 
before sending.
-               wg.Done()
-               t.Fatal("Timeout waiting for Dial to send on testDialChan.")
-       }
-
-       // Step 2: Simulate connManager stopping and closing its 'ret' channel.
-       close(testRetChan)
-       t.Logf("Closed testRetChan (simulating connManager closing tr.ret).")
-
-       // Step 3: Wait for the Dial goroutine to complete.
-       wg.Wait()
-       err := <-dialErrChan
-
-       if err == nil {
-               t.Fatalf("%s: %s", testMsgExpectedError, 
testMsgUnexpectedNilError)
-       }
-
-       if err.Error() != ErrTransportStoppedRetClosed {
-               t.Errorf("%s: got '%v', want '%s'", testMsgWrongError, err, 
ErrTransportStoppedRetClosed)
-       } else {
-               t.Logf("Dial correctly returned '%s'", 
ErrTransportStoppedRetClosed)
-       }
-
-       // Call tr.Stop() for completeness to close the original tr.stop 
channel.
-       // connManager was not started with original channels, so this mainly 
affects tr.stop.
-       tr.Stop()
-}
-
-// TestDial_ConnManagerClosesRetOnStop verifies that connManager closes tr.ret 
upon stopping.
-func TestDial_ConnManagerClosesRetOnStop(t *testing.T) {
-       tr := newTransport("test_connmanager_closes_ret", "127.0.0.1:0")
-       tr.Start()
-
-       // Initiate a Dial to interact with connManager so tr.ret is used.
-       interactionDialErrChan := make(chan error, 1)
-       go func() {
-               _, _, err := tr.Dial("udp")
-               interactionDialErrChan <- err
-       }()
-
-       // Allow the Dial goroutine to interact with connManager.
-       time.Sleep(100 * time.Millisecond)
-
-       // Now stop the transport. connManager should clean up and close tr.ret.
-       tr.Stop()
-
-       // Wait for connManager to fully stop and close its channels.
-       // This duration needs to be sufficient for the select loop in 
connManager to see <-t.stop,
-       // call t.cleanup(true), which in turn calls close(t.ret).
-       time.Sleep(50 * time.Millisecond)
-
-       // Check if tr.ret is actually closed by trying a non-blocking read.
-       select {
-       case _, ok := <-tr.ret:
-               if !ok {
-                       t.Logf("tr.ret channel is closed as expected after 
transport stop.")
-               } else {
-                       t.Errorf("tr.ret channel was not closed after transport 
stop, or a value was read unexpectedly.")
-               }
-       default:
-               // This case means tr.ret is open but blocking (empty).
-               // This would be unexpected if connManager is supposed to close 
it on stop.
-               t.Errorf("tr.ret channel is not closed and is blocking (or 
empty but open).")
-       }
-
-       // Drain the error channel from the initial interaction Dial to ensure 
the goroutine finishes.
-       select {
-       case err := <-interactionDialErrChan:
-               if err != nil {
-                       t.Logf("Interaction Dial completed with error (possibly 
expected due to 127.0.0.1:0 or race with Stop): %v", err)
-               } else {
-                       t.Logf("Interaction Dial completed without error.")
-               }
-       case <-time.After(500 * time.Millisecond): // Timeout for safety if 
Dial hangs
-               t.Logf("Timeout waiting for interaction Dial to complete.")
-       }
-}
-
 // TestDial_MultipleCallsAfterStop tests that multiple Dial calls after Stop
 // consistently return ErrTransportStopped.
 func TestDial_MultipleCallsAfterStop(t *testing.T) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/plugin/pkg/proxy/persistent.go 
new/coredns-1.14.1/plugin/pkg/proxy/persistent.go
--- old/coredns-1.14.0/plugin/pkg/proxy/persistent.go   2026-01-07 
05:21:18.000000000 +0100
+++ new/coredns-1.14.1/plugin/pkg/proxy/persistent.go   2026-01-16 
05:47:07.000000000 +0100
@@ -3,6 +3,7 @@
 import (
        "crypto/tls"
        "sort"
+       "sync"
        "time"
 
        "github.com/miekg/dns"
@@ -16,17 +17,16 @@
 
 // Transport hold the persistent cache.
 type Transport struct {
-       avgDialTime int64                          // kind of average time of 
dial time
-       conns       [typeTotalCount][]*persistConn // Buckets for udp, tcp and 
tcp-tls.
-       expire      time.Duration                  // After this duration a 
connection is expired.
-       addr        string
-       tlsConfig   *tls.Config
-       proxyName   string
-
-       dial  chan string
-       yield chan *persistConn
-       ret   chan *persistConn
-       stop  chan bool
+       avgDialTime  int64                          // kind of average time of 
dial time
+       conns        [typeTotalCount][]*persistConn // Buckets for udp, tcp and 
tcp-tls.
+       expire       time.Duration                  // After this duration a 
connection is expired.
+       maxIdleConns int                            // Max idle connections per 
transport type; 0 means unlimited.
+       addr         string
+       tlsConfig    *tls.Config
+       proxyName    string
+
+       mu   sync.Mutex
+       stop chan struct{}
 }
 
 func newTransport(proxyName, addr string) *Transport {
@@ -35,10 +35,7 @@
                conns:       [typeTotalCount][]*persistConn{},
                expire:      defaultExpire,
                addr:        addr,
-               dial:        make(chan string),
-               yield:       make(chan *persistConn),
-               ret:         make(chan *persistConn),
-               stop:        make(chan bool),
+               stop:        make(chan struct{}),
                proxyName:   proxyName,
        }
        return t
@@ -48,38 +45,12 @@
 func (t *Transport) connManager() {
        ticker := time.NewTicker(defaultExpire)
        defer ticker.Stop()
-Wait:
        for {
                select {
-               case proto := <-t.dial:
-                       transtype := stringToTransportType(proto)
-                       // take the last used conn - complexity O(1)
-                       if stack := t.conns[transtype]; len(stack) > 0 {
-                               pc := stack[len(stack)-1]
-                               if time.Since(pc.used) < t.expire {
-                                       // Found one, remove from pool and 
return this conn.
-                                       t.conns[transtype] = 
stack[:len(stack)-1]
-                                       t.ret <- pc
-                                       continue Wait
-                               }
-                               // clear entire cache if the last conn is 
expired
-                               t.conns[transtype] = nil
-                               // now, the connections being passed to 
closeConns() are not reachable from
-                               // transport methods anymore. So, it's safe to 
close them in a separate goroutine
-                               go closeConns(stack)
-                       }
-                       t.ret <- nil
-
-               case pc := <-t.yield:
-                       transtype := t.transportTypeFromConn(pc)
-                       t.conns[transtype] = append(t.conns[transtype], pc)
-
                case <-ticker.C:
                        t.cleanup(false)
-
                case <-t.stop:
                        t.cleanup(true)
-                       close(t.ret)
                        return
                }
        }
@@ -94,6 +65,9 @@
 
 // cleanup removes connections from cache.
 func (t *Transport) cleanup(all bool) {
+       var toClose []*persistConn
+
+       t.mu.Lock()
        staleTime := time.Now().Add(-t.expire)
        for transtype, stack := range t.conns {
                if len(stack) == 0 {
@@ -101,9 +75,7 @@
                }
                if all {
                        t.conns[transtype] = nil
-                       // now, the connections being passed to closeConns() 
are not reachable from
-                       // transport methods anymore. So, it's safe to close 
them in a separate goroutine
-                       go closeConns(stack)
+                       toClose = append(toClose, stack...)
                        continue
                }
                if stack[0].used.After(staleTime) {
@@ -115,34 +87,38 @@
                        return stack[i].used.After(staleTime)
                })
                t.conns[transtype] = stack[good:]
-               // now, the connections being passed to closeConns() are not 
reachable from
-               // transport methods anymore. So, it's safe to close them in a 
separate goroutine
-               go closeConns(stack[:good])
+               toClose = append(toClose, stack[:good]...)
        }
-}
+       t.mu.Unlock()
 
-// It is hard to pin a value to this, the import thing is to no block forever, 
losing at cached connection is not terrible.
-const yieldTimeout = 25 * time.Millisecond
+       // Close connections after releasing lock
+       closeConns(toClose)
+}
 
 // Yield returns the connection to transport for reuse.
 func (t *Transport) Yield(pc *persistConn) {
-       pc.used = time.Now() // update used time
-
-       // Optimization: Try to return the connection immediately without 
creating a timer.
-       // If the receiver is not ready, we fall back to a timeout-based send 
to avoid blocking forever.
-       // Returning the connection is just an optimization, so dropping it on 
timeout is fine.
+       // Check if transport is stopped before acquiring lock
        select {
-       case t.yield <- pc:
+       case <-t.stop:
+               // If stopped, don't return to pool, just close
+               pc.c.Close()
                return
        default:
        }
 
-       select {
-       case t.yield <- pc:
-               return
-       case <-time.After(yieldTimeout):
+       pc.used = time.Now() // update used time
+
+       t.mu.Lock()
+       defer t.mu.Unlock()
+
+       transtype := t.transportTypeFromConn(pc)
+
+       if t.maxIdleConns > 0 && len(t.conns[transtype]) >= t.maxIdleConns {
+               pc.c.Close()
                return
        }
+
+       t.conns[transtype] = append(t.conns[transtype], pc)
 }
 
 // Start starts the transport's connection manager.
@@ -154,6 +130,10 @@
 // SetExpire sets the connection expire time in transport.
 func (t *Transport) SetExpire(expire time.Duration) { t.expire = expire }
 
+// SetMaxIdleConns sets the maximum idle connections per transport type.
+// A value of 0 means unlimited (default).
+func (t *Transport) SetMaxIdleConns(n int) { t.maxIdleConns = n }
+
 // SetTLSConfig sets the TLS config in transport.
 func (t *Transport) SetTLSConfig(cfg *tls.Config) { t.tlsConfig = cfg }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/plugin/pkg/proxy/persistent_test.go 
new/coredns-1.14.1/plugin/pkg/proxy/persistent_test.go
--- old/coredns-1.14.0/plugin/pkg/proxy/persistent_test.go      2026-01-07 
05:21:18.000000000 +0100
+++ new/coredns-1.14.1/plugin/pkg/proxy/persistent_test.go      2026-01-16 
05:47:07.000000000 +0100
@@ -35,8 +35,9 @@
        if !cached3 {
                t.Error("Expected cached connection (c3)")
        }
-       if c2 != c3 {
-               t.Error("Expected c2 == c3")
+       // FIFO: first yielded (c1) should be first out
+       if c1 != c3 {
+               t.Error("Expected c1 == c3 (FIFO order)")
        }
 
        tr.Yield(c3)
@@ -109,6 +110,122 @@
        }
 }
 
+func TestMaxIdleConns(t *testing.T) {
+       s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
+               ret := new(dns.Msg)
+               ret.SetReply(r)
+               w.WriteMsg(ret)
+       })
+       defer s.Close()
+
+       tr := newTransport("TestMaxIdleConns", s.Addr)
+       tr.SetMaxIdleConns(2) // Limit to 2 connections per type
+       tr.Start()
+       defer tr.Stop()
+
+       // Dial 3 connections
+       c1, _, _ := tr.Dial("udp")
+       c2, _, _ := tr.Dial("udp")
+       c3, _, _ := tr.Dial("udp")
+
+       // Yield all 3
+       tr.Yield(c1)
+       tr.Yield(c2)
+       tr.Yield(c3) // This should be discarded (pool full)
+
+       // Check pool size is capped at 2
+       tr.mu.Lock()
+       poolSize := len(tr.conns[typeUDP])
+       tr.mu.Unlock()
+
+       if poolSize != 2 {
+               t.Errorf("Expected pool size 2, got %d", poolSize)
+       }
+
+       // Verify we get the first 2 back (FIFO)
+       d1, cached1, _ := tr.Dial("udp")
+       d2, cached2, _ := tr.Dial("udp")
+       _, cached3, _ := tr.Dial("udp")
+
+       if !cached1 || !cached2 {
+               t.Error("Expected first 2 dials to be cached")
+       }
+       if cached3 {
+               t.Error("Expected 3rd dial to be non-cached (pool was limited 
to 2)")
+       }
+       if d1 != c1 || d2 != c2 {
+               t.Error("Expected FIFO order: d1==c1, d2==c2")
+       }
+}
+
+func TestMaxIdleConnsUnlimited(t *testing.T) {
+       s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
+               ret := new(dns.Msg)
+               ret.SetReply(r)
+               w.WriteMsg(ret)
+       })
+       defer s.Close()
+
+       tr := newTransport("TestMaxIdleConnsUnlimited", s.Addr)
+       // maxIdleConns defaults to 0 (unlimited)
+       tr.Start()
+       defer tr.Stop()
+
+       // Dial and yield 5 connections
+       conns := make([]*persistConn, 5)
+       for i := range conns {
+               conns[i], _, _ = tr.Dial("udp")
+       }
+       for _, c := range conns {
+               tr.Yield(c)
+       }
+
+       // Check all 5 are in pool
+       tr.mu.Lock()
+       poolSize := len(tr.conns[typeUDP])
+       tr.mu.Unlock()
+
+       if poolSize != 5 {
+               t.Errorf("Expected pool size 5 (unlimited), got %d", poolSize)
+       }
+}
+
+func TestYieldAfterStop(t *testing.T) {
+       s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
+               ret := new(dns.Msg)
+               ret.SetReply(r)
+               w.WriteMsg(ret)
+       })
+       defer s.Close()
+
+       tr := newTransport("TestYieldAfterStop", s.Addr)
+       tr.Start()
+
+       // Dial a connection while transport is running
+       c1, _, err := tr.Dial("udp")
+       if err != nil {
+               t.Fatalf("Failed to dial: %v", err)
+       }
+
+       // Stop the transport
+       tr.Stop()
+
+       // Give cleanup goroutine time to exit
+       time.Sleep(50 * time.Millisecond)
+
+       // Yield the connection after stop - should close it, not pool it
+       tr.Yield(c1)
+
+       // Verify pool is empty (connection was closed, not added)
+       tr.mu.Lock()
+       poolSize := len(tr.conns[typeUDP])
+       tr.mu.Unlock()
+
+       if poolSize != 0 {
+               t.Errorf("Expected pool size 0 after stop, got %d", poolSize)
+       }
+}
+
 func BenchmarkYield(b *testing.B) {
        s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
                ret := new(dns.Msg)
@@ -127,12 +244,12 @@
 
        for b.Loop() {
                tr.Yield(c)
-               // Drain the yield channel so we can yield again without 
blocking/timing out
-               // We need to simulate the consumer side slightly to keep Yield 
flowing
-               select {
-               case <-tr.yield:
-               default:
+               // Simulate FIFO consumption: remove from front
+               tr.mu.Lock()
+               if len(tr.conns[typeUDP]) > 0 {
+                       tr.conns[typeUDP] = tr.conns[typeUDP][1:]
                }
+               tr.mu.Unlock()
                runtime.Gosched()
        }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/plugin/pkg/proxy/proxy.go 
new/coredns-1.14.1/plugin/pkg/proxy/proxy.go
--- old/coredns-1.14.0/plugin/pkg/proxy/proxy.go        2026-01-07 
05:21:18.000000000 +0100
+++ new/coredns-1.14.1/plugin/pkg/proxy/proxy.go        2026-01-16 
05:47:07.000000000 +0100
@@ -52,6 +52,10 @@
 // SetExpire sets the expire duration in the lower p.transport.
 func (p *Proxy) SetExpire(expire time.Duration) { 
p.transport.SetExpire(expire) }
 
+// SetMaxIdleConns sets the maximum idle connections per transport type.
+// A value of 0 means unlimited (default).
+func (p *Proxy) SetMaxIdleConns(n int) { p.transport.SetMaxIdleConns(n) }
+
 func (p *Proxy) GetHealthchecker() HealthChecker {
        return p.health
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/plugin/pkg/proxy/proxy_test.go 
new/coredns-1.14.1/plugin/pkg/proxy/proxy_test.go
--- old/coredns-1.14.0/plugin/pkg/proxy/proxy_test.go   2026-01-07 
05:21:18.000000000 +0100
+++ new/coredns-1.14.1/plugin/pkg/proxy/proxy_test.go   2026-01-16 
05:47:07.000000000 +0100
@@ -5,6 +5,7 @@
        "crypto/tls"
        "errors"
        "math"
+       "net"
        "testing"
        "time"
 
@@ -73,30 +74,66 @@
 }
 
 func TestProtocolSelection(t *testing.T) {
-       p := NewProxy("TestProtocolSelection", "bad_address", transport.DNS)
-       p.readTimeout = 10 * time.Millisecond
+       testCases := []struct {
+               name          string
+               requestTCP    bool // true = TCP request, false = UDP request
+               opts          Options
+               expectedProto string
+       }{
+               {"UDP request, no options", false, Options{}, "udp"},
+               {"UDP request, ForceTCP", false, Options{ForceTCP: true}, 
"tcp"},
+               {"UDP request, PreferUDP", false, Options{PreferUDP: true}, 
"udp"},
+               {"UDP request, ForceTCP+PreferUDP", false, Options{ForceTCP: 
true, PreferUDP: true}, "tcp"},
+               {"TCP request, no options", true, Options{}, "tcp"},
+               {"TCP request, ForceTCP", true, Options{ForceTCP: true}, "tcp"},
+               {"TCP request, PreferUDP", true, Options{PreferUDP: true}, 
"udp"},
+               {"TCP request, ForceTCP+PreferUDP", true, Options{ForceTCP: 
true, PreferUDP: true}, "tcp"},
+       }
 
-       stateUDP := request.Request{W: &test.ResponseWriter{}, Req: 
new(dns.Msg)}
-       stateTCP := request.Request{W: &test.ResponseWriter{TCP: true}, Req: 
new(dns.Msg)}
-       ctx := context.TODO()
-
-       go func() {
-               p.Connect(ctx, stateUDP, Options{})
-               p.Connect(ctx, stateUDP, Options{ForceTCP: true})
-               p.Connect(ctx, stateUDP, Options{PreferUDP: true})
-               p.Connect(ctx, stateUDP, Options{PreferUDP: true, ForceTCP: 
true})
-               p.Connect(ctx, stateTCP, Options{})
-               p.Connect(ctx, stateTCP, Options{ForceTCP: true})
-               p.Connect(ctx, stateTCP, Options{PreferUDP: true})
-               p.Connect(ctx, stateTCP, Options{PreferUDP: true, ForceTCP: 
true})
-       }()
-
-       for i, exp := range []string{"udp", "tcp", "udp", "tcp", "tcp", "tcp", 
"udp", "tcp"} {
-               proto := <-p.transport.dial
-               p.transport.ret <- nil
-               if proto != exp {
-                       t.Errorf("Unexpected protocol in case %d, expected %q, 
actual %q", i, exp, proto)
-               }
+       for _, tc := range testCases {
+               t.Run(tc.name, func(t *testing.T) {
+                       // Track which protocol the server received (use 
channel to avoid data race)
+                       protoChan := make(chan string, 1)
+                       s := dnstest.NewServer(func(w dns.ResponseWriter, r 
*dns.Msg) {
+                               // Determine protocol from the connection type
+                               if _, ok := w.RemoteAddr().(*net.TCPAddr); ok {
+                                       protoChan <- "tcp"
+                               } else {
+                                       protoChan <- "udp"
+                               }
+                               ret := new(dns.Msg)
+                               ret.SetReply(r)
+                               ret.Answer = append(ret.Answer, 
test.A("example.org. IN A 127.0.0.1"))
+                               w.WriteMsg(ret)
+                       })
+                       defer s.Close()
+
+                       p := NewProxy("TestProtocolSelection", s.Addr, 
transport.DNS)
+                       p.readTimeout = 1 * time.Second
+                       p.Start(5 * time.Second)
+                       defer p.Stop()
+
+                       m := new(dns.Msg)
+                       m.SetQuestion("example.org.", dns.TypeA)
+
+                       req := request.Request{
+                               W:   &test.ResponseWriter{TCP: tc.requestTCP},
+                               Req: m,
+                       }
+
+                       resp, err := p.Connect(context.Background(), req, 
tc.opts)
+                       if err != nil {
+                               t.Fatalf("Connect failed: %v", err)
+                       }
+                       if resp == nil {
+                               t.Fatal("Expected response, got nil")
+                       }
+
+                       receivedProto := <-protoChan
+                       if receivedProto != tc.expectedProto {
+                               t.Errorf("Expected protocol %q, but server 
received %q", tc.expectedProto, receivedProto)
+                       }
+               })
        }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/coredns-1.14.0/test/proxy_test.go 
new/coredns-1.14.1/test/proxy_test.go
--- old/coredns-1.14.0/test/proxy_test.go       2026-01-07 05:21:18.000000000 
+0100
+++ new/coredns-1.14.1/test/proxy_test.go       2026-01-16 05:47:07.000000000 
+0100
@@ -1,8 +1,14 @@
 package test
 
 import (
+       "context"
+       "fmt"
+       "net"
        "testing"
 
+       "github.com/coredns/coredns/plugin/forward"
+       "github.com/coredns/coredns/plugin/pkg/dnstest"
+       "github.com/coredns/coredns/plugin/pkg/proxy"
        "github.com/coredns/coredns/plugin/test"
 
        "github.com/miekg/dns"
@@ -76,3 +82,72 @@
                }
        }
 }
+
+// BenchmarkProxyWithMultipleBackends verifies the serialization issue by 
running concurrent load
+// against 1, 2, and 3 backend proxies using the forward plugin.
+func BenchmarkProxyWithMultipleBackends(b *testing.B) {
+       // Start a dummy upstream server
+       s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
+               ret := new(dns.Msg)
+               ret.SetReply(r)
+               w.WriteMsg(ret)
+       })
+       defer s.Close()
+
+       counts := []int{1, 2, 3}
+
+       for _, n := range counts {
+               b.Run(fmt.Sprintf("%d-Backends", n), func(b *testing.B) {
+                       f := forward.New()
+                       f.SetProxyOptions(proxy.Options{PreferUDP: true})
+
+                       proxies := make([]*proxy.Proxy, n)
+                       for i := range n {
+                               p := proxy.NewProxy(fmt.Sprintf("proxy-%d", i), 
s.Addr, "dns")
+                               f.SetProxy(p)
+                               proxies[i] = p
+                       }
+                       defer func() {
+                               for _, p := range proxies {
+                                       p.Stop()
+                               }
+                       }()
+
+                       // Pre-warm connections
+                       ctx := context.Background()
+                       m := new(dns.Msg)
+                       m.SetQuestion("example.org.", dns.TypeA)
+                       noop := &benchmarkResponseWriter{}
+
+                       for range n * 10 {
+                               f.ServeDNS(ctx, noop, m)
+                       }
+
+                       b.ResetTimer()
+                       b.ReportAllocs()
+
+                       b.RunParallel(func(pb *testing.PB) {
+                               m := new(dns.Msg)
+                               m.SetQuestion("example.org.", dns.TypeA)
+                               ctx := context.Background()
+                               w := &benchmarkResponseWriter{}
+
+                               for pb.Next() {
+                                       // forward plugin handles selection via 
its policy (default random)
+                                       f.ServeDNS(ctx, w, m)
+                               }
+                       })
+               })
+       }
+}
+
+type benchmarkResponseWriter struct{}
+
+func (b *benchmarkResponseWriter) LocalAddr() net.Addr         { return nil }
+func (b *benchmarkResponseWriter) RemoteAddr() net.Addr        { return nil }
+func (b *benchmarkResponseWriter) WriteMsg(m *dns.Msg) error   { return nil }
+func (b *benchmarkResponseWriter) Write(p []byte) (int, error) { return 
len(p), nil }
+func (b *benchmarkResponseWriter) Close() error                { return nil }
+func (b *benchmarkResponseWriter) TsigStatus() error           { return nil }
+func (b *benchmarkResponseWriter) TsigTimersOnly(bool)         {}
+func (b *benchmarkResponseWriter) Hijack()                     {}

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/coredns/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.coredns.new.1928/vendor.tar.gz differ: char 37, 
line 1

Reply via email to