Skip to content

Commit fada846

Browse files
committed
fix tests + code adjustment
Signed-off-by: wind57 <[email protected]>
1 parent b971468 commit fada846

File tree

5 files changed

+54
-31
lines changed

5 files changed

+54
-31
lines changed

spring-cloud-kubernetes-fabric8-leader/src/main/java/org/springframework/cloud/kubernetes/fabric8/leader/election/Fabric8LeaderElectionInitiator.java

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@
3131
import org.springframework.core.log.LogAccessor;
3232

3333
import static java.util.concurrent.Executors.newSingleThreadExecutor;
34-
import static org.springframework.cloud.kubernetes.fabric8.leader.election.Fabric8LeaderElectionInitiatorUtil.attachStatusLoggerPipeline;
34+
import static org.springframework.cloud.kubernetes.fabric8.leader.election.Fabric8LeaderElectionInitiatorUtil.attachReadinessLoggerPipeline;
3535
import static org.springframework.cloud.kubernetes.fabric8.leader.election.Fabric8LeaderElectionInitiatorUtil.blockReadinessCheck;
3636
import static org.springframework.cloud.kubernetes.fabric8.leader.election.Fabric8LeaderElectionInitiatorUtil.leaderElector;
37+
import static org.springframework.cloud.kubernetes.fabric8.leader.election.Fabric8LeaderElectionInitiatorUtil.shutDownExecutor;
3738
import static org.springframework.cloud.kubernetes.fabric8.leader.election.Fabric8LeaderElectionInitiatorUtil.sleep;
3839

3940
/**
@@ -103,13 +104,18 @@ void postConstruct() {
103104
// wait in a different thread until the pod is ready
104105
// and don't block the main application from starting
105106
podReadyWaitingExecutor.execute(() -> {
106-
if (waitForPodReady) {
107-
CompletableFuture<?> ready = attachStatusLoggerPipeline(podReadyFuture, candidateIdentity);
108-
blockReadinessCheck(ready);
109-
startLeaderElection();
107+
try {
108+
if (waitForPodReady) {
109+
CompletableFuture<?> ready = attachReadinessLoggerPipeline(podReadyFuture, candidateIdentity);
110+
blockReadinessCheck(ready);
111+
startLeaderElection();
112+
}
113+
else {
114+
startLeaderElection();
115+
}
110116
}
111-
else {
112-
startLeaderElection();
117+
catch (Exception e) {
118+
LOG.error(e, () -> "failure : " + e.getMessage());
113119
}
114120
});
115121

@@ -119,11 +125,6 @@ void postConstruct() {
119125
void preDestroy() {
120126
LOG.info(() -> "preDestroy called on the leader initiator : " + candidateIdentity);
121127

122-
if (!podReadyWaitingExecutor.isShutdown()) {
123-
LOG.debug(() -> "podReadyWaitingExecutor will be shutdown for : " + candidateIdentity);
124-
podReadyWaitingExecutor.shutdownNow();
125-
}
126-
127128
if (podReadyFuture != null && !podReadyFuture.isDone()) {
128129
// if the task is not running, this has no effect.
129130
// if the task is running, calling this will also make sure
@@ -132,6 +133,10 @@ void preDestroy() {
132133
podReadyFuture.cancel(true);
133134
}
134135

136+
if (!podReadyWaitingExecutor.isShutdown()) {
137+
shutDownExecutor(podReadyWaitingExecutor, candidateIdentity);
138+
}
139+
135140
if (leaderFuture != null) {
136141
// needed to release the lock, in case we are holding it.
137142
// fabric8 internally expects this one to be called
@@ -153,8 +158,7 @@ private void startLeaderElection() {
153158

154159
if (error != null) {
155160
// only we have a reference to leaderFuture; and if it is canceled, it is
156-
// only possible
157-
// from our own preDestroy
161+
// only possible from our own preDestroy
158162
if (error instanceof CancellationException) {
159163
LOG.info(() -> "cancel was called on the leader initiator : " + candidateIdentity);
160164
LOG.info(() -> "terminating leadership for : " + candidateIdentity);

spring-cloud-kubernetes-fabric8-leader/src/main/java/org/springframework/cloud/kubernetes/fabric8/leader/election/Fabric8LeaderElectionInitiatorUtil.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.cloud.kubernetes.fabric8.leader.election;
1818

1919
import java.util.concurrent.CompletableFuture;
20+
import java.util.concurrent.ExecutorService;
2021
import java.util.concurrent.TimeUnit;
2122

2223
import io.fabric8.kubernetes.client.KubernetesClient;
@@ -38,7 +39,7 @@ private Fabric8LeaderElectionInitiatorUtil() {
3839
* if 'ready' is already completed at this point, thread will run this, otherwise it
3940
* will attach the pipeline and move on to 'blockReadinessCheck'.
4041
*/
41-
static CompletableFuture<?> attachStatusLoggerPipeline(CompletableFuture<?> innerPodReadyFuture,
42+
static CompletableFuture<?> attachReadinessLoggerPipeline(CompletableFuture<?> innerPodReadyFuture,
4243
String candidateIdentity) {
4344
return innerPodReadyFuture.whenComplete((ok, error) -> {
4445
if (error != null) {
@@ -69,6 +70,18 @@ static void blockReadinessCheck(CompletableFuture<?> ready) {
6970
}
7071
catch (Exception e) {
7172
LOG.error(e, () -> "block readiness check failed with : " + e.getMessage());
73+
throw new RuntimeException(e);
74+
}
75+
}
76+
77+
static void shutDownExecutor(ExecutorService podReadyWaitingExecutor, String candidateIdentity) {
78+
LOG.debug(() -> "podReadyWaitingExecutor will be shutdown for : " + candidateIdentity);
79+
podReadyWaitingExecutor.shutdownNow();
80+
try {
81+
podReadyWaitingExecutor.awaitTermination(3, TimeUnit.SECONDS);
82+
}
83+
catch (InterruptedException e) {
84+
Thread.currentThread().interrupt();
7285
}
7386
}
7487

spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-leader-election/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/election/AbstractLeaderElection.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.fabric8.kubernetes.client.Config;
2525
import io.fabric8.kubernetes.client.KubernetesClient;
2626
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
27+
import org.junit.jupiter.api.AfterAll;
2728
import org.junit.jupiter.api.extension.ExtendWith;
2829
import org.mockito.MockedStatic;
2930
import org.mockito.Mockito;
@@ -56,7 +57,7 @@ abstract class AbstractLeaderElection {
5657

5758
private static K3sContainer container;
5859

59-
private static final MockedStatic<LeaderUtils> LEADER_UTILS_MOCKED_STATIC = Mockito.mockStatic(LeaderUtils.class);
60+
private static MockedStatic<LeaderUtils> LEADER_UTILS_MOCKED_STATIC;
6061

6162
@Autowired
6263
KubernetesClient kubernetesClient;
@@ -65,9 +66,15 @@ static void beforeAll(String candidateIdentity) {
6566
container = Commons.container();
6667
container.start();
6768

69+
LEADER_UTILS_MOCKED_STATIC = Mockito.mockStatic(LeaderUtils.class);
6870
LEADER_UTILS_MOCKED_STATIC.when(LeaderUtils::hostName).thenReturn(candidateIdentity);
6971
}
7072

73+
@AfterAll
74+
static void afterAll() {
75+
LEADER_UTILS_MOCKED_STATIC.close();
76+
}
77+
7178
void stopFutureAndDeleteLease(Fabric8LeaderElectionInitiator initiator) {
7279

7380
initiator.preDestroy();
@@ -124,11 +131,11 @@ BooleanSupplier readinessSupplierFails() {
124131
};
125132
}
126133

127-
// readiness fails after 2 retries
134+
// readiness always fails
128135
@Bean
129136
@Primary
130-
@ConditionalOnProperty(value = "readiness.cycle.false", havingValue = "true", matchIfMissing = false)
131-
BooleanSupplier readinessCycleFalse() {
137+
@ConditionalOnProperty(value = "readiness.never.finishes", havingValue = "true", matchIfMissing = false)
138+
BooleanSupplier readinessNeverFinishes() {
132139
return () -> false;
133140
}
134141

spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-leader-election/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/election/Assertions.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ static void assertAcquireAndRenew(CapturedOutput output, Supplier<Lease> leaseSu
5353
+ candidateIdentity + ")'"));
5454

5555
// 4. lease has been acquired
56-
awaitUntil(5, 100, () -> output.getOut().contains("Acquired lease 'LeaseLock: default - spring-k8s-leader-election-lock "
57-
+ "(" + candidateIdentity + ")'"));
56+
awaitUntil(5, 100,
57+
() -> output.getOut()
58+
.contains("Acquired lease 'LeaseLock: default - spring-k8s-leader-election-lock " + "("
59+
+ candidateIdentity + ")'"));
5860

5961
// 5. we are the leader (comes from fabric8 code)
60-
awaitUntil(5, 100, () -> output.getOut()
61-
.matches("(?s).*Leader changed from (|null) to " + candidateIdentity + ".*"));
62+
awaitUntil(5, 100,
63+
() -> output.getOut().matches("(?s).*Leader changed from (|null) to " + candidateIdentity + ".*"));
6264

6365
// 6. wait until a renewal happens (comes from fabric code)
6466
// this one means that we have extended our leadership

spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-fabric8-leader-election/src/test/java/org/springframework/cloud/kubernetes/fabric8/leader/election/Fabric8LeaderElectionReadinessCanceledIT.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
*
3333
* @author wind57
3434
*/
35-
@TestPropertySource(properties = { "readiness.cycle.false=true",
35+
@TestPropertySource(properties = { "readiness.never.finishes=true",
3636
"spring.cloud.kubernetes.leader.election.wait-for-pod-ready=true" })
3737
class Fabric8LeaderElectionReadinessCanceledIT extends AbstractLeaderElection {
3838

@@ -59,13 +59,6 @@ void test(CapturedOutput output) {
5959

6060
initiator.preDestroy();
6161

62-
try {
63-
Thread.sleep(2_000);
64-
}
65-
catch (InterruptedException e) {
66-
throw new RuntimeException(e);
67-
}
68-
6962
// 1. preDestroy method logs what it will do
7063
assertThat(output.getOut()).contains("podReadyFuture will be canceled for : canceled-readiness-it");
7164

@@ -82,6 +75,10 @@ void test(CapturedOutput output) {
8275
// 5. the scheduled executor where pod readiness is checked is shut down also
8376
awaitUntil(2, 100, () -> output.getOut().contains("Shutting down executor : podReadyExecutor"));
8477

78+
// we need to call preDestroy again, to make sure that leaderFuture was not
79+
// started
80+
initiator.preDestroy();
81+
8582
// 6. leader election is not started, since readiness does not finish
8683
assertThat(output.getOut()).doesNotContain("leaderFuture will be canceled for");
8784

0 commit comments

Comments
 (0)