From bebd3fe959bbeaccf528c668ad21640acce9528e Mon Sep 17 00:00:00 2001 From: erabii Date: Thu, 4 Apr 2024 20:47:03 +0300 Subject: [PATCH 1/3] K8s client lb cleanup 1 (#1625) --- ...KubernetesClientServiceInstanceMapper.java | 34 ++-- ...ernetesClientLoadBalancerPodModeTests.java | 119 -------------- ...tesClientLoadBalancerServiceModeTests.java | 148 ------------------ ...netesClientServiceInstanceMapperTests.java | 72 ++++++--- .../KubernetesServiceInstanceMapper.java | 40 ----- .../KubernetesServiceInstanceMapperTests.java | 145 +---------------- .../Fabric8ServiceInstanceMapper.java | 2 +- 7 files changed, 77 insertions(+), 483 deletions(-) delete mode 100644 spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerPodModeTests.java delete mode 100644 spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerServiceModeTests.java diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapper.java b/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapper.java index 83c7e969fa..297d102332 100644 --- a/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapper.java +++ b/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapper.java @@ -28,23 +28,31 @@ import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesServiceInstance; +import org.springframework.cloud.kubernetes.commons.discovery.ServicePortNameAndNumber; +import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; import org.springframework.cloud.kubernetes.commons.loadbalancer.KubernetesLoadBalancerProperties; import org.springframework.cloud.kubernetes.commons.loadbalancer.KubernetesServiceInstanceMapper; import org.springframework.util.StringUtils; +import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.keysWithPrefix; +import static org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver.Input; + /** * @author Ryan Baxter */ public class KubernetesClientServiceInstanceMapper implements KubernetesServiceInstanceMapper { - private KubernetesLoadBalancerProperties properties; + private final KubernetesLoadBalancerProperties properties; + + private final KubernetesDiscoveryProperties discoveryProperties; - private KubernetesDiscoveryProperties discoveryProperties; + private final ServicePortSecureResolver resolver; public KubernetesClientServiceInstanceMapper(KubernetesLoadBalancerProperties properties, KubernetesDiscoveryProperties discoveryProperties) { this.properties = properties; this.discoveryProperties = discoveryProperties; + resolver = new ServicePortSecureResolver(discoveryProperties); } @Override @@ -66,10 +74,11 @@ else if (ports.size() > 1 && StringUtils.hasText(this.properties.getPortName())) if (port == null) { return null; } - final String host = KubernetesServiceInstanceMapper.createHost(service.getMetadata().getName(), + String host = KubernetesServiceInstanceMapper.createHost(service.getMetadata().getName(), service.getMetadata().getNamespace(), properties.getClusterDomain()); - final boolean secure = KubernetesServiceInstanceMapper.isSecure(service.getMetadata().getLabels(), - service.getMetadata().getAnnotations(), port.getName(), port.getPort()); + + boolean secure = secure(port, service); + return new DefaultKubernetesServiceInstance(meta.getUid(), meta.getName(), host, port.getPort(), getServiceMetadata(service), secure); } @@ -78,17 +87,24 @@ private Map getServiceMetadata(V1Service service) { final Map serviceMetadata = new HashMap<>(); KubernetesDiscoveryProperties.Metadata metadataProps = this.discoveryProperties.metadata(); if (metadataProps.addLabels()) { - Map labelMetadata = KubernetesServiceInstanceMapper - .getMapWithPrefixedKeys(service.getMetadata().getLabels(), metadataProps.labelsPrefix()); + Map labelMetadata = keysWithPrefix(service.getMetadata().getLabels(), + metadataProps.labelsPrefix()); serviceMetadata.putAll(labelMetadata); } if (metadataProps.addAnnotations()) { - Map annotationMetadata = KubernetesServiceInstanceMapper - .getMapWithPrefixedKeys(service.getMetadata().getAnnotations(), metadataProps.annotationsPrefix()); + Map annotationMetadata = keysWithPrefix(service.getMetadata().getAnnotations(), + metadataProps.annotationsPrefix()); serviceMetadata.putAll(annotationMetadata); } return serviceMetadata; } + private boolean secure(V1ServicePort port, V1Service service) { + V1ObjectMeta metadata = service.getMetadata(); + ServicePortNameAndNumber portNameAndNumber = new ServicePortNameAndNumber(port.getPort(), port.getName()); + Input input = new Input(portNameAndNumber, metadata.getName(), metadata.getLabels(), metadata.getAnnotations()); + return resolver.resolve(input); + } + } diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerPodModeTests.java b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerPodModeTests.java deleted file mode 100644 index 68b8471e8b..0000000000 --- a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerPodModeTests.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2013-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.kubernetes.client.loadbalancer; - -import java.io.IOException; -import java.util.Collections; - -import io.kubernetes.client.openapi.ApiClient; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.util.ClientBuilder; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.cloud.client.DefaultServiceInstance; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.LoadBalanced; -import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; -import org.springframework.cloud.kubernetes.client.discovery.KubernetesInformerDiscoveryClient; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; -import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.mock.http.client.MockClientHttpResponse; -import org.springframework.web.client.RestTemplate; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author Ryan Baxter - */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = KubernetesClientLoadBalancerPodModeTests.App.class) -class KubernetesClientLoadBalancerPodModeTests { - - @Autowired - private RestTemplate restTemplate; - - @Test - void testLoadBalancer() { - String resp = restTemplate.getForObject("http://servicea-wiremock", String.class); - assertThat(resp).isEqualTo("hello"); - } - - @SpringBootApplication - static class App { - - @Bean - CoreV1Api coreV1Api(ApiClient apiClient) { - return new CoreV1Api(apiClient); - } - - @Bean - ApiClient apiClient() { - return new ClientBuilder().build(); - } - - @Bean - BlockingLoadBalancerClient blockingLoadBalancerClient() { - BlockingLoadBalancerClient client = mock(BlockingLoadBalancerClient.class); - try { - ClientHttpResponse response = new MockClientHttpResponse("hello".getBytes(), HttpStatus.OK); - when(client.execute(eq("servicea-wiremock"), any(LoadBalancerRequest.class))).thenReturn(response); - when(client.execute(eq("servicea-wiremock"), any(ServiceInstance.class), - any(LoadBalancerRequest.class))).thenReturn(response); - } - catch (IOException e) { - e.printStackTrace(); - } - return client; - } - - @Bean - KubernetesNamespaceProvider kubernetesNamespaceProvider() { - KubernetesNamespaceProvider provider = mock(KubernetesNamespaceProvider.class); - when(provider.getNamespace()).thenReturn("test"); - return provider; - } - - @Bean - KubernetesInformerDiscoveryClient kubernetesInformerDiscoveryClient() { - KubernetesInformerDiscoveryClient client = mock(KubernetesInformerDiscoveryClient.class); - ServiceInstance instance = new DefaultServiceInstance("servicea-wiremock1", "servicea-wiremock", "fake", - 8888, false); - given(client.getInstances(eq("servicea-wiremock"))).willReturn(Collections.singletonList(instance)); - return client; - } - - @Bean - @LoadBalanced - RestTemplate restTemplate() { - return new RestTemplateBuilder().build(); - } - - } - -} diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerServiceModeTests.java b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerServiceModeTests.java deleted file mode 100644 index 3e8c23cf71..0000000000 --- a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerServiceModeTests.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2013-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.kubernetes.client.loadbalancer; - -import java.io.IOException; - -import io.kubernetes.client.openapi.ApiClient; -import io.kubernetes.client.openapi.ApiException; -import io.kubernetes.client.openapi.apis.CoreV1Api; -import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder; -import io.kubernetes.client.openapi.models.V1ServiceBuilder; -import io.kubernetes.client.openapi.models.V1ServiceList; -import io.kubernetes.client.openapi.models.V1ServiceListBuilder; -import io.kubernetes.client.openapi.models.V1ServicePortBuilder; -import io.kubernetes.client.openapi.models.V1ServiceSpecBuilder; -import io.kubernetes.client.util.ClientBuilder; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.cloud.client.ServiceInstance; -import org.springframework.cloud.client.loadbalancer.LoadBalanced; -import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest; -import org.springframework.cloud.kubernetes.client.discovery.KubernetesInformerDiscoveryClient; -import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; -import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpStatus; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.mock.http.client.MockClientHttpResponse; -import org.springframework.web.client.RestTemplate; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author Ryan Baxter - */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = KubernetesClientLoadBalancerServiceModeTests.App.class, - properties = { "spring.cloud.kubernetes.loadbalancer.mode=SERVICE" }) -public class KubernetesClientLoadBalancerServiceModeTests { - - private static final V1ServiceList SERVICE_LIST = new V1ServiceListBuilder() - .addToItems( - new V1ServiceBuilder() - .withMetadata(new V1ObjectMetaBuilder().withName("servicea-wiremock") - .withNamespace("default").withResourceVersion("1").addToLabels("beta", "true") - .addToAnnotations("org.springframework.cloud", "true").withUid("0").build()) - .withSpec(new V1ServiceSpecBuilder().withClusterIP("10.96.0.1").withSessionAffinity("None") - .withType("ClusterIP") - .addToPorts(new V1ServicePortBuilder().withPort(80).withName("http") - .withProtocol("TCP").withNewTargetPort(8080).build()) - .build()) - .build()) - .build(); - - @Autowired - private RestTemplate restTemplate; - - @Test - public void testLoadBalancer() { - String resp = restTemplate.getForObject("http://servicea-wiremock", String.class); - assertThat(resp).isEqualTo("hello"); - } - - @SpringBootApplication - static class App { - - @Bean - public ApiClient apiClient() { - return new ClientBuilder().build(); - } - - @Bean - public CoreV1Api coreV1Api() { - CoreV1Api coreV1Api = mock(CoreV1Api.class); - try { - when(coreV1Api.listNamespacedService(eq("default"), eq(null), eq(null), eq(null), - eq("metadata.name=servicea-wiremock"), eq(null), eq(null), eq(null), eq(null), eq(null), - eq(null), eq(null))).thenReturn(SERVICE_LIST); - } - catch (ApiException e) { - e.printStackTrace(); - } - return coreV1Api; - } - - @Bean - public BlockingLoadBalancerClient blockingLoadBalancerClient() { - BlockingLoadBalancerClient client = mock(BlockingLoadBalancerClient.class); - try { - ClientHttpResponse response = new MockClientHttpResponse("hello".getBytes(), HttpStatus.OK); - when(client.execute(eq("servicea-wiremock"), any(LoadBalancerRequest.class))).thenReturn(response); - when(client.execute(eq("servicea-wiremock"), any(ServiceInstance.class), - any(LoadBalancerRequest.class))).thenReturn(response); - } - catch (IOException e) { - e.printStackTrace(); - } - return client; - } - - @Bean - public KubernetesInformerDiscoveryClient kubernetesInformerDiscoveryClient() { - // Mock this so the real implementation does not try to connect to the K8S API - // Server - KubernetesInformerDiscoveryClient client = mock(KubernetesInformerDiscoveryClient.class); - Mockito.when(client.getOrder()).thenReturn(0); - return client; - } - - @Bean - public KubernetesNamespaceProvider kubernetesNamespaceProvider() { - KubernetesNamespaceProvider provider = mock(KubernetesNamespaceProvider.class); - when(provider.getNamespace()).thenReturn("test"); - return provider; - } - - @Bean - @LoadBalanced - RestTemplate restTemplate() { - return new RestTemplateBuilder().build(); - } - - } - -} diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapperTests.java b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapperTests.java index f1f4f69c39..b3a4273227 100644 --- a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapperTests.java +++ b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapperTests.java @@ -16,12 +16,13 @@ package org.springframework.cloud.kubernetes.client.loadbalancer; -import java.util.HashMap; +import java.util.List; import java.util.Map; import io.kubernetes.client.openapi.models.V1ObjectMetaBuilder; import io.kubernetes.client.openapi.models.V1Service; import io.kubernetes.client.openapi.models.V1ServiceBuilder; +import io.kubernetes.client.openapi.models.V1ServicePort; import io.kubernetes.client.openapi.models.V1ServicePortBuilder; import io.kubernetes.client.openapi.models.V1ServiceSpecBuilder; import org.junit.jupiter.api.Test; @@ -39,48 +40,75 @@ class KubernetesClientServiceInstanceMapperTests { @Test - void basicMap() { + void singlePortNonSecure() { KubernetesLoadBalancerProperties loadBalancerProperties = new KubernetesLoadBalancerProperties(); KubernetesClientServiceInstanceMapper mapper = new KubernetesClientServiceInstanceMapper(loadBalancerProperties, KubernetesDiscoveryProperties.DEFAULT); - V1Service service = new V1ServiceBuilder() - .withMetadata(new V1ObjectMetaBuilder().withName("database").withUid("0").withResourceVersion("0") - .withNamespace("default").addToAnnotations("org.springframework.cloud", "true") - .addToLabels("beta", "true").build()) - .withSpec(new V1ServiceSpecBuilder() - .addToPorts(new V1ServicePortBuilder().withPort(80).withName("http").build()).build()) - .build(); + Map annotations = Map.of("org.springframework.cloud", "true"); + Map labels = Map.of("beta", "true"); + List servicePorts = List.of( + new V1ServicePortBuilder().withName("http").withPort(80).build() + ); + V1Service service = createService("database", "default", annotations, labels, servicePorts); KubernetesServiceInstance serviceInstance = mapper.map(service); - Map metadata = new HashMap<>(); - metadata.put("org.springframework.cloud", "true"); - metadata.put("beta", "true"); + Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true"); DefaultKubernetesServiceInstance result = new DefaultKubernetesServiceInstance("0", "database", "database.default.svc.cluster.local", 80, metadata, false); assertThat(serviceInstance).isEqualTo(result); } + // has an annotation 'secured=true' @Test - void multiportMap() { + void singlePortSecure() { + KubernetesLoadBalancerProperties loadBalancerProperties = new KubernetesLoadBalancerProperties(); + KubernetesClientServiceInstanceMapper mapper = new KubernetesClientServiceInstanceMapper(loadBalancerProperties, + KubernetesDiscoveryProperties.DEFAULT); + + Map annotations = Map.of("org.springframework.cloud", "true", "secured", "true"); + Map labels = Map.of("beta", "true"); + List servicePorts = List.of( + new V1ServicePortBuilder().withName("http").withPort(80).build() + ); + V1Service service = createService("database", "default", annotations, labels, servicePorts); + + KubernetesServiceInstance serviceInstance = mapper.map(service); + Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true", "secured", "true"); + DefaultKubernetesServiceInstance result = new DefaultKubernetesServiceInstance("0", "database", + "database.default.svc.cluster.local", 80, metadata, true); + assertThat(serviceInstance).isEqualTo(result); + } + + @Test + void multiplePortsSecure() { KubernetesLoadBalancerProperties loadBalancerProperties = new KubernetesLoadBalancerProperties(); loadBalancerProperties.setPortName("https"); KubernetesClientServiceInstanceMapper mapper = new KubernetesClientServiceInstanceMapper(loadBalancerProperties, KubernetesDiscoveryProperties.DEFAULT); - V1Service service = new V1ServiceBuilder() - .withMetadata(new V1ObjectMetaBuilder().withName("database").withUid("0").withResourceVersion("0") - .withNamespace("default").build()) - .withSpec(new V1ServiceSpecBuilder() - .addToPorts(new V1ServicePortBuilder().withPort(80).withName("http").build(), - new V1ServicePortBuilder().withPort(443).withName("https").build()) - .build()) - .build(); + Map annotations = Map.of("org.springframework.cloud", "true"); + Map labels = Map.of("beta", "true"); + List servicePorts = List.of( + new V1ServicePortBuilder().withName("http").withPort(80).build(), + new V1ServicePortBuilder().withName("https").withPort(443).build() + ); + V1Service service = createService("database", "default", annotations, labels, servicePorts); + Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true"); KubernetesServiceInstance serviceInstance = mapper.map(service); DefaultKubernetesServiceInstance result = new DefaultKubernetesServiceInstance("0", "database", - "database.default.svc.cluster.local", 443, Map.of(), true); + "database.default.svc.cluster.local", 443, metadata, true); assertThat(serviceInstance).isEqualTo(result); } + private V1Service createService(String name, String namespace, Map annotations, + Map labels, List servicePorts) { + return new V1ServiceBuilder() + .withMetadata(new V1ObjectMetaBuilder().withName(name).withUid("0") + .withNamespace(namespace).addToAnnotations(annotations) + .addToLabels(labels).build()) + .withSpec(new V1ServiceSpecBuilder().addAllToPorts(servicePorts).build()).build(); + } + } diff --git a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/loadbalancer/KubernetesServiceInstanceMapper.java b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/loadbalancer/KubernetesServiceInstanceMapper.java index 57f693c828..9b81e5f81a 100644 --- a/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/loadbalancer/KubernetesServiceInstanceMapper.java +++ b/spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/loadbalancer/KubernetesServiceInstanceMapper.java @@ -16,7 +16,6 @@ package org.springframework.cloud.kubernetes.commons.loadbalancer; -import java.util.Map; import java.util.StringJoiner; import org.apache.commons.logging.LogFactory; @@ -25,8 +24,6 @@ import org.springframework.core.log.LogAccessor; import org.springframework.util.StringUtils; -import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.keysWithPrefix; - /** * @author Ryan Baxter */ @@ -44,41 +41,4 @@ static String createHost(String serviceName, String namespace, String clusterDom return new StringJoiner(".").add(serviceName).add(namespaceToUse).add("svc").add(clusterDomain).toString(); } - static boolean isSecure(Map labels, Map annotations, String servicePortName, - Integer servicePort) { - - if (hasTrueSecuredValue(labels)) { - LOG.debug(() -> "Service has a true 'secured' label"); - return true; - } - - if (hasTrueSecuredValue(annotations)) { - LOG.debug(() -> "Service has a true 'secured' annotation"); - return true; - } - - if (servicePortName != null && servicePortName.endsWith("https")) { - LOG.debug(() -> "Service port name ends with 'https'"); - return true; - } - - if (servicePort != null && servicePort.toString().endsWith("443")) { - LOG.debug(() -> "Service port ends with '443'"); - return true; - } - - return false; - } - - static Map getMapWithPrefixedKeys(Map map, String prefix) { - return keysWithPrefix(map, prefix); - } - - private static boolean hasTrueSecuredValue(Map input) { - if (input != null) { - return "true".equals(input.get("secured")); - } - return false; - } - } diff --git a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/loadbalancer/KubernetesServiceInstanceMapperTests.java b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/loadbalancer/KubernetesServiceInstanceMapperTests.java index 8ae3c77aef..9732fed378 100644 --- a/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/loadbalancer/KubernetesServiceInstanceMapperTests.java +++ b/spring-cloud-kubernetes-commons/src/test/java/org/springframework/cloud/kubernetes/commons/loadbalancer/KubernetesServiceInstanceMapperTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2023 the original author or authors. + * Copyright 2013-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,9 @@ package org.springframework.cloud.kubernetes.commons.loadbalancer; -import java.util.Map; - import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; import static org.assertj.core.api.Assertions.assertThat; @@ -32,14 +29,6 @@ @ExtendWith(OutputCaptureExtension.class) class KubernetesServiceInstanceMapperTests { - private static final String SECURED_LABEL_MESSAGE = "Service has a true 'secured' label"; - - private static final String SECURED_ANNOTATION_MESSAGE = "Service has a true 'secured' annotation"; - - private static final String NAME_ENDS_IN_HTTPS_MESSAGE = "Service port name ends with 'https'"; - - private static final String PORT_ENDS_IN_443_MESSAGE = "Service port ends with '443'"; - @Test void testCreateHostWithNamespace() { String namespace = "customNamespace"; @@ -59,136 +48,4 @@ void testCreateHostWithNullNamespace() { assertThat(host).isEqualTo("serviceName.default.svc.clusterDomain"); } - @Test - void testIsSecureWithTrueLabel(CapturedOutput output) { - Map labels = Map.of("secured", "true"); - Map annotations = Map.of(); - String servicePortName = null; - Integer servicePort = null; - assertThat(KubernetesServiceInstanceMapper.isSecure(labels, annotations, servicePortName, servicePort)) - .isTrue(); - - assertThat(output.getOut().contains(SECURED_LABEL_MESSAGE)).isTrue(); - assertThat(output.getOut().contains(SECURED_ANNOTATION_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(NAME_ENDS_IN_HTTPS_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(PORT_ENDS_IN_443_MESSAGE)).isFalse(); - } - - @Test - void testIsSecureWithTrueAnnotation(CapturedOutput output) { - // empty labels - Map labels = Map.of(); - Map annotations = Map.of("secured", "true"); - String servicePortName = null; - Integer servicePort = null; - assertThat(KubernetesServiceInstanceMapper.isSecure(labels, annotations, servicePortName, servicePort)) - .isTrue(); - - assertThat(output.getOut().contains(SECURED_LABEL_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(SECURED_ANNOTATION_MESSAGE)).isTrue(); - assertThat(output.getOut().contains(NAME_ENDS_IN_HTTPS_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(PORT_ENDS_IN_443_MESSAGE)).isFalse(); - } - - @Test - void testIsSecureWithTrueAnnotationNullLabels(CapturedOutput output) { - // null labels - Map labels = null; - Map annotations = Map.of("secured", "true"); - String servicePortName = null; - Integer servicePort = null; - assertThat(KubernetesServiceInstanceMapper.isSecure(labels, annotations, servicePortName, servicePort)) - .isTrue(); - - assertThat(output.getOut().contains(SECURED_LABEL_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(SECURED_ANNOTATION_MESSAGE)).isTrue(); - assertThat(output.getOut().contains(NAME_ENDS_IN_HTTPS_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(PORT_ENDS_IN_443_MESSAGE)).isFalse(); - } - - @Test - void testIsNotSecureServicePortNameAndServicePortAreNull(CapturedOutput output) { - // null labels - Map labels = null; - // null annotations - Map annotations = null; - String servicePortName = null; - Integer servicePort = null; - assertThat(KubernetesServiceInstanceMapper.isSecure(labels, annotations, servicePortName, servicePort)) - .isFalse(); - - assertThat(output.getOut().contains(SECURED_LABEL_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(SECURED_ANNOTATION_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(NAME_ENDS_IN_HTTPS_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(PORT_ENDS_IN_443_MESSAGE)).isFalse(); - } - - @Test - void testIsNotSecureServicePortNameDoesNotMatch(CapturedOutput output) { - // null labels - Map labels = null; - // null annotations - Map annotations = null; - String servicePortName = "abc_https_def"; - Integer servicePort = null; - assertThat(KubernetesServiceInstanceMapper.isSecure(labels, annotations, servicePortName, servicePort)) - .isFalse(); - - assertThat(output.getOut().contains(SECURED_LABEL_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(SECURED_ANNOTATION_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(NAME_ENDS_IN_HTTPS_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(PORT_ENDS_IN_443_MESSAGE)).isFalse(); - } - - @Test - void testIsSecureServicePortNameMatches(CapturedOutput output) { - // null labels - Map labels = null; - // null annotations - Map annotations = null; - String servicePortName = "abc_https"; - Integer servicePort = null; - assertThat(KubernetesServiceInstanceMapper.isSecure(labels, annotations, servicePortName, servicePort)) - .isTrue(); - - assertThat(output.getOut().contains(SECURED_LABEL_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(SECURED_ANNOTATION_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(NAME_ENDS_IN_HTTPS_MESSAGE)).isTrue(); - assertThat(output.getOut().contains(PORT_ENDS_IN_443_MESSAGE)).isFalse(); - } - - @Test - void testIsNotSecureServicePortDoesNotMatch(CapturedOutput output) { - // null labels - Map labels = null; - // null annotations - Map annotations = null; - String servicePortName = null; - Integer servicePort = 444; - assertThat(KubernetesServiceInstanceMapper.isSecure(labels, annotations, servicePortName, servicePort)) - .isFalse(); - - assertThat(output.getOut().contains(SECURED_LABEL_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(SECURED_ANNOTATION_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(NAME_ENDS_IN_HTTPS_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(PORT_ENDS_IN_443_MESSAGE)).isFalse(); - } - - @Test - void testIsSecureServicePortMatches(CapturedOutput output) { - // null labels - Map labels = null; - // null annotations - Map annotations = null; - String servicePortName = null; - Integer servicePort = 443; - assertThat(KubernetesServiceInstanceMapper.isSecure(labels, annotations, servicePortName, servicePort)) - .isTrue(); - - assertThat(output.getOut().contains(SECURED_LABEL_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(SECURED_ANNOTATION_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(NAME_ENDS_IN_HTTPS_MESSAGE)).isFalse(); - assertThat(output.getOut().contains(PORT_ENDS_IN_443_MESSAGE)).isTrue(); - } - } diff --git a/spring-cloud-kubernetes-fabric8-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/Fabric8ServiceInstanceMapper.java b/spring-cloud-kubernetes-fabric8-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/Fabric8ServiceInstanceMapper.java index 8f2692070d..fab705ec1c 100644 --- a/spring-cloud-kubernetes-fabric8-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/Fabric8ServiceInstanceMapper.java +++ b/spring-cloud-kubernetes-fabric8-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/fabric8/loadbalancer/Fabric8ServiceInstanceMapper.java @@ -122,7 +122,7 @@ Map serviceMetadata(Service service) { return DiscoveryClientUtils.serviceInstanceMetadata(PORTS_DATA, serviceMetadata, discoveryProperties); } - boolean secure(ServicePort port, Service service) { + private boolean secure(ServicePort port, Service service) { ObjectMeta metadata = service.getMetadata(); ServicePortNameAndNumber portNameAndNumber = new ServicePortNameAndNumber(port.getPort(), port.getName()); Input input = new Input(portNameAndNumber, metadata.getName(), metadata.getLabels(), metadata.getAnnotations()); From ff469eba9a3d7eda98b0fd6cf6df9cd9917a77bd Mon Sep 17 00:00:00 2001 From: Ryan Baxter Date: Thu, 4 Apr 2024 14:25:22 -0400 Subject: [PATCH 2/3] Update antora-playbook.yml --- docs/antora-playbook.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/antora-playbook.yml b/docs/antora-playbook.yml index 4841f7cf69..182681506e 100644 --- a/docs/antora-playbook.yml +++ b/docs/antora-playbook.yml @@ -1,10 +1,11 @@ antora: extensions: - '@springio/antora-extensions/partial-build-extension' + # atlas-extension must be before latest-version-extension so latest versions are applied to imported versions + - '@antora/atlas-extension' - require: '@springio/antora-extensions/latest-version-extension' - require: '@springio/antora-extensions/inject-collector-cache-config-extension' - '@antora/collector-extension' - - '@antora/atlas-extension' - require: '@springio/antora-extensions/root-component-extension' root_component_name: 'cloud-kubernetes' - '@springio/antora-extensions/static-page-extension' From 4d0b4fd1a4f1611ae732378d2c7b41729871cbf6 Mon Sep 17 00:00:00 2001 From: erabii Date: Fri, 5 Apr 2024 00:10:10 +0300 Subject: [PATCH 3/3] K8s client lb cleanup 2 (#1626) --- ...KubernetesClientServiceInstanceMapper.java | 33 ++++++++---------- ...netesClientServiceInstanceMapperTests.java | 34 ++++++++----------- ...rnetesClientServicesListSupplierTests.java | 24 +++++++------ 3 files changed, 44 insertions(+), 47 deletions(-) diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapper.java b/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapper.java index 297d102332..83293741d8 100644 --- a/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapper.java +++ b/spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapper.java @@ -16,7 +16,6 @@ package org.springframework.cloud.kubernetes.client.loadbalancer; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -24,17 +23,19 @@ import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1Service; import io.kubernetes.client.openapi.models.V1ServicePort; +import io.kubernetes.client.openapi.models.V1ServiceSpec; import org.springframework.cloud.kubernetes.commons.discovery.DefaultKubernetesServiceInstance; +import org.springframework.cloud.kubernetes.commons.discovery.DiscoveryClientUtils; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; import org.springframework.cloud.kubernetes.commons.discovery.KubernetesServiceInstance; +import org.springframework.cloud.kubernetes.commons.discovery.ServiceMetadata; import org.springframework.cloud.kubernetes.commons.discovery.ServicePortNameAndNumber; import org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver; import org.springframework.cloud.kubernetes.commons.loadbalancer.KubernetesLoadBalancerProperties; import org.springframework.cloud.kubernetes.commons.loadbalancer.KubernetesServiceInstanceMapper; import org.springframework.util.StringUtils; -import static org.springframework.cloud.kubernetes.commons.config.ConfigUtils.keysWithPrefix; import static org.springframework.cloud.kubernetes.commons.discovery.ServicePortSecureResolver.Input; /** @@ -42,6 +43,11 @@ */ public class KubernetesClientServiceInstanceMapper implements KubernetesServiceInstanceMapper { + /** + * empty on purpose, load balancer implementation does not need them. + */ + private static final Map PORTS_DATA = Map.of(); + private final KubernetesLoadBalancerProperties properties; private final KubernetesDiscoveryProperties discoveryProperties; @@ -80,24 +86,15 @@ else if (ports.size() > 1 && StringUtils.hasText(this.properties.getPortName())) boolean secure = secure(port, service); return new DefaultKubernetesServiceInstance(meta.getUid(), meta.getName(), host, port.getPort(), - getServiceMetadata(service), secure); + serviceMetadata(service), secure); } - private Map getServiceMetadata(V1Service service) { - final Map serviceMetadata = new HashMap<>(); - KubernetesDiscoveryProperties.Metadata metadataProps = this.discoveryProperties.metadata(); - if (metadataProps.addLabels()) { - Map labelMetadata = keysWithPrefix(service.getMetadata().getLabels(), - metadataProps.labelsPrefix()); - serviceMetadata.putAll(labelMetadata); - } - if (metadataProps.addAnnotations()) { - Map annotationMetadata = keysWithPrefix(service.getMetadata().getAnnotations(), - metadataProps.annotationsPrefix()); - serviceMetadata.putAll(annotationMetadata); - } - - return serviceMetadata; + private Map serviceMetadata(V1Service service) { + V1ObjectMeta metadata = service.getMetadata(); + V1ServiceSpec serviceSpec = service.getSpec(); + ServiceMetadata serviceMetadata = new ServiceMetadata(metadata.getName(), metadata.getNamespace(), + serviceSpec.getType(), metadata.getLabels(), metadata.getAnnotations()); + return DiscoveryClientUtils.serviceInstanceMetadata(PORTS_DATA, serviceMetadata, discoveryProperties); } private boolean secure(V1ServicePort port, V1Service service) { diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapperTests.java b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapperTests.java index b3a4273227..c825641b08 100644 --- a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapperTests.java +++ b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapperTests.java @@ -47,13 +47,12 @@ void singlePortNonSecure() { Map annotations = Map.of("org.springframework.cloud", "true"); Map labels = Map.of("beta", "true"); - List servicePorts = List.of( - new V1ServicePortBuilder().withName("http").withPort(80).build() - ); + List servicePorts = List.of(new V1ServicePortBuilder().withName("http").withPort(80).build()); V1Service service = createService("database", "default", annotations, labels, servicePorts); KubernetesServiceInstance serviceInstance = mapper.map(service); - Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true"); + Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true", "k8s_namespace", + "default", "type", "V1Service"); DefaultKubernetesServiceInstance result = new DefaultKubernetesServiceInstance("0", "database", "database.default.svc.cluster.local", 80, metadata, false); assertThat(serviceInstance).isEqualTo(result); @@ -64,19 +63,18 @@ void singlePortNonSecure() { void singlePortSecure() { KubernetesLoadBalancerProperties loadBalancerProperties = new KubernetesLoadBalancerProperties(); KubernetesClientServiceInstanceMapper mapper = new KubernetesClientServiceInstanceMapper(loadBalancerProperties, - KubernetesDiscoveryProperties.DEFAULT); + KubernetesDiscoveryProperties.DEFAULT); Map annotations = Map.of("org.springframework.cloud", "true", "secured", "true"); Map labels = Map.of("beta", "true"); - List servicePorts = List.of( - new V1ServicePortBuilder().withName("http").withPort(80).build() - ); + List servicePorts = List.of(new V1ServicePortBuilder().withName("http").withPort(80).build()); V1Service service = createService("database", "default", annotations, labels, servicePorts); KubernetesServiceInstance serviceInstance = mapper.map(service); - Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true", "secured", "true"); + Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true", "secured", "true", + "k8s_namespace", "default", "type", "V1Service"); DefaultKubernetesServiceInstance result = new DefaultKubernetesServiceInstance("0", "database", - "database.default.svc.cluster.local", 80, metadata, true); + "database.default.svc.cluster.local", 80, metadata, true); assertThat(serviceInstance).isEqualTo(result); } @@ -89,13 +87,12 @@ void multiplePortsSecure() { Map annotations = Map.of("org.springframework.cloud", "true"); Map labels = Map.of("beta", "true"); - List servicePorts = List.of( - new V1ServicePortBuilder().withName("http").withPort(80).build(), - new V1ServicePortBuilder().withName("https").withPort(443).build() - ); + List servicePorts = List.of(new V1ServicePortBuilder().withName("http").withPort(80).build(), + new V1ServicePortBuilder().withName("https").withPort(443).build()); V1Service service = createService("database", "default", annotations, labels, servicePorts); - Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true"); + Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true", "k8s_namespace", + "default", "type", "V1Service"); KubernetesServiceInstance serviceInstance = mapper.map(service); DefaultKubernetesServiceInstance result = new DefaultKubernetesServiceInstance("0", "database", "database.default.svc.cluster.local", 443, metadata, true); @@ -105,10 +102,9 @@ void multiplePortsSecure() { private V1Service createService(String name, String namespace, Map annotations, Map labels, List servicePorts) { return new V1ServiceBuilder() - .withMetadata(new V1ObjectMetaBuilder().withName(name).withUid("0") - .withNamespace(namespace).addToAnnotations(annotations) - .addToLabels(labels).build()) - .withSpec(new V1ServiceSpecBuilder().addAllToPorts(servicePorts).build()).build(); + .withMetadata(new V1ObjectMetaBuilder().withName(name).withUid("0").withNamespace(namespace) + .addToAnnotations(annotations).addToLabels(labels).build()) + .withSpec(new V1ServiceSpecBuilder().addAllToPorts(servicePorts).withType("V1Service").build()).build(); } } diff --git a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplierTests.java b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplierTests.java index a7d23e2697..cbfa69a7b8 100644 --- a/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplierTests.java +++ b/spring-cloud-kubernetes-client-loadbalancer/src/test/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplierTests.java @@ -71,16 +71,17 @@ class KubernetesClientServicesListSupplierTests { private static final V1Service SERVICE_A_DEFAULT_NAMESPACE = new V1ServiceBuilder() .withMetadata(new V1ObjectMetaBuilder().withName("service-a").withNamespace("default").withUid("0") .addToLabels("beta", "true").addToAnnotations("org.springframework.cloud", "true").build()) - .withSpec(new V1ServiceSpecBuilder() + .withSpec(new V1ServiceSpecBuilder().withType("V1Service") .addToPorts(new V1ServicePortBuilder().withPort(80).withName("http").build()).build()) .build(); private static final V1Service SERVICE_A_TEST_NAMESPACE = new V1ServiceBuilder() .withMetadata(new V1ObjectMetaBuilder().withName("service-a").withNamespace("test").withUid("1").build()) - .withSpec(new V1ServiceSpecBuilder() - .addToPorts(new V1ServicePortBuilder().withPort(80).withName("http").build(), - new V1ServicePortBuilder().withPort(443).withName("https").build()) - .build()) + .withSpec( + new V1ServiceSpecBuilder().withType("V1Service") + .addToPorts(new V1ServicePortBuilder().withPort(80).withName("http").build(), + new V1ServicePortBuilder().withPort(443).withName("https").build()) + .build()) .build(); private static final V1ServiceList SINGLE_NAMESPACE_SERVICES = new V1ServiceList() @@ -142,7 +143,8 @@ void singleNamespaceTest(CapturedOutput output) { Flux> instances = listSupplier.get(); - Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true"); + Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true", "k8s_namespace", + "default", "type", "V1Service"); DefaultKubernetesServiceInstance serviceA = new DefaultKubernetesServiceInstance("0", "service-a", "service-a.default.svc.cluster.local", 80, metadata, false); List services = new ArrayList<>(); @@ -209,11 +211,12 @@ void allNamespacesTest(CapturedOutput output) { Flux> instances = listSupplier.get(); - Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true"); + Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true", "k8s_namespace", + "default", "type", "V1Service"); DefaultKubernetesServiceInstance serviceADefaultNamespace = new DefaultKubernetesServiceInstance("0", "service-a", "service-a.default.svc.cluster.local", 80, metadata, false); DefaultKubernetesServiceInstance serviceATestNamespace = new DefaultKubernetesServiceInstance("1", "service-a", - "service-a.test.svc.cluster.local", 80, Map.of(), false); + "service-a.test.svc.cluster.local", 80, Map.of("k8s_namespace", "test", "type", "V1Service"), false); List services = new ArrayList<>(); services.add(serviceADefaultNamespace); services.add(serviceATestNamespace); @@ -253,11 +256,12 @@ void selectiveNamespacesTest(CapturedOutput output) { Flux> instances = listSupplier.get(); - Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true"); + Map metadata = Map.of("org.springframework.cloud", "true", "beta", "true", "k8s_namespace", + "default", "type", "V1Service"); DefaultKubernetesServiceInstance serviceADefaultNamespace = new DefaultKubernetesServiceInstance("0", "service-a", "service-a.default.svc.cluster.local", 80, metadata, false); DefaultKubernetesServiceInstance serviceATestNamespace = new DefaultKubernetesServiceInstance("1", "service-a", - "service-a.test.svc.cluster.local", 80, Map.of(), false); + "service-a.test.svc.cluster.local", 80, Map.of("k8s_namespace", "test", "type", "V1Service"), false); List services = new ArrayList<>(); services.add(serviceADefaultNamespace); services.add(serviceATestNamespace);