Repository: kubernetes-sigs/external-dns

Issue:
Fix: IDNA conversion in FindZone breaks on valid TXT record names
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! -->

Hello 👋 

**What happened**:

The `FindZone` function in ExternalDNS fails when processing TXT record hostnames that contain underscores (e.g., `cname._metadata.example.com`). This is due to the use of `idna.Lookup.ToUnicode()` which returns an error when the input string includes underscores — a character that is technically invalid in hostnames per IDNA, but valid in DNS labels, especially for TXT records used for metadata or service verification.

**What you expected to happen**:

The function should gracefully handle hostnames with underscores, as these are valid and commonly used in TXT records. It should not fail zone matching logic just because the IDNA conversion fails or is inappropriate in this context.

**How to reproduce it (as minimally and precisely as possible)**:

1. Use ExternalDNS with a TXT record containing an underscore, e.g., `cname._metadata.example.com`.
2. Observe that `FindZone()` fails to find a suitable zone due to an IDNA conversion error.
3. Logs may show:  
   `Failed to convert hostname 'cname._metadata.example.com' to its Unicode form: idna: disallowed rune U+005F`

**Anything else we need to know?**:

A suggested fix is to skip IDNA conversion if the hostname contains underscores, since IDNA doesn’t support underscores but DNS TXT records do. Example patch:

```go
func (z ZoneIDName) FindZone(hostname string) (suitableZoneID, suitableZoneName string) {
	var name string
	if strings.Contains(hostname, "_") {
		name = hostname
	} else {
		var err error
		name, err = idna.Lookup.ToUnicode(hostname)
		if err != nil {
			log.Warnf("Failed to convert hostname '%s' to its Unicode form: %v", hostname, err)
			name = hostname
		}
	}

	for zoneID, zoneName := range z {
		if name == zoneName || strings.HasSuffix(name, "."+zoneName) {
			if suitableZoneName == "" || len(zoneName) > len(suitableZoneName) {
				suitableZoneID = zoneID
				suitableZoneName = zoneName
			}
		}
	}
	return
}
```

Let me know if you'd like me to open the associated PR.
Thanks

Hints from issue comments:
@ivankatliarchuk: Yes, please open a pull request with the patch

Solution patch:
diff --git a/.github/renovate-config.js b/.github/renovate-config.js
index d21caf1c..9d3803f4 100644
--- a/.github/renovate-config.js
+++ b/.github/renovate-config.js
@@ -52,6 +52,14 @@ module.exports = {
       "depNameTemplate": "kubernetes-sigs/external-dns",
       "datasourceTemplate": "github-releases",
       "versioningTemplate": "semver"
-    }
+    },
+    {
+      "customType": "regex",
+      "fileMatch": [".*"],
+      "matchStrings": [
+        "datasource=(?<datasource>.*?) depName=(?<depName>.*?)( versioning=(?<versioning>.*?))?\\s.*?_VERSION=(?<currentValue>.*)\\s"
+      ],
+      "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver{{/if}}",
+    },
   ]
 };
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 030ad588..777270ff 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -47,3 +47,4 @@ jobs:
       with:
         path-to-profile: profile.cov
       if: github.actor != 'nektos/act'
+      continue-on-error: true
diff --git a/Makefile b/Makefile
index 8b0bd52f..8cff3cba 100644
--- a/Makefile
+++ b/Makefile
@@ -24,28 +24,26 @@ cover-html: cover
 	@go tool cover -html=cover.out
 
 #? controller-gen: download controller-gen if necessary
-controller-gen:
+controller-gen-install:
+	@scripts/install-tools.sh --generator
 ifeq (, $(shell which controller-gen))
-	@{ \
-	set -e ;\
-	go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.15.0 ;\
-	}
 CONTROLLER_GEN=$(GOBIN)/controller-gen
 else
 CONTROLLER_GEN=$(shell which controller-gen)
 endif
 
-#? golangci-lint: Install golangci-lint tool
-golangci-lint:
-	@command -v golangci-lint > /dev/null || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.0.2
+#? controller-gen-install: download controller-gen if necessary
+controller-gen-install:
+	@scripts/install-tools.sh --generator
 
-#? golangci-lint-verify: Verify golangci-lint configuration
-golangci-lint-verify: golangci-lint
-	@golangci-lint config verify
+#? golangci-lint-install: Install golangci-lint tool
+golangci-lint-install:
+	@scripts/install-tools.sh --golangci
 
 #? go-lint: Run the golangci-lint tool
 .PHONY: go-lint
-go-lint: golangci-lint
+go-lint: golangci-lint-install
+	golangci-lint config verify
 	gofmt -l -s -w .
 	golangci-lint run --timeout=30m --fix ./...
 
@@ -71,7 +69,7 @@ lint: licensecheck go-lint oas-lint
 
 #? crd: Generates CRD using controller-gen
 .PHONY: crd
-crd: controller-gen
+crd: controller-gen-install
 	${CONTROLLER_GEN} crd:crdVersions=v1 paths="./endpoint/..." output:crd:stdout > docs/contributing/crd-source/crd-manifest.yaml
 
 #? test: The verify target runs tasks similar to the CI tasks, but without code coverage
diff --git a/go.mod b/go.mod
index e4c6aaab..235c4bc7 100644
--- a/go.mod
+++ b/go.mod
@@ -37,6 +37,7 @@ require (
 	github.com/ffledgling/pdns-go v0.0.0-20180219074714-524e7daccd99
 	github.com/go-gandi/go-gandi v0.7.0
 	github.com/go-logr/logr v1.4.2
+	github.com/goccy/go-yaml v1.17.1
 	github.com/google/go-cmp v0.7.0
 	github.com/google/uuid v1.6.0
 	github.com/linki/instrumented_http v0.3.0
@@ -69,9 +70,7 @@ require (
 	golang.org/x/text v0.24.0
 	golang.org/x/time v0.11.0
 	google.golang.org/api v0.228.0
-	gopkg.in/ns1/ns1-go.v2 v2.14.1
-	gopkg.in/yaml.v2 v2.4.0
-	gopkg.in/yaml.v3 v3.0.1
+	gopkg.in/ns1/ns1-go.v2 v2.14.2
 	istio.io/api v1.25.1
 	istio.io/client-go v1.25.1
 	k8s.io/api v0.32.3
@@ -212,6 +211,8 @@ require (
 	gopkg.in/inf.v0 v0.9.1 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
+	gopkg.in/yaml.v2 v2.4.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
 	k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
 	k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
 	moul.io/http2curl v1.0.0 // indirect
diff --git a/go.sum b/go.sum
index 4a0010b5..4f7be250 100644
--- a/go.sum
+++ b/go.sum
@@ -439,6 +439,8 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
 github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
 github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
+github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY=
+github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
 github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg=
@@ -1449,8 +1451,8 @@ gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
-gopkg.in/ns1/ns1-go.v2 v2.14.1 h1:wruE2g1uB90kMW+jHW8BtWa1HvNkqDfyf7SacTKWtBY=
-gopkg.in/ns1/ns1-go.v2 v2.14.1/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=
+gopkg.in/ns1/ns1-go.v2 v2.14.2 h1:wz/toj9U20wBrmYxW4vTz7sZWED+JJVRjUBBJ7CKrzI=
+gopkg.in/ns1/ns1-go.v2 v2.14.2/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
diff --git a/provider/alibabacloud/alibaba_cloud.go b/provider/alibabacloud/alibaba_cloud.go
index 5183d443..32140c77 100644
--- a/provider/alibabacloud/alibaba_cloud.go
+++ b/provider/alibabacloud/alibaba_cloud.go
@@ -29,8 +29,8 @@ import (
 	"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
 	"github.com/aliyun/alibaba-cloud-sdk-go/services/pvtz"
 	"github.com/denverdino/aliyungo/metadata"
+	yaml "github.com/goccy/go-yaml"
 	log "github.com/sirupsen/logrus"
-	"gopkg.in/yaml.v2"
 
 	"sigs.k8s.io/external-dns/endpoint"
 	"sigs.k8s.io/external-dns/plan"
diff --git a/provider/azure/config.go b/provider/azure/config.go
index eca4ae0d..ac24f0b4 100644
--- a/provider/azure/config.go
+++ b/provider/azure/config.go
@@ -17,6 +17,7 @@ limitations under the License.
 package azure
 
 import (
+	"encoding/json"
 	"fmt"
 	"os"
 	"strings"
@@ -26,7 +27,6 @@ import (
 	"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
 	"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
 	log "github.com/sirupsen/logrus"
-	"gopkg.in/yaml.v2"
 )
 
 // config represents common config items for Azure DNS and Azure Private DNS
@@ -50,9 +50,8 @@ func getConfig(configFile, subscriptionID, resourceGroup, userAssignedIdentityCl
 		return nil, fmt.Errorf("failed to read Azure config file '%s': %v", configFile, err)
 	}
 	cfg := &config{}
-	err = yaml.Unmarshal(contents, &cfg)
-	if err != nil {
-		return nil, fmt.Errorf("failed to read Azure config file '%s': %v", configFile, err)
+	if err := json.Unmarshal(contents, &cfg); err != nil {
+		return nil, fmt.Errorf("failed to parse Azure config file '%s': %v", configFile, err)
 	}
 	// If a subscription ID was given, override what was present in the config file
 	if subscriptionID != "" {
diff --git a/provider/ibmcloud/ibmcloud.go b/provider/ibmcloud/ibmcloud.go
index f442c76a..41fbab62 100644
--- a/provider/ibmcloud/ibmcloud.go
+++ b/provider/ibmcloud/ibmcloud.go
@@ -29,7 +29,7 @@ import (
 	"github.com/IBM/networking-go-sdk/dnsrecordsv1"
 	"github.com/IBM/networking-go-sdk/dnssvcsv1"
 	"github.com/IBM/networking-go-sdk/zonesv1"
-	"gopkg.in/yaml.v2"
+	yaml "github.com/goccy/go-yaml"
 
 	log "github.com/sirupsen/logrus"
 
diff --git a/provider/oci/oci.go b/provider/oci/oci.go
index c526be63..87f57f78 100644
--- a/provider/oci/oci.go
+++ b/provider/oci/oci.go
@@ -23,12 +23,12 @@ import (
 	"strings"
 	"time"
 
+	yaml "github.com/goccy/go-yaml"
 	"github.com/oracle/oci-go-sdk/v65/common"
 	"github.com/oracle/oci-go-sdk/v65/common/auth"
 	"github.com/oracle/oci-go-sdk/v65/dns"
 	"github.com/pkg/errors"
 	log "github.com/sirupsen/logrus"
-	yaml "gopkg.in/yaml.v2"
 
 	"sigs.k8s.io/external-dns/endpoint"
 	"sigs.k8s.io/external-dns/plan"
diff --git a/provider/zonefinder.go b/provider/zonefinder.go
index 6a07646c..a81f997b 100644
--- a/provider/zonefinder.go
+++ b/provider/zonefinder.go
@@ -29,12 +29,34 @@ func (z ZoneIDName) Add(zoneID, zoneName string) {
 	z[zoneID] = zoneName
 }
 
+// FindZone identifies the most suitable DNS zone for a given hostname.
+// It returns the zone ID and name that best match the hostname.
+//
+// The function processes the hostname by splitting it into labels and
+// converting each label to its Unicode form using IDNA (Internationalized
+// Domain Names for Applications) standards.
+//
+// Labels containing underscores ('_') are skipped during Unicode conversion.
+// This is because underscores are often used in special DNS records (e.g.,
+// SRV records as per RFC 2782, or TXT record for services) that are not
+// IDNA-aware and cannot represent non-ASCII labels. Skipping these labels
+// ensures compatibility with such use cases.
 func (z ZoneIDName) FindZone(hostname string) (suitableZoneID, suitableZoneName string) {
-	name, err := idna.Lookup.ToUnicode(hostname)
-	if err != nil {
-		log.Warnf("Failed to convert hostname '%s' to its Unicode form: %v", hostname, err)
-		name = hostname
+	var name string
+	domain_labels := strings.Split(hostname, ".")
+	for i, label := range domain_labels {
+		if strings.Contains(label, "_") {
+			continue
+		}
+		convertedLabel, err := idna.Lookup.ToUnicode(label)
+		if err != nil {
+			log.Warnf("Failed to convert label '%s' of hostname '%s' to its Unicode form: %v", label, hostname, err)
+			convertedLabel = label
+		}
+		domain_labels[i] = convertedLabel
 	}
+	name = strings.Join(domain_labels, ".")
+
 	for zoneID, zoneName := range z {
 		if name == zoneName || strings.HasSuffix(name, "."+zoneName) {
 			if suitableZoneName == "" || len(zoneName) > len(suitableZoneName) {
diff --git a/scripts/install-tools.sh b/scripts/install-tools.sh
new file mode 100755
index 00000000..56b44077
--- /dev/null
+++ b/scripts/install-tools.sh
@@ -0,0 +1,95 @@
+#!/usr/bin/env bash
+
+# Copyright 2025 The Kubernetes Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# renovate: datasource=github-releases depName=kubernetes-sigs/controller-tools
+CONTROLLER_TOOLS_GENERATOR_VERSION=v0.15.0
+# renovate: datasource=github-releases depName=golangci/golangci-lint
+GOLANG_CI_LINTER_VERSION=v2.0.2
+
+# Execute
+# scripts/install-tools.sh
+# scripts/install-tools.sh -h
+# scripts/install-tools.sh --generator
+# scripts/install-tools.sh --golangci
+
+show_help() {
+cat << EOF
+'external-dns' helm linter helper commands
+
+Usage: $(basename "$0") <options>
+    -h, --help          Display help
+    --generator         Install generator
+    --golangci         Install golangci linter
+EOF
+}
+
+install_generator() {
+  # https://github.com/kubernetes-sigs/controller-tools/blob/main/cmd/controller-gen/main.go
+  local install=false
+  if [[ -x $(which controller-gen) ]]; then
+      local version=$(controller-gen --version | sed 's/Version: //')
+      if [[ "${version}" == "${CONTROLLER_TOOLS_GENERATOR_VERSION}" ]]; then
+          install=false
+        else
+          install=true
+      fi
+    else
+      install=true
+  fi
+  if [[ "$install" == true ]]; then
+      set -ex ;\
+	    go install sigs.k8s.io/controller-tools/cmd/controller-gen@${CONTROLLER_TOOLS_GENERATOR_VERSION} ;
+  fi
+}
+
+install_golangci() {
+  local install=false
+  if [[ -x $(which golangci-lint) ]]; then
+      local version=$(golangci-lint version --short)
+      if [[ "${version}" == "${GOLANG_CI_LINTER_VERSION#v}" ]]; then
+          install=false
+        else
+          install=true
+      fi
+    else
+      install=true
+  fi
+  if [[ "$install" == true ]]; then
+      curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/cc3567e3127d8530afb69be1b7bd20ba9ebcc7c1/install.sh \
+        | sh -s -- -b $(go env GOPATH)/bin "${GOLANG_CI_LINTER_VERSION}"
+  fi
+}
+
+function main() {
+  case $1 in
+    --generator)
+      install_generator
+      ;;
+    --golangci)
+      install_golangci
+      ;;
+    -h|--help)
+      show_help
+      ;;
+    *)
+      echo "unknown sub-command" >&2
+      show_help
+      exit 1
+      ;;
+  esac
+}
+
+main "$@"



Test patch:
diff --git a/internal/testutils/log.go b/internal/testutils/log.go
index 232ac78f..25b7a427 100644
--- a/internal/testutils/log.go
+++ b/internal/testutils/log.go
@@ -18,11 +18,9 @@ package testutils
 
 import (
 	"bytes"
-	"flag"
 	"testing"
 
 	log "github.com/sirupsen/logrus"
-	"k8s.io/klog/v2"
 )
 
 // LogsToBuffer redirects log(s) output to a buffer for testing purposes
@@ -38,12 +36,5 @@ func LogsToBuffer(level log.Level, t *testing.T) *bytes.Buffer {
 	buf := new(bytes.Buffer)
 	log.SetOutput(buf)
 	log.SetLevel(level)
-	klog.SetOutput(buf)
-	flags := &flag.FlagSet{}
-	klog.InitFlags(flags)
-	// make sure klog doesn't write to stderr by default in tests
-	_ = flags.Set("logtostderr", "false")
-	_ = flags.Set("alsologtostderr", "false")
-	_ = flags.Set("stderrthreshold", "4")
 	return buf
 }
diff --git a/provider/aws/aws_utils_test.go b/provider/aws/aws_utils_test.go
index a7c7e2aa..eddb8dc8 100644
--- a/provider/aws/aws_utils_test.go
+++ b/provider/aws/aws_utils_test.go
@@ -24,8 +24,8 @@ import (
 
 	"github.com/aws/aws-sdk-go-v2/service/route53"
 	route53types "github.com/aws/aws-sdk-go-v2/service/route53/types"
+	yaml "github.com/goccy/go-yaml"
 	"github.com/stretchr/testify/assert"
-	"gopkg.in/yaml.v3"
 	"sigs.k8s.io/external-dns/endpoint"
 	"sigs.k8s.io/external-dns/provider"
 )
diff --git a/provider/zonefinder_test.go b/provider/zonefinder_test.go
index 0037edad..8b33f566 100644
--- a/provider/zonefinder_test.go
+++ b/provider/zonefinder_test.go
@@ -30,11 +30,15 @@ func TestZoneIDName(t *testing.T) {
 	z.Add("123456", "qux.baz")
 	z.Add("654321", "foo.qux.baz")
 	z.Add("987654", "エイミー.みんな")
+	z.Add("123123", "_metadata.example.com")
+	z.Add("456456", "_metadata.エイミー.みんな")
 
 	assert.Equal(t, ZoneIDName{
 		"123456": "qux.baz",
 		"654321": "foo.qux.baz",
 		"987654": "エイミー.みんな",
+		"123123": "_metadata.example.com",
+		"456456": "_metadata.エイミー.みんな",
 	}, z)
 
 	// simple entry in a domain
@@ -73,6 +77,6 @@ func TestZoneIDName(t *testing.T) {
 	assert.Equal(t, "987654", zoneID)
 
 	b := testutils.LogsToBuffer(log.WarnLevel, t)
-	zoneID, zoneName = z.FindZone("???")
-	assert.Contains(t, b.String(), "level=warning msg=\"Failed to convert hostname '???' to its Unicode form: idna: disallowed rune U+003F\"")
+	_, _ = z.FindZone("???")
+	assert.Contains(t, b.String(), "level=warning msg=\"Failed to convert label '???' of hostname '???' to its Unicode form: idna: disallowed rune U+003F\"")
 }
diff --git a/source/gateway_httproute_test.go b/source/gateway_httproute_test.go
index a09f25bc..19f009fb 100644
--- a/source/gateway_httproute_test.go
+++ b/source/gateway_httproute_test.go
@@ -17,7 +17,6 @@ limitations under the License.
 package source
 
 import (
-	"bytes"
 	"context"
 	"testing"
 
@@ -1506,10 +1505,8 @@ func TestGatewayHTTPRouteSourceEndpoints(t *testing.T) {
 			src, err := NewGatewayHTTPRouteSource(clients, &tt.config)
 			require.NoError(t, err, "failed to create Gateway HTTPRoute Source")
 
-			var b *bytes.Buffer
-			if len(tt.logExpectations) > 0 {
-				b = testutils.LogsToBuffer(log.DebugLevel, t)
-			}
+			b := testutils.LogsToBuffer(log.DebugLevel, t)
+
 			endpoints, err := src.Endpoints(ctx)
 			require.NoError(t, err, "failed to get Endpoints")
 			validateEndpoints(t, endpoints, tt.endpoints)
diff --git a/source/node_test.go b/source/node_test.go
index a3ad0a60..4e05cde3 100644
--- a/source/node_test.go
+++ b/source/node_test.go
@@ -394,10 +394,7 @@ func testNodeSourceEndpoints(t *testing.T) {
 	} {
 		tc := tc
 		t.Run(tc.title, func(t *testing.T) {
-			var buf *bytes.Buffer
-			if len(tc.expectedLogs) != 0 || len(tc.expectedAbsentLogs) != 0 {
-				buf = testutils.LogsToBuffer(log.DebugLevel, t)
-			}
+			buf := testutils.LogsToBuffer(log.DebugLevel, t)
 
 			labelSelector := labels.Everything()
 			if tc.labelSelector != "" {