Merge branch '3.1.x'

This commit is contained in:
Ryan Baxter
2025-01-14 09:01:31 -05:00
14 changed files with 39 additions and 173 deletions

View File

@@ -49,10 +49,10 @@ class Fabric8DiscoveryAllServicesIT extends Fabric8DiscoveryBase {
private void externalNameServices(Phase phase) {
if (phase == Phase.CREATE) {
util.createAndWait(NAMESPACE, null, null, externalServiceName, null, true);
util.createAndWait(NAMESPACE, null, null, externalServiceName, true);
}
else {
util.deleteAndWait(NAMESPACE, null, externalServiceName, null);
util.deleteAndWait(NAMESPACE, null, externalServiceName);
}
}

View File

@@ -51,16 +51,16 @@ class Fabric8DiscoveryFilterMatchOneNamespaceIT extends Fabric8DiscoveryBase {
util.createNamespace(NAMESPACE_A_UAT);
util.createNamespace(NAMESPACE_B_UAT);
util.wiremock(NAMESPACE_A_UAT, "/wiremock", Phase.CREATE, false);
util.wiremock(NAMESPACE_B_UAT, "/wiremock", Phase.CREATE, false);
util.wiremock(NAMESPACE_A_UAT, Phase.CREATE);
util.wiremock(NAMESPACE_B_UAT, Phase.CREATE);
}
@AfterEach
void afterEach() {
util.wiremock(NAMESPACE_A_UAT, "/wiremock", Phase.DELETE, false);
util.wiremock(NAMESPACE_B_UAT, "/wiremock", Phase.DELETE, false);
util.wiremock(NAMESPACE_A_UAT, Phase.DELETE);
util.wiremock(NAMESPACE_B_UAT, Phase.DELETE);
util.deleteNamespace(NAMESPACE_A_UAT);
util.deleteNamespace(NAMESPACE_B_UAT);

View File

@@ -51,16 +51,16 @@ class Fabric8DiscoveryFilterMatchTwoNamespacesIT extends Fabric8DiscoveryBase {
util.createNamespace(NAMESPACE_A_UAT);
util.createNamespace(NAMESPACE_B_UAT);
util.wiremock(NAMESPACE_A_UAT, "/wiremock", Phase.CREATE, false);
util.wiremock(NAMESPACE_B_UAT, "/wiremock", Phase.CREATE, false);
util.wiremock(NAMESPACE_A_UAT, Phase.CREATE);
util.wiremock(NAMESPACE_B_UAT, Phase.CREATE);
}
@AfterEach
void afterEach() {
util.wiremock(NAMESPACE_A_UAT, "/wiremock", Phase.DELETE, false);
util.wiremock(NAMESPACE_B_UAT, "/wiremock", Phase.DELETE, false);
util.wiremock(NAMESPACE_A_UAT, Phase.DELETE);
util.wiremock(NAMESPACE_B_UAT, Phase.DELETE);
util.deleteNamespace(NAMESPACE_A_UAT);
util.deleteNamespace(NAMESPACE_B_UAT);

View File

@@ -1,8 +1,3 @@
logging:
level:
org:
springframework: DEBUG
spring:
cloud:
istio:

View File

@@ -21,7 +21,6 @@ import java.util.List;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.client.utils.Serialization;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
@@ -97,7 +96,7 @@ class Fabric8IstioIT {
@Test
void test() {
WebClient client = builder().baseUrl("http://localhost/profiles").build();
WebClient client = builder().baseUrl("http://localhost:32321/profiles").build();
@SuppressWarnings("unchecked")
List<String> result = client.method(HttpMethod.GET)
@@ -114,18 +113,15 @@ class Fabric8IstioIT {
InputStream deploymentStream = util.inputStream("istio-deployment.yaml");
InputStream serviceStream = util.inputStream("istio-service.yaml");
InputStream ingressStream = util.inputStream("istio-ingress.yaml");
Deployment deployment = Serialization.unmarshal(deploymentStream, Deployment.class);
Service service = Serialization.unmarshal(serviceStream, Service.class);
Ingress ingress = Serialization.unmarshal(ingressStream, Ingress.class);
if (phase.equals(Phase.CREATE)) {
util.createAndWait(NAMESPACE, null, deployment, service, ingress, true);
util.createAndWait(NAMESPACE, null, deployment, service, true);
}
else {
util.deleteAndWait(NAMESPACE, deployment, service, ingress);
util.deleteAndWait(NAMESPACE, deployment, service);
}
}

View File

@@ -1,16 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: spring-cloud-kubernetes-fabric8-client-istio
namespace: istio-test
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: spring-cloud-kubernetes-fabric8-client-istio
port:
number: 8080

View File

@@ -9,6 +9,7 @@ spec:
- name: http
port: 8080
targetPort: 8080
nodePort: 32321
selector:
app: spring-cloud-kubernetes-fabric8-client-istio
type: ClusterIP
type: NodePort

View File

@@ -37,9 +37,9 @@ import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.springframework.cloud.kubernetes.fabric8.client.reload.TestAssertions.builder;
import static org.springframework.cloud.kubernetes.fabric8.client.reload.TestAssertions.manifests;
import static org.springframework.cloud.kubernetes.fabric8.client.reload.TestAssertions.retrySpec;
import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.builder;
import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.retrySpec;
/**
* @author wind57
@@ -95,7 +95,7 @@ class BootstrapEnabledPollingReloadConfigMapMountIT {
Commons.waitForLogStatement("will add file-based property source : /tmp/application.properties", K3S,
IMAGE_NAME);
// (3)
WebClient webClient = builder().baseUrl("http://localhost/key").build();
WebClient webClient = builder().baseUrl("http://localhost:32321/key").build();
String result = webClient.method(HttpMethod.GET)
.retrieve()
.bodyToMono(String.class)
@@ -112,7 +112,8 @@ class BootstrapEnabledPollingReloadConfigMapMountIT {
configMap.setData(Map.of(Constants.APPLICATION_PROPERTIES, "from.properties.key=as-mount-changed"));
client.configMaps().inNamespace("default").resource(configMap).createOrReplace();
await().timeout(Duration.ofSeconds(360))
await().atMost(Duration.ofSeconds(120))
.pollInterval(Duration.ofSeconds(1))
.until(() -> webClient.method(HttpMethod.GET)
.retrieve()
.bodyToMono(String.class)

View File

@@ -37,9 +37,9 @@ import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.springframework.cloud.kubernetes.fabric8.client.reload.TestAssertions.builder;
import static org.springframework.cloud.kubernetes.fabric8.client.reload.TestAssertions.manifests;
import static org.springframework.cloud.kubernetes.fabric8.client.reload.TestAssertions.retrySpec;
import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.builder;
import static org.springframework.cloud.kubernetes.integration.tests.commons.Commons.retrySpec;
/**
* @author wind57
@@ -96,7 +96,7 @@ class ConfigMapMountPollingReloadDelegateIT {
Commons.waitForLogStatement("will add file-based property source : /tmp/application.properties", K3S,
IMAGE_NAME);
// (3)
WebClient webClient = builder().baseUrl("http://localhost/key").build();
WebClient webClient = builder().baseUrl("http://localhost:32321/key").build();
String result = webClient.method(HttpMethod.GET)
.retrieve()
.bodyToMono(String.class)
@@ -113,7 +113,8 @@ class ConfigMapMountPollingReloadDelegateIT {
configMap.setData(Map.of(Constants.APPLICATION_PROPERTIES, "from.properties.key=as-mount-changed"));
client.configMaps().inNamespace("default").resource(configMap).createOrReplace();
await().timeout(Duration.ofSeconds(360))
await().atMost(Duration.ofSeconds(120))
.pollInterval(Duration.ofSeconds(1))
.until(() -> webClient.method(HttpMethod.GET)
.retrieve()
.bodyToMono(String.class)

View File

@@ -18,24 +18,17 @@ package org.springframework.cloud.kubernetes.fabric8.client.reload;
import java.io.InputStream;
import java.time.Duration;
import java.util.Objects;
import io.fabric8.kubernetes.api.model.ConfigMap;
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.utils.Serialization;
import reactor.netty.http.client.HttpClient;
import reactor.util.retry.Retry;
import reactor.util.retry.RetryBackoffSpec;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.cloud.kubernetes.integration.tests.commons.Phase;
import org.springframework.cloud.kubernetes.integration.tests.commons.fabric8_client.Util;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import static org.testcontainers.shaded.org.awaitility.Awaitility.await;
@@ -96,32 +89,22 @@ final class TestAssertions {
InputStream deploymentStream = util.inputStream("manifests/deployment.yaml");
InputStream serviceStream = util.inputStream("manifests/service.yaml");
InputStream ingressStream = util.inputStream("manifests/ingress.yaml");
InputStream configMapAsStream = util.inputStream("manifests/configmap.yaml");
Deployment deployment = Serialization.unmarshal(deploymentStream, Deployment.class);
Service service = Serialization.unmarshal(serviceStream, Service.class);
Ingress ingress = Serialization.unmarshal(ingressStream, Ingress.class);
ConfigMap configMap = Serialization.unmarshal(configMapAsStream, ConfigMap.class);
if (phase.equals(Phase.CREATE)) {
util.createAndWait(namespace, configMap, null);
util.createAndWait(namespace, null, deployment, service, ingress, true);
util.createAndWait(namespace, null, deployment, service, true);
}
else {
util.deleteAndWait(namespace, configMap, null);
util.deleteAndWait(namespace, deployment, service, ingress);
util.deleteAndWait(namespace, deployment, service);
}
}
static WebClient.Builder builder() {
return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
}
static RetryBackoffSpec retrySpec() {
return Retry.fixedDelay(120, Duration.ofSeconds(2)).filter(Objects::nonNull);
}
}

View File

@@ -1,16 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: spring-cloud-kubernetes-fabric8-client-reload-ingress
namespace: default
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: spring-cloud-kubernetes-fabric8-client-reload
port:
number: 8080

View File

@@ -9,6 +9,7 @@ spec:
- name: http
port: 8080
targetPort: 8080
nodePort: 32321
selector:
app: spring-cloud-kubernetes-fabric8-client-reload
type: ClusterIP
type: NodePort

View File

@@ -37,7 +37,7 @@ final class FixedPortsK3sContainer extends K3sContainer {
/**
* Test containers exposed ports.
*/
private static final int[] EXPOSED_PORTS = new int[] { 80, 6443, 8080, 8888, 9092 };
private static final int[] EXPOSED_PORTS = new int[] { 80, 6443, 8080, 8888, 9092, 32321 };
/**
* Rancher version to use for test-containers.

View File

@@ -31,8 +31,6 @@ import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.ServiceAccount;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import io.fabric8.kubernetes.api.model.networking.v1.IngressLoadBalancerIngress;
import io.fabric8.kubernetes.api.model.rbac.Role;
import io.fabric8.kubernetes.api.model.rbac.RoleBinding;
import io.fabric8.kubernetes.client.Config;
@@ -77,7 +75,7 @@ public final class Util {
*
*/
public void createAndWait(String namespace, String name, @Nullable Deployment deployment, @Nullable Service service,
@Nullable Ingress ingress, boolean changeVersion) {
boolean changeVersion) {
try {
if (deployment != null) {
@@ -108,11 +106,6 @@ public final class Util {
if (service != null) {
client.services().inNamespace(namespace).resource(service).create();
}
if (ingress != null) {
client.network().v1().ingresses().inNamespace(namespace).resource(ingress).create();
waitForIngress(namespace, ingress);
}
}
catch (Exception e) {
throw new RuntimeException(e);
@@ -132,15 +125,14 @@ public final class Util {
Service service = client.services().load(serviceStream).item();
if (phase.equals(Phase.CREATE)) {
createAndWait(namespace, "busybox", deployment, service, null, false);
createAndWait(namespace, "busybox", deployment, service, false);
}
else if (phase.equals(Phase.DELETE)) {
deleteAndWait(namespace, deployment, service, null);
deleteAndWait(namespace, deployment, service);
}
}
public void deleteAndWait(String namespace, @Nullable Deployment deployment, Service service,
@Nullable Ingress ingress) {
public void deleteAndWait(String namespace, @Nullable Deployment deployment, Service service) {
try {
long startTime = System.currentTimeMillis();
@@ -160,11 +152,6 @@ public final class Util {
client.services().inNamespace(namespace).resource(service).delete();
if (ingress != null) {
client.network().v1().ingresses().inNamespace(namespace).resource(ingress).delete();
waitForIngressToBeDeleted(namespace, ingress);
}
}
catch (Exception e) {
throw new RuntimeException(e);
@@ -284,10 +271,10 @@ public final class Util {
istioctlDeployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(imageWithVersion);
if (phase.equals(Phase.CREATE)) {
createAndWait(namespace, null, istioctlDeployment, null, null, false);
createAndWait(namespace, null, istioctlDeployment, null, false);
}
else {
deleteAndWait(namespace, istioctlDeployment, null, null);
deleteAndWait(namespace, istioctlDeployment, null);
}
}
@@ -308,14 +295,9 @@ public final class Util {
});
}
public void wiremock(String namespace, String path, Phase phase) {
wiremock(namespace, path, phase, true);
}
public void wiremock(String namespace, String path, Phase phase, boolean withIngress) {
public void wiremock(String namespace, Phase phase) {
InputStream deploymentStream = inputStream("wiremock/wiremock-deployment.yaml");
InputStream serviceStream = inputStream("wiremock/wiremock-service.yaml");
InputStream ingressStream = inputStream("wiremock/wiremock-ingress.yaml");
Deployment deployment = client.apps().deployments().load(deploymentStream).item();
String imageWithoutVersion = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
@@ -323,27 +305,14 @@ public final class Util {
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(imageWithVersion);
Service service = client.services().load(serviceStream).item();
Ingress ingress = null;
if (phase.equals(Phase.CREATE)) {
if (withIngress) {
ingress = client.network().v1().ingresses().load(ingressStream).get();
ingress.getMetadata().setNamespace(namespace);
ingress.getSpec().getRules().get(0).getHttp().getPaths().get(0).setPath(path);
}
deployment.getMetadata().setNamespace(namespace);
service.getMetadata().setNamespace(namespace);
createAndWait(namespace, "wiremock", deployment, service, ingress, false);
createAndWait(namespace, "wiremock", deployment, service, false);
}
else {
if (withIngress) {
ingress = client.network().v1().ingresses().load(ingressStream).get();
}
deleteAndWait(namespace, deployment, service, ingress);
deleteAndWait(namespace, deployment, service);
}
}
@@ -365,14 +334,6 @@ public final class Util {
});
}
private void waitForIngressToBeDeleted(String namespace, Ingress ingress) {
String ingressName = ingressName(ingress);
await().pollInterval(Duration.ofSeconds(1)).atMost(30, TimeUnit.SECONDS).until(() -> {
Ingress inner = client.network().v1().ingresses().inNamespace(namespace).withName(ingressName).get();
return inner == null;
});
}
private void waitForDeploymentToBeDeleted(String namespace, Deployment deployment) {
String deploymentName = deploymentName(deployment);
@@ -408,43 +369,6 @@ public final class Util {
return availableReplicas != null && availableReplicas >= 1;
}
public void waitForIngress(String namespace, Ingress ingress) {
String ingressName = ingressName(ingress);
try {
await().pollInterval(Duration.ofSeconds(2)).atMost(180, TimeUnit.SECONDS).until(() -> {
Ingress inner = client.network().v1().ingresses().inNamespace(namespace).withName(ingressName).get();
if (inner == null) {
LOG.info("ingress : " + ingressName + " not ready yet present");
return false;
}
List<IngressLoadBalancerIngress> loadBalancerIngress = inner.getStatus().getLoadBalancer().getIngress();
if (loadBalancerIngress == null || loadBalancerIngress.isEmpty()) {
LOG.info("ingress : " + ingressName + " not ready yet (loadbalancer ingress not yet present)");
return false;
}
String ip = loadBalancerIngress.get(0).getIp();
if (ip == null) {
LOG.info("ingress : " + ingressName + " not ready yet");
return false;
}
LOG.info("ingress : " + ingressName + " ready with ip : " + ip);
return true;
});
}
catch (Exception e) {
LOG.error("Error waiting for ingress");
e.printStackTrace();
}
}
private void innerSetup(String namespace, InputStream serviceAccountAsStream, InputStream roleBindingAsStream,
InputStream roleAsStream) {
ServiceAccount serviceAccountFromStream = client.serviceAccounts()
@@ -485,10 +409,6 @@ public final class Util {
return deployment.getMetadata().getName();
}
private String ingressName(Ingress ingress) {
return ingress.getMetadata().getName();
}
private String configMapName(ConfigMap configMap) {
return configMap.getMetadata().getName();
}