Skip to content

Commit 8168ebf

Browse files
csviriclaude
andauthored
fix: wait for pods to be ready before port-forwarding in MetricsHandlingE2E (#3210)
Replace one-shot pod lookup with an awaitility-based readiness wait (up to 3 minutes) to avoid IllegalStateException when pods are not yet scheduled after observability stack installation. Signed-off-by: Attila Mészáros <a_meszaros@apple.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 78eecc0 commit 8168ebf

File tree

1 file changed

+33
-13
lines changed
  • sample-operators/metrics-processing/src/test/java/io/javaoperatorsdk/operator/sample/metrics

1 file changed

+33
-13
lines changed

sample-operators/metrics-processing/src/test/java/io/javaoperatorsdk/operator/sample/metrics/MetricsHandlingE2E.java

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.time.Duration;
2323
import java.util.ArrayDeque;
2424
import java.util.Deque;
25+
import java.util.Optional;
26+
import java.util.concurrent.atomic.AtomicReference;
2527

2628
import org.junit.jupiter.api.AfterAll;
2729
import org.junit.jupiter.api.BeforeAll;
@@ -31,6 +33,7 @@
3133
import org.slf4j.Logger;
3234
import org.slf4j.LoggerFactory;
3335

36+
import io.fabric8.kubernetes.api.model.Pod;
3437
import io.fabric8.kubernetes.client.CustomResource;
3538
import io.fabric8.kubernetes.client.KubernetesClient;
3639
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
@@ -81,15 +84,14 @@ class MetricsHandlingE2E {
8184
.build();
8285

8386
@BeforeAll
84-
void setupObservability() throws InterruptedException {
87+
void setupObservability() {
8588
log.info("Setting up observability stack...");
8689
installObservabilityServices();
8790
prometheusPortForward = portForward(NAME_LABEL_KEY, "prometheus", PROMETHEUS_PORT);
8891
if (isLocal()) {
8992
otelCollectorPortForward =
9093
portForward(NAME_LABEL_KEY, "otel-collector-collector", OTEL_COLLECTOR_PORT);
9194
}
92-
Thread.sleep(2000);
9395
}
9496

9597
@AfterAll
@@ -99,25 +101,43 @@ void cleanup() throws IOException {
99101
}
100102

101103
private LocalPortForward portForward(String labelKey, String labelValue, int port) {
104+
log.info("Waiting for pod with label {}={} to be ready...", labelKey, labelValue);
105+
AtomicReference<Pod> portForwardPod = new AtomicReference<>();
106+
107+
await()
108+
.atMost(Duration.ofMinutes(15))
109+
.pollInterval(Duration.ofSeconds(10))
110+
.untilAsserted(
111+
() -> {
112+
var pod = findReadyPod(labelKey, labelValue);
113+
assertThat(pod).isPresent();
114+
portForwardPod.set(pod.orElseThrow());
115+
});
116+
var pod = portForwardPod.get();
117+
log.info(
118+
"Pod {} is ready, establishing port-forward on port {}", pod.getMetadata().getName(), port);
119+
return client
120+
.pods()
121+
.inNamespace(OBSERVABILITY_NAMESPACE)
122+
.withName(pod.getMetadata().getName())
123+
.portForward(port, port);
124+
}
125+
126+
private Optional<Pod> findReadyPod(String labelKey, String labelValue) {
102127
return client
103128
.pods()
104129
.inNamespace(OBSERVABILITY_NAMESPACE)
105130
.withLabel(labelKey, labelValue)
106131
.list()
107132
.getItems()
108133
.stream()
109-
.findFirst()
110-
.map(
134+
.filter(
111135
pod ->
112-
client
113-
.pods()
114-
.inNamespace(OBSERVABILITY_NAMESPACE)
115-
.withName(pod.getMetadata().getName())
116-
.portForward(port, port))
117-
.orElseThrow(
118-
() ->
119-
new IllegalStateException(
120-
"Pod not found for label " + labelKey + "=" + labelValue));
136+
pod.getStatus() != null
137+
&& pod.getStatus().getConditions() != null
138+
&& pod.getStatus().getConditions().stream()
139+
.anyMatch(c -> "Ready".equals(c.getType()) && "True".equals(c.getStatus())))
140+
.findFirst();
121141
}
122142

123143
private void closePortForward(LocalPortForward pf) throws IOException {

0 commit comments

Comments
 (0)