Initial commit
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-kubernetes-controllers</artifactId>
|
||||
<version>3.0.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-kubernetes-discoveryserver</artifactId>
|
||||
<version>3.0.4-SNAPSHOT</version>
|
||||
<description>Spring Cloud parent pom, managing plugins and dependencies for Spring
|
||||
Cloud projects</description>
|
||||
<url>https://cloud.spring.io/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-discoveryserver</url>
|
||||
<inceptionYear>2017</inceptionYear>
|
||||
<organization>
|
||||
<name>Pivotal Software, Inc.</name>
|
||||
<url>https://www.spring.io</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License, Version 2.0</name>
|
||||
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>dsyer</id>
|
||||
<name>Dave Syer</name>
|
||||
<email>dsyer at pivotal.io</email>
|
||||
<organization>Pivotal Software, Inc.</organization>
|
||||
<organizationUrl>https://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>lead</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>sgibb</id>
|
||||
<name>Spencer Gibb</name>
|
||||
<email>sgibb at pivotal.io</email>
|
||||
<organization>Pivotal Software, Inc.</organization>
|
||||
<organizationUrl>https://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>lead</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>mgrzejszczak</id>
|
||||
<name>Marcin Grzejszczak</name>
|
||||
<email>mgrzejszczak at pivotal.io</email>
|
||||
<organization>Pivotal Software, Inc.</organization>
|
||||
<organizationUrl>https://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>rbaxter</id>
|
||||
<name>Ryan Baxter</name>
|
||||
<email>rbaxter at pivotal.io</email>
|
||||
<organization>Pivotal Software, Inc.</organization>
|
||||
<organizationUrl>https://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>omaciaszeksharma</id>
|
||||
<name>Olga Maciaszek-Sharma</name>
|
||||
<email>omaciaszeksharma at pivotal.io</email>
|
||||
<organization>Pivotal Software, Inc.</organization>
|
||||
<organizationUrl>https://www.spring.io</organizationUrl>
|
||||
<roles>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-kubernetes.git/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-discoveryserver</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-kubernetes.git/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-discoveryserver</developerConnection>
|
||||
<url>https://github.com/spring-cloud/spring-cloud-kubernetes/spring-cloud-kubernetes-controllers/spring-cloud-kubernetes-discoveryserver</url>
|
||||
</scm>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
<version>3.0.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
<version>3.0.7</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-kubernetes-client</artifactId>
|
||||
<version>3.0.4-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,130 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-cloud-kubernetes-controllers</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<version>3.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-cloud-kubernetes-discoveryserver</artifactId>
|
||||
|
||||
<properties>
|
||||
<docker.registry.organization>springcloud</docker.registry.organization>
|
||||
<plexus-archiver.version>4.1.0</plexus-archiver.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-kubernetes-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock-jre8-standalone</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-kubernetes-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<image>
|
||||
<name>${env.IMAGE}</name>
|
||||
</image>
|
||||
<goal>build-image</goal>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build-image</id>
|
||||
<configuration>
|
||||
<skip>${skip.build.image}</skip>
|
||||
</configuration>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>build-image</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>repackage</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>dockerpush</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.spotify</groupId>
|
||||
<artifactId>dockerfile-maven-plugin</artifactId>
|
||||
<version>1.4.12</version>
|
||||
<configuration>
|
||||
<repository>${docker.registry.organization}/${artifactId}</repository>
|
||||
<tag>${project.version}</tag>
|
||||
<username>${env.DOCKER_HUB_USERNAME}</username>
|
||||
<password>${env.DOCKER_HUB_PASSWORD}</password>
|
||||
<build>
|
||||
<noCache>true</noCache>
|
||||
</build>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-archiver</artifactId>
|
||||
<version>${plexus-archiver.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>imagename</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>!env.IMAGE</name>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<env.IMAGE>springcloud/${project.artifactId}:${project.version}</env.IMAGE>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.springframewok.cloud.kubernetes.discoveryserver;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class DiscoveryServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(DiscoveryServerApplication.class).run(args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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.springframewok.cloud.kubernetes.discoveryserver;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.kubernetes.client.discovery.reactive.KubernetesInformerReactiveDiscoveryClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@RestController
|
||||
public class DiscoveryServerController {
|
||||
|
||||
private final KubernetesInformerReactiveDiscoveryClient reactiveDiscoveryClient;
|
||||
|
||||
public DiscoveryServerController(KubernetesInformerReactiveDiscoveryClient reactiveDiscoveryClient) {
|
||||
this.reactiveDiscoveryClient = reactiveDiscoveryClient;
|
||||
}
|
||||
|
||||
@GetMapping("/apps")
|
||||
public Flux<Service> apps() {
|
||||
return reactiveDiscoveryClient.getServices().flatMap(service -> reactiveDiscoveryClient.getInstances(service)
|
||||
.collectList().flatMap(serviceInstances -> Mono.just(new Service(service, serviceInstances))));
|
||||
}
|
||||
|
||||
@GetMapping("/apps/{name}")
|
||||
public Flux<ServiceInstance> appInstances(@PathVariable String name) {
|
||||
return reactiveDiscoveryClient.getInstances(name);
|
||||
}
|
||||
|
||||
@GetMapping("/app/{name}/{instanceId}")
|
||||
public Mono<ServiceInstance> appInstance(@PathVariable String name, @PathVariable String instanceId) {
|
||||
return reactiveDiscoveryClient.getInstances(name)
|
||||
.filter(serviceInstance -> serviceInstance.getInstanceId().equals(instanceId)).singleOrEmpty();
|
||||
}
|
||||
|
||||
private record Service(String name, List<ServiceInstance> serviceInstances) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
server:
|
||||
port: 8761
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* 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.springframewok.cloud.kubernetes.discoveryserver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.kubernetes.client.discovery.reactive.KubernetesInformerReactiveDiscoveryClient;
|
||||
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesServiceInstance;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
class DiscoveryServerControllerTests {
|
||||
|
||||
private static final KubernetesServiceInstance serviceAInstance1 = new KubernetesServiceInstance("serviceAInstance1",
|
||||
"serviceAInstance1", "2.2.2.2", 8080, new HashMap<>(), false, "namespace1", null);
|
||||
|
||||
private static final KubernetesServiceInstance serviceAInstance2 = new KubernetesServiceInstance("serviceAInstance2",
|
||||
"serviceAInstance2", "2.2.2.2", 8080, new HashMap<>(), false, "namespace1", null);
|
||||
|
||||
private static final KubernetesServiceInstance serviceAInstance3 = new KubernetesServiceInstance("serviceAInstance3",
|
||||
"serviceAInstance3", "2.2.2.2", 8080, new HashMap<>(), false, "namespace2", null);
|
||||
|
||||
private static final KubernetesServiceInstance serviceBInstance1 = new KubernetesServiceInstance("serviceBInstance1",
|
||||
"serviceBInstance1", "2.2.2.2", 8080, new HashMap<>(), false, "namespace1", null);
|
||||
|
||||
private static final KubernetesServiceInstance serviceCInstance1 = new KubernetesServiceInstance("serviceCInstance1",
|
||||
"serviceCInstance1", "2.2.2.2", 8080, new HashMap<>(), false, "namespace2", null);
|
||||
|
||||
private static DiscoveryServerController.Service serviceA = new DiscoveryServerController.Service();
|
||||
private static DiscoveryServerController.Service serviceB = new DiscoveryServerController.Service();
|
||||
private static DiscoveryServerController.Service serviceC = new DiscoveryServerController.Service();
|
||||
|
||||
private static KubernetesInformerReactiveDiscoveryClient discoveryClient;
|
||||
|
||||
@BeforeAll
|
||||
static void beforeAll() {
|
||||
Flux<String> services = Flux.just("serviceA", "serviceB", "serviceC");
|
||||
|
||||
List<ServiceInstance> serviceAInstanceList = new ArrayList<>();
|
||||
serviceAInstanceList.add(serviceAInstance1);
|
||||
serviceAInstanceList.add(serviceAInstance2);
|
||||
serviceAInstanceList.add(serviceAInstance3);
|
||||
|
||||
Flux<ServiceInstance> serviceAInstances = Flux.fromIterable(serviceAInstanceList);
|
||||
|
||||
List<ServiceInstance> serviceBInstanceList = Collections.singletonList(serviceBInstance1);
|
||||
Flux<ServiceInstance> serviceBInstances = Flux.fromIterable(serviceBInstanceList);
|
||||
|
||||
List<ServiceInstance> serviceCInstanceList = Collections.singletonList(serviceCInstance1);
|
||||
Flux<ServiceInstance> serviceCInstances = Flux.fromIterable(serviceCInstanceList);
|
||||
|
||||
discoveryClient = mock(KubernetesInformerReactiveDiscoveryClient.class);
|
||||
when(discoveryClient.getServices()).thenReturn(services);
|
||||
when(discoveryClient.getInstances(eq("serviceA"))).thenReturn(serviceAInstances);
|
||||
when(discoveryClient.getInstances(eq("serviceB"))).thenReturn(serviceBInstances);
|
||||
when(discoveryClient.getInstances(eq("serviceC"))).thenReturn(serviceCInstances);
|
||||
when(discoveryClient.getInstances(eq("serviceD"))).thenReturn(Flux.empty());
|
||||
|
||||
serviceA.setName("serviceA");
|
||||
serviceA.setServiceInstances(serviceAInstanceList);
|
||||
|
||||
serviceB.setName("serviceB");
|
||||
serviceB.setServiceInstances(serviceBInstanceList);
|
||||
|
||||
serviceC.setName("serviceC");
|
||||
serviceC.setServiceInstances(serviceCInstanceList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
void apps() {
|
||||
DiscoveryServerController controller = new DiscoveryServerController(discoveryClient);
|
||||
StepVerifier.create(controller.apps()).expectNext(serviceA, serviceB, serviceC).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void appInstances() {
|
||||
DiscoveryServerController controller = new DiscoveryServerController(discoveryClient);
|
||||
StepVerifier.create(controller.appInstances("serviceA")).expectNext(serviceAInstance1, serviceAInstance2, serviceAInstance3).verifyComplete();
|
||||
StepVerifier.create(controller.appInstances("serviceB")).expectNext(serviceBInstance1).verifyComplete();
|
||||
StepVerifier.create(controller.appInstances("serviceC")).expectNext(serviceCInstance1).verifyComplete();
|
||||
StepVerifier.create(controller.appInstances("serviceD")).expectNextCount(0).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void appInstance() {
|
||||
DiscoveryServerController controller = new DiscoveryServerController(discoveryClient);
|
||||
StepVerifier.create(controller.appInstance("serviceA", "serviceAInstance2")).expectNext(serviceAInstance2).verifyComplete();
|
||||
StepVerifier.create(controller.appInstance("serviceB", "doesnotexist")).expectNextCount(0).verifyComplete();
|
||||
}
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
* 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.springframewok.cloud.kubernetes.discoveryserver;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||
import com.github.tomakehurst.wiremock.client.WireMock;
|
||||
import io.kubernetes.client.openapi.ApiClient;
|
||||
import io.kubernetes.client.openapi.JSON;
|
||||
import io.kubernetes.client.openapi.models.V1EndpointAddress;
|
||||
import io.kubernetes.client.openapi.models.V1EndpointPort;
|
||||
import io.kubernetes.client.openapi.models.V1EndpointSubset;
|
||||
import io.kubernetes.client.openapi.models.V1Endpoints;
|
||||
import io.kubernetes.client.openapi.models.V1EndpointsListBuilder;
|
||||
import io.kubernetes.client.openapi.models.V1ListMetaBuilder;
|
||||
import io.kubernetes.client.openapi.models.V1ObjectMeta;
|
||||
import io.kubernetes.client.openapi.models.V1ObjectReferenceBuilder;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceListBuilder;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceSpec;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceStatus;
|
||||
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.cloud.kubernetes.commons.KubernetesNamespaceProvider;
|
||||
import org.springframework.cloud.kubernetes.commons.discovery.KubernetesServiceInstance;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.get;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
|
||||
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = DiscoveryServerIntegrationTests.TestConfig.class,
|
||||
properties = {"debug=true"})
|
||||
public class DiscoveryServerIntegrationTests {
|
||||
|
||||
private static final V1Service testService1 = new V1Service()
|
||||
.metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1"))
|
||||
.spec(new V1ServiceSpec().loadBalancerIP("1.1.1.1")).status(new V1ServiceStatus());
|
||||
private static final V1Endpoints testEndpoints1 = new V1Endpoints()
|
||||
.metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace1"))
|
||||
.addSubsetsItem(new V1EndpointSubset().addPortsItem(new V1EndpointPort().port(8080).name("http"))
|
||||
.addAddressesItem(new V1EndpointAddress().ip("2.2.2.2").targetRef(new V1ObjectReferenceBuilder().withUid("uid1").build())));
|
||||
|
||||
private static final V1Service testService2 = new V1Service()
|
||||
.metadata(new V1ObjectMeta().name("test-svc-1").namespace("namespace2"))
|
||||
.spec(new V1ServiceSpec().loadBalancerIP("1.1.1.1")).status(new V1ServiceStatus());
|
||||
|
||||
private static final V1Service testService3 = new V1Service()
|
||||
.metadata(new V1ObjectMeta().name("test-svc-3").namespace("namespace1").putLabelsItem("spring", "true")
|
||||
.putLabelsItem("k8s", "true"))
|
||||
.spec(new V1ServiceSpec().loadBalancerIP("1.1.1.1")).status(new V1ServiceStatus());
|
||||
private static final V1Endpoints testEndpoints3 = new V1Endpoints()
|
||||
.metadata(new V1ObjectMeta().name("test-svc-3").namespace("namespace1"))
|
||||
.addSubsetsItem(new V1EndpointSubset().addPortsItem(new V1EndpointPort().port(8080).name("http"))
|
||||
.addAddressesItem(new V1EndpointAddress().ip("2.2.2.2").targetRef(new V1ObjectReferenceBuilder().withUid("uid2").build())));
|
||||
|
||||
|
||||
private static WireMockServer wireMockServer;
|
||||
|
||||
@Autowired
|
||||
WebTestClient webTestClient;
|
||||
|
||||
@Test
|
||||
void apps(){
|
||||
Map<String, String> kubernetesServiceInstance1Metadata = new HashMap<>();
|
||||
kubernetesServiceInstance1Metadata.put(testEndpoints1.getSubsets().get(0).getPorts().get(0).getName(), testEndpoints1.getSubsets().get(0).getPorts().get(0).getPort().toString());
|
||||
|
||||
Map<String, String> kubernetesServiceInstance2Metadata = new HashMap<>();
|
||||
kubernetesServiceInstance2Metadata.put(testEndpoints3.getSubsets().get(0).getPorts().get(0).getName(), testEndpoints3.getSubsets().get(0).getPorts().get(0).getPort().toString());
|
||||
kubernetesServiceInstance2Metadata.putAll(testService3.getMetadata().getLabels());
|
||||
|
||||
KubernetesServiceInstance kubernetesServiceInstance1 = new KubernetesServiceInstance(testEndpoints1.getSubsets().get(0).getAddresses().get(0).getTargetRef().getUid(), testService1.getMetadata().getName(), testEndpoints1.getSubsets().get(0).getAddresses().get(0).getIp(), testEndpoints1.getSubsets().get(0).getPorts().get(0).getPort(), kubernetesServiceInstance1Metadata, false, testService1.getMetadata().getNamespace(), null);
|
||||
KubernetesServiceInstance kubernetesServiceInstance3 = new KubernetesServiceInstance(testEndpoints3.getSubsets().get(0).getAddresses().get(0).getTargetRef().getUid(), testService3.getMetadata().getName(), testEndpoints3.getSubsets().get(0).getAddresses().get(0).getIp(), testEndpoints3.getSubsets().get(0).getPorts().get(0).getPort(), kubernetesServiceInstance2Metadata, false, testService3.getMetadata().getNamespace(), null);
|
||||
|
||||
webTestClient.get().uri("/apps").exchange().expectBodyList(KubernetesService.class).hasSize(2).contains(new KubernetesService(testService1.getMetadata().getName(),
|
||||
Collections.singletonList(kubernetesServiceInstance1)), new KubernetesService(testService3.getMetadata().getName(), Collections.singletonList(kubernetesServiceInstance3)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void appsName() {
|
||||
Map<String, String> kubernetesServiceInstance2Metadata = new HashMap<>();
|
||||
kubernetesServiceInstance2Metadata.put(testEndpoints3.getSubsets().get(0).getPorts().get(0).getName(), testEndpoints3.getSubsets().get(0).getPorts().get(0).getPort().toString());
|
||||
kubernetesServiceInstance2Metadata.putAll(testService3.getMetadata().getLabels());
|
||||
KubernetesServiceInstance kubernetesServiceInstance3 = new KubernetesServiceInstance(testEndpoints3.getSubsets().get(0).getAddresses().get(0).getTargetRef().getUid(), testService3.getMetadata().getName(), testEndpoints3.getSubsets().get(0).getAddresses().get(0).getIp(), testEndpoints3.getSubsets().get(0).getPorts().get(0).getPort(), kubernetesServiceInstance2Metadata, false, testService3.getMetadata().getNamespace(), null);
|
||||
webTestClient.get().uri("/apps/test-svc-3").exchange().expectBodyList(KubernetesServiceInstance.class).hasSize(1).contains(kubernetesServiceInstance3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void instance() {
|
||||
Map<String, String> kubernetesServiceInstance2Metadata = new HashMap<>();
|
||||
kubernetesServiceInstance2Metadata.put(testEndpoints3.getSubsets().get(0).getPorts().get(0).getName(), testEndpoints3.getSubsets().get(0).getPorts().get(0).getPort().toString());
|
||||
kubernetesServiceInstance2Metadata.putAll(testService3.getMetadata().getLabels());
|
||||
KubernetesServiceInstance kubernetesServiceInstance3 = new KubernetesServiceInstance(testEndpoints3.getSubsets().get(0).getAddresses().get(0).getTargetRef().getUid(), testService3.getMetadata().getName(), testEndpoints3.getSubsets().get(0).getAddresses().get(0).getIp(), testEndpoints3.getSubsets().get(0).getPorts().get(0).getPort(), kubernetesServiceInstance2Metadata, false, testService3.getMetadata().getNamespace(), null);
|
||||
webTestClient.get().uri("/app/test-svc-3/uid2").exchange().expectBody(KubernetesServiceInstance.class).isEqualTo(kubernetesServiceInstance3);
|
||||
}
|
||||
|
||||
@SpringBootApplication
|
||||
protected static class TestConfig {
|
||||
|
||||
@Bean
|
||||
public KubernetesNamespaceProvider kubernetesNamespaceProvider() {
|
||||
KubernetesNamespaceProvider provider = mock(KubernetesNamespaceProvider.class);
|
||||
when(provider.getNamespace()).thenReturn("namespace1");
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApiClient apiClient() {
|
||||
wireMockServer = new WireMockServer(options().dynamicPort());
|
||||
wireMockServer.start();
|
||||
WireMock.configureFor(wireMockServer.port());
|
||||
stubFor(get("/api/v1/namespaces/namespace1/endpoints?resourceVersion=0&watch=false")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1EndpointsListBuilder()
|
||||
.withMetadata(new V1ListMetaBuilder().withNewResourceVersion("0").build()).addToItems(testEndpoints1, testEndpoints3).build()))));
|
||||
stubFor(get("/api/v1/namespaces/namespace1/services?resourceVersion=0&watch=false")
|
||||
.willReturn(aResponse().withStatus(200).withBody(new JSON().serialize(new V1ServiceListBuilder()
|
||||
.withMetadata(new V1ListMetaBuilder().withNewResourceVersion("0").build()).addToItems(testService1, testService2, testService3).build()))));
|
||||
stubFor(get("/api/v1/namespaces/namespace1/endpoints?watch=true")
|
||||
.willReturn(aResponse().withStatus(200)));
|
||||
stubFor(get("/api/v1/namespaces/namespace1/services?watch=true")
|
||||
.willReturn(aResponse().withStatus(200)));
|
||||
ApiClient apiClient = new ClientBuilder().setBasePath(wireMockServer.baseUrl()).build();
|
||||
return apiClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class KubernetesService {
|
||||
|
||||
private String name;
|
||||
|
||||
private List<KubernetesServiceInstance> serviceInstances;
|
||||
|
||||
public KubernetesService() { }
|
||||
|
||||
public KubernetesService(String name, List<KubernetesServiceInstance> serviceInstances) {
|
||||
this.name = name;
|
||||
this.serviceInstances = serviceInstances;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<KubernetesServiceInstance> getServiceInstances() {
|
||||
return serviceInstances;
|
||||
}
|
||||
|
||||
public void setServiceInstances(List<KubernetesServiceInstance> serviceInstances) {
|
||||
this.serviceInstances = serviceInstances;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
KubernetesService service = (KubernetesService) o;
|
||||
return Objects.equals(getName(), service.getName()) && Objects.equals(getServiceInstances(), service.getServiceInstances());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getName(), getServiceInstances());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KubernetesService{" +
|
||||
"name='" + name + '\'' +
|
||||
", serviceInstances=" + serviceInstances +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user