Skip to content

Commit 8f05e6c

Browse files
csviriCopilot
andauthored
improve: log diagnostic for remote deployment junit extension (#3306)
Signed-off-by: Attila Mészáros <a_meszaros@apple.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 4ad9a16 commit 8f05e6c

2 files changed

Lines changed: 134 additions & 3 deletions

File tree

operator-framework-junit/src/main/java/io/javaoperatorsdk/operator/junit/ClusterDeployedOperatorExtension.java

Lines changed: 131 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,14 @@
3232
import org.slf4j.Logger;
3333
import org.slf4j.LoggerFactory;
3434

35+
import io.fabric8.kubernetes.api.model.ContainerStatus;
3536
import io.fabric8.kubernetes.api.model.HasMetadata;
37+
import io.fabric8.kubernetes.api.model.Pod;
38+
import io.fabric8.kubernetes.api.model.apps.Deployment;
3639
import io.fabric8.kubernetes.api.model.rbac.ClusterRoleBinding;
3740
import io.fabric8.kubernetes.client.KubernetesClient;
3841
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
42+
import io.fabric8.kubernetes.client.KubernetesClientTimeoutException;
3943

4044
public class ClusterDeployedOperatorExtension extends AbstractOperatorExtension {
4145

@@ -139,9 +143,14 @@ protected void before(ExtensionContext context) {
139143
});
140144

141145
kubernetesClient.resourceList(operatorDeployment).inNamespace(namespace).createOrReplace();
142-
kubernetesClient
143-
.resourceList(operatorDeployment)
144-
.waitUntilReady(operatorDeploymentTimeout.toMillis(), TimeUnit.MILLISECONDS);
146+
try {
147+
kubernetesClient
148+
.resourceList(operatorDeployment)
149+
.waitUntilReady(operatorDeploymentTimeout.toMillis(), TimeUnit.MILLISECONDS);
150+
} catch (KubernetesClientTimeoutException e) {
151+
logDiagnosticInfo(kubernetesClient);
152+
throw e;
153+
}
145154
LOGGER.debug("Operator resources deployed.");
146155
}
147156

@@ -153,6 +162,125 @@ protected void deleteOperator() {
153162
.delete();
154163
}
155164

165+
private void logDiagnosticInfo(KubernetesClient kubernetesClient) {
166+
LOGGER.error(
167+
"Operator deployment timed out after {} seconds in namespace: {}",
168+
operatorDeploymentTimeout.getSeconds(),
169+
namespace);
170+
try {
171+
// Log deployment status
172+
var deployments =
173+
kubernetesClient.apps().deployments().inNamespace(namespace).list().getItems();
174+
for (Deployment deployment : deployments) {
175+
var status = deployment.getStatus();
176+
LOGGER.error(
177+
"Deployment '{}': replicas={}, readyReplicas={}, availableReplicas={},"
178+
+ " unavailableReplicas={}, conditions={}",
179+
deployment.getMetadata().getName(),
180+
status != null ? status.getReplicas() : "null",
181+
status != null ? status.getReadyReplicas() : "null",
182+
status != null ? status.getAvailableReplicas() : "null",
183+
status != null ? status.getUnavailableReplicas() : "null",
184+
status != null ? status.getConditions() : "null");
185+
}
186+
187+
// Log pod status and container details
188+
var pods = kubernetesClient.pods().inNamespace(namespace).list().getItems();
189+
for (Pod pod : pods) {
190+
var podStatus = pod.getStatus();
191+
LOGGER.error(
192+
"Pod '{}': phase={}, reason={}, message={}",
193+
pod.getMetadata().getName(),
194+
podStatus != null ? podStatus.getPhase() : "null",
195+
podStatus != null ? podStatus.getReason() : "null",
196+
podStatus != null ? podStatus.getMessage() : "null");
197+
198+
if (podStatus != null && podStatus.getContainerStatuses() != null) {
199+
for (ContainerStatus cs : podStatus.getContainerStatuses()) {
200+
LOGGER.error(
201+
" Container '{}': ready={}, restartCount={}, state={}",
202+
cs.getName(),
203+
cs.getReady(),
204+
cs.getRestartCount(),
205+
cs.getState());
206+
}
207+
}
208+
if (podStatus != null && podStatus.getInitContainerStatuses() != null) {
209+
for (ContainerStatus cs : podStatus.getInitContainerStatuses()) {
210+
LOGGER.error(
211+
" InitContainer '{}': ready={}, restartCount={}, state={}",
212+
cs.getName(),
213+
cs.getReady(),
214+
cs.getRestartCount(),
215+
cs.getState());
216+
}
217+
}
218+
219+
// Log pod events
220+
var events =
221+
kubernetesClient
222+
.v1()
223+
.events()
224+
.inNamespace(namespace)
225+
.withField("involvedObject.name", pod.getMetadata().getName())
226+
.list()
227+
.getItems();
228+
for (var event : events) {
229+
LOGGER.error(
230+
" Event: type={}, reason={}, message={}",
231+
event.getType(),
232+
event.getReason(),
233+
event.getMessage());
234+
}
235+
236+
// Try to get container logs
237+
try {
238+
String logs =
239+
kubernetesClient
240+
.pods()
241+
.inNamespace(namespace)
242+
.withName(pod.getMetadata().getName())
243+
.tailingLines(50)
244+
.getLog();
245+
if (logs != null && !logs.isEmpty()) {
246+
LOGGER.error(" Logs for pod '{}':\n{}", pod.getMetadata().getName(), logs);
247+
}
248+
} catch (Exception logEx) {
249+
LOGGER.error(
250+
" Could not retrieve logs for pod '{}'", pod.getMetadata().getName(), logEx);
251+
}
252+
}
253+
254+
if (pods.isEmpty()) {
255+
LOGGER.error(
256+
"No pods found in namespace '{}'. The deployment may have failed to"
257+
+ " create pods. Check if the image exists and is pullable.",
258+
namespace);
259+
260+
// Log deployment events when no pods exist
261+
for (Deployment deployment : deployments) {
262+
var events =
263+
kubernetesClient
264+
.v1()
265+
.events()
266+
.inNamespace(namespace)
267+
.withField("involvedObject.name", deployment.getMetadata().getName())
268+
.list()
269+
.getItems();
270+
for (var event : events) {
271+
LOGGER.error(
272+
" Deployment event: type={}, reason={}, message={}",
273+
event.getType(),
274+
event.getReason(),
275+
event.getMessage());
276+
}
277+
}
278+
}
279+
} catch (Exception diagEx) {
280+
LOGGER.error("Failed to collect diagnostic info: {}", diagEx.getMessage(), diagEx);
281+
}
282+
}
283+
156284
public static class Builder extends AbstractBuilder<Builder> {
157285
private final List<HasMetadata> operatorDeployment;
158286
private Duration deploymentTimeout;

sample-operators/tomcat-operator/src/test/resources/log4j2.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
</Console>
2424
</Appenders>
2525
<Loggers>
26+
<Logger level="debug" name="io.javaoperatorsdk.operator" additivity="false">
27+
<AppenderRef ref="Console"/>
28+
</Logger>
2629
<Root level="info">
2730
<AppenderRef ref="Console"/>
2831
</Root>

0 commit comments

Comments
 (0)