Skip to content

Commit 5175a84

Browse files
committed
started work
Signed-off-by: wind57 <[email protected]>
1 parent b5c8a61 commit 5175a84

File tree

5 files changed

+252
-17
lines changed

5 files changed

+252
-17
lines changed

spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/main/java/org/springframework/cloud/kubernetes/k8s/client/discovery/DiscoveryApplicationListener.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
/**
3030
* @author wind57
3131
*/
32-
@Component
32+
//@Component
33+
//TODO remove this?
3334
public class DiscoveryApplicationListener implements ApplicationListener<InstanceRegisteredEvent<?>> {
3435

3536
private static final LogAccessor LOG = new LogAccessor(LogFactory.getLog(DiscoveryApplicationListener.class));

spring-cloud-kubernetes-integration-tests/spring-cloud-kubernetes-k8s-client-discovery/src/test/java/org/springframework/cloud/kubernetes/k8s/client/discovery/KubernetesClientDiscoveryClientIT.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -100,22 +100,7 @@ static void afterAll() {
100100
*/
101101
@Test
102102
@Order(1)
103-
void testSimple() throws Exception {
104-
105-
util.busybox(NAMESPACE, Phase.CREATE);
106-
107-
// find both pods
108-
String[] both = K3S.execInContainer("sh", "-c", "kubectl get pods -l app=busybox -o=name --no-headers")
109-
.getStdout()
110-
.split("\n");
111-
// add a label to first pod
112-
K3S.execInContainer("sh", "-c",
113-
"kubectl label pods " + both[0].split("/")[1] + " custom-label=custom-label-value");
114-
// add annotation to the second pod
115-
K3S.execInContainer("sh", "-c",
116-
"kubectl annotate pods " + both[1].split("/")[1] + " custom-annotation=custom-annotation-value");
117-
118-
Commons.waitForLogStatement("serviceSharedInformer will use namespace : default", K3S, IMAGE_NAME);
103+
void testSimple() {
119104

120105
WebClient servicesClient = builder().baseUrl("http://localhost/services").build();
121106

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright 2013-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.kubernetes.k8s.client.discovery.it;
18+
19+
import java.io.IOException;
20+
import java.io.StringReader;
21+
import java.time.Duration;
22+
import java.util.ArrayList;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.Objects;
26+
import java.util.Optional;
27+
import java.util.Set;
28+
29+
import io.fabric8.kubernetes.client.KubernetesClient;
30+
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
31+
import io.kubernetes.client.openapi.ApiClient;
32+
import io.kubernetes.client.openapi.apis.CoreV1Api;
33+
import io.kubernetes.client.openapi.models.V1Deployment;
34+
import io.kubernetes.client.openapi.models.V1EnvVar;
35+
import io.kubernetes.client.openapi.models.V1Ingress;
36+
import io.kubernetes.client.openapi.models.V1Service;
37+
import io.kubernetes.client.util.Config;
38+
import org.junit.jupiter.api.AfterAll;
39+
import org.junit.jupiter.api.Assertions;
40+
import org.junit.jupiter.api.BeforeAll;
41+
import org.junit.jupiter.api.MethodOrderer;
42+
import org.junit.jupiter.api.Order;
43+
import org.junit.jupiter.api.Test;
44+
import org.junit.jupiter.api.TestMethodOrder;
45+
import org.junit.jupiter.api.extension.ExtendWith;
46+
import org.springframework.boot.test.context.SpringBootTest;
47+
import org.springframework.boot.test.context.TestConfiguration;
48+
import org.springframework.boot.test.system.OutputCaptureExtension;
49+
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
50+
import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util;
51+
import org.springframework.cloud.kubernetes.k8s.client.discovery.DiscoveryApp;
52+
import org.springframework.context.annotation.Bean;
53+
import org.springframework.context.annotation.Primary;
54+
import org.springframework.test.context.TestPropertySource;
55+
import org.testcontainers.k3s.K3sContainer;
56+
import reactor.netty.http.client.HttpClient;
57+
import reactor.util.retry.Retry;
58+
import reactor.util.retry.RetryBackoffSpec;
59+
60+
import org.springframework.cloud.client.ServiceInstance;
61+
import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance;
62+
import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
63+
import org.springframework.cloud.kubernetes.integration.tests.commons.Images;
64+
import org.springframework.cloud.kubernetes.integration.tests.commons.Phase;
65+
import org.springframework.core.ParameterizedTypeReference;
66+
import org.springframework.http.HttpMethod;
67+
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
68+
import org.springframework.web.reactive.function.client.WebClient;
69+
70+
/**
71+
* @author wind57
72+
*/
73+
@TestPropertySource(properties = { "spring.main.cloud-platform=kubernetes",
74+
"spring.cloud.config.import-check.enabled=false", "spring.cloud.kubernetes.client.namespace=default",
75+
"spring.cloud.kubernetes.discovery.metadata.add-pod-labels=true",
76+
"spring.cloud.kubernetes.discovery.metadata.add-pod-annotations=true",
77+
"logging.level.org.springframework.cloud.kubernetes.client.discovery=debug" })
78+
@ExtendWith(OutputCaptureExtension.class)
79+
abstract class KubernetesClientDiscoveryBase {
80+
81+
protected static final String NAMESPACE = "default";
82+
83+
protected static final K3sContainer K3S = Commons.container();
84+
85+
protected static Util util;
86+
87+
@BeforeAll
88+
protected static void beforeAll() {
89+
K3S.start();
90+
util = new Util(K3S);
91+
}
92+
93+
protected static ApiClient apiClient() {
94+
String kubeConfigYaml = K3S.getKubeConfigYaml();
95+
96+
ApiClient client;
97+
try {
98+
client = Config.fromConfig(new StringReader(kubeConfigYaml));
99+
}
100+
catch (IOException e) {
101+
throw new RuntimeException(e);
102+
}
103+
return new CoreV1Api(client).getApiClient();
104+
}
105+
106+
protected static KubernetesDiscoveryProperties discoveryProperties(boolean useEndpointSlices,
107+
Set<String> namespaces) {
108+
return new KubernetesDiscoveryProperties(true, false, namespaces, true, 60, false, null, Set.of(443, 8443),
109+
null, null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0, useEndpointSlices, true, null);
110+
}
111+
112+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright 2013-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.kubernetes.k8s.client.discovery.it;
18+
19+
import java.util.List;
20+
import java.util.Set;
21+
22+
import io.kubernetes.client.openapi.ApiClient;
23+
import org.junit.jupiter.api.AfterEach;
24+
import org.junit.jupiter.api.BeforeEach;
25+
import org.junit.jupiter.api.Test;
26+
27+
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.boot.test.context.SpringBootTest;
29+
import org.springframework.boot.test.context.TestConfiguration;
30+
import org.springframework.boot.test.system.CapturedOutput;
31+
import org.springframework.cloud.client.discovery.DiscoveryClient;
32+
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties;
33+
import org.springframework.cloud.kubernetes.integration.tests.commons.Images;
34+
import org.springframework.cloud.kubernetes.integration.tests.commons.Phase;
35+
import org.springframework.cloud.kubernetes.k8s.client.discovery.DiscoveryApp;
36+
import org.springframework.context.annotation.Bean;
37+
import org.springframework.context.annotation.Primary;
38+
39+
import static org.springframework.cloud.kubernetes.k8s.client.discovery.it.TestAssertions.assertLogStatement;
40+
41+
/**
42+
* @author wind57
43+
*/
44+
@SpringBootTest(classes = { DiscoveryApp.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
45+
class KubernetesClientDiscoverySimpleIT extends KubernetesClientDiscoveryBase {
46+
47+
@Autowired
48+
private DiscoveryClient discoveryClient;
49+
50+
@BeforeEach
51+
void beforeEach() {
52+
Images.loadBusybox(K3S);
53+
util.busybox(NAMESPACE, Phase.CREATE);
54+
}
55+
56+
@AfterEach
57+
void afterEach() {
58+
util.busybox(NAMESPACE, Phase.DELETE);
59+
}
60+
61+
@Test
62+
void test(CapturedOutput output) throws Exception {
63+
64+
// find both pods
65+
String[] both = K3S.execInContainer("sh", "-c", "kubectl get pods -l app=busybox -o=name --no-headers")
66+
.getStdout()
67+
.split("\n");
68+
// add a label to first pod
69+
K3S.execInContainer("sh", "-c",
70+
"kubectl label pods " + both[0].split("/")[1] + " custom-label=custom-label-value");
71+
// add annotation to the second pod
72+
K3S.execInContainer("sh", "-c",
73+
"kubectl annotate pods " + both[1].split("/")[1] + " custom-annotation=custom-annotation-value");
74+
75+
assertLogStatement(output, "serviceSharedInformer will use namespace : default");
76+
77+
List<String> services = discoveryClient.getServices();
78+
System.out.println("111111 : " + services);
79+
80+
}
81+
82+
@TestConfiguration
83+
static class TestConfig {
84+
85+
@Bean
86+
@Primary
87+
ApiClient client() {
88+
return apiClient();
89+
}
90+
91+
@Bean
92+
@Primary
93+
KubernetesDiscoveryProperties kubernetesDiscoveryProperties() {
94+
return discoveryProperties(false, Set.of(NAMESPACE));
95+
}
96+
97+
}
98+
99+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2013-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.kubernetes.k8s.client.discovery.it;
18+
19+
import java.time.Duration;
20+
21+
import org.springframework.boot.test.system.CapturedOutput;
22+
23+
import static org.awaitility.Awaitility.await;
24+
import static org.assertj.core.api.Assertions.assertThat;
25+
26+
final class TestAssertions {
27+
28+
private TestAssertions() {
29+
30+
}
31+
32+
static void assertLogStatement(CapturedOutput output, String textToAssert) {
33+
await().atMost(Duration.ofSeconds(60))
34+
.pollInterval(Duration.ofMillis(200))
35+
.untilAsserted(() -> assertThat(output.getOut()).contains(textToAssert));
36+
}
37+
38+
}

0 commit comments

Comments
 (0)