Repository: metallb/metallb
Pull request #2359 (2024-04-08 02:42:42)

Bump go.uber.org/zap from 1.26.0 to 1.27.0
Bumps [go.uber.org/zap](https://github.com/uber-go/zap) from 1.26.0 to 1.27.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/uber-go/zap/releases">go.uber.org/zap's releases</a>.</em></p>
<blockquote>
<h2>v1.27.0</h2>
<p>Enhancements:</p>
<ul>
<li><a href="https://redirect.github.com/uber-go/zap/issues/1378">#1378</a>[]: Add <code>WithLazy</code> method for <code>SugaredLogger</code>.</li>
<li><a href="https://redirect.github.com/uber-go/zap/issues/1399">#1399</a>[]: zaptest: Add <code>NewTestingWriter</code> for customizing TestingWriter with more flexibility than <code>NewLogger</code>.</li>
<li><a href="https://redirect.github.com/uber-go/zap/issues/1406">#1406</a>[]: Add <code>Log</code>, <code>Logw</code>, <code>Logln</code> methods for <code>SugaredLogger</code>.</li>
<li><a href="https://redirect.github.com/uber-go/zap/issues/1416">#1416</a>[]: Add <code>WithPanicHook</code> option for testing panic logs.</li>
</ul>
<p>Thanks to <a href="https://github.com/defval"><code>@​defval</code></a>, <a href="https://github.com/dimmo"><code>@​dimmo</code></a>, <a href="https://github.com/arxeiss"><code>@​arxeiss</code></a>, and <a href="https://github.com/MKrupauskas"><code>@​MKrupauskas</code></a> for their contributions to this release.</p>
<p><a href="https://redirect.github.com/uber-go/zap/issues/1378">#1378</a>: <a href="https://redirect.github.com/uber-go/zap/pull/1378">uber-go/zap#1378</a>
<a href="https://redirect.github.com/uber-go/zap/issues/1399">#1399</a>: <a href="https://redirect.github.com/uber-go/zap/pull/1399">uber-go/zap#1399</a>
<a href="https://redirect.github.com/uber-go/zap/issues/1406">#1406</a>: <a href="https://redirect.github.com/uber-go/zap/pull/1406">uber-go/zap#1406</a>
<a href="https://redirect.github.com/uber-go/zap/issues/1416">#1416</a>: <a href="https://redirect.github.com/uber-go/zap/pull/1416">uber-go/zap#1416</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/uber-go/zap/blob/master/CHANGELOG.md">go.uber.org/zap's changelog</a>.</em></p>
<blockquote>
<h2>1.27.0 (20 Feb 2024)</h2>
<p>Enhancements:</p>
<ul>
<li><a href="https://redirect.github.com/uber-go/zap/issues/1378">#1378</a>[]: Add <code>WithLazy</code> method for <code>SugaredLogger</code>.</li>
<li><a href="https://redirect.github.com/uber-go/zap/issues/1399">#1399</a>[]: zaptest: Add <code>NewTestingWriter</code> for customizing TestingWriter with more flexibility than <code>NewLogger</code>.</li>
<li><a href="https://redirect.github.com/uber-go/zap/issues/1406">#1406</a>[]: Add <code>Log</code>, <code>Logw</code>, <code>Logln</code> methods for <code>SugaredLogger</code>.</li>
<li><a href="https://redirect.github.com/uber-go/zap/issues/1416">#1416</a>[]: Add <code>WithPanicHook</code> option for testing panic logs.</li>
</ul>
<p>Thanks to <a href="https://github.com/defval"><code>@​defval</code></a>, <a href="https://github.com/dimmo"><code>@​dimmo</code></a>, <a href="https://github.com/arxeiss"><code>@​arxeiss</code></a>, and <a href="https://github.com/MKrupauskas"><code>@​MKrupauskas</code></a> for their contributions to this release.</p>
<p><a href="https://redirect.github.com/uber-go/zap/issues/1378">#1378</a>: <a href="https://redirect.github.com/uber-go/zap/pull/1378">uber-go/zap#1378</a>
<a href="https://redirect.github.com/uber-go/zap/issues/1399">#1399</a>: <a href="https://redirect.github.com/uber-go/zap/pull/1399">uber-go/zap#1399</a>
<a href="https://redirect.github.com/uber-go/zap/issues/1406">#1406</a>: <a href="https://redirect.github.com/uber-go/zap/pull/1406">uber-go/zap#1406</a>
<a href="https://redirect.github.com/uber-go/zap/issues/1416">#1416</a>: <a href="https://redirect.github.com/uber-go/zap/pull/1416">uber-go/zap#1416</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/uber-go/zap/commit/fcf8ee58669e358bbd6460bef5c2ee7a53c0803a"><code>fcf8ee5</code></a> Release v1.27.0 (<a href="https://redirect.github.com/uber-go/zap/issues/1419">#1419</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/e5a56ee593d51f611de3a73cf3140f1c1927d68e"><code>e5a56ee</code></a> Add WithPanicHook logger option for panic log tests (<a href="https://redirect.github.com/uber-go/zap/issues/1416">#1416</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/0e2aa4e0412dfb49d87f9ec96b47c8296189cfa3"><code>0e2aa4e</code></a> assets: Fix logo color profile (<a href="https://redirect.github.com/uber-go/zap/issues/1418">#1418</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/956a21c19cf77ea7a78f9f08ca44b6f77f95053a"><code>956a21c</code></a> Add methods for logging with level as argument (<a href="https://redirect.github.com/uber-go/zap/issues/1406">#1406</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/2a893f61347ef844d78dcb4ad3b454ee11ae7641"><code>2a893f6</code></a> build(deps): bump golangci/golangci-lint-action from 3 to 4 (<a href="https://redirect.github.com/uber-go/zap/issues/1417">#1417</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/e5745d6095ecc2497281569e8713835f2c4a029f"><code>e5745d6</code></a> ci: Test with Go 1.22 (<a href="https://redirect.github.com/uber-go/zap/issues/1409">#1409</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/7db06bc9b095571d3dc3d4eebdfbe4dd9bd20405"><code>7db06bc</code></a> zapslog: rename Option to HandlerOption (<a href="https://redirect.github.com/uber-go/zap/issues/1411">#1411</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/35ded09102db8ce0b2eba3e87f54ba6ce14f2359"><code>35ded09</code></a> zapslog: fix all with slogtest, support inline group, ignore empty group. (<a href="https://redirect.github.com/uber-go/zap/issues/1">#1</a>...</li>
<li><a href="https://github.com/uber-go/zap/commit/27b96e378909082d0bf2f0c5802a9f648150fe98"><code>27b96e3</code></a> Make zaptest.NewTestingWriter public (<a href="https://redirect.github.com/uber-go/zap/issues/1399">#1399</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/70f61bb342203a50f8192b05f7faf40a0f809a91"><code>70f61bb</code></a> zapslog: Bump zap from v1.24.0 to v1.26.0 (<a href="https://redirect.github.com/uber-go/zap/issues/1404">#1404</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/uber-go/zap/compare/v1.26.0...v1.27.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=go.uber.org/zap&package-manager=go_modules&previous-version=1.26.0&new-version=1.27.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/configmaptocrs/Dockerfile b/configmaptocrs/Dockerfile
index c4a0c98c..59ae08df 100644
--- a/configmaptocrs/Dockerfile
+++ b/configmaptocrs/Dockerfile
@@ -1,12 +1,12 @@
 # syntax=docker/dockerfile:1.2
 
-FROM --platform=$BUILDPLATFORM docker.io/golang:1.21.8 AS builder
+FROM --platform=$BUILDPLATFORM docker.io/golang:1.21.9 AS builder
 WORKDIR $GOPATH/go.universe.tf/metallb
 
 RUN --mount=type=cache,target=/go/pkg/mod/ \
-    --mount=type=bind,source=go.sum,target=go.sum \
-    --mount=type=bind,source=go.mod,target=go.mod \
-    go mod download -x
+  --mount=type=bind,source=go.sum,target=go.sum \
+  --mount=type=bind,source=go.mod,target=go.mod \
+  go mod download -x
 
 ARG GIT_COMMIT=dev
 ARG GIT_BRANCH=dev
diff --git a/controller/Dockerfile b/controller/Dockerfile
index 5e0a4da3..c26bcdcf 100644
--- a/controller/Dockerfile
+++ b/controller/Dockerfile
@@ -1,12 +1,12 @@
 # syntax=docker/dockerfile:1.2
 
-FROM --platform=$BUILDPLATFORM docker.io/golang:1.21.8 AS builder
+FROM --platform=$BUILDPLATFORM docker.io/golang:1.21.9 AS builder
 WORKDIR $GOPATH/go.universe.tf/metallb
 
 RUN --mount=type=cache,target=/go/pkg/mod/ \
-    --mount=type=bind,source=go.sum,target=go.sum \
-    --mount=type=bind,source=go.mod,target=go.mod \
-    go mod download -x
+  --mount=type=bind,source=go.sum,target=go.sum \
+  --mount=type=bind,source=go.mod,target=go.mod \
+  go mod download -x
 
 ARG GIT_COMMIT=dev
 ARG GIT_BRANCH=dev
diff --git a/go.mod b/go.mod
index 977c71f0..aab72bb4 100644
--- a/go.mod
+++ b/go.mod
@@ -18,7 +18,7 @@ require (
 	github.com/ory/dockertest/v3 v3.10.0
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.19.0
-	go.uber.org/zap v1.26.0
+	go.uber.org/zap v1.27.0
 	golang.org/x/sys v0.18.0
 	k8s.io/api v0.29.3
 	k8s.io/apiextensions-apiserver v0.29.3
diff --git a/go.sum b/go.sum
index 40084757..aa3d8864 100644
--- a/go.sum
+++ b/go.sum
@@ -275,8 +275,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
 go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
 go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
-go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
-go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
diff --git a/internal/bgp/frr/config.go b/internal/bgp/frr/config.go
index 7ffcc88a..9a7a7626 100644
--- a/internal/bgp/frr/config.go
+++ b/internal/bgp/frr/config.go
@@ -182,7 +182,7 @@ func templateConfig(data interface{}) (string, error) {
 	return b.String(), err
 }
 
-// writeConfigFile writes the FRR configuration file (represented as a string)
+// writeConfig writes the FRR configuration file (represented as a string)
 // to 'filename'.
 func writeConfig(config string, filename string) error {
 	return os.WriteFile(filename, []byte(config), 0600)
diff --git a/internal/k8s/epslices/endpoint_slices.go b/internal/k8s/epslices/endpoint_slices.go
index e4d0c0b6..8dfa8cec 100644
--- a/internal/k8s/epslices/endpoint_slices.go
+++ b/internal/k8s/epslices/endpoint_slices.go
@@ -11,16 +11,15 @@ import (
 
 const SlicesServiceIndexName = "ServiceName"
 
-// IsConditionServing tells if the conditions represent a serving state, deferring
-// to ready state if serving == nil.
-func IsConditionServing(conditions discovery.EndpointConditions) bool {
-	if conditions.Serving == nil {
-		if conditions.Ready == nil {
-			return true
-		}
-		return *conditions.Ready
+// EndpointCanServe tells if the conditions represent a ready state or serving state is ready.
+func EndpointCanServe(conditions discovery.EndpointConditions) bool {
+	if conditions.Ready == nil || *conditions.Ready {
+		return true
 	}
-	return *conditions.Serving
+	if conditions.Serving != nil && *conditions.Serving {
+		return true
+	}
+	return false
 }
 
 func ServiceKeyForSlice(endpointSlice *discovery.EndpointSlice) (types.NamespacedName, error) {
diff --git a/internal/k8s/webhooks/webhookv1beta1/l2advertisement_webhook.go b/internal/k8s/webhooks/webhookv1beta1/l2advertisement_webhook.go
index c68e955b..0c99d3df 100644
--- a/internal/k8s/webhooks/webhookv1beta1/l2advertisement_webhook.go
+++ b/internal/k8s/webhooks/webhookv1beta1/l2advertisement_webhook.go
@@ -118,7 +118,7 @@ func validateL2AdvCreate(l2Adv *v1beta1.L2Advertisement) error {
 	return nil
 }
 
-// validateL2Update implements webhook.Validator so a webhook will be registered for v1beta1.L2Advertisement.
+// validateL2AdvUpdate implements webhook.Validator so a webhook will be registered for v1beta1.L2Advertisement.
 func validateL2AdvUpdate(l2Adv *v1beta1.L2Advertisement, _ *v1beta1.L2Advertisement) error {
 	level.Debug(Logger).Log("webhook", "v1beta1.L2Advertisement", "action", "update", "name", l2Adv.Name, "namespace", l2Adv.Namespace)
 
diff --git a/speaker/Dockerfile b/speaker/Dockerfile
index aeaf8f1c..670af170 100644
--- a/speaker/Dockerfile
+++ b/speaker/Dockerfile
@@ -1,12 +1,12 @@
 # syntax=docker/dockerfile:1.2
 
-FROM --platform=$BUILDPLATFORM docker.io/golang:1.21.8 AS builder
+FROM --platform=$BUILDPLATFORM docker.io/golang:1.21.9 AS builder
 WORKDIR $GOPATH/go.universe.tf/metallb
 
 RUN --mount=type=cache,target=/go/pkg/mod/ \
-    --mount=type=bind,source=go.sum,target=go.sum \
-    --mount=type=bind,source=go.mod,target=go.mod \
-    go mod download -x
+  --mount=type=bind,source=go.sum,target=go.sum \
+  --mount=type=bind,source=go.mod,target=go.mod \
+  go mod download -x
 
 ARG GIT_COMMIT=dev
 ARG GIT_BRANCH=dev
diff --git a/speaker/bgp_controller.go b/speaker/bgp_controller.go
index 5351cd36..244b9ee9 100644
--- a/speaker/bgp_controller.go
+++ b/speaker/bgp_controller.go
@@ -125,13 +125,13 @@ func hasHealthyEndpoint(eps []discovery.EndpointSlice, filterNode func(*string)
 				continue
 			}
 			for _, addr := range ep.Addresses {
-				if _, ok := ready[addr]; !ok && epslices.IsConditionServing(ep.Conditions) {
+				if _, ok := ready[addr]; !ok && epslices.EndpointCanServe(ep.Conditions) {
 					// Only set true if nothing else has expressed an
 					// opinion. This means that false will take precedence
 					// if there's any unready ports for a given endpoint.
 					ready[addr] = true
 				}
-				if !epslices.IsConditionServing(ep.Conditions) {
+				if !epslices.EndpointCanServe(ep.Conditions) {
 					ready[addr] = false
 				}
 			}
diff --git a/speaker/layer2_controller.go b/speaker/layer2_controller.go
index 175ad808..77055934 100644
--- a/speaker/layer2_controller.go
+++ b/speaker/layer2_controller.go
@@ -54,7 +54,7 @@ func usableNodes(eps []discovery.EndpointSlice, speakers map[string]bool) []stri
 	usable := map[string]bool{}
 	for _, slice := range eps {
 		for _, ep := range slice.Endpoints {
-			if !epslices.IsConditionServing(ep.Conditions) {
+			if !epslices.EndpointCanServe(ep.Conditions) {
 				continue
 			}
 			if ep.NodeName == nil {
@@ -204,7 +204,7 @@ func nodesWithActiveSpeakers(speakers map[string]bool) []string {
 func activeEndpointExists(eps []discovery.EndpointSlice) bool {
 	for _, slice := range eps {
 		for _, ep := range slice.Endpoints {
-			if !epslices.IsConditionServing(ep.Conditions) {
+			if !epslices.EndpointCanServe(ep.Conditions) {
 				continue
 			}
 			return true


Test patch:
diff --git a/e2etest/pkg/frr/bgp.go b/e2etest/pkg/frr/bgp.go
index 9eff0019..dacd1576 100644
--- a/e2etest/pkg/frr/bgp.go
+++ b/e2etest/pkg/frr/bgp.go
@@ -16,7 +16,7 @@ import (
 // useful for fetching informations from FRR (such as metrics) and we may need to move it
 // to metallb.
 
-// NeighborForContainer returns informations for the given neighbor in the given
+// NeighborInfo returns informations for the given neighbor in the given
 // executor.
 func NeighborInfo(neighborName string, exec executor.Executor) (*Neighbor, error) {
 	res, err := exec.Exec("vtysh", "-c", fmt.Sprintf("show bgp neighbor %s json", neighborName))
@@ -31,7 +31,7 @@ func NeighborInfo(neighborName string, exec executor.Executor) (*Neighbor, error
 	return neighbor, nil
 }
 
-// NeighborsForContainer returns informations for the all the neighbors in the given
+// NeighborsInfo returns informations for the all the neighbors in the given
 // executor.
 func NeighborsInfo(exec executor.Executor) ([]*Neighbor, error) {
 	res, err := exec.Exec("vtysh", "-c", "show bgp neighbor json")
diff --git a/internal/k8s/epslices/endpoint_slices_test.go b/internal/k8s/epslices/endpoint_slices_test.go
new file mode 100644
index 00000000..4266ec0b
--- /dev/null
+++ b/internal/k8s/epslices/endpoint_slices_test.go
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier:Apache-2.0
+
+package epslices
+
+import (
+	"testing"
+
+	v1 "k8s.io/api/discovery/v1"
+	"k8s.io/utils/ptr"
+)
+
+func TestIsConditionReadyOrServing(t *testing.T) {
+	tests := []struct {
+		name       string
+		conditions v1.EndpointConditions
+		want       bool
+	}{
+		{
+			name: "Is Ready",
+			conditions: v1.EndpointConditions{
+				Ready: ptr.To(true),
+			},
+			want: true,
+		},
+		{
+			name: "Is Serving",
+			conditions: v1.EndpointConditions{
+				Serving: ptr.To(true),
+			},
+			want: true,
+		},
+		{
+			name: "Is Ready but not serving",
+			conditions: v1.EndpointConditions{
+				Ready:   ptr.To(true),
+				Serving: ptr.To(false),
+			},
+			want: true,
+		},
+		{
+			name:       "Ready and Serving not set",
+			conditions: v1.EndpointConditions{},
+			want:       true,
+		},
+		{
+			name: "Ready not set and not serving",
+			conditions: v1.EndpointConditions{
+				Serving: ptr.To(false),
+			},
+			want: true,
+		},
+		{
+			name: "Not Ready",
+			conditions: v1.EndpointConditions{
+				Ready: ptr.To(false),
+			},
+			want: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := EndpointCanServe(tt.conditions); got != tt.want {
+				t.Errorf("EndpointCanServe() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/speaker/bgp_controller_test.go b/speaker/bgp_controller_test.go
index 725b385a..e11f6e53 100644
--- a/speaker/bgp_controller_test.go
+++ b/speaker/bgp_controller_test.go
@@ -617,6 +617,41 @@ func TestBGPSpeakerEPSlices(t *testing.T) {
 			},
 		},
 
+		{
+			desc:     "Endpoint list contains ready but not serving endpoints",
+			balancer: "test1",
+			svc: &v1.Service{
+				Spec: v1.ServiceSpec{
+					Type:                  "LoadBalancer",
+					ExternalTrafficPolicy: "Cluster",
+				},
+				Status: statusAssigned("10.20.30.1"),
+			},
+			eps: []discovery.EndpointSlice{
+				{
+					Endpoints: []discovery.Endpoint{
+						{
+							Addresses: []string{
+								"2.3.4.5",
+							},
+							NodeName: ptr.To("iris"),
+							Conditions: discovery.EndpointConditions{
+								Ready:   ptr.To(true),
+								Serving: ptr.To(false),
+							},
+						},
+					},
+				},
+			},
+			wantAds: map[string][]*bgp.Advertisement{
+				"1.2.3.4:0": {
+					{
+						Prefix: ipnet("10.20.30.1/32"),
+					},
+				},
+			},
+		},
+
 		{
 			desc: "Multiple advertisement config",
 			config: &config.Config{
diff --git a/speaker/layer2_controller_test.go b/speaker/layer2_controller_test.go
index ad640ce6..572fc878 100644
--- a/speaker/layer2_controller_test.go
+++ b/speaker/layer2_controller_test.go
@@ -222,6 +222,37 @@ func TestUsableNodesEPSlices(t *testing.T) {
 			usableSpeakers:  map[string]bool{"iris1": true, "iris2": true},
 			cExpectedResult: []string{"iris1", "iris2"},
 		},
+		{
+			desc: "Two endpoints, different hosts, ready but not serving",
+			eps: []discovery.EndpointSlice{
+				{
+					Endpoints: []discovery.Endpoint{
+						{
+							Addresses: []string{
+								"2.3.4.5",
+							},
+							NodeName: ptr.To("iris1"),
+							Conditions: discovery.EndpointConditions{
+								Ready:   ptr.To(true),
+								Serving: ptr.To(false),
+							},
+						},
+						{
+							Addresses: []string{
+								"2.3.4.15",
+							},
+							NodeName: ptr.To("iris2"),
+							Conditions: discovery.EndpointConditions{
+								Ready:   ptr.To(true),
+								Serving: ptr.To(false),
+							},
+						},
+					},
+				},
+			},
+			usableSpeakers:  map[string]bool{"iris1": true, "iris2": true},
+			cExpectedResult: []string{"iris1", "iris2"},
+		},
 	}
 
 	for _, test := range tests {