Skip to content

Commit cc5850d

Browse files
Merge pull request #44
[ACC-2066] Improve resource waiter to print events & container logs
2 parents f9f4386 + 0000136 commit cc5850d

28 files changed

+1502
-92
lines changed

contentgrid-junit-jupiter-k8s/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ dependencies {
3434
testImplementation 'org.assertj:assertj-core'
3535
testImplementation 'org.mockito:mockito-core'
3636
testImplementation 'org.skyscreamer:jsonassert'
37+
testImplementation 'ch.qos.logback:logback-classic'
3738
testImplementation files(tasks.named("testResourcesJar"))
3839

3940
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
40-
testRuntimeOnly 'org.slf4j:slf4j-simple'
4141
}
4242

4343

contentgrid-junit-jupiter-k8s/src/main/java/com/contentgrid/junit/jupiter/externalsecrets/ExternalSecretsExtension.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* and {@link SecretStore} fields.
3131
*/
3232
@Slf4j
33-
public class ExternalSecretsExtension implements HasHelmClient, HasKubernetesClient, BeforeAllCallback, AfterAllCallback,
33+
public class ExternalSecretsExtension implements HasHelmClient, HasKubernetesClient, BeforeAllCallback,
3434
BeforeEachCallback, ParameterResolver {
3535

3636
private static final Namespace NAMESPACE = Namespace.create(ExternalSecretsExtension.class);
@@ -127,10 +127,4 @@ private static String convertToValidName(String input) {
127127
// Truncate if needed
128128
return name.substring(0, Math.min(253, name.length()));
129129
}
130-
131-
@Override
132-
public void afterAll(ExtensionContext context) {
133-
// Shutdown helm chart
134-
getHelmChartHandle(context).close();
135-
}
136130
}

contentgrid-junit-jupiter-k8s/src/main/java/com/contentgrid/junit/jupiter/helm/HelmChartHandle.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@
2929
import lombok.RequiredArgsConstructor;
3030
import lombok.SneakyThrows;
3131
import lombok.extern.slf4j.Slf4j;
32+
import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource;
3233

3334
/**
3435
* A handle to a helm chart created by the {@link HelmChart @HelmChart} annotation.
3536
*/
3637
@Slf4j
3738
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
3839
@Builder
39-
public class HelmChartHandle implements AutoCloseable {
40+
public class HelmChartHandle implements CloseableResource {
4041

4142
@NonNull
4243
private final Helm helmClient;
Lines changed: 36 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,66 @@
11
package com.contentgrid.junit.jupiter.k8s;
22

33
import static java.util.concurrent.TimeUnit.SECONDS;
4-
import static org.awaitility.Awaitility.await;
54

5+
import com.contentgrid.junit.jupiter.k8s.wait.KubernetesResourceWaiter;
6+
import com.contentgrid.junit.jupiter.k8s.wait.ResourceMatcher;
7+
import io.fabric8.kubernetes.api.model.apps.ReplicaSet;
68
import io.fabric8.kubernetes.client.KubernetesClient;
79
import java.util.List;
8-
import java.util.Objects;
9-
import java.util.stream.Collectors;
10+
import java.util.function.UnaryOperator;
1011
import lombok.experimental.UtilityClass;
1112
import lombok.extern.slf4j.Slf4j;
12-
import org.awaitility.core.ConditionEvaluationLogger;
13-
import org.hamcrest.Matchers;
13+
import org.awaitility.core.ConditionFactory;
1414

15+
/**
16+
* @deprecated Use {@link KubernetesResourceWaiter} to wait on configurable resources instead
17+
*/
1518
@Slf4j
1619
@UtilityClass
20+
@Deprecated(since = "0.1.0", forRemoval = true)
1721
public class K8sTestUtils {
1822

19-
public static void waitUntilDeploymentsReady(int timeout, List<String> deployments,
20-
KubernetesClient kubernetesClient, String namespace) {
21-
var client = namespace == null
22-
? kubernetesClient.apps().deployments()
23-
: kubernetesClient.apps().deployments().inNamespace(namespace);
24-
// wait until expected deployments have available-replica
25-
await()
26-
.conditionEvaluationListener(new ConditionEvaluationLogger(log::info, SECONDS))
27-
.pollInterval(1, SECONDS)
28-
.atMost(timeout, SECONDS)
29-
.until(() -> deployments.stream()
30-
.map(name -> client.withName(name).get())
31-
.filter(deployment -> {
32-
if (deployment == null || deployment.getStatus() == null || deployment.getStatus().getReplicas() == null) {
33-
return true;
34-
}
35-
return deployment.getStatus().getReplicas() -
36-
Objects.requireNonNullElse(deployment.getStatus().getReadyReplicas(), 0)
37-
> 0;
38-
})
39-
.collect(Collectors.toSet()),
40-
Matchers.empty()
41-
);
23+
private static UnaryOperator<ConditionFactory> createAwait(int timeout) {
24+
return await -> await.pollInterval(1, SECONDS).atMost(timeout, SECONDS);
4225
}
4326

4427
public static void waitUntilDeploymentsReady(int timeout, List<String> deployments,
45-
KubernetesClient kubernetesClient) {
46-
waitUntilDeploymentsReady(timeout, deployments, kubernetesClient, null);
47-
}
28+
KubernetesClient kubernetesClient, String namespace) {
4829

49-
public static void waitUntilReplicaSetsReady(int timeout, List<String> replicaSets,
50-
KubernetesClient kubernetesClient) {
51-
waitUntilReplicaSetsReady(timeout, replicaSets, kubernetesClient, null);
30+
new KubernetesResourceWaiter(kubernetesClient)
31+
.deployments(ResourceMatcher.named(deployments.toArray(String[]::new)).inNamespace(namespace))
32+
.await(createAwait(timeout));
5233
}
5334

54-
public static void waitUntilReplicaSetsReady(int timeout, List<String> replicaSets,
55-
KubernetesClient kubernetesClient, String namespace) {
56-
var client = namespace == null
57-
? kubernetesClient.apps().replicaSets()
58-
: kubernetesClient.apps().replicaSets().inNamespace(namespace);
59-
60-
// wait until expected replicaSets have available-replica
61-
await()
62-
.conditionEvaluationListener(new ConditionEvaluationLogger(log::info, SECONDS))
63-
.pollInterval(1, SECONDS)
64-
.atMost(timeout, SECONDS)
65-
.until(() -> replicaSets.stream()
66-
.map(name -> client.withName(name).get())
67-
.filter(replicaset -> {
68-
if (replicaset == null || replicaset.getStatus() == null || replicaset.getStatus().getReplicas() == null) {
69-
return true;
70-
}
71-
return replicaset.getStatus().getReplicas() -
72-
Objects.requireNonNullElse(replicaset.getStatus().getReadyReplicas(), 0)
73-
> 0;
74-
})
75-
.collect(Collectors.toSet()),
76-
Matchers.empty()
77-
);
35+
public static void waitUntilDeploymentsReady(int timeout, List<String> deployments,
36+
KubernetesClient kubernetesClient) {
37+
new KubernetesResourceWaiter(kubernetesClient)
38+
.deployments(ResourceMatcher.named(deployments.toArray(String[]::new)))
39+
.await(createAwait(timeout));
7840
}
7941

8042
public static void waitUntilStatefulSetsReady(int timeout, List<String> statefulSets, KubernetesClient kubernetesClient) {
81-
waitUntilStatefulSetsReady(timeout, statefulSets, kubernetesClient, null);
43+
new KubernetesResourceWaiter(kubernetesClient)
44+
.statefulSets(ResourceMatcher.named(statefulSets.toArray(String[]::new)))
45+
.await(createAwait(timeout));
8246
}
8347

8448
public static void waitUntilStatefulSetsReady(int timeout, List<String> statefulSets,
8549
KubernetesClient kubernetesClient, String namespace) {
86-
var client = namespace == null
87-
? kubernetesClient.apps().statefulSets()
88-
: kubernetesClient.apps().statefulSets().inNamespace(namespace);
89-
await()
90-
.conditionEvaluationListener(new ConditionEvaluationLogger(log::info, SECONDS))
91-
.pollInterval(1, SECONDS)
92-
.atMost(timeout, SECONDS)
93-
.until(() -> statefulSets.stream()
94-
.map(name -> client.withName(name).get())
95-
.filter(statefulSet -> {
96-
if (statefulSet == null || statefulSet.getStatus() == null || statefulSet.getStatus().getReplicas() == null) {
97-
return true;
98-
}
99-
return statefulSet.getStatus().getReplicas() -
100-
Objects.requireNonNullElse(statefulSet.getStatus().getReadyReplicas(), 0)
101-
> 0;
102-
})
103-
.collect(Collectors.toSet()),
104-
Matchers.empty()
105-
);
50+
new KubernetesResourceWaiter(kubernetesClient)
51+
.statefulSets(ResourceMatcher.named(statefulSets.toArray(String[]::new)).inNamespace(namespace))
52+
.await(createAwait(timeout));
10653
}
10754

108-
// TODO We might want to simplify these very-similar looking methods at some point, but I couldn't get past making
109-
// a generic <T extends HasMetadata> method where I run into issues on .filter(resource -> resource.getStatus())
110-
// because Fabric8 doesn't have an interface for "has status", and besides, the status on a StatefulSet is a
111-
// different type than on a Deployment.
55+
public static void waitUntilReplicaSetsReady(int timeout, List<String> replicaSets, KubernetesClient kubernetesClient) {
56+
new KubernetesResourceWaiter(kubernetesClient)
57+
.include(ReplicaSet.class, ResourceMatcher.named(replicaSets.toArray(String[]::new)))
58+
.await(createAwait(timeout));
59+
}
11260

61+
public static void waitUntilReplicaSetsReady(int timeout, List<String> replicaSets, KubernetesClient kubernetesClient, String namespace) {
62+
new KubernetesResourceWaiter(kubernetesClient)
63+
.include(ReplicaSet.class, ResourceMatcher.named(replicaSets.toArray(String[]::new)).inNamespace(namespace))
64+
.await(createAwait(timeout));
65+
}
11366
}

0 commit comments

Comments
 (0)