removes ribbon support
This commit is contained in:
@@ -1,124 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2013-2018 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.
|
||||
~
|
||||
-->
|
||||
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-cloud-kubernetes</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-kubernetes-ribbon</artifactId>
|
||||
<name>Spring Cloud Kubernetes :: Ribbon</name>
|
||||
|
||||
<properties>
|
||||
<service.occurrence>1</service.occurrence>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-kubernetes-discovery</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<artifactId>kubernetes-client</artifactId>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.fabric8</groupId>
|
||||
<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>
|
||||
<artifactId>spock-spring</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy-all</artifactId>
|
||||
<version>${groovy.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Dservice</argLine>
|
||||
<systemPropertyVariables>
|
||||
<service.occurrence>${service.occurrence}</service.occurrence>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -1,138 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.netflix.client.config.IClientConfigKey;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Kubernetes implementation of a Ribbon {@link IClientConfigKey}.
|
||||
*
|
||||
* @param <T> type of key
|
||||
* @author Ioannis Canellos
|
||||
*/
|
||||
public abstract class KubernetesConfigKey<T> implements IClientConfigKey<T> {
|
||||
|
||||
/**
|
||||
* Namespace configuration key.
|
||||
*/
|
||||
public static final IClientConfigKey<String> Namespace = new KubernetesConfigKey<String>(
|
||||
"KubernetesNamespace") {
|
||||
};
|
||||
|
||||
/**
|
||||
* Port name configuration key.
|
||||
*/
|
||||
public static final IClientConfigKey<String> PortName = new KubernetesConfigKey<String>(
|
||||
"PortName") {
|
||||
};
|
||||
|
||||
private static final Set<IClientConfigKey> keys = new HashSet<IClientConfigKey>();
|
||||
|
||||
static {
|
||||
for (Field f : KubernetesConfigKey.class.getDeclaredFields()) {
|
||||
if (Modifier.isStatic(f.getModifiers()) // &&
|
||||
// Modifier.isPublic(f.getModifiers())
|
||||
&& IClientConfigKey.class.isAssignableFrom(f.getType())) {
|
||||
try {
|
||||
keys.add((IClientConfigKey) f.get(null));
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final String configKey;
|
||||
|
||||
private final Class<T> type;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected KubernetesConfigKey(String configKey) {
|
||||
this.configKey = configKey;
|
||||
Type superclass = getClass().getGenericSuperclass();
|
||||
Assert.isTrue(superclass instanceof ParameterizedType,
|
||||
superclass + " isn't parameterized");
|
||||
Type runtimeType = ((ParameterizedType) superclass).getActualTypeArguments()[0];
|
||||
this.type = (Class<T>) Types.rawType(runtimeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated see {@link #keys()}
|
||||
* @return array of {@link IClientConfigKey}
|
||||
*/
|
||||
@Deprecated
|
||||
public static IClientConfigKey[] values() {
|
||||
return keys().toArray(new IClientConfigKey[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the public static keys defined in this class
|
||||
*/
|
||||
public static Set<IClientConfigKey> keys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public static IClientConfigKey valueOf(final String name) {
|
||||
for (IClientConfigKey key : keys()) {
|
||||
if (key.key().equals(name)) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return new IClientConfigKey() {
|
||||
@Override
|
||||
public String key() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return String.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> type() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.netflix.niws.client.ClientConfig#key()
|
||||
*/
|
||||
@Override
|
||||
public String key() {
|
||||
return this.configKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.configKey;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,96 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import io.fabric8.kubernetes.api.model.EndpointAddress;
|
||||
import io.fabric8.kubernetes.api.model.EndpointPort;
|
||||
import io.fabric8.kubernetes.api.model.EndpointSubset;
|
||||
import io.fabric8.kubernetes.api.model.Endpoints;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.utils.Utils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* the KubernetesEndpointsServerList description.
|
||||
*
|
||||
* @author wuzishu
|
||||
*/
|
||||
public class KubernetesEndpointsServerList extends KubernetesServerList {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(KubernetesEndpointsServerList.class);
|
||||
|
||||
/**
|
||||
* Instantiates a new Kubernetes endpoints server list.
|
||||
* @param client the client
|
||||
* @param properties the properties
|
||||
*/
|
||||
KubernetesEndpointsServerList(KubernetesClient client,
|
||||
KubernetesRibbonProperties properties) {
|
||||
super(client, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Server> getUpdatedListOfServers() {
|
||||
List<Server> result = new ArrayList<>();
|
||||
Endpoints endpoints = StringUtils.isNotBlank(this.getNamespace())
|
||||
? this.getClient().endpoints().inNamespace(this.getNamespace())
|
||||
.withName(this.getServiceId()).get()
|
||||
: this.getClient().endpoints().withName(this.getServiceId()).get();
|
||||
if (endpoints != null) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(String.format(
|
||||
"Found [%d] endpoints in l [%s] for name [%s] and portName [%s]",
|
||||
endpoints.getSubsets().size(),
|
||||
endpoints.getMetadata().getNamespace(), this.getServiceId(),
|
||||
this.getPortName()));
|
||||
}
|
||||
for (EndpointSubset subset : endpoints.getSubsets()) {
|
||||
|
||||
if (subset.getPorts().size() == 1) {
|
||||
EndpointPort port = subset.getPorts().get(getFIRST());
|
||||
for (EndpointAddress address : subset.getAddresses()) {
|
||||
result.add(new Server(address.getIp(), port.getPort()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (EndpointPort port : subset.getPorts()) {
|
||||
if (Utils.isNullOrEmpty(this.getPortName())
|
||||
|| this.getPortName().endsWith(port.getName())) {
|
||||
for (EndpointAddress address : subset.getAddresses()) {
|
||||
result.add(new Server(address.getIp(), port.getPort()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
LOG.warn(String.format(
|
||||
"Did not find any endpoints in ribbon in namespace [%s] for name [%s] and portName [%s]",
|
||||
this.getNamespace(), this.getServiceId(), this.getPortName()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.ServerList;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Kubernetes version of a Ribbon client configuration.
|
||||
*
|
||||
* @author Ioannis Canellos
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(KubernetesRibbonProperties.class)
|
||||
public class KubernetesRibbonClientConfiguration {
|
||||
|
||||
public KubernetesRibbonClientConfiguration() {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ServerList<?> ribbonServerList(KubernetesClient client, IClientConfig config,
|
||||
KubernetesRibbonProperties properties) {
|
||||
KubernetesServerList serverList;
|
||||
if (properties.getMode() == KubernetesRibbonMode.SERVICE) {
|
||||
serverList = new KubernetesServicesServerList(client, properties);
|
||||
}
|
||||
else {
|
||||
serverList = new KubernetesEndpointsServerList(client, properties);
|
||||
}
|
||||
serverList.initWithNiwsConfig(config);
|
||||
return serverList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
/**
|
||||
* the KubernetesRibbonMode description.
|
||||
*
|
||||
* @author wuzishu
|
||||
*/
|
||||
public enum KubernetesRibbonMode {
|
||||
|
||||
/**
|
||||
* using pod ip and port.
|
||||
*/
|
||||
POD,
|
||||
/**
|
||||
* using kubernetes service name and port.
|
||||
*/
|
||||
SERVICE
|
||||
|
||||
}
|
||||
@@ -1,91 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* The type Kubernetes ribbon properties.
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "spring.cloud.kubernetes.ribbon")
|
||||
public class KubernetesRibbonProperties {
|
||||
|
||||
/**
|
||||
* Ribbon enabled,default true.
|
||||
*/
|
||||
private Boolean enabled = true;
|
||||
|
||||
/**
|
||||
* {@link KubernetesRibbonMode} setting ribbon server list with ip of pod or service
|
||||
* name. default value is POD.
|
||||
*/
|
||||
private KubernetesRibbonMode mode = KubernetesRibbonMode.POD;
|
||||
|
||||
/**
|
||||
* cluster domain.
|
||||
*/
|
||||
private String clusterDomain = "cluster.local";
|
||||
|
||||
/**
|
||||
* Get cluster domain.
|
||||
* @return the cluster domain
|
||||
*/
|
||||
public String getClusterDomain() {
|
||||
return clusterDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets cluster domain.
|
||||
* @param clusterDomain the cluster domain
|
||||
*/
|
||||
public void setClusterDomain(String clusterDomain) {
|
||||
this.clusterDomain = clusterDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets mode.
|
||||
* @return the mode
|
||||
*/
|
||||
public KubernetesRibbonMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets mode.
|
||||
* @param mode the mode
|
||||
*/
|
||||
public void setMode(KubernetesRibbonMode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets enabled.
|
||||
* @return the enabled
|
||||
*/
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets enabled.
|
||||
* @param enabled the enabled
|
||||
*/
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,120 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.client.config.IClientConfig;
|
||||
import com.netflix.loadbalancer.AbstractServerList;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import com.netflix.loadbalancer.ServerList;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
|
||||
/**
|
||||
* Kubernetes {@link ServerList}.
|
||||
*
|
||||
* @author Ioannis Canellos
|
||||
* @author wuzishu
|
||||
*/
|
||||
public abstract class KubernetesServerList extends AbstractServerList<Server>
|
||||
implements ServerList<Server> {
|
||||
|
||||
private static final int FIRST = 0;
|
||||
|
||||
private final KubernetesClient client;
|
||||
|
||||
private String serviceId;
|
||||
|
||||
private String namespace;
|
||||
|
||||
private String portName;
|
||||
|
||||
private KubernetesRibbonProperties properties;
|
||||
|
||||
/**
|
||||
* Instantiates a new Kubernetes server list.
|
||||
* @param client the client
|
||||
* @param properties the properties
|
||||
*/
|
||||
public KubernetesServerList(KubernetesClient client,
|
||||
KubernetesRibbonProperties properties) {
|
||||
this.client = client;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public void initWithNiwsConfig(IClientConfig clientConfig) {
|
||||
this.serviceId = clientConfig.getClientName();
|
||||
this.namespace = clientConfig.getPropertyAsString(KubernetesConfigKey.Namespace,
|
||||
this.client.getNamespace());
|
||||
this.portName = clientConfig.getPropertyAsString(KubernetesConfigKey.PortName,
|
||||
null);
|
||||
}
|
||||
|
||||
public List<Server> getInitialListOfServers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets first.
|
||||
* @return the first
|
||||
*/
|
||||
static int getFIRST() {
|
||||
return FIRST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets client.
|
||||
* @return the client
|
||||
*/
|
||||
KubernetesClient getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets service id.
|
||||
* @return the service id
|
||||
*/
|
||||
String getServiceId() {
|
||||
return serviceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets namespace.
|
||||
* @return the namespace
|
||||
*/
|
||||
String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets port name.
|
||||
* @return the port name
|
||||
*/
|
||||
String getPortName() {
|
||||
return portName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets properties.
|
||||
* @return the properties
|
||||
*/
|
||||
KubernetesRibbonProperties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,96 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.kubernetes.api.model.ServicePort;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import io.fabric8.kubernetes.client.utils.Utils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* the KubernetesServicesServerList description.
|
||||
*
|
||||
* @author wuzishu
|
||||
*/
|
||||
public class KubernetesServicesServerList extends KubernetesServerList {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(KubernetesServicesServerList.class);
|
||||
|
||||
/**
|
||||
* Instantiates a new Kubernetes services server list.
|
||||
* @param client the client
|
||||
* @param properties the properties
|
||||
*/
|
||||
KubernetesServicesServerList(KubernetesClient client,
|
||||
KubernetesRibbonProperties properties) {
|
||||
super(client, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat service fully qualified domain name.
|
||||
* @param service Service model
|
||||
* @return service FQDN
|
||||
*/
|
||||
private String concatServiceFQDN(Service service) {
|
||||
return String.format("%s.%s.svc.%s", service.getMetadata().getName(),
|
||||
StringUtils.isNotBlank(service.getMetadata().getNamespace())
|
||||
? service.getMetadata().getNamespace() : "default",
|
||||
this.getProperties().getClusterDomain());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Server> getUpdatedListOfServers() {
|
||||
List<Server> result = new ArrayList<>();
|
||||
Service service = StringUtils.isNotBlank(this.getNamespace())
|
||||
? this.getClient().services().inNamespace(this.getNamespace())
|
||||
.withName(this.getServiceId()).get()
|
||||
: this.getClient().services().withName(this.getServiceId()).get();
|
||||
if (service != null) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Found Service[" + service.getMetadata().getName() + "]");
|
||||
}
|
||||
if (service.getSpec().getPorts().size() == 1) {
|
||||
result.add(new Server(this.concatServiceFQDN(service),
|
||||
service.getSpec().getPorts().get(0).getPort()));
|
||||
}
|
||||
else {
|
||||
for (ServicePort servicePort : service.getSpec().getPorts()) {
|
||||
if (Utils.isNotNullOrEmpty(this.getPortName())
|
||||
|| this.getPortName().endsWith(servicePort.getName())) {
|
||||
result.add(new Server(concatServiceFQDN(service),
|
||||
servicePort.getPort()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
LOG.warn(String.format(
|
||||
"Did not find any service in ribbon in namespace [%s] for name [%s] and portName [%s]",
|
||||
this.getNamespace(), this.getServiceId(), this.getPortName()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClients;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Auto configuration for Ribbon.
|
||||
*
|
||||
* @author Ioannis Canellos
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@ConditionalOnBean(SpringClientFactory.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.kubernetes.ribbon.enabled",
|
||||
matchIfMissing = true)
|
||||
@AutoConfigureAfter(RibbonAutoConfiguration.class)
|
||||
@RibbonClients(defaultConfiguration = KubernetesRibbonClientConfiguration.class)
|
||||
public class RibbonKubernetesAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -1,55 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.WildcardType;
|
||||
|
||||
final class Types {
|
||||
|
||||
private Types() {
|
||||
// Utlity
|
||||
}
|
||||
|
||||
static Class rawType(Type type) {
|
||||
if (type instanceof Class) {
|
||||
return (Class) type;
|
||||
}
|
||||
else if (type instanceof TypeVariable) {
|
||||
return rawType(firstOrObject(((TypeVariable) type).getBounds()));
|
||||
}
|
||||
else if (type instanceof WildcardType) {
|
||||
return rawType(firstOrObject(((WildcardType) type).getUpperBounds()));
|
||||
}
|
||||
else if (type instanceof GenericArrayType) {
|
||||
return rawType(((GenericArrayType) type).getGenericComponentType());
|
||||
}
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
private static Type firstOrObject(Type[] types) {
|
||||
if (types.length > 0) {
|
||||
return rawType(types[0]);
|
||||
}
|
||||
else {
|
||||
return Void.class;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.kubernetes.ribbon.RibbonKubernetesAutoConfiguration
|
||||
@@ -1,48 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class KubernetesConfigKeyTest {
|
||||
|
||||
@Test
|
||||
public <T extends TypeOne, I> void testTypes() {
|
||||
// with class
|
||||
KubernetesConfigKey<String> key1 = new KubernetesConfigKey<String>("key1") {
|
||||
};
|
||||
|
||||
// with type variable
|
||||
KubernetesConfigKey<T> key2 = new KubernetesConfigKey<T>("key2") {
|
||||
};
|
||||
|
||||
// with type variable with no bounds
|
||||
KubernetesConfigKey<I> key3 = new KubernetesConfigKey<I>("key3") {
|
||||
};
|
||||
|
||||
assertThat(key1.type()).isEqualTo(String.class);
|
||||
assertThat(key2.type()).isEqualTo(TypeOne.class);
|
||||
assertThat(key3.type()).isEqualTo(Object.class);
|
||||
}
|
||||
|
||||
private class TypeOne<T> {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,185 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Endpoints;
|
||||
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.mockwebserver.DefaultMockServer;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
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.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
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;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* @author Charles Moulliard
|
||||
*/
|
||||
@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" })
|
||||
@EnableAutoConfiguration
|
||||
@EnableDiscoveryClient
|
||||
public class RibbonFallbackTest {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(RibbonFallbackTest.class);
|
||||
|
||||
@ClassRule
|
||||
public static KubernetesServer mockServer = new KubernetesServer(false);
|
||||
|
||||
public static DefaultMockServer mockEndpoint;
|
||||
|
||||
public static KubernetesClient mockClient;
|
||||
|
||||
@Autowired
|
||||
RestTemplate restTemplate;
|
||||
|
||||
@Value("${service.occurrence}")
|
||||
private int serviceOccurrence;
|
||||
|
||||
@Value("${testapp.ribbon.ServerListRefreshInterval}")
|
||||
private int serverListRefreshInterval;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBefore() throws Exception {
|
||||
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");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
mockEndpoint = new DefaultMockServer(false);
|
||||
mockEndpoint.start();
|
||||
}
|
||||
|
||||
public static Endpoints newEndpoint(String name, String namespace,
|
||||
DefaultMockServer mockServer) {
|
||||
// @formatter:off
|
||||
return new EndpointsBuilder()
|
||||
.withNewMetadata()
|
||||
.withName(name)
|
||||
.withNamespace(namespace)
|
||||
.endMetadata()
|
||||
.addNewSubset()
|
||||
.addNewAddress()
|
||||
.withIp(mockServer.getHostName())
|
||||
.endAddress()
|
||||
.addNewPort("http", mockServer.getPort(), "http")
|
||||
.endSubset()
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFallBackGreetingEndpoint() {
|
||||
/**
|
||||
* Scenario tested 1. Register the mock endpoint of the service into
|
||||
* KubeMockServer and call /greeting service 2. Unregister the mock endpoint and
|
||||
* verify that Ribbon doesn't have any instances anymore in its list 3. Re
|
||||
* register the mock endpoint and play step 1)
|
||||
**/
|
||||
|
||||
LOG.info(">>>>>>>>>> BEGIN PART 1 <<<<<<<<<<<<<");
|
||||
|
||||
// As Ribbon refreshes its list every serverListRefreshInterval ms,
|
||||
// we configure the API Server endpoint to reply to exactly serviceOccurrence
|
||||
// attempts
|
||||
// to be sure that Ribbon will get the mockendpoint to access it for the call
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/testns/endpoints/testapp")
|
||||
.andReturn(200, newEndpoint("testapp-a", "testns", mockEndpoint))
|
||||
.times(this.serviceOccurrence);
|
||||
|
||||
mockEndpoint.expect().get().withPath("/greeting").andReturn(200, "Hello from A")
|
||||
.once();
|
||||
|
||||
String response = this.restTemplate.getForObject("http://testapp/greeting",
|
||||
String.class);
|
||||
assertThat(response).isEqualTo("Hello from A");
|
||||
LOG.info(">>>>>>>>>> END PART 1 <<<<<<<<<<<<<");
|
||||
|
||||
LOG.info(">>>>>>>>>> BEGIN PART 2 <<<<<<<<<<<<<");
|
||||
try {
|
||||
ensureEndpointsNoLongerReturnedByAPIServer();
|
||||
this.restTemplate.getForObject("http://testapp/greeting", String.class);
|
||||
fail("Ribbon was supposed to throw an Exception due to not knowing of any endpoints to route the request to");
|
||||
}
|
||||
catch (Exception e) {
|
||||
// No endpoint is available anymore and Ribbon list is empty
|
||||
assertThat(e.getMessage()).isEqualTo("No instances available for testapp");
|
||||
}
|
||||
LOG.info(">>>>>>>>>> END PART 2 <<<<<<<<<<<<<");
|
||||
|
||||
LOG.info(">>>>>>>>>> BEGIN PART 3 <<<<<<<<<<<<<");
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/testns/endpoints/testapp")
|
||||
.andReturn(200, newEndpoint("testapp-a", "testns", mockEndpoint))
|
||||
.always();
|
||||
|
||||
// the purpose of sleeping here is to make sure that even after some refreshes to
|
||||
// it's list
|
||||
// Ribbon still has endpoints to route to
|
||||
// This is different than the first part of the test because the API server has
|
||||
// now been
|
||||
// configured to always respond with some endpoints as opposed to only a certain
|
||||
// amount of
|
||||
// requests which was the case in part 1
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
mockEndpoint.expect().get().withPath("/greeting").andReturn(200, "Hello from A")
|
||||
.once();
|
||||
response = this.restTemplate.getForObject("http://testapp/greeting",
|
||||
String.class);
|
||||
assertThat(response).isEqualTo("Hello from A");
|
||||
LOG.info(">>>>>>>>>> END PART 3 <<<<<<<<<<<<<");
|
||||
}
|
||||
|
||||
// This works because the (mock) API server is configured to return the endpoints
|
||||
// exactly
|
||||
// serviceOccurrence times while Ribbon refreshes it's list every
|
||||
// serverListRefreshInterval milliseconds
|
||||
private void ensureEndpointsNoLongerReturnedByAPIServer()
|
||||
throws InterruptedException {
|
||||
Thread.sleep((this.serviceOccurrence + 1) * this.serverListRefreshInterval);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,114 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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.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.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
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
|
||||
*/
|
||||
@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" })
|
||||
@EnableAutoConfiguration
|
||||
@EnableDiscoveryClient
|
||||
public class RibbonTest {
|
||||
|
||||
@ClassRule
|
||||
public static KubernetesServer server = new KubernetesServer();
|
||||
|
||||
@ClassRule
|
||||
public static KubernetesServer mockEndpointA = new KubernetesServer(false);
|
||||
|
||||
@ClassRule
|
||||
public static KubernetesServer mockEndpointB = new KubernetesServer(false);
|
||||
|
||||
private static KubernetesClient mockClient;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBefore() {
|
||||
mockClient = server.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");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
// Configured
|
||||
server.expect().get().withPath("/api/v1/namespaces/testns/endpoints/testapp")
|
||||
.andReturn(200,
|
||||
new EndpointsBuilder().withNewMetadata().withName("testapp-a")
|
||||
.endMetadata().addNewSubset().addNewAddress()
|
||||
.withIp(mockEndpointA.getMockServer().getHostName())
|
||||
.endAddress()
|
||||
.addNewPort("http",
|
||||
mockEndpointA.getMockServer().getPort(), "http")
|
||||
.endSubset().addNewSubset().addNewAddress()
|
||||
.withIp(mockEndpointB.getMockServer().getHostName())
|
||||
.endAddress()
|
||||
.addNewPort("http",
|
||||
mockEndpointB.getMockServer().getPort(), "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();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGreetingEndpoint() {
|
||||
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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,116 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.loadbalancer.ILoadBalancer;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import io.fabric8.kubernetes.api.model.IntOrString;
|
||||
import io.fabric8.kubernetes.api.model.ServiceBuilder;
|
||||
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.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* the RibbonWithServiceModeTest description.
|
||||
*
|
||||
* @author wuzishu
|
||||
*/
|
||||
@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.enabled=true",
|
||||
"spring.cloud.kubernetes.discovery.enabled=true",
|
||||
"spring.cloud.kubernetes.ribbon.enabled=true",
|
||||
"spring.cloud.kubernetes.ribbon.mode=SERVICE",
|
||||
"spring.cloud.kubernetes.ribbon.clusterDomain=test.com" })
|
||||
@EnableAutoConfiguration
|
||||
@EnableDiscoveryClient
|
||||
public class RibbonWithServiceModeTest {
|
||||
|
||||
@ClassRule
|
||||
public static KubernetesServer server = new KubernetesServer();
|
||||
|
||||
@ClassRule
|
||||
public static KubernetesServer mockEndpointA = new KubernetesServer(false);
|
||||
|
||||
private static KubernetesClient mockClient;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpBefore() {
|
||||
mockClient = server.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");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
// Configured
|
||||
server.expect().get().withPath("/api/v1/namespaces/testns/services/testapp")
|
||||
.andReturn(200, new ServiceBuilder().withNewMetadata().withName("testapp")
|
||||
.withNamespace("testns").endMetadata().withNewSpec()
|
||||
.addToSelector("app", "testapp-a").addNewPort().withName("http")
|
||||
.withPort(mockEndpointA.getMockServer().getPort())
|
||||
.withTargetPort(
|
||||
new IntOrString(mockEndpointA.getMockServer().getPort()))
|
||||
.withProtocol("TCP").endPort().endSpec().build())
|
||||
.always();
|
||||
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
@Test
|
||||
public void testGreetingWithServiceMode() {
|
||||
SpringClientFactory springClientFactory = context
|
||||
.getBean(SpringClientFactory.class);
|
||||
ILoadBalancer testapp = springClientFactory.getLoadBalancer("testapp");
|
||||
List<Server> allServers = testapp.getAllServers();
|
||||
assertThat(allServers.stream()
|
||||
.map(c -> String.format("%s:%s", c.getHost(), c.getPort())))
|
||||
.containsOnly("testapp.testns.svc.test.com:"
|
||||
+ mockEndpointA.getMockServer().getPort());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +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
|
||||
*
|
||||
* 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.ribbon;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author Charles Moulliard
|
||||
*/
|
||||
@SpringBootConfiguration
|
||||
public class TestApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(TestApplication.class, args);
|
||||
}
|
||||
|
||||
@LoadBalanced
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
testapp:
|
||||
ribbon:
|
||||
eureka:
|
||||
enabled: false
|
||||
ServerListRefreshInterval: 500
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||
<logger name="org.hibernate.validator"
|
||||
level="info"/> <!-- Validator prints a lot of debug messages during integration tests -->
|
||||
<logger name="okhttp3.mockwebserver" level="debug"/>
|
||||
</configuration>
|
||||
@@ -1,53 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2013-2018 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.
|
||||
~
|
||||
-->
|
||||
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-cloud-kubernetes</artifactId>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
|
||||
<name>Spring Cloud Kubernetes :: Starter :: Ribbon</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-kubernetes-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-kubernetes-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-kubernetes-ribbon</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
Reference in New Issue
Block a user