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
