Remove redundant groovy tests and replace useful ones with java tests (#336)
Fixes: #310
This commit is contained in:
committed by
Ryan Baxter
parent
a72a4ad291
commit
c9a225ed1b
10
pom.xml
10
pom.xml
@@ -73,7 +73,6 @@
|
||||
<maven-failsafe-plugin.version>2.18.1</maven-failsafe-plugin.version>
|
||||
<maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version>
|
||||
<fabric8.maven.plugin.version>3.5.37</fabric8.maven.plugin.version>
|
||||
<gmavenplus-plugin.version>1.6</gmavenplus-plugin.version>
|
||||
<groovy.version>2.4.12</groovy.version>
|
||||
<restassured.version>3.0.2</restassured.version>
|
||||
<spock-spring.version>1.1-groovy-2.4</spock-spring.version>
|
||||
@@ -152,15 +151,6 @@
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmavenplus</groupId>
|
||||
<artifactId>gmavenplus-plugin</artifactId>
|
||||
<version>${gmavenplus-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
||||
@@ -185,19 +185,4 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmavenplus</groupId>
|
||||
<artifactId>gmavenplus-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compileTests</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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
|
||||
*
|
||||
* http://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.config
|
||||
|
||||
import groovy.util.logging.Slf4j
|
||||
import io.fabric8.kubernetes.api.model.ConfigMapBuilder
|
||||
import io.fabric8.kubernetes.api.model.SecretBuilder
|
||||
import io.fabric8.kubernetes.client.Config
|
||||
import io.fabric8.kubernetes.client.KubernetesClient
|
||||
import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer
|
||||
import spock.lang.Specification
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.core.env.Environment
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
|
||||
@Slf4j
|
||||
@ContextConfiguration(classes = [TestApplication.class])
|
||||
@SpringBootTest(properties = [
|
||||
"spring.application.name=testapp",
|
||||
"spring.cloud.kubernetes.client.namespace=testns",
|
||||
"spring.cloud.kubernetes.client.trustCerts=true",
|
||||
"spring.cloud.kubernetes.config.namespace=testns",
|
||||
"spring.cloud.kubernetes.secrets.enableApi=true"
|
||||
])
|
||||
@EnableConfigurationProperties
|
||||
class CoreTest extends Specification {
|
||||
|
||||
private static KubernetesMockServer mockServer = new KubernetesMockServer()
|
||||
private static KubernetesClient mockClient
|
||||
|
||||
@Autowired
|
||||
Environment environment
|
||||
|
||||
@Autowired(required = false)
|
||||
Config config
|
||||
|
||||
@Autowired(required = false)
|
||||
KubernetesClient client
|
||||
|
||||
def setupSpec() {
|
||||
mockServer.init()
|
||||
mockClient = mockServer.createClient()
|
||||
|
||||
mockServer.expect().get()
|
||||
.withPath("/api/v1/namespaces/testns/configmaps/testapp")
|
||||
.andReturn(
|
||||
200,
|
||||
new ConfigMapBuilder()
|
||||
.withData([
|
||||
'spring.kubernetes.test.value': 'value1'])
|
||||
.build())
|
||||
.always()
|
||||
mockServer.expect().get()
|
||||
.withPath("/api/v1/namespaces/testns/secrets/testapp")
|
||||
.andReturn(
|
||||
200,
|
||||
new SecretBuilder()
|
||||
.withData([
|
||||
'amq.pwd': 'MWYyZDFlMmU2N2Rm',
|
||||
'amq.usr': 'YWRtaW4K'
|
||||
])
|
||||
.build())
|
||||
.always()
|
||||
|
||||
//Configure the kubernetes master url to point to the mock server
|
||||
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.
|
||||
getConfiguration().getMasterUrl())
|
||||
System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true")
|
||||
System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false")
|
||||
System.
|
||||
setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false")
|
||||
}
|
||||
|
||||
def cleanupSpec() {
|
||||
mockServer.destroy();
|
||||
}
|
||||
|
||||
def "Kubernetes client config bean should be present"() {
|
||||
expect:
|
||||
config != null
|
||||
}
|
||||
|
||||
def "Kubernetes client config bean should be configurable via system properties"() {
|
||||
expect:
|
||||
config.getMasterUrl().equals(mockClient.getConfiguration().getMasterUrl())
|
||||
config.getNamespace().equals("testns")
|
||||
config.trustCerts
|
||||
}
|
||||
|
||||
def "Kubernetes client bean should be present"() {
|
||||
expect:
|
||||
client != null
|
||||
}
|
||||
|
||||
def "Kubernetes client should be configured from system properties"() {
|
||||
expect:
|
||||
client.getConfiguration().getMasterUrl().
|
||||
equals(mockClient.getConfiguration().getMasterUrl())
|
||||
}
|
||||
|
||||
def "properties should be read from config map"() {
|
||||
expect:
|
||||
environment.getProperty("spring.kubernetes.test.value").equals("value1")
|
||||
}
|
||||
|
||||
def "properties should be read from secrets"() {
|
||||
expect:
|
||||
environment.getProperty("amq.pwd").equals("1f2d1e2e67df")
|
||||
environment.getProperty("amq.usr").equals('admin');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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
|
||||
*
|
||||
* http://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.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.ConfigMapBuilder;
|
||||
import io.fabric8.kubernetes.api.model.SecretBuilder;
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = TestApplication.class, properties = {
|
||||
"spring.application.name=testapp",
|
||||
"spring.cloud.kubernetes.client.namespace=testns",
|
||||
"spring.cloud.kubernetes.client.trustCerts=true",
|
||||
"spring.cloud.kubernetes.config.namespace=testns",
|
||||
"spring.cloud.kubernetes.secrets.enableApi=true" })
|
||||
public class CoreTest {
|
||||
|
||||
@ClassRule
|
||||
public static KubernetesServer mockServer = new KubernetesServer();
|
||||
|
||||
private static KubernetesClient mockClient;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Autowired(required = false)
|
||||
private Config config;
|
||||
|
||||
@Autowired(required = false)
|
||||
private KubernetesClient client;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBeforeClass() {
|
||||
mockClient = mockServer.getClient();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/testns/configmaps/testapp")
|
||||
.andReturn(200,
|
||||
new ConfigMapBuilder().withData(new HashMap<String, String>() {
|
||||
{
|
||||
put("spring.kubernetes.test.value", "value1");
|
||||
}
|
||||
}).build())
|
||||
.always();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/testns/secrets/testapp")
|
||||
.andReturn(200,
|
||||
new SecretBuilder().withData(new HashMap<String, String>() {
|
||||
{
|
||||
put("amq.user", "YWRtaW4K");
|
||||
put("amq.pwd", "MWYyZDFlMmU2N2Rm");
|
||||
}
|
||||
}).build())
|
||||
.always();
|
||||
|
||||
// Configure the kubernetes master url to point to the mock server
|
||||
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY,
|
||||
mockClient.getConfiguration().getMasterUrl());
|
||||
System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");
|
||||
System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY,
|
||||
"false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void kubernetesClientConfigBeanShouldBeConfigurableViaSystemProperties() {
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getMasterUrl())
|
||||
.isEqualTo(mockClient.getConfiguration().getMasterUrl());
|
||||
assertThat(config.getNamespace()).isEqualTo("testns");
|
||||
assertThat(config.isTrustCerts()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void kubernetesClientBeanShouldBeConfigurableViaSystemProperties() {
|
||||
assertThat(client).isNotNull();
|
||||
assertThat(client.getConfiguration().getMasterUrl())
|
||||
.isEqualTo(mockClient.getConfiguration().getMasterUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertiesShouldBeReadFromConfigMap() {
|
||||
assertThat(environment.getProperty("spring.kubernetes.test.value"))
|
||||
.isEqualTo("value1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertiesShouldBeReadFromSecret() {
|
||||
assertThat(environment.getProperty("amq.user")).isEqualTo("admin");
|
||||
assertThat(environment.getProperty("amq.pwd")).isEqualTo("1f2d1e2e67df");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,15 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.kubernetes.config
|
||||
package org.springframework.cloud.kubernetes.config;
|
||||
|
||||
import org.springframework.boot.SpringApplication
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
class TestApplication {
|
||||
public class TestApplication {
|
||||
|
||||
def main(String[] args) {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(TestApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
<artifactId>kubernetes-server-mock</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -122,19 +122,4 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmavenplus</groupId>
|
||||
<artifactId>gmavenplus-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compileTests</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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
|
||||
*
|
||||
* http://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.discovery
|
||||
|
||||
import io.fabric8.kubernetes.api.model.EndpointsBuilder
|
||||
import io.fabric8.kubernetes.api.model.ServiceBuilder
|
||||
import io.fabric8.kubernetes.api.model.ServiceListBuilder
|
||||
import io.fabric8.kubernetes.client.Config
|
||||
import io.fabric8.kubernetes.client.KubernetesClient
|
||||
import io.fabric8.kubernetes.server.mock.KubernetesMockServer
|
||||
import spock.lang.Specification
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat
|
||||
|
||||
class KubernetesDiscoveryClientTest extends Specification {
|
||||
|
||||
private static KubernetesMockServer mockServer = new KubernetesMockServer()
|
||||
private static KubernetesClient mockClient
|
||||
|
||||
|
||||
def setupSpec() {
|
||||
mockServer.init()
|
||||
mockClient = mockServer.createClient()
|
||||
|
||||
//Configure the kubernetes master url to point to the mock server
|
||||
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.
|
||||
getConfiguration().getMasterUrl())
|
||||
System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true")
|
||||
System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false")
|
||||
System.
|
||||
setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false")
|
||||
}
|
||||
|
||||
def cleanupSpec() {
|
||||
mockServer.destroy()
|
||||
}
|
||||
|
||||
def "getInstances should be able to handle endpoints single address"() {
|
||||
given:
|
||||
mockServer.expect().get().
|
||||
withPath("/api/v1/namespaces/test/endpoints/endpoint").
|
||||
andReturn(200, new EndpointsBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("endpoint")
|
||||
.endMetadata()
|
||||
.addNewSubset()
|
||||
.addNewAddress()
|
||||
.withIp("ip1")
|
||||
.endAddress()
|
||||
.addNewPort("http", 80, "TCP")
|
||||
.endSubset()
|
||||
.build()).once()
|
||||
|
||||
and:
|
||||
mockServer.expect().get().
|
||||
withPath("/api/v1/namespaces/test/services/endpoint").
|
||||
andReturn(200, new ServiceBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("endpoint")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("l", "v")
|
||||
}
|
||||
})
|
||||
.endMetadata()
|
||||
.build()).once()
|
||||
|
||||
final properties = new KubernetesDiscoveryProperties()
|
||||
DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(
|
||||
mockClient, properties, { client ->
|
||||
client.services()
|
||||
}, new DefaultIsServicePortSecureResolver(properties))
|
||||
|
||||
when:
|
||||
List<ServiceInstance> instances = discoveryClient.getInstances("endpoint")
|
||||
|
||||
then:
|
||||
instances != null
|
||||
instances.size() == 1
|
||||
instances.find({ s -> s.host == "ip1" && !s.secure })
|
||||
}
|
||||
|
||||
|
||||
def "getInstances should be able to handle endpoints multiple addresses"() {
|
||||
given:
|
||||
mockServer.expect().get().
|
||||
withPath("/api/v1/namespaces/test/endpoints/endpoint").
|
||||
andReturn(200, new EndpointsBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("endpoint")
|
||||
.endMetadata()
|
||||
.addNewSubset()
|
||||
.addNewAddress()
|
||||
.withIp("ip1")
|
||||
.endAddress()
|
||||
.addNewAddress()
|
||||
.withIp("ip2")
|
||||
.endAddress()
|
||||
.addNewPort("https", 443, "TCP")
|
||||
.endSubset()
|
||||
.build()).once()
|
||||
|
||||
and:
|
||||
mockServer.expect().get().
|
||||
withPath("/api/v1/namespaces/test/services/endpoint").
|
||||
andReturn(200, new ServiceBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("endpoint")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("l", "v")
|
||||
}
|
||||
})
|
||||
.endMetadata()
|
||||
.build()).once()
|
||||
|
||||
final properties = new KubernetesDiscoveryProperties()
|
||||
DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(
|
||||
mockClient, properties, { client ->
|
||||
client.services()
|
||||
}, new DefaultIsServicePortSecureResolver(properties))
|
||||
|
||||
when:
|
||||
List<ServiceInstance> instances = discoveryClient.getInstances("endpoint")
|
||||
|
||||
then:
|
||||
instances != null
|
||||
instances.size() == 2
|
||||
instances.find({ s -> s.host == "ip1" && s.secure })
|
||||
instances.find({ s -> s.host == "ip2" && s.secure })
|
||||
|
||||
}
|
||||
|
||||
def "getServices should return all services when no labels are applied to the client"() {
|
||||
given:
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services").
|
||||
andReturn(200, new ServiceListBuilder()
|
||||
.addNewItem()
|
||||
.withNewMetadata()
|
||||
.withName("s1")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value")
|
||||
}
|
||||
})
|
||||
.endMetadata()
|
||||
.endItem()
|
||||
.addNewItem()
|
||||
.withNewMetadata()
|
||||
.withName("s2")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value")
|
||||
put("label2", "value2")
|
||||
}
|
||||
})
|
||||
.endMetadata()
|
||||
.endItem()
|
||||
.addNewItem()
|
||||
.withNewMetadata()
|
||||
.withName("s3")
|
||||
.endMetadata()
|
||||
.endItem()
|
||||
.build()).once()
|
||||
|
||||
and:
|
||||
DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(
|
||||
mockClient, new KubernetesDiscoveryProperties(), { client ->
|
||||
client.services()
|
||||
})
|
||||
|
||||
when:
|
||||
List<String> instances = discoveryClient.getServices()
|
||||
|
||||
then:
|
||||
assertThat(instances).containsOnly("s1", "s2", "s3")
|
||||
}
|
||||
|
||||
def "getServices should return only matching services when labels are applied to the client"() {
|
||||
given:
|
||||
// this is the URL that is created by the KubernetesClient when a a label named 'label'
|
||||
// with a value of 'value' is specified
|
||||
mockServer.expect().get().
|
||||
withPath("/api/v1/namespaces/test/services?labelSelector=label%3Dvalue").
|
||||
andReturn(200, new ServiceListBuilder()
|
||||
.addNewItem()
|
||||
.withNewMetadata()
|
||||
.withName("s1")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value")
|
||||
}
|
||||
})
|
||||
.endMetadata()
|
||||
.endItem()
|
||||
.addNewItem()
|
||||
.withNewMetadata()
|
||||
.withName("s2")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value")
|
||||
put("label2", "value2")
|
||||
}
|
||||
})
|
||||
.endMetadata()
|
||||
.endItem()
|
||||
.build()).once()
|
||||
|
||||
and:
|
||||
DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(
|
||||
mockClient,
|
||||
new KubernetesDiscoveryProperties(), { client ->
|
||||
client.services().withLabels(["label": "value"])
|
||||
})
|
||||
|
||||
when:
|
||||
List<String> instances = discoveryClient.getServices()
|
||||
|
||||
then:
|
||||
assertThat(instances).containsOnly("s1", "s2")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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
|
||||
*
|
||||
* http://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.discovery;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.EndpointsBuilder;
|
||||
import io.fabric8.kubernetes.api.model.ServiceBuilder;
|
||||
import io.fabric8.kubernetes.api.model.ServiceListBuilder;
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.client.ServiceInstance;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class KubernetesDiscoveryClientTest {
|
||||
|
||||
@ClassRule
|
||||
public static KubernetesServer mockServer = new KubernetesServer();
|
||||
|
||||
private static KubernetesClient mockClient;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mockClient = mockServer.getClient();
|
||||
|
||||
// Configure the kubernetes master url to point to the mock server
|
||||
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY,
|
||||
mockClient.getConfiguration().getMasterUrl());
|
||||
System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");
|
||||
System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY,
|
||||
"false");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstancesShouldBeAbleToHandleEndpointsSingleAddress() {
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint")
|
||||
.andReturn(200,
|
||||
new EndpointsBuilder().withNewMetadata().withName("endpoint")
|
||||
.endMetadata().addNewSubset().addNewAddress()
|
||||
.withIp("ip1").endAddress().addNewPort("http", 80, "TCP")
|
||||
.endSubset().build())
|
||||
.once();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint")
|
||||
.andReturn(200, new ServiceBuilder().withNewMetadata()
|
||||
.withName("endpoint").withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("l", "v");
|
||||
}
|
||||
}).endMetadata().build())
|
||||
.once();
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
|
||||
properties, KubernetesClient::services,
|
||||
new DefaultIsServicePortSecureResolver(properties));
|
||||
|
||||
final List<ServiceInstance> instances = discoveryClient.getInstances("endpoint");
|
||||
|
||||
assertThat(instances).hasSize(1)
|
||||
.filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInstancesShouldBeAbleToHandleEndpointsMultipleAddresses() {
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint")
|
||||
.andReturn(200, new EndpointsBuilder().withNewMetadata()
|
||||
.withName("endpoint").endMetadata().addNewSubset().addNewAddress()
|
||||
.withIp("ip1").endAddress().addNewAddress().withIp("ip2")
|
||||
.endAddress().addNewPort("https", 443, "TCP").endSubset().build())
|
||||
.once();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint")
|
||||
.andReturn(200, new ServiceBuilder().withNewMetadata()
|
||||
.withName("endpoint").withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("l", "v");
|
||||
}
|
||||
}).endMetadata().build())
|
||||
.once();
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
|
||||
properties, KubernetesClient::services,
|
||||
new DefaultIsServicePortSecureResolver(properties));
|
||||
|
||||
final List<ServiceInstance> instances = discoveryClient.getInstances("endpoint");
|
||||
|
||||
assertThat(instances).hasSize(2).filteredOn(ServiceInstance::isSecure)
|
||||
.extracting(ServiceInstance::getHost).containsOnly("ip1", "ip2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServicesShouldReturnAllServicesWhenNoLabelsAreAppliedToTheClient() {
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services")
|
||||
.andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata()
|
||||
.withName("s1").withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().addNewItem().withNewMetadata()
|
||||
.withName("s2").withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
put("label2", "value2");
|
||||
}
|
||||
}).endMetadata().endItem().addNewItem().withNewMetadata()
|
||||
.withName("s3").endMetadata().endItem().build())
|
||||
.once();
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
|
||||
properties, KubernetesClient::services,
|
||||
new DefaultIsServicePortSecureResolver(properties));
|
||||
|
||||
final List<String> services = discoveryClient.getServices();
|
||||
|
||||
assertThat(services).containsOnly("s1", "s2", "s3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getServicesShouldReturnOnlyMatchingServicesWhenLabelsAreAppliedToTheClient() {
|
||||
mockServer.expect().get()
|
||||
.withPath("/api/v1/namespaces/test/services?labelSelector=label%3Dvalue")
|
||||
.andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata()
|
||||
.withName("s1").withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().addNewItem().withNewMetadata()
|
||||
.withName("s2").withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
put("label2", "value2");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.once();
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
|
||||
properties,
|
||||
client -> client.services().withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}), new DefaultIsServicePortSecureResolver(properties));
|
||||
|
||||
final List<String> services = discoveryClient.getServices();
|
||||
|
||||
assertThat(services).containsOnly("s1", "s2");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -75,8 +75,18 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
<artifactId>kubernetes-server-mock</artifactId>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
@@ -93,17 +103,6 @@
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmavenplus</groupId>
|
||||
<artifactId>gmavenplus-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compileTests</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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
|
||||
*
|
||||
* http://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.ribbon.test
|
||||
|
||||
import io.fabric8.kubernetes.api.model.EndpointsBuilder
|
||||
import io.fabric8.kubernetes.client.Config
|
||||
import io.fabric8.kubernetes.client.KubernetesClient
|
||||
import io.fabric8.kubernetes.server.mock.KubernetesMockServer
|
||||
import spock.lang.Specification
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor
|
||||
import org.springframework.cloud.kubernetes.ribbon.KubernetesRibbonClientConfiguration
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClient
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.web.client.RestTemplate
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@ContextConfiguration(classes = [TestApplication.class])
|
||||
@SpringBootTest(properties =
|
||||
[
|
||||
"spring.application.name=testapp",
|
||||
"spring.cloud.kubernetes.client.namespace=testns",
|
||||
"spring.cloud.kubernetes.client.trustCerts=true",
|
||||
"spring.cloud.kubernetes.config.namespace=testns"
|
||||
])
|
||||
@RibbonClient(name = "testapp", configuration = KubernetesRibbonClientConfiguration.class)
|
||||
class RibbonTest extends Specification {
|
||||
|
||||
private static KubernetesMockServer mockServer = new KubernetesMockServer()
|
||||
private static KubernetesMockServer mockEndpointA = new KubernetesMockServer(false)
|
||||
private static KubernetesMockServer mockEndpointB = new KubernetesMockServer(false)
|
||||
private static KubernetesClient mockClient;
|
||||
|
||||
@Autowired
|
||||
RestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
LoadBalancerInterceptor interceptor;
|
||||
|
||||
def setupSpec() {
|
||||
mockServer.init()
|
||||
mockEndpointA.init()
|
||||
mockEndpointB.init()
|
||||
mockClient = mockServer.createClient()
|
||||
|
||||
//Configure the kubernetes master url to point to the mock server
|
||||
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.
|
||||
getConfiguration().getMasterUrl())
|
||||
System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true")
|
||||
System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false")
|
||||
System.
|
||||
setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false")
|
||||
|
||||
//Configured
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/testns/endpoints/testapp").
|
||||
andReturn(200, new EndpointsBuilder()
|
||||
.withNewMetadata()
|
||||
.withName("testapp-a")
|
||||
.endMetadata()
|
||||
.addNewSubset()
|
||||
.addNewAddress().withIp(mockEndpointA.getServer().hostName).endAddress()
|
||||
.addNewPort("http", mockEndpointA.getServer().port, "http")
|
||||
.endSubset()
|
||||
.addNewSubset()
|
||||
.addNewAddress().withIp(mockEndpointB.getServer().hostName).endAddress()
|
||||
.addNewPort("http", mockEndpointB.getServer().port, "http")
|
||||
.endSubset()
|
||||
.build()).always()
|
||||
|
||||
mockEndpointA.expect().get().withPath("/greeting").andReturn(200, "Hello from A").
|
||||
always()
|
||||
mockEndpointB.expect().get().withPath("/greeting").andReturn(200, "Hello from B").
|
||||
always()
|
||||
}
|
||||
|
||||
def cleanupSpec() {
|
||||
mockServer.destroy()
|
||||
mockEndpointA.destroy()
|
||||
mockEndpointB.destroy()
|
||||
}
|
||||
|
||||
|
||||
def "A ribbon rest template should round robin over the available kubernetes endpoints"() {
|
||||
given:
|
||||
List<String> grettings = new ArrayList<>()
|
||||
when:
|
||||
for (int i = 0; i < 2; i++) {
|
||||
grettings.add(restTemplate.
|
||||
getForObject("http://testapp/greeting", String.class))
|
||||
}
|
||||
then:
|
||||
grettings.contains("Hello from A")
|
||||
grettings.contains("Hello from B")
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2019 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
|
||||
*
|
||||
* http://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.ribbon.test
|
||||
|
||||
import org.springframework.boot.SpringApplication
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.web.client.RestTemplate
|
||||
|
||||
@SpringBootApplication
|
||||
class TestApplication {
|
||||
|
||||
def main(String[] args) {
|
||||
SpringApplication.run(TestApplication.class, args);
|
||||
}
|
||||
|
||||
@LoadBalanced
|
||||
@Bean
|
||||
def RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import java.util.List;
|
||||
import io.fabric8.kubernetes.api.model.EndpointsBuilder;
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.server.mock.KubernetesServer;
|
||||
import io.fabric8.kubernetes.client.server.mock.KubernetesServer;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
@@ -35,6 +35,8 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Charles Moulliard
|
||||
*/
|
||||
@@ -57,13 +59,13 @@ public class RibbonTest {
|
||||
@ClassRule
|
||||
public static KubernetesServer mockEndpointB = new KubernetesServer(false);
|
||||
|
||||
public static KubernetesClient mockClient;
|
||||
private static KubernetesClient mockClient;
|
||||
|
||||
@Autowired
|
||||
RestTemplate restTemplate;
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBefore() throws Exception {
|
||||
public static void setUpBefore() {
|
||||
mockClient = server.getClient();
|
||||
|
||||
// Configure the kubernetes master url to point to the mock server
|
||||
@@ -99,13 +101,13 @@ public class RibbonTest {
|
||||
|
||||
@Test
|
||||
public void testGreetingEndpoint() {
|
||||
List<String> greetings = new ArrayList<>();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
greetings.add(this.restTemplate.getForObject("http://testapp/greeting",
|
||||
String.class));
|
||||
}
|
||||
greetings.contains("Hello from A");
|
||||
greetings.contains("Hello from B");
|
||||
final List<String> greetings = new ArrayList<>();
|
||||
greetings.add(
|
||||
this.restTemplate.getForObject("http://testapp/greeting", String.class));
|
||||
greetings.add(
|
||||
this.restTemplate.getForObject("http://testapp/greeting", String.class));
|
||||
|
||||
assertThat(greetings).containsOnly("Hello from A", "Hello from B");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.cloud.kubernetes.ribbon;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
@@ -26,7 +25,6 @@ import org.springframework.web.client.RestTemplate;
|
||||
/**
|
||||
* @author Charles Moulliard
|
||||
*/
|
||||
@EnableAutoConfiguration
|
||||
@SpringBootConfiguration
|
||||
public class TestApplication {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user