Skip to content

Commit 03089b1

Browse files
committed
Merge branch '3.1.x'
2 parents 2d7cbda + f7e7ce3 commit 03089b1

File tree

9 files changed

+231
-176
lines changed

9 files changed

+231
-176
lines changed

spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadConfigMapTest.java

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@
2020
import java.util.List;
2121
import java.util.Map;
2222
import java.util.Set;
23+
import java.util.concurrent.atomic.AtomicBoolean;
2324

2425
import com.github.tomakehurst.wiremock.WireMockServer;
2526
import com.github.tomakehurst.wiremock.client.WireMock;
27+
import com.github.tomakehurst.wiremock.stubbing.Scenario;
2628
import io.kubernetes.client.openapi.ApiClient;
2729
import io.kubernetes.client.openapi.Configuration;
2830
import io.kubernetes.client.openapi.JSON;
@@ -59,8 +61,10 @@
5961
import org.springframework.mock.env.MockEnvironment;
6062

6163
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
64+
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
6265
import static com.github.tomakehurst.wiremock.client.WireMock.get;
6366
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
67+
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching;
6468
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
6569

6670
/**
@@ -81,7 +85,11 @@ class EventReloadConfigMapTest {
8185

8286
private static final String NAMESPACE = "spring-k8s";
8387

84-
private static final boolean[] strategyCalled = new boolean[] { false };
88+
private static final String SCENARIO_NAME = "reload-test";
89+
90+
private static final String PATH = "/api/v1/namespaces/spring-k8s/configmaps";
91+
92+
private static final AtomicBoolean STRATEGY_CALLED = new AtomicBoolean(false);
8593

8694
private static CoreV1Api coreV1Api;
8795

@@ -98,6 +106,12 @@ static void setup() {
98106
wireMockServer.start();
99107
WireMock.configureFor("localhost", wireMockServer.port());
100108

109+
// something that the informer can work with. Since we do not care about this one
110+
// in the test, we mock it to return a 500 as it does not matter anyway.
111+
stubFor(get(urlPathMatching(PATH)).withQueryParam("resourceVersion", equalTo("0"))
112+
.withQueryParam("watch", equalTo("false"))
113+
.willReturn(aResponse().withStatus(500).withBody("Error From Informer")));
114+
101115
ApiClient client = new ClientBuilder().setBasePath("http://localhost:" + wireMockServer.port()).build();
102116
client.setDebugging(true);
103117
MOCK_STATIC.when(KubernetesClientUtils::createApiClientForInformerClient).thenReturn(client);
@@ -107,30 +121,6 @@ static void setup() {
107121
.thenReturn(NAMESPACE);
108122
Configuration.setDefaultApiClient(client);
109123
coreV1Api = new CoreV1Api();
110-
111-
String path = "/api/v1/namespaces/spring-k8s/configmaps";
112-
V1ConfigMap configMapOne = configMap(CONFIG_MAP_NAME, Map.of());
113-
V1ConfigMapList listOne = new V1ConfigMapList().addItemsItem(configMapOne);
114-
115-
// needed so that our environment is populated with 'something'
116-
// this call is done in the method that returns the AbstractEnvironment
117-
stubFor(get(path).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(listOne)))
118-
.inScenario("mine-test")
119-
.willSetStateTo("go-to-fail"));
120-
121-
// first call will fail
122-
stubFor(get(path).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))
123-
.inScenario("mine-test")
124-
.whenScenarioStateIs("go-to-fail")
125-
.willSetStateTo("go-to-ok"));
126-
127-
// second call passes (change data so that reload is triggered)
128-
configMapOne = configMap(CONFIG_MAP_NAME, Map.of("a", "b"));
129-
listOne = new V1ConfigMapList().addItemsItem(configMapOne);
130-
stubFor(get(path).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(listOne)))
131-
.inScenario("mine-test")
132-
.whenScenarioStateIs("go-to-ok")
133-
.willSetStateTo("done"));
134124
}
135125

136126
@AfterAll
@@ -149,6 +139,13 @@ static void after() {
149139
*/
150140
@Test
151141
void test(CapturedOutput output) {
142+
143+
// first call will fail
144+
stubFor(get(PATH).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))
145+
.inScenario(SCENARIO_NAME)
146+
.whenScenarioStateIs("go-to-fail")
147+
.willSetStateTo("go-to-ok"));
148+
152149
V1ConfigMap configMapNotMine = configMap("not" + CONFIG_MAP_NAME, Map.of());
153150
kubernetesClientEventBasedConfigMapChangeDetector.onEvent(configMapNotMine);
154151

@@ -158,17 +155,25 @@ void test(CapturedOutput output) {
158155
boolean two = output.getOut().contains("Failed to load source");
159156
boolean three = output.getOut()
160157
.contains("Reloadable condition was not satisfied, reload will not be triggered");
161-
boolean updateStrategyNotCalled = !strategyCalled[0];
158+
boolean updateStrategyNotCalled = !STRATEGY_CALLED.get();
162159
return one && two && three && updateStrategyNotCalled;
163160
});
164161

162+
// second call passes (change data so that reload is triggered)
163+
V1ConfigMap configMap = configMap(CONFIG_MAP_NAME, Map.of("a", "b"));
164+
V1ConfigMapList configMapList = new V1ConfigMapList().addItemsItem(configMap);
165+
stubFor(get(PATH).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList)))
166+
.inScenario(SCENARIO_NAME)
167+
.whenScenarioStateIs("go-to-ok")
168+
.willSetStateTo("done"));
169+
165170
// trigger the call again
166171
V1ConfigMap configMapMine = configMap(CONFIG_MAP_NAME, Map.of());
167172
kubernetesClientEventBasedConfigMapChangeDetector.onEvent(configMapMine);
168173
Awaitility.await()
169174
.atMost(Duration.ofSeconds(10))
170175
.pollInterval(Duration.ofSeconds(1))
171-
.until(() -> strategyCalled[0]);
176+
.until(STRATEGY_CALLED::get);
172177
}
173178

174179
private static V1ConfigMap configMap(String name, Map<String, String> data) {
@@ -193,6 +198,17 @@ VisibleKubernetesClientEventBasedConfigMapChangeDetector kubernetesClientEventBa
193198
@Bean
194199
@Primary
195200
AbstractEnvironment environment() {
201+
202+
V1ConfigMap configMap = configMap(CONFIG_MAP_NAME, Map.of());
203+
V1ConfigMapList configMapList = new V1ConfigMapList().addItemsItem(configMap);
204+
205+
// needed so that our environment is populated with 'something'
206+
// this call is done in the method that returns the AbstractEnvironment
207+
stubFor(get(PATH).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(configMapList)))
208+
.inScenario(SCENARIO_NAME)
209+
.whenScenarioStateIs(Scenario.STARTED)
210+
.willSetStateTo("go-to-fail"));
211+
196212
MockEnvironment mockEnvironment = new MockEnvironment();
197213
mockEnvironment.setProperty("spring.cloud.kubernetes.client.namespace", NAMESPACE);
198214

@@ -216,7 +232,7 @@ AbstractEnvironment environment() {
216232
@Primary
217233
ConfigReloadProperties configReloadProperties() {
218234
return new ConfigReloadProperties(true, true, false, ConfigReloadProperties.ReloadStrategy.REFRESH,
219-
ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(2000), Set.of("non-default"),
235+
ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(2000), Set.of("spring-k8s"),
220236
false, Duration.ofSeconds(2));
221237
}
222238

@@ -237,7 +253,7 @@ KubernetesNamespaceProvider namespaceProvider(AbstractEnvironment environment) {
237253
@Primary
238254
ConfigurationUpdateStrategy configurationUpdateStrategy() {
239255
return new ConfigurationUpdateStrategy("to-console", () -> {
240-
strategyCalled[0] = true;
256+
STRATEGY_CALLED.set(true);
241257
});
242258
}
243259

spring-cloud-kubernetes-client-config/src/test/java/org/springframework/cloud/kubernetes/client/config/reload_it/EventReloadSecretTest.java

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
import java.util.List;
2222
import java.util.Map;
2323
import java.util.Set;
24+
import java.util.concurrent.atomic.AtomicBoolean;
2425
import java.util.stream.Collectors;
2526

2627
import com.github.tomakehurst.wiremock.WireMockServer;
2728
import com.github.tomakehurst.wiremock.client.WireMock;
29+
import com.github.tomakehurst.wiremock.stubbing.Scenario;
2830
import io.kubernetes.client.openapi.ApiClient;
2931
import io.kubernetes.client.openapi.Configuration;
3032
import io.kubernetes.client.openapi.JSON;
@@ -61,8 +63,10 @@
6163
import org.springframework.mock.env.MockEnvironment;
6264

6365
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
66+
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
6467
import static com.github.tomakehurst.wiremock.client.WireMock.get;
6568
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
69+
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching;
6670
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
6771

6872
/**
@@ -83,7 +87,11 @@ class EventReloadSecretTest {
8387

8488
private static final String NAMESPACE = "spring-k8s";
8589

86-
private static final boolean[] strategyCalled = new boolean[] { false };
90+
private static final String PATH = "/api/v1/namespaces/spring-k8s/secrets";
91+
92+
private static final String SCENARIO_NAME = "reload-test";
93+
94+
private static final AtomicBoolean STRATEGY_CALLED = new AtomicBoolean(false);
8795

8896
private static CoreV1Api coreV1Api;
8997

@@ -100,6 +108,12 @@ static void setup() {
100108
wireMockServer.start();
101109
WireMock.configureFor("localhost", wireMockServer.port());
102110

111+
// something that the informer can work with. Since we do not care about this one
112+
// in the test, we mock it to return a 500 as it does not matter anyway.
113+
stubFor(get(urlPathMatching(PATH)).withQueryParam("resourceVersion", equalTo("0"))
114+
.withQueryParam("watch", equalTo("false"))
115+
.willReturn(aResponse().withStatus(500).withBody("Error From Informer")));
116+
103117
ApiClient client = new ClientBuilder().setBasePath("http://localhost:" + wireMockServer.port()).build();
104118
client.setDebugging(true);
105119
MOCK_STATIC.when(KubernetesClientUtils::createApiClientForInformerClient).thenReturn(client);
@@ -109,30 +123,6 @@ static void setup() {
109123
.thenReturn(NAMESPACE);
110124
Configuration.setDefaultApiClient(client);
111125
coreV1Api = new CoreV1Api();
112-
113-
String path = "/api/v1/namespaces/spring-k8s/secrets";
114-
V1Secret secretOne = secret(SECRET_NAME, Map.of());
115-
V1SecretList listOne = new V1SecretList().addItemsItem(secretOne);
116-
117-
// needed so that our environment is populated with 'something'
118-
// this call is done in the method that returns the AbstractEnvironment
119-
stubFor(get(path).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(listOne)))
120-
.inScenario("mine-test")
121-
.willSetStateTo("go-to-fail"));
122-
123-
// first call will fail
124-
stubFor(get(path).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))
125-
.inScenario("mine-test")
126-
.whenScenarioStateIs("go-to-fail")
127-
.willSetStateTo("go-to-ok"));
128-
129-
// second call passes (change data so that reload is triggered)
130-
secretOne = secret(SECRET_NAME, Map.of("a", "b"));
131-
listOne = new V1SecretList().addItemsItem(secretOne);
132-
stubFor(get(path).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(listOne)))
133-
.inScenario("mine-test")
134-
.whenScenarioStateIs("go-to-ok")
135-
.willSetStateTo("done"));
136126
}
137127

138128
@AfterAll
@@ -151,6 +141,12 @@ static void after() {
151141
*/
152142
@Test
153143
void test(CapturedOutput output) {
144+
// first call will fail
145+
stubFor(get(PATH).willReturn(aResponse().withStatus(500).withBody("Internal Server Error"))
146+
.inScenario(SCENARIO_NAME)
147+
.whenScenarioStateIs("go-to-fail")
148+
.willSetStateTo("go-to-ok"));
149+
154150
V1Secret secretNotMine = secret("not" + SECRET_NAME, Map.of());
155151
kubernetesClientEventBasedSecretsChangeDetector.onEvent(secretNotMine);
156152

@@ -160,17 +156,25 @@ void test(CapturedOutput output) {
160156
boolean two = output.getOut().contains("Failed to load source");
161157
boolean three = output.getOut()
162158
.contains("Reloadable condition was not satisfied, reload will not be triggered");
163-
boolean updateStrategyNotCalled = !strategyCalled[0];
159+
boolean updateStrategyNotCalled = !STRATEGY_CALLED.get();
164160
return one && two && three && updateStrategyNotCalled;
165161
});
166162

163+
// second call passes (change data so that reload is triggered)
164+
V1Secret secret = secret(SECRET_NAME, Map.of("a", "b"));
165+
V1SecretList secretList = new V1SecretList().addItemsItem(secret);
166+
stubFor(get(PATH).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList)))
167+
.inScenario(SCENARIO_NAME)
168+
.whenScenarioStateIs("go-to-ok")
169+
.willSetStateTo("done"));
170+
167171
// trigger the call again
168172
V1Secret secretMine = secret(SECRET_NAME, Map.of());
169173
kubernetesClientEventBasedSecretsChangeDetector.onEvent(secretMine);
170174
Awaitility.await()
171175
.atMost(Duration.ofSeconds(10))
172176
.pollInterval(Duration.ofSeconds(1))
173-
.until(() -> strategyCalled[0]);
177+
.until(STRATEGY_CALLED::get);
174178
}
175179

176180
private static V1Secret secret(String name, Map<String, String> data) {
@@ -199,6 +203,17 @@ VisibleKubernetesClientEventBasedSecretsChangeDetector kubernetesClientEventBase
199203
@Bean
200204
@Primary
201205
AbstractEnvironment environment() {
206+
207+
// needed so that our environment is populated with 'something'
208+
// this call is done in the method that returns the AbstractEnvironment
209+
V1Secret secret = secret(SECRET_NAME, Map.of());
210+
V1SecretList secretList = new V1SecretList().addItemsItem(secret);
211+
212+
stubFor(get(PATH).willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(secretList)))
213+
.inScenario(SCENARIO_NAME)
214+
.whenScenarioStateIs(Scenario.STARTED)
215+
.willSetStateTo("go-to-fail"));
216+
202217
MockEnvironment mockEnvironment = new MockEnvironment();
203218
mockEnvironment.setProperty("spring.cloud.kubernetes.client.namespace", NAMESPACE);
204219

@@ -221,7 +236,7 @@ AbstractEnvironment environment() {
221236
@Primary
222237
ConfigReloadProperties configReloadProperties() {
223238
return new ConfigReloadProperties(true, true, false, ConfigReloadProperties.ReloadStrategy.REFRESH,
224-
ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(2000), Set.of("non-default"),
239+
ConfigReloadProperties.ReloadDetectionMode.POLLING, Duration.ofMillis(2000), Set.of("spring-k8s"),
225240
false, Duration.ofSeconds(2));
226241
}
227242

@@ -242,7 +257,7 @@ KubernetesNamespaceProvider namespaceProvider(AbstractEnvironment environment) {
242257
@Primary
243258
ConfigurationUpdateStrategy configurationUpdateStrategy() {
244259
return new ConfigurationUpdateStrategy("to-console", () -> {
245-
strategyCalled[0] = true;
260+
STRATEGY_CALLED.set(true);
246261
});
247262
}
248263

0 commit comments

Comments
 (0)