@@ -59,7 +59,8 @@
|
||||
|spring.cloud.kubernetes.config.sources | |
|
||||
|spring.cloud.kubernetes.config.use-name-as-prefix | `+++false+++` |
|
||||
|spring.cloud.kubernetes.discovery.all-namespaces | `+++false+++` |
|
||||
|spring.cloud.kubernetes.discovery.cache-loading-timeout-seconds | `+++60+++` |
|
||||
|spring.cloud.kubernetes.discovery.namespaces | `+++[]+++` |
|
||||
|spring.cloud.kubernetes.discovery.cache-loading-timeout-seconds | `+++60+++` |
|
||||
|spring.cloud.kubernetes.discovery.enabled | `+++true+++` |
|
||||
|spring.cloud.kubernetes.discovery.filter | |
|
||||
|spring.cloud.kubernetes.discovery.include-not-ready-addresses | `+++false+++` |
|
||||
|
||||
@@ -78,6 +78,16 @@ spring.cloud.kubernetes.discovery.all-namespaces=true
|
||||
----
|
||||
====
|
||||
|
||||
To discover services and endpoints only from specified namespaces you should set property `all-namespaces` to `false` and set the following property in `application.properties` (in this example namespaces are: `ns1` and `ns2`).
|
||||
|
||||
====
|
||||
[source]
|
||||
----
|
||||
spring.cloud.kubernetes.discovery.namespaces[0]=ns1
|
||||
spring.cloud.kubernetes.discovery.namespaces[1]=ns2
|
||||
----
|
||||
====
|
||||
|
||||
To discover service endpoint addresses that are not marked as "ready" by the kubernetes api server, you can set the following property in `application.properties` (default: false):
|
||||
|
||||
====
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import io.kubernetes.client.extended.wait.Wait;
|
||||
import io.kubernetes.client.informer.SharedInformer;
|
||||
@@ -98,14 +99,17 @@ public class KubernetesInformerDiscoveryClient implements DiscoveryClient, Initi
|
||||
log.warn("Namespace is null or empty, this may cause issues looking up services");
|
||||
}
|
||||
|
||||
V1Service service = properties.allNamespaces() ? this.serviceLister.list().stream()
|
||||
.filter(svc -> serviceId.equals(svc.getMetadata().getName())).findFirst().orElse(null)
|
||||
: this.serviceLister.namespace(this.namespace).get(serviceId);
|
||||
if (service == null || !matchServiceLabels(service)) {
|
||||
List<V1Service> services = properties.allNamespaces() ? this.serviceLister.list().stream()
|
||||
.filter(svc -> serviceId.equals(svc.getMetadata().getName())).toList()
|
||||
: List.of(this.serviceLister.namespace(this.namespace).get(serviceId));
|
||||
if (services.size() == 0 || !services.stream().anyMatch(this::matchServiceLabels)) {
|
||||
// no such service present in the cluster
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return services.stream().flatMap(s -> getServiceInstanceDetails(s, serviceId)).toList();
|
||||
}
|
||||
|
||||
private Stream<ServiceInstance> getServiceInstanceDetails(V1Service service, String serviceId) {
|
||||
Map<String, String> svcMetadata = new HashMap<>();
|
||||
if (this.properties.metadata() != null) {
|
||||
if (this.properties.metadata().addLabels()) {
|
||||
@@ -132,7 +136,7 @@ public class KubernetesInformerDiscoveryClient implements DiscoveryClient, Initi
|
||||
.get(service.getMetadata().getName());
|
||||
if (ep == null || ep.getSubsets() == null) {
|
||||
// no available endpoints in the cluster
|
||||
return new ArrayList<>();
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
Optional<String> discoveredPrimaryPortName = Optional.empty();
|
||||
@@ -166,7 +170,7 @@ public class KubernetesInformerDiscoveryClient implements DiscoveryClient, Initi
|
||||
addr.getTargetRef() != null ? addr.getTargetRef().getUid() : "", serviceId,
|
||||
addr.getIp(), port, metadata, false, service.getMetadata().getNamespace(),
|
||||
service.getMetadata().getClusterName()));
|
||||
}).collect(Collectors.toList());
|
||||
});
|
||||
}
|
||||
|
||||
private int findEndpointPort(List<V1EndpointPort> endpointPorts, String primaryPortName, String serviceId) {
|
||||
|
||||
@@ -65,6 +65,11 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
.addSubsetsItem(new V1EndpointSubset().addPortsItem(new V1EndpointPort().port(8080))
|
||||
.addAddressesItem(new V1EndpointAddress().ip("2.2.2.2")));
|
||||
|
||||
private static final V1Endpoints testEndpoints2 = new V1Endpoints()
|
||||
.metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace2"))
|
||||
.addSubsetsItem(new V1EndpointSubset().addPortsItem(new V1EndpointPort().port(8080))
|
||||
.addAddressesItem(new V1EndpointAddress().ip("2.2.2.2")));
|
||||
|
||||
private static final V1Endpoints testEndpointWithoutReadyAddresses = new V1Endpoints()
|
||||
.metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1"))
|
||||
.addSubsetsItem(new V1EndpointSubset().addPortsItem(new V1EndpointPort().port(8080))
|
||||
@@ -108,7 +113,8 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpointWithUnsetPortName);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true,
|
||||
true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), Map.of(), null,
|
||||
KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -141,7 +147,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
labels.put("spring", "true");
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true,
|
||||
true, 60, false, null, Set.of(), labels, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), labels, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("",
|
||||
sharedInformerFactory, serviceLister, null, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -160,7 +166,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
labels.put("spring", "true");
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true,
|
||||
true, 60, false, null, Set.of(), labels, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), labels, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -188,7 +194,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpoints1);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true,
|
||||
true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -203,7 +209,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpoints1);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false,
|
||||
true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -230,7 +236,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpointWithoutReadyAddresses);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false,
|
||||
true, 60, true, null, Set.of(), null, null, null, 0);
|
||||
Set.of(), true, 60, true, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -271,7 +277,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpointWithMultiplePorts);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false,
|
||||
true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -290,7 +296,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
testEndpointWithMultiplePortsWithoutSupportedPortNames);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false,
|
||||
true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -306,7 +312,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpointWithMultiplePorts);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false,
|
||||
true, 60, false, null, Set.of(), null, "https", null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, "https", null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -322,7 +328,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
testEndpointWithMultiplePortsWithoutSupportedPortNames);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false,
|
||||
true, 60, false, null, Set.of(), null, "oops", null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, "oops", null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -337,7 +343,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpointWithMultiplePorts);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false,
|
||||
true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -352,7 +358,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpointWithMultiplePortsWithoutHttps);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false,
|
||||
true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -368,7 +374,7 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
testEndpointWithMultiplePortsWithoutSupportedPortNames);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false,
|
||||
true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient("namespace1",
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
@@ -377,6 +383,24 @@ public class KubernetesInformerDiscoveryClientTests {
|
||||
"test-svc-1", "1.1.1.1", 80, new HashMap<>(), false, "namespace1", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstancesShouldReturnInstancesWithTheSameServiceIdFromNamespaces() {
|
||||
Lister<V1Service> serviceLister = setupServiceLister(testService1, testService2);
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpoints1, testEndpoints2);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true,
|
||||
Set.of(), true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesInformerDiscoveryClient discoveryClient = new KubernetesInformerDiscoveryClient(null,
|
||||
sharedInformerFactory, serviceLister, endpointsLister, null, null, kubernetesDiscoveryProperties);
|
||||
|
||||
assertThat(discoveryClient.getInstances("test-svc-1")).containsOnly(
|
||||
new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, new HashMap<>(), false,
|
||||
"namespace1", null),
|
||||
new DefaultKubernetesServiceInstance("", "test-svc-1", "2.2.2.2", 8080, new HashMap<>(), false,
|
||||
"namespace2", null));
|
||||
}
|
||||
|
||||
private Lister<V1Service> setupServiceLister(V1Service... services) {
|
||||
Cache<V1Service> serviceCache = new Cache<>();
|
||||
Lister<V1Service> serviceLister = new Lister<>(serviceCache);
|
||||
|
||||
@@ -101,7 +101,7 @@ public class KubernetesInformerReactiveDiscoveryClientTests {
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpoints1);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true,
|
||||
true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesInformerReactiveDiscoveryClient discoveryClient = new KubernetesInformerReactiveDiscoveryClient(
|
||||
new KubernetesNamespaceProvider(new MockEnvironment()), sharedInformerFactory, serviceLister,
|
||||
@@ -120,7 +120,7 @@ public class KubernetesInformerReactiveDiscoveryClientTests {
|
||||
Lister<V1Endpoints> endpointsLister = setupEndpointsLister(testEndpoints1);
|
||||
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, false,
|
||||
true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), null, null, null, 0);
|
||||
|
||||
KubernetesNamespaceProvider kubernetesNamespaceProvider = mock(KubernetesNamespaceProvider.class);
|
||||
when(kubernetesNamespaceProvider.getNamespace()).thenReturn("namespace1");
|
||||
|
||||
@@ -146,7 +146,8 @@ class KubernetesClientServicesListSupplierTests {
|
||||
KubernetesNamespaceProvider kubernetesNamespaceProvider = mock(KubernetesNamespaceProvider.class);
|
||||
when(kubernetesNamespaceProvider.getNamespace()).thenReturn("default");
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties = new KubernetesDiscoveryProperties(true, true,
|
||||
true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
Set.of(), true, 60, false, null, Set.of(), Map.of(), null,
|
||||
KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
CoreV1Api coreV1Api = new CoreV1Api();
|
||||
KubernetesClientServiceInstanceMapper mapper = new KubernetesClientServiceInstanceMapper(
|
||||
new KubernetesLoadBalancerProperties(), kubernetesDiscoveryProperties);
|
||||
|
||||
@@ -27,6 +27,8 @@ import static org.springframework.cloud.client.discovery.DiscoveryClient.DEFAULT
|
||||
/**
|
||||
* @param enabled if kubernetes discovery is enabled
|
||||
* @param allNamespaces if discover is enabled for all namespaces
|
||||
* @param namespaces If set and allNamespaces is false, then only the services and
|
||||
* endpoints matching these namespaces will be fetched from the Kubernetes API server.
|
||||
* @param waitCacheReady wait for the discovery cache (service and endpoints) to be fully
|
||||
* loaded, otherwise aborts the application on starting
|
||||
* @param cacheLoadingTimeoutSeconds timeout for initializing discovery cache, will abort
|
||||
@@ -45,6 +47,7 @@ import static org.springframework.cloud.client.discovery.DiscoveryClient.DEFAULT
|
||||
@ConfigurationProperties("spring.cloud.kubernetes.discovery")
|
||||
public record KubernetesDiscoveryProperties(
|
||||
@DefaultValue("true") boolean enabled, boolean allNamespaces,
|
||||
@DefaultValue Set<String> namespaces,
|
||||
@DefaultValue("true") boolean waitCacheReady,
|
||||
@DefaultValue("60") long cacheLoadingTimeoutSeconds,
|
||||
boolean includeNotReadyAddresses, String filter,
|
||||
@@ -57,8 +60,8 @@ public record KubernetesDiscoveryProperties(
|
||||
/**
|
||||
* Default instance.
|
||||
*/
|
||||
public static final KubernetesDiscoveryProperties DEFAULT = new KubernetesDiscoveryProperties(true, false, true, 60,
|
||||
false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
public static final KubernetesDiscoveryProperties DEFAULT = new KubernetesDiscoveryProperties(true, false, Set.of(),
|
||||
true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
|
||||
/**
|
||||
* @param addLabels include labels as metadata
|
||||
|
||||
@@ -43,6 +43,7 @@ class KubernetesDiscoveryPropertiesTests {
|
||||
|
||||
assertThat(props.enabled()).isTrue();
|
||||
assertThat(props.allNamespaces()).isFalse();
|
||||
assertThat(props.namespaces()).isEmpty();
|
||||
assertThat(props.waitCacheReady()).isTrue();
|
||||
assertThat(props.cacheLoadingTimeoutSeconds()).isEqualTo(60);
|
||||
assertThat(props.includeNotReadyAddresses()).isFalse();
|
||||
@@ -59,7 +60,9 @@ class KubernetesDiscoveryPropertiesTests {
|
||||
new ApplicationContextRunner().withUserConfiguration(KubernetesDiscoveryPropertiesMetadataTests.Config.class)
|
||||
.withPropertyValues("spring.cloud.kubernetes.discovery.filter=some-filter",
|
||||
"spring.cloud.kubernetes.discovery.knownSecurePorts[0]=222",
|
||||
"spring.cloud.kubernetes.discovery.metadata.labelsPrefix=labelsPrefix")
|
||||
"spring.cloud.kubernetes.discovery.metadata.labelsPrefix=labelsPrefix",
|
||||
"spring.cloud.kubernetes.discovery.namespaces[0]=ns1",
|
||||
"spring.cloud.kubernetes.discovery.namespaces[1]=ns2")
|
||||
.run(context -> {
|
||||
KubernetesDiscoveryProperties props = context.getBean(KubernetesDiscoveryProperties.class);
|
||||
assertThat(props).isNotNull();
|
||||
@@ -69,6 +72,7 @@ class KubernetesDiscoveryPropertiesTests {
|
||||
|
||||
assertThat(props.enabled()).isTrue();
|
||||
assertThat(props.allNamespaces()).isFalse();
|
||||
assertThat(props.namespaces()).containsExactlyInAnyOrder("ns1", "ns2");
|
||||
assertThat(props.waitCacheReady()).isTrue();
|
||||
assertThat(props.cacheLoadingTimeoutSeconds()).isEqualTo(60);
|
||||
assertThat(props.includeNotReadyAddresses()).isFalse();
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@@ -54,7 +55,7 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
KubernetesServiceInstance[] responseBody = rest.getForEntity(
|
||||
properties.getDiscoveryServerUrl() + "/apps/" + serviceId, KubernetesServiceInstance[].class).getBody();
|
||||
if (responseBody != null && responseBody.length > 0) {
|
||||
response = Arrays.asList(responseBody);
|
||||
response = Arrays.stream(responseBody).filter(this::matchNamespaces).collect(Collectors.toList());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@@ -64,9 +65,24 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
List<String> response = Collections.emptyList();
|
||||
Service[] services = rest.getForEntity(properties.getDiscoveryServerUrl() + "/apps", Service[].class).getBody();
|
||||
if (services != null && services.length > 0) {
|
||||
response = Arrays.stream(services).map(service -> service.getName()).collect(Collectors.toList());
|
||||
response = Arrays.stream(services).filter(this::matchNamespaces).map(Service::getName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private boolean matchNamespaces(KubernetesServiceInstance kubernetesServiceInstance) {
|
||||
if (CollectionUtils.isEmpty(properties.getNamespaces())) {
|
||||
return true;
|
||||
}
|
||||
return properties.getNamespaces().contains(kubernetesServiceInstance.getNamespace());
|
||||
}
|
||||
|
||||
private boolean matchNamespaces(Service service) {
|
||||
if (CollectionUtils.isEmpty(service.getServiceInstances())) {
|
||||
return true;
|
||||
}
|
||||
return service.getServiceInstances().stream().anyMatch(this::matchNamespaces);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.kubernetes.discovery;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
@@ -28,6 +31,12 @@ public class KubernetesDiscoveryClientProperties {
|
||||
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* If set then only the services and endpoints matching these namespaces will be
|
||||
* fetched from the Kubernetes API server.
|
||||
*/
|
||||
private List<String> namespaces = new ArrayList<>();
|
||||
|
||||
public String getDiscoveryServerUrl() {
|
||||
return discoveryServerUrl;
|
||||
}
|
||||
@@ -44,4 +53,12 @@ public class KubernetesDiscoveryClientProperties {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
List<String> getNamespaces() {
|
||||
return namespaces;
|
||||
}
|
||||
|
||||
void setNamespaces(List<String> namespaces) {
|
||||
this.namespaces = namespaces;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,14 +18,20 @@ package org.springframework.cloud.kubernetes.discovery;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
@@ -39,9 +45,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class KubernetesDiscoveryClientTests {
|
||||
|
||||
private static final String APPS = "[{\"name\":\"test-svc-1\",\"serviceInstances\":[{\"instanceId\":\"uid1\",\"serviceId\":\"test-svc-1\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"http\":\"8080\"},\"namespace\":\"namespace1\",\"cluster\":null,\"scheme\":\"http\"}]},{\"name\":\"test-svc-3\",\"serviceInstances\":[{\"instanceId\":\"uid2\",\"serviceId\":\"test-svc-3\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"spring\":\"true\",\"http\":\"8080\",\"k8s\":\"true\"},\"namespace\":\"namespace1\",\"cluster\":null,\"scheme\":\"http\"}]}]";
|
||||
private static final String APPS = "[{\"name\":\"test-svc-1\",\"serviceInstances\":[{\"instanceId\":\"uid1\",\"serviceId\":\"test-svc-1\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"http\":\"8080\"},\"namespace\":\"namespace1\",\"cluster\":null,\"scheme\":\"http\"}]},{\"name\":\"test-svc-3\",\"serviceInstances\":[{\"instanceId\":\"uid2\",\"serviceId\":\"test-svc-3\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"spring\":\"true\",\"http\":\"8080\",\"k8s\":\"true\"},\"namespace\":\"namespace2\",\"cluster\":null,\"scheme\":\"http\"}]}]";
|
||||
|
||||
private static final String APPS_NAME = "[{\"instanceId\":\"uid2\",\"serviceId\":\"test-svc-3\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"spring\":\"true\",\"http\":\"8080\",\"k8s\":\"true\"},\"namespace\":\"namespace1\",\"cluster\":null,\"scheme\":\"http\"}]";
|
||||
private static final String APPS_NAME = "[{\"instanceId\":\"uid2\",\"serviceId\":\"test-svc-3\",\"host\":\"2.2.2.2\",\"port\":8080,\"uri\":\"http://2.2.2.2:8080\",\"secure\":false,\"metadata\":{\"spring\":\"true\",\"http\":\"8080\",\"k8s\":\"true\"},\"namespace\":\"namespace2\",\"cluster\":null,\"scheme\":\"http\"}]";
|
||||
|
||||
private static WireMockServer wireMockServer;
|
||||
|
||||
@@ -79,8 +85,44 @@ class KubernetesDiscoveryClientTests {
|
||||
metadata.put("k8s", "true");
|
||||
assertThat(discoveryClient.getInstances("test-svc-3"))
|
||||
.contains(new KubernetesServiceInstance("uid2", "test-svc-3", "2.2.2.2", 8080, false,
|
||||
URI.create("http://2.2.2.2:8080"), metadata, "http", "namespace1"));
|
||||
URI.create("http://2.2.2.2:8080"), metadata, "http", "namespace2"));
|
||||
assertThat(discoveryClient.getInstances("does-not-exist")).isEmpty();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("servicesFilteredByNamespacesSource")
|
||||
void getServicesFilteredByNamespaces(List<String> namespaces, List<String> expectedServices) {
|
||||
RestTemplate rest = new RestTemplateBuilder().build();
|
||||
KubernetesDiscoveryClientProperties properties = new KubernetesDiscoveryClientProperties();
|
||||
properties.setNamespaces(namespaces);
|
||||
properties.setDiscoveryServerUrl(wireMockServer.baseUrl());
|
||||
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(rest, properties);
|
||||
assertThat(discoveryClient.getServices()).containsExactlyInAnyOrderElementsOf(expectedServices);
|
||||
}
|
||||
|
||||
static Stream<Arguments> servicesFilteredByNamespacesSource() {
|
||||
return Stream.of(Arguments.of(List.of(), List.of("test-svc-1", "test-svc-3")),
|
||||
Arguments.of(List.of("namespace1", "namespace2"), List.of("test-svc-1", "test-svc-3")),
|
||||
Arguments.of(List.of("namespace1"), List.of("test-svc-1")),
|
||||
Arguments.of(List.of("namespace2", "does-not-exist"), List.of("test-svc-3")));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("instancesFilteredByNamespacesSource")
|
||||
void getInstancesFilteredByNamespaces(List<String> namespaces, String serviceId, List<String> expectedInstances) {
|
||||
RestTemplate rest = new RestTemplateBuilder().build();
|
||||
KubernetesDiscoveryClientProperties properties = new KubernetesDiscoveryClientProperties();
|
||||
properties.setNamespaces(namespaces);
|
||||
properties.setDiscoveryServerUrl(wireMockServer.baseUrl());
|
||||
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(rest, properties);
|
||||
assertThat(discoveryClient.getInstances(serviceId)).map(ServiceInstance::getInstanceId)
|
||||
.containsExactlyInAnyOrderElementsOf(expectedInstances);
|
||||
}
|
||||
|
||||
static Stream<Arguments> instancesFilteredByNamespacesSource() {
|
||||
return Stream.of(Arguments.of(List.of(), "test-svc-3", List.of("uid2")),
|
||||
Arguments.of(List.of("namespace1"), "test-svc-3", List.of()),
|
||||
Arguments.of(List.of("namespace2"), "test-svc-3", List.of("uid2")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -121,11 +121,24 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
}
|
||||
|
||||
public List<Endpoints> getEndPointsList(String serviceId) {
|
||||
return this.properties.allNamespaces()
|
||||
? this.client.endpoints().inAnyNamespace().withField("metadata.name", serviceId)
|
||||
.withLabels(properties.serviceLabels()).list().getItems()
|
||||
: this.client.endpoints().withField("metadata.name", serviceId).withLabels(properties.serviceLabels())
|
||||
.list().getItems();
|
||||
if (this.properties.allNamespaces()) {
|
||||
return this.client.endpoints().inAnyNamespace().withField("metadata.name", serviceId)
|
||||
.withLabels(properties.serviceLabels()).list().getItems();
|
||||
}
|
||||
if (properties.namespaces().isEmpty()) {
|
||||
return this.client.endpoints().withField("metadata.name", serviceId).withLabels(properties.serviceLabels())
|
||||
.list().getItems();
|
||||
}
|
||||
return findEndPointsFilteredByNamespaces(serviceId);
|
||||
}
|
||||
|
||||
private List<Endpoints> findEndPointsFilteredByNamespaces(String serviceId) {
|
||||
List<Endpoints> endpoints = new ArrayList<>();
|
||||
for (String ns : properties.namespaces()) {
|
||||
endpoints.addAll(getClient().endpoints().inNamespace(ns).withField("metadata.name", serviceId)
|
||||
.withLabels(properties.serviceLabels()).list().getItems());
|
||||
}
|
||||
return endpoints;
|
||||
}
|
||||
|
||||
private List<ServiceInstance> getNamespaceServiceInstances(EndpointSubsetNS es, String serviceId) {
|
||||
@@ -297,8 +310,16 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
}
|
||||
|
||||
public List<String> getServices(Predicate<Service> filter) {
|
||||
return this.kubernetesClientServicesFunction.apply(this.client).list().getItems().stream().filter(filter)
|
||||
.map(s -> s.getMetadata().getName()).collect(Collectors.toList());
|
||||
if (properties.namespaces().isEmpty()) {
|
||||
return this.kubernetesClientServicesFunction.apply(this.client).list().getItems().stream().filter(filter)
|
||||
.map(s -> s.getMetadata().getName()).collect(Collectors.toList());
|
||||
}
|
||||
List<String> services = new ArrayList<>();
|
||||
for (String ns : properties.namespaces()) {
|
||||
services.addAll(getClient().services().inNamespace(ns).list().getItems().stream().filter(filter)
|
||||
.map(s -> s.getMetadata().getName()).toList());
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -245,8 +245,8 @@ class Fabric8KubernetesCatalogWatchTests {
|
||||
when(namespaceProvider.getNamespace()).thenReturn(namespace);
|
||||
|
||||
// all-namespaces = false
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, "",
|
||||
Set.of(), labels, "", null, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, "", Set.of(), labels, "", null, 0);
|
||||
|
||||
KubernetesCatalogWatch watch = new KubernetesCatalogWatch(mockClient, properties, namespaceProvider);
|
||||
watch.setApplicationEventPublisher(APPLICATION_EVENT_PUBLISHER);
|
||||
@@ -257,8 +257,8 @@ class Fabric8KubernetesCatalogWatchTests {
|
||||
private KubernetesCatalogWatch createWatcherInAllNamespacesAndLabels(Map<String, String> labels) {
|
||||
|
||||
// all-namespaces = true
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, true, 60, false, "",
|
||||
Set.of(), labels, "", null, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60,
|
||||
false, "", Set.of(), labels, "", null, 0);
|
||||
|
||||
KubernetesCatalogWatch watch = new KubernetesCatalogWatch(mockClient, properties, namespaceProvider);
|
||||
watch.setApplicationEventPublisher(APPLICATION_EVENT_PUBLISHER);
|
||||
|
||||
@@ -365,8 +365,8 @@ class KubernetesCatalogWatchTest {
|
||||
when(MIXED_OPERATION.withLabels(Map.of())).thenReturn(MIXED_OPERATION);
|
||||
|
||||
// all-namespaces = true
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, true, 60, false, "",
|
||||
Set.of(), Map.of(), "", null, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60,
|
||||
false, "", Set.of(), Map.of(), "", null, 0);
|
||||
|
||||
kubernetesCatalogWatch = new KubernetesCatalogWatch(CLIENT, properties, namespaceProvider);
|
||||
kubernetesCatalogWatch.setApplicationEventPublisher(APPLICATION_EVENT_PUBLISHER);
|
||||
@@ -375,8 +375,8 @@ class KubernetesCatalogWatchTest {
|
||||
private void createInSpecificNamespaceWatcher() {
|
||||
|
||||
// all-namespaces = false
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, "",
|
||||
Set.of(), Map.of(), "", null, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, "", Set.of(), Map.of(), "", null, 0);
|
||||
|
||||
kubernetesCatalogWatch = new KubernetesCatalogWatch(CLIENT, properties, namespaceProvider);
|
||||
kubernetesCatalogWatch.setApplicationEventPublisher(APPLICATION_EVENT_PUBLISHER);
|
||||
|
||||
@@ -79,8 +79,8 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
final String serviceId = "s";
|
||||
|
||||
Metadata metadata = new Metadata(false, null, false, null, false, null);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, null,
|
||||
Set.of(), Map.of(), null, metadata, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, null, Set.of(), Map.of(), null, metadata, 0);
|
||||
|
||||
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(CLIENT, properties, a -> null);
|
||||
|
||||
@@ -109,8 +109,8 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
final String serviceId = "s";
|
||||
|
||||
Metadata metadata = new Metadata(true, null, false, null, false, null);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, null,
|
||||
Set.of(), Map.of(), null, metadata, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, null, Set.of(), Map.of(), null, metadata, 0);
|
||||
|
||||
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(CLIENT, properties, a -> null);
|
||||
|
||||
@@ -140,8 +140,8 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
final String serviceId = "s";
|
||||
|
||||
Metadata metadata = new Metadata(true, "l_", false, null, false, null);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, null,
|
||||
Set.of(), Map.of(), null, metadata, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, null, Set.of(), Map.of(), null, metadata, 0);
|
||||
|
||||
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(CLIENT, properties, a -> null);
|
||||
|
||||
@@ -171,8 +171,8 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
final String serviceId = "s";
|
||||
|
||||
Metadata metadata = new Metadata(false, null, true, null, false, null);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, null,
|
||||
Set.of(), Map.of(), null, metadata, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, null, Set.of(), Map.of(), null, metadata, 0);
|
||||
|
||||
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(CLIENT, properties, a -> null);
|
||||
|
||||
@@ -202,8 +202,8 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
final String serviceId = "s";
|
||||
|
||||
Metadata metadata = new Metadata(false, null, true, "a_", false, null);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, null,
|
||||
Set.of(), Map.of(), null, metadata, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, null, Set.of(), Map.of(), null, metadata, 0);
|
||||
|
||||
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(CLIENT, properties, a -> null);
|
||||
|
||||
@@ -233,8 +233,8 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
final String serviceId = "s";
|
||||
|
||||
Metadata metadata = new Metadata(false, null, false, null, true, null);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, null,
|
||||
Set.of(), Map.of(), null, metadata, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, null, Set.of(), Map.of(), null, metadata, 0);
|
||||
|
||||
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(CLIENT, properties, a -> null);
|
||||
|
||||
@@ -264,8 +264,8 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
final String serviceId = "s";
|
||||
|
||||
Metadata metadata = new Metadata(false, null, false, null, true, "p_");
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, null,
|
||||
Set.of(), Map.of(), null, metadata, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, null, Set.of(), Map.of(), null, metadata, 0);
|
||||
|
||||
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(CLIENT, properties, a -> null);
|
||||
|
||||
@@ -295,8 +295,8 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
final String serviceId = "s";
|
||||
|
||||
Metadata metadata = new Metadata(true, "l_", true, "a_", true, "p_");
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, null,
|
||||
Set.of(), Map.of(), null, metadata, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, null, Set.of(), Map.of(), null, metadata, 0);
|
||||
|
||||
KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(CLIENT, properties, a -> null);
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@ public class KubernetesDiscoveryClientFilterTest {
|
||||
when(this.serviceOperation.list()).thenReturn(serviceList);
|
||||
when(this.kubernetesClient.services()).thenReturn(this.serviceOperation);
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false,
|
||||
"metadata.additionalProperties['spring-boot']", Set.of(), Map.of(), null,
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, "metadata.additionalProperties['spring-boot']", Set.of(), Map.of(), null,
|
||||
KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
KubernetesDiscoveryClient client = new KubernetesDiscoveryClient(this.kubernetesClient, properties,
|
||||
this.kubernetesClientServicesFunction);
|
||||
@@ -94,8 +94,8 @@ public class KubernetesDiscoveryClientFilterTest {
|
||||
when(this.serviceOperation.list()).thenReturn(serviceList);
|
||||
when(this.kubernetesClient.services()).thenReturn(this.serviceOperation);
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false,
|
||||
"metadata.name.startsWith('service')", Set.of(), Map.of(), null,
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, "metadata.name.startsWith('service')", Set.of(), Map.of(), null,
|
||||
KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
KubernetesDiscoveryClient client = new KubernetesDiscoveryClient(this.kubernetesClient, properties,
|
||||
this.kubernetesClientServicesFunction);
|
||||
@@ -115,8 +115,8 @@ public class KubernetesDiscoveryClientFilterTest {
|
||||
when(this.serviceOperation.list()).thenReturn(serviceList);
|
||||
when(this.kubernetesClient.services()).thenReturn(this.serviceOperation);
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false, "",
|
||||
Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true, 60,
|
||||
false, "", Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
KubernetesDiscoveryClient client = new KubernetesDiscoveryClient(this.kubernetesClient, properties,
|
||||
this.kubernetesClientServicesFunction);
|
||||
|
||||
|
||||
@@ -21,9 +21,11 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Endpoints;
|
||||
import io.fabric8.kubernetes.api.model.EndpointsBuilder;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.kubernetes.api.model.ServiceBuilder;
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
@@ -109,8 +111,8 @@ public class KubernetesDiscoveryClientTest {
|
||||
|
||||
mockClient.services().inNamespace("test").create(service);
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, true, 60, false,
|
||||
null, Set.of(), labels, "http_tcp", Metadata.DEFAULT, 0);
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true,
|
||||
60, false, null, Set.of(), labels, "http_tcp", Metadata.DEFAULT, 0);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
@@ -143,6 +145,64 @@ public class KubernetesDiscoveryClientTest {
|
||||
assertThat(result_endpoints).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEndPointsListTestAllNamespaces() {
|
||||
|
||||
final var namespace1 = "ns1";
|
||||
final var namespace2 = "ns2";
|
||||
|
||||
Endpoints endPoint1 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace(namespace1)
|
||||
.endMetadata().build();
|
||||
|
||||
Endpoints endPoint2 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace(namespace2)
|
||||
.endMetadata().build();
|
||||
|
||||
mockClient.endpoints().inNamespace(namespace1).create(endPoint1);
|
||||
mockClient.endpoints().inNamespace(namespace2).create(endPoint2);
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true,
|
||||
60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
|
||||
final KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
|
||||
final List<Endpoints> result_endpoints = discoveryClient.getEndPointsList("endpoint");
|
||||
|
||||
assertThat(result_endpoints).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEndPointsListShouldHandleNamespaces() {
|
||||
|
||||
final var namespace1 = "ns1";
|
||||
final var namespace2 = "ns2";
|
||||
final var namespace3 = "ns3";
|
||||
|
||||
Endpoints endPoint1 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace(namespace1)
|
||||
.endMetadata().build();
|
||||
Endpoints endPoint2 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace(namespace2)
|
||||
.endMetadata().build();
|
||||
Endpoints endPoint3 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace(namespace3)
|
||||
.endMetadata().build();
|
||||
|
||||
mockClient.endpoints().inNamespace(namespace1).create(endPoint1);
|
||||
mockClient.endpoints().inNamespace(namespace2).create(endPoint2);
|
||||
mockClient.endpoints().inNamespace(namespace3).create(endPoint3);
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false,
|
||||
Set.of(namespace1, namespace3), true, 60, false, null, Set.of(), Map.of(), null,
|
||||
KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
|
||||
final KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
|
||||
final List<Endpoints> result_endpoints = discoveryClient.getEndPointsList("endpoint");
|
||||
|
||||
assertThat(result_endpoints).hasSize(2);
|
||||
assertThat(result_endpoints.stream().map(Endpoints::getMetadata).map(ObjectMeta::getNamespace)
|
||||
.collect(Collectors.toList())).containsOnly(namespace1, namespace3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstancesShouldBeAbleToHandleEndpointsMultipleAddresses() {
|
||||
Map<String, String> labels = new HashMap<>();
|
||||
@@ -162,8 +222,8 @@ public class KubernetesDiscoveryClientTest {
|
||||
mockClient.services().inNamespace("test").create(service);
|
||||
|
||||
Metadata metadata = new Metadata(false, null, false, null, true, "port.");
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, true, 60, false,
|
||||
null, Set.of(443, 8443), labels, null, metadata, 0);
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true,
|
||||
60, false, null, Set.of(443, 8443), labels, null, metadata, 0);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
@@ -228,6 +288,38 @@ public class KubernetesDiscoveryClientTest {
|
||||
assertThat(services).containsOnly("s1", "s2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServicesShouldReturnServicesInNamespaces() {
|
||||
|
||||
final var nameSpace1 = "ns1";
|
||||
final var nameSpace2 = "ns2";
|
||||
final var nameSpace3 = "ns3";
|
||||
|
||||
Service service1 = new ServiceBuilder().withNewMetadata().withName("s1").withNamespace(nameSpace1).endMetadata()
|
||||
.build();
|
||||
|
||||
Service service2 = new ServiceBuilder().withNewMetadata().withName("s2").withNamespace(nameSpace2).endMetadata()
|
||||
.build();
|
||||
|
||||
Service service3 = new ServiceBuilder().withNewMetadata().withName("s3").withNamespace(nameSpace3).endMetadata()
|
||||
.build();
|
||||
|
||||
mockClient.services().inNamespace(nameSpace1).create(service1);
|
||||
mockClient.services().inNamespace(nameSpace2).create(service2);
|
||||
mockClient.services().inNamespace(nameSpace3).create(service3);
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false,
|
||||
Set.of(nameSpace1, nameSpace2), true, 60, false, null, Set.of(), Map.of(), null,
|
||||
KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
|
||||
final List<String> services = discoveryClient.getServices();
|
||||
|
||||
assertThat(services).containsOnly("s1", "s2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstancesShouldBeAbleToHandleEndpointsFromMultipleNamespaces() {
|
||||
Endpoints endPoints1 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
@@ -250,8 +342,8 @@ public class KubernetesDiscoveryClientTest {
|
||||
mockClient.services().inNamespace("test").create(service1);
|
||||
mockClient.services().inNamespace("test2").create(service2);
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, true, 60, false,
|
||||
null, Set.of(), Map.of(), null, Metadata.DEFAULT, 0);
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true,
|
||||
60, false, null, Set.of(), Map.of(), null, Metadata.DEFAULT, 0);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
@@ -302,8 +394,8 @@ public class KubernetesDiscoveryClientTest {
|
||||
|
||||
mockClient.services().inNamespace("test").create(service);
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, true, 60, false,
|
||||
null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0);
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true,
|
||||
60, false, null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
@@ -333,8 +425,8 @@ public class KubernetesDiscoveryClientTest {
|
||||
|
||||
mockClient.services().inNamespace("test").create(service);
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false,
|
||||
null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0);
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true,
|
||||
60, false, null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
@@ -363,8 +455,8 @@ public class KubernetesDiscoveryClientTest {
|
||||
|
||||
mockClient.services().inNamespace("test").create(service);
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false,
|
||||
null, Set.of(443, 8443), Map.of(), "oops", Metadata.DEFAULT, 0);
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true,
|
||||
60, false, null, Set.of(443, 8443), Map.of(), "oops", Metadata.DEFAULT, 0);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
@@ -392,8 +484,8 @@ public class KubernetesDiscoveryClientTest {
|
||||
|
||||
mockClient.services().inNamespace("test").create(service);
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, true, 60, false,
|
||||
null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0);
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, false, Set.of(), true,
|
||||
60, false, null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
@@ -449,8 +541,8 @@ public class KubernetesDiscoveryClientTest {
|
||||
|
||||
mockClient.services().inNamespace("test").create(service);
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, true, 60, true,
|
||||
null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0);
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true,
|
||||
60, true, null, Set.of(443, 8443), Map.of(), null, Metadata.DEFAULT, 0);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new ServicePortSecureResolver(properties));
|
||||
|
||||
@@ -50,8 +50,9 @@ class ServicePortSecureResolverTest {
|
||||
|
||||
@Test
|
||||
void testPortNumbersOnly() {
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, true, 60, false, null,
|
||||
Set.of(443, 8443, 12345), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60,
|
||||
false, null, Set.of(443, 8443, 12345), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT,
|
||||
0);
|
||||
|
||||
ServicePortSecureResolver secureResolver = new ServicePortSecureResolver(properties);
|
||||
|
||||
|
||||
@@ -301,8 +301,8 @@ class KubernetesReactiveDiscoveryClientTests {
|
||||
}).endMetadata().build())
|
||||
.once();
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, true, 60, false, null,
|
||||
Set.of(), Map.of(), "https_tcp", Metadata.DEFAULT, 0);
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties(true, true, Set.of(), true, 60,
|
||||
false, null, Set.of(), Map.of(), "https_tcp", Metadata.DEFAULT, 0);
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties,
|
||||
KubernetesClient::services);
|
||||
Flux<ServiceInstance> instances = client.getInstances("existing-service");
|
||||
|
||||
@@ -78,8 +78,8 @@ class Fabric8ServiceInstanceMapperTests {
|
||||
@Test
|
||||
void testMapperSecureNullLabelsAndAnnotations() {
|
||||
KubernetesLoadBalancerProperties properties = new KubernetesLoadBalancerProperties();
|
||||
KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(true, true, true, 60,
|
||||
false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(true, true, Set.of(),
|
||||
true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
List<ServicePort> ports = new ArrayList<>();
|
||||
ports.add(new ServicePortBuilder().withPort(443).build());
|
||||
Service service = buildService("test", "abc", ports, null, null);
|
||||
|
||||
@@ -95,8 +95,8 @@ class KubernetesServiceListSupplierTests {
|
||||
ServiceList serviceList = new ServiceList();
|
||||
serviceList.getItems().add(buildService("test-service", 8080));
|
||||
when(this.multiDeletable.list()).thenReturn(serviceList);
|
||||
KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(true, true, true, 60,
|
||||
false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
KubernetesDiscoveryProperties discoveryProperties = new KubernetesDiscoveryProperties(true, true, Set.of(),
|
||||
true, 60, false, null, Set.of(), Map.of(), null, KubernetesDiscoveryProperties.Metadata.DEFAULT, 0);
|
||||
KubernetesServicesListSupplier supplier = new Fabric8ServicesListSupplier(environment, client, mapper,
|
||||
discoveryProperties);
|
||||
List<ServiceInstance> instances = supplier.get().blockFirst();
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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.discoveryclient.it;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import io.kubernetes.client.openapi.ApiException;
|
||||
import io.kubernetes.client.openapi.apis.AppsV1Api;
|
||||
import io.kubernetes.client.openapi.apis.CoreV1Api;
|
||||
import io.kubernetes.client.openapi.apis.NetworkingV1Api;
|
||||
import io.kubernetes.client.openapi.apis.RbacAuthorizationV1Api;
|
||||
import io.kubernetes.client.openapi.models.V1ClusterRoleBinding;
|
||||
import io.kubernetes.client.openapi.models.V1Container;
|
||||
import io.kubernetes.client.openapi.models.V1Deployment;
|
||||
import io.kubernetes.client.openapi.models.V1EnvVar;
|
||||
import io.kubernetes.client.openapi.models.V1EnvVarBuilder;
|
||||
import io.kubernetes.client.openapi.models.V1Ingress;
|
||||
import io.kubernetes.client.openapi.models.V1Namespace;
|
||||
import io.kubernetes.client.openapi.models.V1ObjectMeta;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.k3s.K3sContainer;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
import reactor.util.retry.Retry;
|
||||
import reactor.util.retry.RetryBackoffSpec;
|
||||
|
||||
import org.springframework.cloud.kubernetes.discovery.KubernetesServiceInstance;
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.createApiClient;
|
||||
import static org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils.getPomVersion;
|
||||
|
||||
/**
|
||||
* @author mbialkowski1
|
||||
*/
|
||||
class DiscoveryClientFilterNamespaceIT {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(DiscoveryClientFilterNamespaceIT.class);
|
||||
|
||||
private static final String DISCOVERY_SERVER_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryserver-deployment";
|
||||
|
||||
private static final String DISCOVERY_SERVER_APP_NAME = "spring-cloud-kubernetes-discoveryserver";
|
||||
|
||||
private static final String SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME = "spring-cloud-kubernetes-discoveryclient-it-deployment";
|
||||
|
||||
private static final String SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME = "spring-cloud-kubernetes-discoveryclient-it";
|
||||
|
||||
private static final String MOCK_DEPLOYMENT_NAME = "servicea-wiremock-deployment";
|
||||
|
||||
private static final String MOCK_CLIENT_APP_NAME = "servicea-wiremock";
|
||||
|
||||
private static final String MOCK_IMAGE_NAME = "wiremock";
|
||||
|
||||
private static final String NAMESPACE = "default";
|
||||
|
||||
private static final String NAMESPACE_1 = "namespace1";
|
||||
|
||||
private static final String NAMESPACE_2 = "namespace2";
|
||||
|
||||
private static CoreV1Api api;
|
||||
|
||||
private static AppsV1Api appsApi;
|
||||
|
||||
private static NetworkingV1Api networkingApi;
|
||||
|
||||
private static RbacAuthorizationV1Api authApi;
|
||||
|
||||
private static K8SUtils k8SUtils;
|
||||
|
||||
private static final K3sContainer K3S = Commons.container();
|
||||
|
||||
@SuppressWarnings("checkstyle:WhitespaceAround")
|
||||
@BeforeAll
|
||||
static void beforeAll() throws Exception {
|
||||
K3S.start();
|
||||
|
||||
Commons.validateImage(DISCOVERY_SERVER_APP_NAME, K3S);
|
||||
Commons.loadSpringCloudKubernetesImage(DISCOVERY_SERVER_APP_NAME, K3S);
|
||||
|
||||
Commons.validateImage(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S);
|
||||
Commons.loadSpringCloudKubernetesImage(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S);
|
||||
|
||||
String[] mockImage = K8SUtils.getImageFromDeployment(getMockServiceDeployment()).split(":");
|
||||
Commons.pullImage(mockImage[0], mockImage[1], K3S);
|
||||
Commons.loadImage(mockImage[0], mockImage[1], MOCK_IMAGE_NAME, K3S);
|
||||
|
||||
createApiClient(K3S.getKubeConfigYaml());
|
||||
api = new CoreV1Api();
|
||||
appsApi = new AppsV1Api();
|
||||
networkingApi = new NetworkingV1Api();
|
||||
authApi = new RbacAuthorizationV1Api();
|
||||
k8SUtils = new K8SUtils(api, appsApi);
|
||||
k8SUtils.setUp(NAMESPACE);
|
||||
|
||||
deployDiscoveryServer();
|
||||
|
||||
// Check to make sure the discovery server deployment is ready
|
||||
k8SUtils.waitForDeployment(DISCOVERY_SERVER_DEPLOYMENT_NAME, NAMESPACE);
|
||||
|
||||
// Check to see if endpoint is ready
|
||||
k8SUtils.waitForEndpointReady(DISCOVERY_SERVER_APP_NAME, NAMESPACE);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void afterAll() throws Exception {
|
||||
Commons.cleanUp(DISCOVERY_SERVER_APP_NAME, K3S);
|
||||
Commons.cleanUp(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, K3S);
|
||||
Commons.cleanUpDownloadedImage(MOCK_IMAGE_NAME);
|
||||
|
||||
appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
|
||||
"metadata.name=" + DISCOVERY_SERVER_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null,
|
||||
null);
|
||||
|
||||
api.deleteNamespacedService(DISCOVERY_SERVER_APP_NAME, NAMESPACE, null, null, null, null, null, null);
|
||||
networkingApi.deleteNamespacedIngress("discoveryserver-ingress", NAMESPACE, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void afterEach() throws ApiException {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDiscoveryClient() throws Exception {
|
||||
deploySampleAppInNamespace(NAMESPACE_1);
|
||||
deploySampleAppInNamespace(NAMESPACE_2);
|
||||
deployDiscoveryIt();
|
||||
|
||||
testLoadBalancer();
|
||||
testHealth();
|
||||
}
|
||||
|
||||
private void cleanup() throws ApiException {
|
||||
appsApi.deleteCollectionNamespacedDeployment(NAMESPACE, null, null, null,
|
||||
"metadata.name=" + SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME, null, null, null, null, null,
|
||||
null, null, null, null);
|
||||
api.deleteNamespacedService(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_APP_NAME, NAMESPACE, null, null, null, null, null,
|
||||
null);
|
||||
networkingApi.deleteNamespacedIngress("it-ingress", NAMESPACE, null, null, null, null, null, null);
|
||||
|
||||
appsApi.deleteCollectionNamespacedDeployment(NAMESPACE_1, null, null, null,
|
||||
"metadata.name=" + MOCK_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null, null);
|
||||
appsApi.deleteCollectionNamespacedDeployment(NAMESPACE_2, null, null, null,
|
||||
"metadata.name=" + MOCK_DEPLOYMENT_NAME, null, null, null, null, null, null, null, null, null);
|
||||
|
||||
api.deleteNamespacedService(MOCK_CLIENT_APP_NAME, NAMESPACE_1, null, null, null, null, null, null);
|
||||
api.deleteNamespacedService(MOCK_CLIENT_APP_NAME, NAMESPACE_2, null, null, null, null, null, null);
|
||||
|
||||
networkingApi.deleteNamespacedIngress("servicea-wiremock-ingress", NAMESPACE_1, null, null, null, null, null,
|
||||
null);
|
||||
networkingApi.deleteNamespacedIngress("servicea-wiremock-ingress", NAMESPACE_2, null, null, null, null, null,
|
||||
null);
|
||||
|
||||
}
|
||||
|
||||
private void testLoadBalancer() {
|
||||
|
||||
// Check to make sure the controller deployment is ready
|
||||
k8SUtils.waitForDeployment(SPRING_CLOUD_K8S_DISCOVERY_CLIENT_DEPLOYMENT_NAME, NAMESPACE);
|
||||
WebClient.Builder builder = builder();
|
||||
WebClient serviceClient = builder.baseUrl("http://localhost:80/discoveryclient-it/services").build();
|
||||
|
||||
String[] result = serviceClient.method(HttpMethod.GET).retrieve().bodyToMono(String[].class)
|
||||
.retryWhen(retrySpec()).block();
|
||||
LOG.info("Services: " + Arrays.toString(result));
|
||||
assertThat(result).containsAnyOf("servicea-wiremock");
|
||||
|
||||
// ServiceInstance
|
||||
WebClient serviceInstanceClient = builder
|
||||
.baseUrl("http://localhost:80/discoveryclient-it/service/servicea-wiremock").build();
|
||||
List<KubernetesServiceInstance> serviceInstances = serviceInstanceClient.method(HttpMethod.GET).retrieve()
|
||||
.bodyToMono(new ParameterizedTypeReference<List<KubernetesServiceInstance>>() {
|
||||
}).retryWhen(retrySpec()).block();
|
||||
|
||||
assertThat(serviceInstances.size()).isEqualTo(1);
|
||||
assertThat(serviceInstances.get(0).getNamespace()).isEqualTo(NAMESPACE_1);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
void testHealth() {
|
||||
WebClient.Builder builder = builder();
|
||||
WebClient serviceClient = builder.baseUrl("http://localhost:80/discoveryclient-it/actuator/health").build();
|
||||
|
||||
ResolvableType resolvableType = ResolvableType.forClassWithGenerics(Map.class, String.class, Object.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> health = (Map<String, Object>) serviceClient.method(HttpMethod.GET).retrieve()
|
||||
.bodyToMono(ParameterizedTypeReference.forType(resolvableType.getType())).retryWhen(retrySpec())
|
||||
.block();
|
||||
|
||||
Map<String, Object> components = (Map<String, Object>) health.get("components");
|
||||
|
||||
Map<String, Object> discoveryComposite = (Map<String, Object>) components.get("discoveryComposite");
|
||||
assertThat(discoveryComposite.get("status")).isEqualTo("UP");
|
||||
}
|
||||
|
||||
private void deployDiscoveryIt() throws Exception {
|
||||
appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryItDeployment(), null, null, null);
|
||||
api.createNamespacedService(NAMESPACE, getDiscoveryService(), null, null, null);
|
||||
|
||||
V1Ingress ingress = getDiscoveryItIngress();
|
||||
networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null);
|
||||
k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE);
|
||||
}
|
||||
|
||||
private static V1Deployment getDiscoveryItDeployment() throws Exception {
|
||||
V1Deployment deployment = (V1Deployment) k8SUtils
|
||||
.readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-deployment.yaml");
|
||||
|
||||
// add namespaces filter property for namespace1
|
||||
var env = new V1EnvVarBuilder().withName("JAVA_OPTS")
|
||||
.withValue("-Dspring.cloud.kubernetes.discovery.namespaces[0]=" + NAMESPACE_1).build();
|
||||
var container = deployment.getSpec().getTemplate().getSpec().getContainers().get(0);
|
||||
container.setEnv(List.of(env));
|
||||
|
||||
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
|
||||
+ getPomVersion();
|
||||
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
|
||||
return deployment;
|
||||
}
|
||||
|
||||
private static void deployDiscoveryServer() throws Exception {
|
||||
|
||||
V1ClusterRoleBinding clusterRoleBinding = getClusterRoleBinding();
|
||||
authApi.createClusterRoleBinding(clusterRoleBinding, null, null, null);
|
||||
|
||||
appsApi.createNamespacedDeployment(NAMESPACE, getDiscoveryServerDeployment(), null, null, null);
|
||||
api.createNamespacedService(NAMESPACE, getDiscoveryServerService(), null, null, null);
|
||||
|
||||
V1Ingress ingress = getDiscoveryServerIngress();
|
||||
networkingApi.createNamespacedIngress(NAMESPACE, ingress, null, null, null);
|
||||
k8SUtils.waitForIngress(ingress.getMetadata().getName(), NAMESPACE);
|
||||
}
|
||||
|
||||
private static void deploySampleAppInNamespace(final String namespace) throws Exception {
|
||||
|
||||
V1Namespace namespace1 = new V1Namespace();
|
||||
V1ObjectMeta meta = new V1ObjectMeta();
|
||||
meta.setName(namespace);
|
||||
namespace1.setMetadata(meta);
|
||||
|
||||
api.createNamespace(namespace1, null, null, null);
|
||||
|
||||
V1Deployment deployment = getMockServiceDeployment();
|
||||
deployment.getMetadata().setNamespace(namespace);
|
||||
|
||||
appsApi.createNamespacedDeployment(namespace, deployment, null, null, null);
|
||||
V1Service service = getMockServiceService();
|
||||
service.getMetadata().setNamespace(namespace);
|
||||
api.createNamespacedService(namespace, service, null, null, null);
|
||||
V1Ingress ingress = getMockIngress();
|
||||
ingress.getMetadata().setNamespace(namespace);
|
||||
|
||||
ingress.getSpec().getRules().get(0).getHttp().getPaths().get(0).setPath("/wiremock-" + namespace);
|
||||
networkingApi.createNamespacedIngress(namespace, ingress, null, null, null);
|
||||
k8SUtils.waitForIngress(ingress.getMetadata().getName(), namespace);
|
||||
}
|
||||
|
||||
private static V1Deployment getDiscoveryServerDeployment() throws Exception {
|
||||
V1Deployment deployment = (V1Deployment) k8SUtils
|
||||
.readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-deployment.yaml");
|
||||
String image = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage() + ":"
|
||||
+ getPomVersion();
|
||||
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(image);
|
||||
// setup all-namespaces property
|
||||
V1EnvVar env = new V1EnvVarBuilder().withName("JAVA_OPTS")
|
||||
.withValue("-Dspring.cloud.kubernetes.discovery.all-namespaces=true").build();
|
||||
V1Container container = deployment.getSpec().getTemplate().getSpec().getContainers().get(0);
|
||||
container.setEnv(List.of(env));
|
||||
|
||||
return deployment;
|
||||
}
|
||||
|
||||
private static V1Ingress getDiscoveryServerIngress() throws Exception {
|
||||
return (V1Ingress) K8SUtils
|
||||
.readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-ingress.yaml");
|
||||
}
|
||||
|
||||
private static V1Service getDiscoveryServerService() throws Exception {
|
||||
return (V1Service) K8SUtils
|
||||
.readYamlFromClasspath("server/spring-cloud-kubernetes-discoveryserver-service.yaml");
|
||||
}
|
||||
|
||||
private static V1Ingress getDiscoveryItIngress() throws Exception {
|
||||
return (V1Ingress) K8SUtils
|
||||
.readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-ingress.yaml");
|
||||
}
|
||||
|
||||
private static V1Service getDiscoveryService() throws Exception {
|
||||
return (V1Service) K8SUtils
|
||||
.readYamlFromClasspath("client/spring-cloud-kubernetes-discoveryclient-it-service.yaml");
|
||||
}
|
||||
|
||||
private static V1ClusterRoleBinding getClusterRoleBinding() throws Exception {
|
||||
return (V1ClusterRoleBinding) K8SUtils
|
||||
.readYamlFromClasspath("namespace-filter/cluster-admin-serviceaccount-role.yaml");
|
||||
}
|
||||
|
||||
private static V1Deployment getMockServiceDeployment() throws Exception {
|
||||
return (V1Deployment) k8SUtils.readYamlFromClasspath("wiremock/discovery-wiremock-deployment.yaml");
|
||||
}
|
||||
|
||||
private static V1Service getMockServiceService() throws Exception {
|
||||
|
||||
return (V1Service) K8SUtils.readYamlFromClasspath("wiremock/discovery-wiremock-service.yaml");
|
||||
}
|
||||
|
||||
private static V1Ingress getMockIngress() throws Exception {
|
||||
return (V1Ingress) K8SUtils.readYamlFromClasspath("wiremock/discovery-wiremock-ingress.yaml");
|
||||
}
|
||||
|
||||
private WebClient.Builder builder() {
|
||||
return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
|
||||
}
|
||||
|
||||
private RetryBackoffSpec retrySpec() {
|
||||
return Retry.fixedDelay(15, Duration.ofSeconds(1)).filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: admin-default
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: spring-cloud-kubernetes-serviceaccount
|
||||
namespace: default
|
||||
@@ -0,0 +1,27 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: servicea-wiremock-deployment
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: servicea-wiremock
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: servicea-wiremock
|
||||
spec:
|
||||
containers:
|
||||
- name: servicea-wiremock
|
||||
image: wiremock/wiremock:2.32.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
port: 8080
|
||||
path: /__admin/mappings
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
port: 8080
|
||||
path: /__admin/mappings
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: servicea-wiremock-ingress
|
||||
spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: /wiremock
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: servicea-wiremock
|
||||
port:
|
||||
number: 8080
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app: servicea-wiremock
|
||||
name: servicea-wiremock
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: servicea-wiremock
|
||||
type: ClusterIP
|
||||
@@ -18,8 +18,11 @@ package org.springframework.cloud.kubernetes.fabric8.configmap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Endpoints;
|
||||
|
||||
import org.springframework.cloud.kubernetes.fabric8.discovery.KubernetesDiscoveryClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
@@ -39,4 +42,9 @@ public class Fabric8DiscoveryController {
|
||||
return discoveryClient.getServices();
|
||||
}
|
||||
|
||||
@GetMapping("/endpoints/{serviceId}")
|
||||
public List<Endpoints> getEndPointsList(@PathVariable("serviceId") String serviceId) {
|
||||
return discoveryClient.getEndPointsList(serviceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright 2013-2021 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.fabric8.configmap;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Endpoints;
|
||||
import io.fabric8.kubernetes.api.model.EnvVar;
|
||||
import io.fabric8.kubernetes.api.model.Namespace;
|
||||
import io.fabric8.kubernetes.api.model.ObjectMeta;
|
||||
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.Config;
|
||||
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.k3s.K3sContainer;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
import reactor.util.retry.Retry;
|
||||
import reactor.util.retry.RetryBackoffSpec;
|
||||
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.Commons;
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.Fabric8Utils;
|
||||
import org.springframework.cloud.kubernetes.integration.tests.commons.K8SUtils;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* @author mbialkowski1
|
||||
*/
|
||||
class Fabric8DiscoveryNamespaceFilterIT {
|
||||
|
||||
private static final String NAMESPACE = "default";
|
||||
|
||||
private static final String NAMESPACE_1 = "namespace1";
|
||||
|
||||
private static final String NAMESPACE_2 = "namespace2";
|
||||
|
||||
private static final String IMAGE_NAME = "spring-cloud-kubernetes-fabric8-client-discovery";
|
||||
|
||||
private static KubernetesClient client;
|
||||
|
||||
private static String deploymentName;
|
||||
|
||||
private static String serviceName;
|
||||
|
||||
private static String ingressName;
|
||||
|
||||
private static String mockServiceName;
|
||||
|
||||
private static String mockDeploymentName;
|
||||
|
||||
private static String mockDeploymentImage;
|
||||
|
||||
private static final K3sContainer K3S = Commons.container();
|
||||
|
||||
@BeforeAll
|
||||
static void beforeAll() throws Exception {
|
||||
K3S.start();
|
||||
Commons.validateImage(IMAGE_NAME, K3S);
|
||||
Commons.loadSpringCloudKubernetesImage(IMAGE_NAME, K3S);
|
||||
|
||||
Config config = Config.fromKubeconfig(K3S.getKubeConfigYaml());
|
||||
client = new DefaultKubernetesClient(config);
|
||||
Fabric8Utils.setUp(client, NAMESPACE);
|
||||
|
||||
deployManifests();
|
||||
deployMockManifests();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void after() throws Exception {
|
||||
deleteManifests();
|
||||
Commons.cleanUp(IMAGE_NAME, K3S);
|
||||
Commons.cleanUpDownloadedImage(mockDeploymentImage);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
WebClient clientServices = builder().baseUrl("localhost/services").build();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> services = (List<String>) clientServices.method(HttpMethod.GET).retrieve().bodyToMono(List.class)
|
||||
.retryWhen(retrySpec()).block();
|
||||
|
||||
Assertions.assertEquals(services.size(), 1);
|
||||
Assertions.assertTrue(services.contains("servicea-wiremock"));
|
||||
|
||||
WebClient clientEndpoints = builder().baseUrl("localhost/endpoints/servicea-wiremock").build();
|
||||
|
||||
List<Endpoints> endpoints = clientEndpoints.method(HttpMethod.GET).retrieve()
|
||||
.bodyToMono(new ParameterizedTypeReference<List<Endpoints>>() {
|
||||
}).retryWhen(retrySpec()).block();
|
||||
|
||||
Assertions.assertEquals(endpoints.size(), 1);
|
||||
Assertions.assertEquals(endpoints.get(0).getMetadata().getNamespace(), NAMESPACE_1);
|
||||
|
||||
}
|
||||
|
||||
private static void deleteManifests() {
|
||||
|
||||
try {
|
||||
|
||||
client.apps().deployments().inNamespace(NAMESPACE).withName(deploymentName).delete();
|
||||
client.services().inNamespace(NAMESPACE).withName(serviceName).delete();
|
||||
client.network().v1().ingresses().inNamespace(NAMESPACE).withName(ingressName).delete();
|
||||
|
||||
client.services().inNamespace(NAMESPACE_1).withName(mockServiceName).delete();
|
||||
client.apps().deployments().inNamespace(NAMESPACE_1).withName(mockDeploymentName).delete();
|
||||
|
||||
client.services().inNamespace(NAMESPACE_2).withName(mockServiceName).delete();
|
||||
client.apps().deployments().inNamespace(NAMESPACE_2).withName(mockDeploymentName).delete();
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void deployManifests() {
|
||||
|
||||
try {
|
||||
|
||||
Deployment deployment = client.apps().deployments().load(getDeployment()).get();
|
||||
|
||||
String version = K8SUtils.getPomVersion();
|
||||
String currentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
|
||||
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(currentImage + ":" + version);
|
||||
List<EnvVar> env = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getEnv();
|
||||
env.add(new EnvVar("JAVA_OPTS", "-Dspring.cloud.kubernetes.discovery.namespaces[0]=" + NAMESPACE_1, null));
|
||||
|
||||
deployment.getSpec().getTemplate().getSpec().getContainers().get(0).setEnv(env);
|
||||
|
||||
client.apps().deployments().inNamespace(NAMESPACE).create(deployment);
|
||||
deploymentName = deployment.getMetadata().getName();
|
||||
|
||||
Service service = client.services().load(getService()).get();
|
||||
serviceName = service.getMetadata().getName();
|
||||
client.services().inNamespace(NAMESPACE).create(service);
|
||||
|
||||
Ingress ingress = client.network().v1().ingresses().load(getIngress()).get();
|
||||
ingressName = ingress.getMetadata().getName();
|
||||
client.network().v1().ingresses().inNamespace(NAMESPACE).create(ingress);
|
||||
|
||||
client.rbac().clusterRoleBindings().create(client.rbac().clusterRoleBindings().load(getAdminRole()).get());
|
||||
|
||||
Fabric8Utils.waitForDeployment(client, "spring-cloud-kubernetes-fabric8-client-discovery-deployment",
|
||||
NAMESPACE, 2, 600);
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void deployMockManifests() {
|
||||
|
||||
try {
|
||||
deployInMockInNamespace(NAMESPACE_1);
|
||||
deployInMockInNamespace(NAMESPACE_2);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void deployInMockInNamespace(String namespace) throws Exception {
|
||||
|
||||
Namespace namespaceDef = new Namespace();
|
||||
ObjectMeta meta = new ObjectMeta();
|
||||
meta.setName(namespace);
|
||||
meta.setNamespace(namespace);
|
||||
namespaceDef.setMetadata(meta);
|
||||
client.namespaces().create(namespaceDef);
|
||||
|
||||
Deployment deployment = client.apps().deployments().load(getMockDeployment()).get();
|
||||
String[] image = K8SUtils.getImageFromDeployment(deployment).split(":");
|
||||
Commons.pullImage(image[0], image[1], K3S);
|
||||
Commons.loadImage(image[0], image[1], "wiremock", K3S);
|
||||
client.apps().deployments().inNamespace(namespace).create(deployment);
|
||||
mockDeploymentName = deployment.getMetadata().getName();
|
||||
mockDeploymentImage = deployment.getSpec().getTemplate().getSpec().getContainers().get(0).getImage();
|
||||
|
||||
Service service = client.services().load(getMockService()).get();
|
||||
mockServiceName = service.getMetadata().getName();
|
||||
client.services().inNamespace(namespace).create(service);
|
||||
|
||||
Fabric8Utils.waitForDeployment(client, "servicea-wiremock-deployment", namespace, 2, 600);
|
||||
}
|
||||
|
||||
private static InputStream getService() {
|
||||
return Fabric8Utils.inputStream("fabric8-discovery-service.yaml");
|
||||
}
|
||||
|
||||
private static InputStream getDeployment() {
|
||||
return Fabric8Utils.inputStream("fabric8-discovery-deployment.yaml");
|
||||
}
|
||||
|
||||
private static InputStream getAdminRole() {
|
||||
return Fabric8Utils.inputStream("namespace-filter/fabric8-cluster-admin-serviceaccount-role.yaml");
|
||||
}
|
||||
|
||||
private static InputStream getIngress() {
|
||||
return Fabric8Utils.inputStream("fabric8-discovery-ingress.yaml");
|
||||
}
|
||||
|
||||
private static InputStream getMockService() {
|
||||
return Fabric8Utils.inputStream("wiremock/fabric8-discovery-wiremock-service.yaml");
|
||||
}
|
||||
|
||||
private static InputStream getMockDeployment() {
|
||||
return Fabric8Utils.inputStream("wiremock/fabric8-discovery-wiremock-deployment.yaml");
|
||||
}
|
||||
|
||||
private WebClient.Builder builder() {
|
||||
return WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create()));
|
||||
}
|
||||
|
||||
private RetryBackoffSpec retrySpec() {
|
||||
return Retry.fixedDelay(15, Duration.ofSeconds(2)).filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: admin-default
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: spring-cloud-kubernetes-serviceaccount
|
||||
namespace: default
|
||||
Reference in New Issue
Block a user