Bumping versions
This commit is contained in:
@@ -41,26 +41,21 @@ public class BootstrapConfiguration {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(KubernetesAutoConfiguration.class)
|
||||
@EnableConfigurationProperties({ ConfigMapConfigProperties.class,
|
||||
SecretsConfigProperties.class })
|
||||
@EnableConfigurationProperties({ ConfigMapConfigProperties.class, SecretsConfigProperties.class })
|
||||
protected static class KubernetesPropertySourceConfiguration {
|
||||
|
||||
@Autowired
|
||||
private KubernetesClient client;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "spring.cloud.kubernetes.config.enabled",
|
||||
matchIfMissing = true)
|
||||
public ConfigMapPropertySourceLocator configMapPropertySourceLocator(
|
||||
ConfigMapConfigProperties properties) {
|
||||
@ConditionalOnProperty(name = "spring.cloud.kubernetes.config.enabled", matchIfMissing = true)
|
||||
public ConfigMapPropertySourceLocator configMapPropertySourceLocator(ConfigMapConfigProperties properties) {
|
||||
return new ConfigMapPropertySourceLocator(this.client, properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "spring.cloud.kubernetes.secrets.enabled",
|
||||
matchIfMissing = true)
|
||||
public SecretsPropertySourceLocator secretsPropertySourceLocator(
|
||||
SecretsConfigProperties properties) {
|
||||
@ConditionalOnProperty(name = "spring.cloud.kubernetes.secrets.enabled", matchIfMissing = true)
|
||||
public SecretsPropertySourceLocator secretsPropertySourceLocator(SecretsConfigProperties properties) {
|
||||
return new SecretsPropertySourceLocator(this.client, properties);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,8 +82,7 @@ public class ConfigMapConfigProperties extends AbstractConfigProperties {
|
||||
};
|
||||
}
|
||||
|
||||
return this.sources.stream().map(s -> s.normalize(this.name, this.namespace))
|
||||
.collect(Collectors.toList());
|
||||
return this.sources.stream().map(s -> s.normalize(this.name, this.namespace)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -135,10 +134,8 @@ public class ConfigMapConfigProperties extends AbstractConfigProperties {
|
||||
}
|
||||
|
||||
public NormalizedSource normalize(String defaultName, String defaultNamespace) {
|
||||
final String normalizedName = StringUtils.isEmpty(this.name) ? defaultName
|
||||
: this.name;
|
||||
final String normalizedNamespace = StringUtils.isEmpty(this.namespace)
|
||||
? defaultNamespace : this.namespace;
|
||||
final String normalizedName = StringUtils.isEmpty(this.name) ? defaultName : this.name;
|
||||
final String normalizedNamespace = StringUtils.isEmpty(this.namespace) ? defaultNamespace : this.namespace;
|
||||
|
||||
return new NormalizedSource(normalizedName, normalizedNamespace);
|
||||
}
|
||||
|
||||
@@ -60,40 +60,31 @@ public class ConfigMapPropertySource extends MapPropertySource {
|
||||
this(client, name, null, (Environment) null);
|
||||
}
|
||||
|
||||
public ConfigMapPropertySource(KubernetesClient client, String name, String namespace,
|
||||
String[] profiles) {
|
||||
public ConfigMapPropertySource(KubernetesClient client, String name, String namespace, String[] profiles) {
|
||||
this(client, name, namespace, createEnvironmentWithActiveProfiles(profiles));
|
||||
}
|
||||
|
||||
private static Environment createEnvironmentWithActiveProfiles(
|
||||
String[] activeProfiles) {
|
||||
private static Environment createEnvironmentWithActiveProfiles(String[] activeProfiles) {
|
||||
StandardEnvironment environment = new StandardEnvironment();
|
||||
environment.setActiveProfiles(activeProfiles);
|
||||
return environment;
|
||||
}
|
||||
|
||||
public ConfigMapPropertySource(KubernetesClient client, String name, String namespace,
|
||||
Environment environment) {
|
||||
super(getName(client, name, namespace),
|
||||
asObjectMap(getData(client, name, namespace, environment)));
|
||||
public ConfigMapPropertySource(KubernetesClient client, String name, String namespace, Environment environment) {
|
||||
super(getName(client, name, namespace), asObjectMap(getData(client, name, namespace, environment)));
|
||||
}
|
||||
|
||||
private static String getName(KubernetesClient client, String name,
|
||||
String namespace) {
|
||||
return new StringBuilder().append(PREFIX)
|
||||
.append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name)
|
||||
private static String getName(KubernetesClient client, String name, String namespace) {
|
||||
return new StringBuilder().append(PREFIX).append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name)
|
||||
.append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR)
|
||||
.append(namespace == null || namespace.isEmpty() ? client.getNamespace()
|
||||
: namespace)
|
||||
.toString();
|
||||
.append(namespace == null || namespace.isEmpty() ? client.getNamespace() : namespace).toString();
|
||||
}
|
||||
|
||||
private static Map<String, Object> getData(KubernetesClient client, String name,
|
||||
String namespace, Environment environment) {
|
||||
private static Map<String, Object> getData(KubernetesClient client, String name, String namespace,
|
||||
Environment environment) {
|
||||
try {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
ConfigMap map = StringUtils.isEmpty(namespace)
|
||||
? client.configMaps().withName(name).get()
|
||||
ConfigMap map = StringUtils.isEmpty(namespace) ? client.configMaps().withName(name).get()
|
||||
: client.configMaps().inNamespace(namespace).withName(name).get();
|
||||
|
||||
if (map != null) {
|
||||
@@ -107,12 +98,10 @@ public class ConfigMapPropertySource extends MapPropertySource {
|
||||
|
||||
ConfigMap mapWithProfile = StringUtils.isEmpty(namespace)
|
||||
? client.configMaps().withName(mapNameWithProfile).get()
|
||||
: client.configMaps().inNamespace(namespace)
|
||||
.withName(mapNameWithProfile).get();
|
||||
: client.configMaps().inNamespace(namespace).withName(mapNameWithProfile).get();
|
||||
|
||||
if (mapWithProfile != null) {
|
||||
result.putAll(
|
||||
processAllEntries(mapWithProfile.getData(), environment));
|
||||
result.putAll(processAllEntries(mapWithProfile.getData(), environment));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -122,15 +111,13 @@ public class ConfigMapPropertySource extends MapPropertySource {
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn("Can't read configMap with name: [" + name + "] in namespace:["
|
||||
+ namespace + "]. Ignoring.", e);
|
||||
LOG.warn("Can't read configMap with name: [" + name + "] in namespace:[" + namespace + "]. Ignoring.", e);
|
||||
}
|
||||
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
private static Map<String, Object> processAllEntries(Map<String, String> input,
|
||||
Environment environment) {
|
||||
private static Map<String, Object> processAllEntries(Map<String, String> input, Environment environment) {
|
||||
|
||||
Set<Entry<String, String>> entrySet = input.entrySet();
|
||||
if (entrySet.size() == 1) {
|
||||
@@ -141,12 +128,10 @@ public class ConfigMapPropertySource extends MapPropertySource {
|
||||
String propertyValue = singleEntry.getValue();
|
||||
if (propertyName.endsWith(".yml") || propertyName.endsWith(".yaml")) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("The single property with name: [" + propertyName
|
||||
+ "] will be treated as a yaml file");
|
||||
LOG.debug("The single property with name: [" + propertyName + "] will be treated as a yaml file");
|
||||
}
|
||||
|
||||
return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP)
|
||||
.apply(propertyValue);
|
||||
return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP).apply(propertyValue);
|
||||
}
|
||||
else if (propertyName.endsWith(".properties")) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
@@ -154,8 +139,7 @@ public class ConfigMapPropertySource extends MapPropertySource {
|
||||
+ "] will be treated as a properties file");
|
||||
}
|
||||
|
||||
return KEY_VALUE_TO_PROPERTIES.andThen(PROPERTIES_TO_MAP)
|
||||
.apply(propertyValue);
|
||||
return KEY_VALUE_TO_PROPERTIES.andThen(PROPERTIES_TO_MAP).apply(propertyValue);
|
||||
}
|
||||
else {
|
||||
return defaultProcessAllEntries(input, environment);
|
||||
@@ -165,23 +149,17 @@ public class ConfigMapPropertySource extends MapPropertySource {
|
||||
return defaultProcessAllEntries(input, environment);
|
||||
}
|
||||
|
||||
private static Map<String, Object> defaultProcessAllEntries(Map<String, String> input,
|
||||
Environment environment) {
|
||||
private static Map<String, Object> defaultProcessAllEntries(Map<String, String> input, Environment environment) {
|
||||
|
||||
return input.entrySet().stream()
|
||||
.map(e -> extractProperties(e.getKey(), e.getValue(), environment))
|
||||
return input.entrySet().stream().map(e -> extractProperties(e.getKey(), e.getValue(), environment))
|
||||
.filter(m -> !m.isEmpty()).flatMap(m -> m.entrySet().stream())
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue,
|
||||
throwingMerger(), LinkedHashMap::new));
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, throwingMerger(), LinkedHashMap::new));
|
||||
}
|
||||
|
||||
private static Map<String, Object> extractProperties(String resourceName,
|
||||
String content, Environment environment) {
|
||||
private static Map<String, Object> extractProperties(String resourceName, String content, Environment environment) {
|
||||
|
||||
if (resourceName.equals(APPLICATION_YAML)
|
||||
|| resourceName.equals(APPLICATION_YML)) {
|
||||
return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP)
|
||||
.apply(content);
|
||||
if (resourceName.equals(APPLICATION_YAML) || resourceName.equals(APPLICATION_YML)) {
|
||||
return yamlParserGenerator(environment).andThen(PROPERTIES_TO_MAP).apply(content);
|
||||
}
|
||||
else if (resourceName.equals(APPLICATION_PROPERTIES)) {
|
||||
return KEY_VALUE_TO_PROPERTIES.andThen(PROPERTIES_TO_MAP).apply(content);
|
||||
@@ -195,8 +173,8 @@ public class ConfigMapPropertySource extends MapPropertySource {
|
||||
}
|
||||
|
||||
private static Map<String, Object> asObjectMap(Map<String, Object> source) {
|
||||
return source.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,
|
||||
Map.Entry::getValue, throwingMerger(), LinkedHashMap::new));
|
||||
return source.entrySet().stream().collect(
|
||||
Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, throwingMerger(), LinkedHashMap::new));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,15 +52,13 @@ import static org.springframework.cloud.kubernetes.config.PropertySourceUtils.ya
|
||||
@Order(0)
|
||||
public class ConfigMapPropertySourceLocator implements PropertySourceLocator {
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(ConfigMapPropertySourceLocator.class);
|
||||
private static final Log LOG = LogFactory.getLog(ConfigMapPropertySourceLocator.class);
|
||||
|
||||
private final KubernetesClient client;
|
||||
|
||||
private final ConfigMapConfigProperties properties;
|
||||
|
||||
public ConfigMapPropertySourceLocator(KubernetesClient client,
|
||||
ConfigMapConfigProperties properties) {
|
||||
public ConfigMapPropertySourceLocator(KubernetesClient client, ConfigMapConfigProperties properties) {
|
||||
this.client = client;
|
||||
this.properties = properties;
|
||||
}
|
||||
@@ -70,13 +68,10 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator {
|
||||
if (environment instanceof ConfigurableEnvironment) {
|
||||
ConfigurableEnvironment env = (ConfigurableEnvironment) environment;
|
||||
|
||||
List<ConfigMapConfigProperties.NormalizedSource> sources = this.properties
|
||||
.determineSources();
|
||||
CompositePropertySource composite = new CompositePropertySource(
|
||||
"composite-configmap");
|
||||
List<ConfigMapConfigProperties.NormalizedSource> sources = this.properties.determineSources();
|
||||
CompositePropertySource composite = new CompositePropertySource("composite-configmap");
|
||||
if (this.properties.isEnableApi()) {
|
||||
sources.forEach(s -> composite.addFirstPropertySource(
|
||||
getMapPropertySourceForSingleConfigMap(env, s)));
|
||||
sources.forEach(s -> composite.addFirstPropertySource(getMapPropertySourceForSingleConfigMap(env, s)));
|
||||
}
|
||||
|
||||
addPropertySourcesFromPaths(environment, composite);
|
||||
@@ -86,20 +81,17 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator {
|
||||
return null;
|
||||
}
|
||||
|
||||
private MapPropertySource getMapPropertySourceForSingleConfigMap(
|
||||
ConfigurableEnvironment environment, NormalizedSource normalizedSource) {
|
||||
private MapPropertySource getMapPropertySourceForSingleConfigMap(ConfigurableEnvironment environment,
|
||||
NormalizedSource normalizedSource) {
|
||||
|
||||
String configurationTarget = this.properties.getConfigurationTarget();
|
||||
return new ConfigMapPropertySource(this.client,
|
||||
getApplicationName(environment, normalizedSource.getName(),
|
||||
configurationTarget),
|
||||
getApplicationNamespace(this.client, normalizedSource.getNamespace(),
|
||||
configurationTarget),
|
||||
getApplicationName(environment, normalizedSource.getName(), configurationTarget),
|
||||
getApplicationNamespace(this.client, normalizedSource.getNamespace(), configurationTarget),
|
||||
environment);
|
||||
}
|
||||
|
||||
private void addPropertySourcesFromPaths(Environment environment,
|
||||
CompositePropertySource composite) {
|
||||
private void addPropertySourcesFromPaths(Environment environment, CompositePropertySource composite) {
|
||||
this.properties.getPaths().stream().map(Paths::get).peek(p -> {
|
||||
if (!Files.exists(p)) {
|
||||
LOG.warn("Configured input path: " + p
|
||||
@@ -107,23 +99,18 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator {
|
||||
}
|
||||
}).filter(Files::exists).peek(p -> {
|
||||
if (!Files.isRegularFile(p)) {
|
||||
LOG.warn("Configured input path: " + p
|
||||
+ " will be ignored because it is not a regular file");
|
||||
LOG.warn("Configured input path: " + p + " will be ignored because it is not a regular file");
|
||||
}
|
||||
}).filter(Files::isRegularFile).forEach(p -> {
|
||||
try {
|
||||
String content = new String(Files.readAllBytes(p)).trim();
|
||||
String filename = p.getFileName().toString().toLowerCase();
|
||||
if (filename.endsWith(".properties")) {
|
||||
addPropertySourceIfNeeded(
|
||||
c -> PROPERTIES_TO_MAP
|
||||
.apply(KEY_VALUE_TO_PROPERTIES.apply(c)),
|
||||
content, filename, composite);
|
||||
addPropertySourceIfNeeded(c -> PROPERTIES_TO_MAP.apply(KEY_VALUE_TO_PROPERTIES.apply(c)), content,
|
||||
filename, composite);
|
||||
}
|
||||
else if (filename.endsWith(".yml") || filename.endsWith(".yaml")) {
|
||||
addPropertySourceIfNeeded(
|
||||
c -> PROPERTIES_TO_MAP
|
||||
.apply(yamlParserGenerator(environment).apply(c)),
|
||||
addPropertySourceIfNeeded(c -> PROPERTIES_TO_MAP.apply(yamlParserGenerator(environment).apply(c)),
|
||||
content, filename, composite);
|
||||
}
|
||||
}
|
||||
@@ -133,15 +120,13 @@ public class ConfigMapPropertySourceLocator implements PropertySourceLocator {
|
||||
});
|
||||
}
|
||||
|
||||
private void addPropertySourceIfNeeded(
|
||||
Function<String, Map<String, Object>> contentToMapFunction, String content,
|
||||
private void addPropertySourceIfNeeded(Function<String, Map<String, Object>> contentToMapFunction, String content,
|
||||
String name, CompositePropertySource composite) {
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.putAll(contentToMapFunction.apply(content));
|
||||
if (map.isEmpty()) {
|
||||
LOG.warn("Property source: " + name
|
||||
+ "will be ignored because no properties could be found");
|
||||
LOG.warn("Property source: " + name + "will be ignored because no properties could be found");
|
||||
}
|
||||
else {
|
||||
composite.addFirstPropertySource(new MapPropertySource(name, map));
|
||||
|
||||
@@ -39,16 +39,14 @@ public final class ConfigUtils {
|
||||
throw new IllegalStateException("Can't instantiate a utility class");
|
||||
}
|
||||
|
||||
public static <C extends AbstractConfigProperties> String getApplicationName(
|
||||
Environment env, String configName, String configurationTarget) {
|
||||
public static <C extends AbstractConfigProperties> String getApplicationName(Environment env, String configName,
|
||||
String configurationTarget) {
|
||||
String name = configName;
|
||||
if (StringUtils.isEmpty(name)) {
|
||||
// TODO: use relaxed binding
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(configurationTarget
|
||||
+ " name has not been set, taking it from property/env "
|
||||
+ SPRING_APPLICATION_NAME + " (default="
|
||||
+ FALLBACK_APPLICATION_NAME + ")");
|
||||
LOG.debug(configurationTarget + " name has not been set, taking it from property/env "
|
||||
+ SPRING_APPLICATION_NAME + " (default=" + FALLBACK_APPLICATION_NAME + ")");
|
||||
}
|
||||
|
||||
name = env.getProperty(SPRING_APPLICATION_NAME, FALLBACK_APPLICATION_NAME);
|
||||
@@ -57,13 +55,12 @@ public final class ConfigUtils {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static <C extends AbstractConfigProperties> String getApplicationNamespace(
|
||||
KubernetesClient client, String configNamespace, String configurationTarget) {
|
||||
public static <C extends AbstractConfigProperties> String getApplicationNamespace(KubernetesClient client,
|
||||
String configNamespace, String configurationTarget) {
|
||||
String namespace = configNamespace;
|
||||
if (StringUtils.isEmpty(namespace)) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(configurationTarget
|
||||
+ " namespace has not been set, taking it from client (ns="
|
||||
LOG.debug(configurationTarget + " namespace has not been set, taking it from client (ns="
|
||||
+ client.getNamespace() + ")");
|
||||
}
|
||||
|
||||
|
||||
@@ -52,9 +52,9 @@ public final class PropertySourceUtils {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
};
|
||||
static final Function<Properties, Map<String, Object>> PROPERTIES_TO_MAP = p -> p
|
||||
.entrySet().stream().collect(Collectors.toMap(e -> String.valueOf(e.getKey()),
|
||||
Map.Entry::getValue, throwingMerger(), java.util.LinkedHashMap::new));
|
||||
static final Function<Properties, Map<String, Object>> PROPERTIES_TO_MAP = p -> p.entrySet().stream()
|
||||
.collect(Collectors.toMap(e -> String.valueOf(e.getKey()), Map.Entry::getValue, throwingMerger(),
|
||||
java.util.LinkedHashMap::new));
|
||||
|
||||
private PropertySourceUtils() {
|
||||
throw new IllegalStateException("Can't instantiate a utility class");
|
||||
@@ -66,8 +66,7 @@ public final class PropertySourceUtils {
|
||||
yamlFactory.setDocumentMatchers(properties -> {
|
||||
String profiles = properties.getProperty("spring.profiles");
|
||||
if (environment != null && StringUtils.hasText(profiles)) {
|
||||
return environment.acceptsProfiles(Profiles.of(profiles)) ? FOUND
|
||||
: NOT_FOUND;
|
||||
return environment.acceptsProfiles(Profiles.of(profiles)) ? FOUND : NOT_FOUND;
|
||||
}
|
||||
else {
|
||||
return ABSTAIN;
|
||||
|
||||
@@ -94,16 +94,13 @@ public class SecretsConfigProperties extends AbstractConfigProperties {
|
||||
if (this.sources.isEmpty()) {
|
||||
return new ArrayList<SecretsConfigProperties.NormalizedSource>() {
|
||||
{
|
||||
add(new SecretsConfigProperties.NormalizedSource(
|
||||
SecretsConfigProperties.this.name,
|
||||
SecretsConfigProperties.this.namespace,
|
||||
SecretsConfigProperties.this.labels));
|
||||
add(new SecretsConfigProperties.NormalizedSource(SecretsConfigProperties.this.name,
|
||||
SecretsConfigProperties.this.namespace, SecretsConfigProperties.this.labels));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return this.sources.stream()
|
||||
.map(s -> s.normalize(this.name, this.namespace, this.labels))
|
||||
return this.sources.stream().map(s -> s.normalize(this.name, this.namespace, this.labels))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -161,17 +158,13 @@ public class SecretsConfigProperties extends AbstractConfigProperties {
|
||||
return StringUtils.isEmpty(this.name) && StringUtils.isEmpty(this.namespace);
|
||||
}
|
||||
|
||||
public SecretsConfigProperties.NormalizedSource normalize(String defaultName,
|
||||
String defaultNamespace, Map<String, String> defaultLabels) {
|
||||
final String normalizedName = StringUtils.isEmpty(this.name) ? defaultName
|
||||
: this.name;
|
||||
final String normalizedNamespace = StringUtils.isEmpty(this.namespace)
|
||||
? defaultNamespace : this.namespace;
|
||||
final Map<String, String> normalizedLabels = this.labels.isEmpty()
|
||||
? defaultLabels : this.labels;
|
||||
public SecretsConfigProperties.NormalizedSource normalize(String defaultName, String defaultNamespace,
|
||||
Map<String, String> defaultLabels) {
|
||||
final String normalizedName = StringUtils.isEmpty(this.name) ? defaultName : this.name;
|
||||
final String normalizedNamespace = StringUtils.isEmpty(this.namespace) ? defaultNamespace : this.namespace;
|
||||
final Map<String, String> normalizedLabels = this.labels.isEmpty() ? defaultLabels : this.labels;
|
||||
|
||||
return new SecretsConfigProperties.NormalizedSource(normalizedName,
|
||||
normalizedNamespace, normalizedLabels);
|
||||
return new SecretsConfigProperties.NormalizedSource(normalizedName, normalizedNamespace, normalizedLabels);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,22 +41,18 @@ public class SecretsPropertySource extends MapPropertySource {
|
||||
|
||||
private static final String PREFIX = "secrets";
|
||||
|
||||
public SecretsPropertySource(KubernetesClient client, Environment env, String name,
|
||||
public SecretsPropertySource(KubernetesClient client, Environment env, String name, String namespace,
|
||||
Map<String, String> labels) {
|
||||
super(getSourceName(client, env, name, namespace), getSourceData(client, env, name, namespace, labels));
|
||||
}
|
||||
|
||||
private static String getSourceName(KubernetesClient client, Environment env, String name, String namespace) {
|
||||
return new StringBuilder().append(PREFIX).append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name)
|
||||
.append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(namespace).toString();
|
||||
}
|
||||
|
||||
private static Map<String, Object> getSourceData(KubernetesClient client, Environment env, String name,
|
||||
String namespace, Map<String, String> labels) {
|
||||
super(getSourceName(client, env, name, namespace),
|
||||
getSourceData(client, env, name, namespace, labels));
|
||||
}
|
||||
|
||||
private static String getSourceName(KubernetesClient client, Environment env,
|
||||
String name, String namespace) {
|
||||
return new StringBuilder().append(PREFIX)
|
||||
.append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(name)
|
||||
.append(Constants.PROPERTY_SOURCE_NAME_SEPARATOR).append(namespace)
|
||||
.toString();
|
||||
}
|
||||
|
||||
private static Map<String, Object> getSourceData(KubernetesClient client,
|
||||
Environment env, String name, String namespace, Map<String, String> labels) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
try {
|
||||
@@ -73,19 +69,17 @@ public class SecretsPropertySource extends MapPropertySource {
|
||||
// Read for secrets api (label)
|
||||
if (!labels.isEmpty()) {
|
||||
if (StringUtils.isEmpty(namespace)) {
|
||||
client.secrets().withLabels(labels).list().getItems()
|
||||
.forEach(s -> putAll(s, result));
|
||||
client.secrets().withLabels(labels).list().getItems().forEach(s -> putAll(s, result));
|
||||
}
|
||||
else {
|
||||
client.secrets().inNamespace(namespace).withLabels(labels).list()
|
||||
.getItems().forEach(s -> putAll(s, result));
|
||||
client.secrets().inNamespace(namespace).withLabels(labels).list().getItems()
|
||||
.forEach(s -> putAll(s, result));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn("Can't read secret with name: [" + name + "] or labels [" + labels
|
||||
+ "] in namespace:[" + namespace + "] (cause: " + e.getMessage()
|
||||
+ "). Ignoring");
|
||||
LOG.warn("Can't read secret with name: [" + name + "] or labels [" + labels + "] in namespace:[" + namespace
|
||||
+ "] (cause: " + e.getMessage() + "). Ignoring");
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -96,8 +90,7 @@ public class SecretsPropertySource extends MapPropertySource {
|
||||
// *****************************
|
||||
private static void putAll(Secret secret, Map<String, Object> result) {
|
||||
if (secret != null && secret.getData() != null) {
|
||||
secret.getData().forEach((k, v) -> result.put(k,
|
||||
new String(Base64.getDecoder().decode(v)).trim()));
|
||||
secret.getData().forEach((k, v) -> result.put(k, new String(Base64.getDecoder().decode(v)).trim()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,7 @@ public class SecretsPropertySourceLocator implements PropertySourceLocator {
|
||||
|
||||
private final SecretsConfigProperties properties;
|
||||
|
||||
public SecretsPropertySourceLocator(KubernetesClient client,
|
||||
SecretsConfigProperties properties) {
|
||||
public SecretsPropertySourceLocator(KubernetesClient client, SecretsConfigProperties properties) {
|
||||
this.client = client;
|
||||
this.properties = properties;
|
||||
}
|
||||
@@ -65,13 +64,11 @@ public class SecretsPropertySourceLocator implements PropertySourceLocator {
|
||||
if (environment instanceof ConfigurableEnvironment) {
|
||||
ConfigurableEnvironment env = (ConfigurableEnvironment) environment;
|
||||
|
||||
List<SecretsConfigProperties.NormalizedSource> sources = this.properties
|
||||
.determineSources();
|
||||
CompositePropertySource composite = new CompositePropertySource(
|
||||
"composite-secrets");
|
||||
List<SecretsConfigProperties.NormalizedSource> sources = this.properties.determineSources();
|
||||
CompositePropertySource composite = new CompositePropertySource("composite-secrets");
|
||||
if (this.properties.isEnableApi()) {
|
||||
sources.forEach(s -> composite.addFirstPropertySource(
|
||||
getKubernetesPropertySourceForSingleSecret(env, s)));
|
||||
sources.forEach(
|
||||
s -> composite.addFirstPropertySource(getKubernetesPropertySourceForSingleSecret(env, s)));
|
||||
}
|
||||
|
||||
// read for secrets mount
|
||||
@@ -82,29 +79,24 @@ public class SecretsPropertySourceLocator implements PropertySourceLocator {
|
||||
return null;
|
||||
}
|
||||
|
||||
private MapPropertySource getKubernetesPropertySourceForSingleSecret(
|
||||
ConfigurableEnvironment environment,
|
||||
private MapPropertySource getKubernetesPropertySourceForSingleSecret(ConfigurableEnvironment environment,
|
||||
SecretsConfigProperties.NormalizedSource normalizedSource) {
|
||||
|
||||
String configurationTarget = this.properties.getConfigurationTarget();
|
||||
return new SecretsPropertySource(this.client, environment,
|
||||
getApplicationName(environment, normalizedSource.getName(),
|
||||
configurationTarget),
|
||||
getApplicationNamespace(this.client, normalizedSource.getNamespace(),
|
||||
configurationTarget),
|
||||
getApplicationName(environment, normalizedSource.getName(), configurationTarget),
|
||||
getApplicationNamespace(this.client, normalizedSource.getNamespace(), configurationTarget),
|
||||
normalizedSource.getLabels());
|
||||
}
|
||||
|
||||
private void putPathConfig(CompositePropertySource composite) {
|
||||
this.properties.getPaths().stream().map(Paths::get).filter(Files::exists)
|
||||
.forEach(p -> putAll(p, composite));
|
||||
this.properties.getPaths().stream().map(Paths::get).filter(Files::exists).forEach(p -> putAll(p, composite));
|
||||
}
|
||||
|
||||
private void putAll(Path path, CompositePropertySource composite) {
|
||||
try {
|
||||
|
||||
Files.walk(path).filter(Files::isRegularFile)
|
||||
.forEach(p -> readFile(p, composite));
|
||||
Files.walk(path).filter(Files::isRegularFile).forEach(p -> readFile(p, composite));
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn("Error walking properties files", e);
|
||||
@@ -114,11 +106,10 @@ public class SecretsPropertySourceLocator implements PropertySourceLocator {
|
||||
private void readFile(Path path, CompositePropertySource composite) {
|
||||
try {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put(path.getFileName().toString(),
|
||||
new String(Files.readAllBytes(path)).trim());
|
||||
result.put(path.getFileName().toString(), new String(Files.readAllBytes(path)).trim());
|
||||
if (!result.isEmpty()) {
|
||||
composite.addFirstPropertySource(new MapPropertySource(
|
||||
path.getFileName().toString().toLowerCase(), result));
|
||||
composite.addFirstPropertySource(
|
||||
new MapPropertySource(path.getFileName().toString().toLowerCase(), result));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
|
||||
@@ -50,8 +50,8 @@ import org.springframework.util.Assert;
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(value = "spring.cloud.kubernetes.enabled", matchIfMissing = true)
|
||||
@ConditionalOnClass(EndpointAutoConfiguration.class)
|
||||
@AutoConfigureAfter({ InfoEndpointAutoConfiguration.class,
|
||||
RefreshEndpointAutoConfiguration.class, RefreshAutoConfiguration.class })
|
||||
@AutoConfigureAfter({ InfoEndpointAutoConfiguration.class, RefreshEndpointAutoConfiguration.class,
|
||||
RefreshAutoConfiguration.class })
|
||||
@EnableConfigurationProperties(ConfigReloadProperties.class)
|
||||
|
||||
public class ConfigReloadAutoConfiguration {
|
||||
@@ -84,22 +84,17 @@ public class ConfigReloadAutoConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ConfigurationChangeDetector propertyChangeWatcher(
|
||||
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy) {
|
||||
public ConfigurationChangeDetector propertyChangeWatcher(ConfigReloadProperties properties,
|
||||
ConfigurationUpdateStrategy strategy) {
|
||||
switch (properties.getMode()) {
|
||||
case POLLING:
|
||||
return new PollingConfigurationChangeDetector(this.environment,
|
||||
properties, this.kubernetesClient, strategy,
|
||||
this.configMapPropertySourceLocator,
|
||||
this.secretsPropertySourceLocator);
|
||||
return new PollingConfigurationChangeDetector(this.environment, properties, this.kubernetesClient,
|
||||
strategy, this.configMapPropertySourceLocator, this.secretsPropertySourceLocator);
|
||||
case EVENT:
|
||||
return new EventBasedConfigurationChangeDetector(this.environment,
|
||||
properties, this.kubernetesClient, strategy,
|
||||
this.configMapPropertySourceLocator,
|
||||
this.secretsPropertySourceLocator);
|
||||
return new EventBasedConfigurationChangeDetector(this.environment, properties, this.kubernetesClient,
|
||||
strategy, this.configMapPropertySourceLocator, this.secretsPropertySourceLocator);
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"Unsupported configuration reload mode: " + properties.getMode());
|
||||
throw new IllegalStateException("Unsupported configuration reload mode: " + properties.getMode());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,35 +106,29 @@ public class ConfigReloadAutoConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ConfigurationUpdateStrategy configurationUpdateStrategy(
|
||||
ConfigReloadProperties properties, ConfigurableApplicationContext ctx,
|
||||
@Autowired(required = false) RestartEndpoint restarter,
|
||||
public ConfigurationUpdateStrategy configurationUpdateStrategy(ConfigReloadProperties properties,
|
||||
ConfigurableApplicationContext ctx, @Autowired(required = false) RestartEndpoint restarter,
|
||||
ContextRefresher refresher) {
|
||||
switch (properties.getStrategy()) {
|
||||
case RESTART_CONTEXT:
|
||||
Assert.notNull(restarter, "Restart endpoint is not enabled");
|
||||
return new ConfigurationUpdateStrategy(properties.getStrategy().name(),
|
||||
() -> {
|
||||
wait(properties);
|
||||
restarter.restart();
|
||||
});
|
||||
return new ConfigurationUpdateStrategy(properties.getStrategy().name(), () -> {
|
||||
wait(properties);
|
||||
restarter.restart();
|
||||
});
|
||||
case REFRESH:
|
||||
return new ConfigurationUpdateStrategy(properties.getStrategy().name(),
|
||||
refresher::refresh);
|
||||
return new ConfigurationUpdateStrategy(properties.getStrategy().name(), refresher::refresh);
|
||||
case SHUTDOWN:
|
||||
return new ConfigurationUpdateStrategy(properties.getStrategy().name(),
|
||||
() -> {
|
||||
wait(properties);
|
||||
ctx.close();
|
||||
});
|
||||
return new ConfigurationUpdateStrategy(properties.getStrategy().name(), () -> {
|
||||
wait(properties);
|
||||
ctx.close();
|
||||
});
|
||||
}
|
||||
throw new IllegalStateException("Unsupported configuration update strategy: "
|
||||
+ properties.getStrategy());
|
||||
throw new IllegalStateException("Unsupported configuration update strategy: " + properties.getStrategy());
|
||||
}
|
||||
|
||||
private static void wait(ConfigReloadProperties properties) {
|
||||
final long waitMillis = ThreadLocalRandom.current()
|
||||
.nextLong(properties.getMaxWaitForRestart().toMillis());
|
||||
final long waitMillis = ThreadLocalRandom.current().nextLong(properties.getMaxWaitForRestart().toMillis());
|
||||
try {
|
||||
Thread.sleep(waitMillis);
|
||||
}
|
||||
|
||||
@@ -69,22 +69,17 @@ public class ConfigReloadDefaultAutoConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ConfigurationChangeDetector propertyChangeWatcher(
|
||||
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy) {
|
||||
public ConfigurationChangeDetector propertyChangeWatcher(ConfigReloadProperties properties,
|
||||
ConfigurationUpdateStrategy strategy) {
|
||||
switch (properties.getMode()) {
|
||||
case POLLING:
|
||||
return new PollingConfigurationChangeDetector(this.environment,
|
||||
properties, this.kubernetesClient, strategy,
|
||||
this.configMapPropertySourceLocator,
|
||||
this.secretsPropertySourceLocator);
|
||||
return new PollingConfigurationChangeDetector(this.environment, properties, this.kubernetesClient,
|
||||
strategy, this.configMapPropertySourceLocator, this.secretsPropertySourceLocator);
|
||||
case EVENT:
|
||||
return new EventBasedConfigurationChangeDetector(this.environment,
|
||||
properties, this.kubernetesClient, strategy,
|
||||
this.configMapPropertySourceLocator,
|
||||
this.secretsPropertySourceLocator);
|
||||
return new EventBasedConfigurationChangeDetector(this.environment, properties, this.kubernetesClient,
|
||||
strategy, this.configMapPropertySourceLocator, this.secretsPropertySourceLocator);
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"Unsupported configuration reload mode: " + properties.getMode());
|
||||
throw new IllegalStateException("Unsupported configuration reload mode: " + properties.getMode());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,23 +91,20 @@ public class ConfigReloadDefaultAutoConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ConfigurationUpdateStrategy configurationUpdateStrategy(
|
||||
ConfigReloadProperties properties, ConfigurableApplicationContext ctx) {
|
||||
public ConfigurationUpdateStrategy configurationUpdateStrategy(ConfigReloadProperties properties,
|
||||
ConfigurableApplicationContext ctx) {
|
||||
switch (properties.getStrategy()) {
|
||||
case SHUTDOWN:
|
||||
return new ConfigurationUpdateStrategy(properties.getStrategy().name(),
|
||||
() -> {
|
||||
wait(properties);
|
||||
ctx.close();
|
||||
});
|
||||
return new ConfigurationUpdateStrategy(properties.getStrategy().name(), () -> {
|
||||
wait(properties);
|
||||
ctx.close();
|
||||
});
|
||||
}
|
||||
throw new IllegalStateException("Unsupported configuration update strategy: "
|
||||
+ properties.getStrategy());
|
||||
throw new IllegalStateException("Unsupported configuration update strategy: " + properties.getStrategy());
|
||||
}
|
||||
|
||||
private static void wait(ConfigReloadProperties properties) {
|
||||
final long waitMillis = ThreadLocalRandom.current()
|
||||
.nextLong(properties.getMaxWaitForRestart().toMillis());
|
||||
final long waitMillis = ThreadLocalRandom.current().nextLong(properties.getMaxWaitForRestart().toMillis());
|
||||
try {
|
||||
Thread.sleep(waitMillis);
|
||||
}
|
||||
|
||||
@@ -54,9 +54,8 @@ public abstract class ConfigurationChangeDetector {
|
||||
|
||||
protected ConfigurationUpdateStrategy strategy;
|
||||
|
||||
public ConfigurationChangeDetector(ConfigurableEnvironment environment,
|
||||
ConfigReloadProperties properties, KubernetesClient kubernetesClient,
|
||||
ConfigurationUpdateStrategy strategy) {
|
||||
public ConfigurationChangeDetector(ConfigurableEnvironment environment, ConfigReloadProperties properties,
|
||||
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy) {
|
||||
this.environment = environment;
|
||||
this.properties = properties;
|
||||
this.kubernetesClient = kubernetesClient;
|
||||
@@ -95,13 +94,11 @@ public abstract class ConfigurationChangeDetector {
|
||||
return s1 == null ? s2 != null : !s1.equals(s2);
|
||||
}
|
||||
|
||||
protected boolean changed(List<? extends MapPropertySource> l1,
|
||||
List<? extends MapPropertySource> l2) {
|
||||
protected boolean changed(List<? extends MapPropertySource> l1, List<? extends MapPropertySource> l2) {
|
||||
|
||||
if (l1.size() != l2.size()) {
|
||||
this.log.warn(
|
||||
"The current number of ConfigMap PropertySources does not match "
|
||||
+ "the ones loaded from the Kubernetes - No reload will take place");
|
||||
this.log.warn("The current number of ConfigMap PropertySources does not match "
|
||||
+ "the ones loaded from the Kubernetes - No reload will take place");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -136,12 +133,10 @@ public abstract class ConfigurationChangeDetector {
|
||||
* @param sourceClass class for which property sources will be found
|
||||
* @return finds all registered property sources of the given type
|
||||
*/
|
||||
protected <S extends PropertySource<?>> List<S> findPropertySources(
|
||||
Class<S> sourceClass) {
|
||||
protected <S extends PropertySource<?>> List<S> findPropertySources(Class<S> sourceClass) {
|
||||
List<S> managedSources = new LinkedList<>();
|
||||
|
||||
LinkedList<PropertySource<?>> sources = toLinkedList(
|
||||
this.environment.getPropertySources());
|
||||
LinkedList<PropertySource<?>> sources = toLinkedList(this.environment.getPropertySources());
|
||||
while (!sources.isEmpty()) {
|
||||
PropertySource<?> source = sources.pop();
|
||||
if (source instanceof CompositePropertySource) {
|
||||
@@ -152,8 +147,7 @@ public abstract class ConfigurationChangeDetector {
|
||||
managedSources.add(sourceClass.cast(source));
|
||||
}
|
||||
else if (BootstrapPropertySource.class.isInstance(source)) {
|
||||
PropertySource propertySource = ((BootstrapPropertySource) source)
|
||||
.getDelegate();
|
||||
PropertySource propertySource = ((BootstrapPropertySource) source).getDelegate();
|
||||
if (sourceClass.isInstance(propertySource)) {
|
||||
sources.add(propertySource);
|
||||
}
|
||||
@@ -179,8 +173,8 @@ public abstract class ConfigurationChangeDetector {
|
||||
* @return a list of MapPropertySource that correspond to the current state of the
|
||||
* system
|
||||
*/
|
||||
protected List<MapPropertySource> locateMapPropertySources(
|
||||
PropertySourceLocator propertySourceLocator, Environment environment) {
|
||||
protected List<MapPropertySource> locateMapPropertySources(PropertySourceLocator propertySourceLocator,
|
||||
Environment environment) {
|
||||
|
||||
List<MapPropertySource> result = new ArrayList<>();
|
||||
PropertySource propertySource = propertySourceLocator.locate(environment);
|
||||
@@ -188,13 +182,12 @@ public abstract class ConfigurationChangeDetector {
|
||||
result.add((MapPropertySource) propertySource);
|
||||
}
|
||||
else if (propertySource instanceof CompositePropertySource) {
|
||||
result.addAll(((CompositePropertySource) propertySource).getPropertySources()
|
||||
.stream().filter(p -> p instanceof MapPropertySource)
|
||||
.map(p -> (MapPropertySource) p).collect(Collectors.toList()));
|
||||
result.addAll(((CompositePropertySource) propertySource).getPropertySources().stream()
|
||||
.filter(p -> p instanceof MapPropertySource).map(p -> (MapPropertySource) p)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
else {
|
||||
this.log.debug("Found property source that cannot be handled: "
|
||||
+ propertySource.getClass());
|
||||
this.log.debug("Found property source that cannot be handled: " + propertySource.getClass());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -50,9 +50,8 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe
|
||||
|
||||
private Map<String, Watch> watches;
|
||||
|
||||
public EventBasedConfigurationChangeDetector(AbstractEnvironment environment,
|
||||
ConfigReloadProperties properties, KubernetesClient kubernetesClient,
|
||||
ConfigurationUpdateStrategy strategy,
|
||||
public EventBasedConfigurationChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
|
||||
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
|
||||
ConfigMapPropertySourceLocator configMapPropertySourceLocator,
|
||||
SecretsPropertySourceLocator secretsPropertySourceLocator) {
|
||||
super(environment, properties, kubernetesClient, strategy);
|
||||
@@ -69,22 +68,19 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe
|
||||
if (this.properties.isMonitoringConfigMaps()) {
|
||||
try {
|
||||
String name = "config-maps-watch";
|
||||
this.watches.put(name, this.kubernetesClient.configMaps()
|
||||
.watch(new Watcher<ConfigMap>() {
|
||||
@Override
|
||||
public void eventReceived(Action action,
|
||||
ConfigMap configMap) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(name + " received event for ConfigMap "
|
||||
+ configMap.getMetadata().getName());
|
||||
}
|
||||
onEvent(configMap);
|
||||
}
|
||||
this.watches.put(name, this.kubernetesClient.configMaps().watch(new Watcher<ConfigMap>() {
|
||||
@Override
|
||||
public void eventReceived(Action action, ConfigMap configMap) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(name + " received event for ConfigMap " + configMap.getMetadata().getName());
|
||||
}
|
||||
onEvent(configMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(KubernetesClientException e) {
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onClose(KubernetesClientException e) {
|
||||
}
|
||||
}));
|
||||
activated = true;
|
||||
this.log.info("Added new Kubernetes watch: " + name);
|
||||
}
|
||||
@@ -99,34 +95,30 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe
|
||||
try {
|
||||
activated = false;
|
||||
String name = "secrets-watch";
|
||||
this.watches.put(name,
|
||||
this.kubernetesClient.secrets().watch(new Watcher<Secret>() {
|
||||
@Override
|
||||
public void eventReceived(Action action, Secret secret) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(name + " received and event for Secret "
|
||||
+ secret.getMetadata().getName());
|
||||
}
|
||||
onEvent(secret);
|
||||
}
|
||||
this.watches.put(name, this.kubernetesClient.secrets().watch(new Watcher<Secret>() {
|
||||
@Override
|
||||
public void eventReceived(Action action, Secret secret) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(name + " received and event for Secret " + secret.getMetadata().getName());
|
||||
}
|
||||
onEvent(secret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(KubernetesClientException e) {
|
||||
}
|
||||
}));
|
||||
@Override
|
||||
public void onClose(KubernetesClientException e) {
|
||||
}
|
||||
}));
|
||||
activated = true;
|
||||
this.log.info("Added new Kubernetes watch: " + name);
|
||||
}
|
||||
catch (Exception e) {
|
||||
this.log.error(
|
||||
"Error while establishing a connection to watch secrets: configuration may remain stale",
|
||||
this.log.error("Error while establishing a connection to watch secrets: configuration may remain stale",
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
if (activated) {
|
||||
this.log.info(
|
||||
"Kubernetes event-based configuration change detector activated");
|
||||
this.log.info("Kubernetes event-based configuration change detector activated");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,9 +139,7 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe
|
||||
}
|
||||
|
||||
protected void onEvent(ConfigMap configMap) {
|
||||
boolean changed = changed(
|
||||
locateMapPropertySources(this.configMapPropertySourceLocator,
|
||||
this.environment),
|
||||
boolean changed = changed(locateMapPropertySources(this.configMapPropertySourceLocator, this.environment),
|
||||
findPropertySources(ConfigMapPropertySource.class));
|
||||
if (changed) {
|
||||
this.log.info("Detected change in config maps");
|
||||
@@ -158,9 +148,7 @@ public class EventBasedConfigurationChangeDetector extends ConfigurationChangeDe
|
||||
}
|
||||
|
||||
protected void onEvent(Secret secret) {
|
||||
boolean changed = changed(
|
||||
locateMapPropertySources(this.secretsPropertySourceLocator,
|
||||
this.environment),
|
||||
boolean changed = changed(locateMapPropertySources(this.secretsPropertySourceLocator, this.environment),
|
||||
findPropertySources(SecretsPropertySource.class));
|
||||
if (changed) {
|
||||
this.log.info("Detected change in secrets");
|
||||
|
||||
@@ -47,9 +47,8 @@ public class PollingConfigurationChangeDetector extends ConfigurationChangeDetec
|
||||
|
||||
private SecretsPropertySourceLocator secretsPropertySourceLocator;
|
||||
|
||||
public PollingConfigurationChangeDetector(AbstractEnvironment environment,
|
||||
ConfigReloadProperties properties, KubernetesClient kubernetesClient,
|
||||
ConfigurationUpdateStrategy strategy,
|
||||
public PollingConfigurationChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
|
||||
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
|
||||
ConfigMapPropertySourceLocator configMapPropertySourceLocator,
|
||||
SecretsPropertySourceLocator secretsPropertySourceLocator) {
|
||||
super(environment, properties, kubernetesClient, strategy);
|
||||
@@ -74,19 +73,17 @@ public class PollingConfigurationChangeDetector extends ConfigurationChangeDetec
|
||||
|
||||
if (!currentConfigMapSources.isEmpty()) {
|
||||
changedConfigMap = changed(
|
||||
locateMapPropertySources(this.configMapPropertySourceLocator,
|
||||
this.environment),
|
||||
locateMapPropertySources(this.configMapPropertySourceLocator, this.environment),
|
||||
currentConfigMapSources);
|
||||
}
|
||||
}
|
||||
|
||||
boolean changedSecrets = false;
|
||||
if (this.properties.isMonitoringSecrets()) {
|
||||
List<MapPropertySource> currentSecretSources = locateMapPropertySources(
|
||||
this.secretsPropertySourceLocator, this.environment);
|
||||
List<MapPropertySource> currentSecretSources = locateMapPropertySources(this.secretsPropertySourceLocator,
|
||||
this.environment);
|
||||
if (currentSecretSources != null && !currentSecretSources.isEmpty()) {
|
||||
List<SecretsPropertySource> propertySources = findPropertySources(
|
||||
SecretsPropertySource.class);
|
||||
List<SecretsPropertySource> propertySources = findPropertySources(SecretsPropertySource.class);
|
||||
changedSecrets = changed(currentSecretSources, propertySources);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,7 @@ final class ConfigMapTestUtil {
|
||||
static String readResourceFile(String file) {
|
||||
String resource;
|
||||
try {
|
||||
resource = IOHelpers.readFully(
|
||||
ConfigMapTestUtil.class.getClassLoader().getResourceAsStream(file));
|
||||
resource = IOHelpers.readFully(ConfigMapTestUtil.class.getClassLoader().getResourceAsStream(file));
|
||||
}
|
||||
catch (IOException e) {
|
||||
resource = "";
|
||||
|
||||
@@ -39,12 +39,10 @@ import static org.assertj.core.util.Lists.newArrayList;
|
||||
import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.createFileWithContent;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class,
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
|
||||
properties = { "spring.application.name=configmap-path-example",
|
||||
"spring.cloud.kubernetes.config.enableApi=false",
|
||||
"spring.cloud.kubernetes.config.paths="
|
||||
+ ConfigMapsFromFilePathsTests.FIRST_FILE_NAME_FULL_PATH + ","
|
||||
"spring.cloud.kubernetes.config.paths=" + ConfigMapsFromFilePathsTests.FIRST_FILE_NAME_FULL_PATH + ","
|
||||
+ ConfigMapsFromFilePathsTests.SECOND_FILE_NAME_FULL_PATH })
|
||||
public class ConfigMapsFromFilePathsTests {
|
||||
|
||||
@@ -56,14 +54,11 @@ public class ConfigMapsFromFilePathsTests {
|
||||
|
||||
protected static final String UNUSED_FILE_NAME = "unused.properties";
|
||||
|
||||
protected static final String FIRST_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/"
|
||||
+ FIRST_FILE_NAME;
|
||||
protected static final String FIRST_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" + FIRST_FILE_NAME;
|
||||
|
||||
protected static final String SECOND_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/"
|
||||
+ SECOND_FILE_NAME;
|
||||
protected static final String SECOND_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" + SECOND_FILE_NAME;
|
||||
|
||||
protected static final String UNUSED_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/"
|
||||
+ UNUSED_FILE_NAME;
|
||||
protected static final String UNUSED_FILE_NAME_FULL_PATH = FILES_ROOT_PATH + "/" + UNUSED_FILE_NAME;
|
||||
|
||||
@ClassRule
|
||||
public static KubernetesServer server = new KubernetesServer();
|
||||
@@ -78,27 +73,23 @@ public class ConfigMapsFromFilePathsTests {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
Files.createDirectories(Paths.get(FILES_ROOT_PATH));
|
||||
createFileWithContent(FIRST_FILE_NAME_FULL_PATH,
|
||||
"bean.greeting=Hello from path!");
|
||||
createFileWithContent(FIRST_FILE_NAME_FULL_PATH, "bean.greeting=Hello from path!");
|
||||
createFileWithContent(SECOND_FILE_NAME_FULL_PATH, "bean.farewell=Bye from path!");
|
||||
createFileWithContent(UNUSED_FILE_NAME_FULL_PATH,
|
||||
"bean.morning=Morning from path!");
|
||||
createFileWithContent(UNUSED_FILE_NAME_FULL_PATH, "bean.morning=Morning from path!");
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardownAfterClass() {
|
||||
newArrayList(FIRST_FILE_NAME_FULL_PATH, SECOND_FILE_NAME_FULL_PATH,
|
||||
SECOND_FILE_NAME_FULL_PATH, FILES_ROOT_PATH).forEach(fn -> {
|
||||
newArrayList(FIRST_FILE_NAME_FULL_PATH, SECOND_FILE_NAME_FULL_PATH, SECOND_FILE_NAME_FULL_PATH, FILES_ROOT_PATH)
|
||||
.forEach(fn -> {
|
||||
try {
|
||||
Files.delete(Paths.get(fn));
|
||||
}
|
||||
@@ -109,20 +100,20 @@ public class ConfigMapsFromFilePathsTests {
|
||||
|
||||
@Test
|
||||
public void greetingInputShouldReturnPropertyFromFirstFile() {
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content").isEqualTo("Hello from path!");
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Hello from path!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void farewellInputShouldReturnPropertyFromSecondFile() {
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content").isEqualTo("Bye from path!");
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Bye from path!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void morningInputShouldReturnDefaultValue() {
|
||||
this.webClient.get().uri("/api/morning").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content").isEqualTo("Good morning, World!");
|
||||
this.webClient.get().uri("/api/morning").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Good morning, World!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,12 +41,10 @@ import static org.assertj.core.util.Lists.newArrayList;
|
||||
import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class,
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
|
||||
properties = { "spring.application.name=" + ConfigMapsMixedTests.APPLICATION_NAME,
|
||||
"spring.cloud.kubernetes.config.enableApi=true",
|
||||
"spring.cloud.kubernetes.config.paths="
|
||||
+ ConfigMapsMixedTests.FILE_NAME_FULL_PATH })
|
||||
"spring.cloud.kubernetes.config.paths=" + ConfigMapsMixedTests.FILE_NAME_FULL_PATH })
|
||||
public class ConfigMapsMixedTests {
|
||||
|
||||
protected static final String FILES_ROOT_PATH = "/tmp/scktests";
|
||||
@@ -70,24 +68,21 @@ public class ConfigMapsMixedTests {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
Files.createDirectories(Paths.get(FILES_ROOT_PATH));
|
||||
ConfigMapTestUtil.createFileWithContent(FILE_NAME_FULL_PATH,
|
||||
readResourceFile("application-path.yaml"));
|
||||
ConfigMapTestUtil.createFileWithContent(FILE_NAME_FULL_PATH, readResourceFile("application-path.yaml"));
|
||||
|
||||
HashMap<String, String> data = new HashMap<>();
|
||||
data.put("bean.morning", "Buenos Dias ConfigMap, %s");
|
||||
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(APPLICATION_NAME).endMetadata().addToData(data).build())
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata()
|
||||
.addToData(data).build())
|
||||
.always();
|
||||
}
|
||||
|
||||
@@ -104,22 +99,19 @@ public class ConfigMapsMixedTests {
|
||||
|
||||
@Test
|
||||
public void greetingInputShouldReturnPropertyFromFile() {
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content")
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Hello ConfigMap, World from path");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void farewellInputShouldReturnPropertyFromFile() {
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content")
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Bye ConfigMap, World from path");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void morningInputShouldReturnPropertyFromApi() {
|
||||
this.webClient.get().uri("/api/morning").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content")
|
||||
this.webClient.get().uri("/api/morning").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Buenos Dias ConfigMap, World");
|
||||
}
|
||||
|
||||
|
||||
@@ -51,11 +51,9 @@ public class ConfigMapsTest {
|
||||
|
||||
@Test
|
||||
public void testConfigMapGet() {
|
||||
this.server.expect().withPath("/api/v1/namespaces/ns2/configmaps")
|
||||
.andReturn(200,
|
||||
new ConfigMapBuilder().withNewMetadata()
|
||||
.withName("reload-example").endMetadata()
|
||||
.addToData("KEY", "123").build())
|
||||
this.server
|
||||
.expect().withPath("/api/v1/namespaces/ns2/configmaps").andReturn(200, new ConfigMapBuilder()
|
||||
.withNewMetadata().withName("reload-example").endMetadata().addToData("KEY", "123").build())
|
||||
.once();
|
||||
|
||||
KubernetesClient client = this.server.getClient();
|
||||
@@ -63,8 +61,7 @@ public class ConfigMapsTest {
|
||||
assertThat(configMapList).isNotNull();
|
||||
assertThat(configMapList.getAdditionalProperties()).containsKey("data");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> data = (Map<String, String>) configMapList
|
||||
.getAdditionalProperties().get("data");
|
||||
Map<String, String> data = (Map<String, String>) configMapList.getAdditionalProperties().get("data");
|
||||
assertThat(data.get("KEY")).isEqualTo("123");
|
||||
}
|
||||
|
||||
@@ -72,18 +69,13 @@ public class ConfigMapsTest {
|
||||
public void testConfigMapFromSingleApplicationProperties() {
|
||||
String configMapName = "app-properties-test";
|
||||
String namespace = "app-props";
|
||||
this.server.expect()
|
||||
.withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace,
|
||||
configMapName))
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(configMapName).endMetadata()
|
||||
.addToData("application.properties",
|
||||
readResourceFile("application.properties"))
|
||||
.build())
|
||||
this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName))
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata()
|
||||
.addToData("application.properties", readResourceFile("application.properties")).build())
|
||||
.once();
|
||||
|
||||
ConfigMapPropertySource cmps = new ConfigMapPropertySource(
|
||||
this.server.getClient().inNamespace(namespace), configMapName);
|
||||
ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace),
|
||||
configMapName);
|
||||
|
||||
assertThat(cmps.getProperty("dummy.property.string1")).isEqualTo("a");
|
||||
assertThat(cmps.getProperty("dummy.property.int1")).isEqualTo("1");
|
||||
@@ -94,19 +86,13 @@ public class ConfigMapsTest {
|
||||
public void testConfigMapFromSingleApplicationYaml() {
|
||||
String configMapName = "app-yaml-test";
|
||||
String namespace = "app-props";
|
||||
this.server.expect()
|
||||
.withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace,
|
||||
configMapName))
|
||||
.andReturn(200,
|
||||
new ConfigMapBuilder().withNewMetadata().withName(configMapName)
|
||||
.endMetadata()
|
||||
.addToData("application.yaml",
|
||||
readResourceFile("application.yaml"))
|
||||
.build())
|
||||
this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName))
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata()
|
||||
.addToData("application.yaml", readResourceFile("application.yaml")).build())
|
||||
.once();
|
||||
|
||||
ConfigMapPropertySource cmps = new ConfigMapPropertySource(
|
||||
this.server.getClient().inNamespace(namespace), configMapName);
|
||||
ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace),
|
||||
configMapName);
|
||||
|
||||
assertThat(cmps.getProperty("dummy.property.string2")).isEqualTo("a");
|
||||
assertThat(cmps.getProperty("dummy.property.int2")).isEqualTo(1);
|
||||
@@ -117,16 +103,13 @@ public class ConfigMapsTest {
|
||||
public void testConfigMapFromSingleNonStandardFileName() {
|
||||
String configMapName = "single-non-standard-test";
|
||||
String namespace = "app-props";
|
||||
this.server.expect()
|
||||
.withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace,
|
||||
configMapName))
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(configMapName).endMetadata()
|
||||
this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName))
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata()
|
||||
.addToData("adhoc.yml", readResourceFile("adhoc.yml")).build())
|
||||
.once();
|
||||
|
||||
ConfigMapPropertySource cmps = new ConfigMapPropertySource(
|
||||
this.server.getClient().inNamespace(namespace), configMapName);
|
||||
ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace),
|
||||
configMapName);
|
||||
|
||||
assertThat(cmps.getProperty("dummy.property.string3")).isEqualTo("a");
|
||||
assertThat(cmps.getProperty("dummy.property.int3")).isEqualTo(1);
|
||||
@@ -137,17 +120,12 @@ public class ConfigMapsTest {
|
||||
public void testConfigMapFromSingleInvalidPropertiesContent() {
|
||||
String configMapName = "single-unparseable-properties-test";
|
||||
String namespace = "app-props";
|
||||
this.server.expect()
|
||||
.withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace,
|
||||
configMapName))
|
||||
.andReturn(200,
|
||||
new ConfigMapBuilder().withNewMetadata().withName(configMapName)
|
||||
.endMetadata()
|
||||
.addToData("application.properties", "somevalue").build())
|
||||
this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName))
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata()
|
||||
.addToData("application.properties", "somevalue").build())
|
||||
.once();
|
||||
|
||||
new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace),
|
||||
configMapName);
|
||||
new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), configMapName);
|
||||
|
||||
// no exception is thrown for unparseable content
|
||||
}
|
||||
@@ -156,17 +134,12 @@ public class ConfigMapsTest {
|
||||
public void testConfigMapFromSingleInvalidYamlContent() {
|
||||
String configMapName = "single-unparseable-yaml-test";
|
||||
String namespace = "app-props";
|
||||
this.server.expect()
|
||||
.withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace,
|
||||
configMapName))
|
||||
.andReturn(200,
|
||||
new ConfigMapBuilder().withNewMetadata().withName(configMapName)
|
||||
.endMetadata().addToData("application.yaml", "somevalue")
|
||||
.build())
|
||||
this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName))
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata()
|
||||
.addToData("application.yaml", "somevalue").build())
|
||||
.once();
|
||||
|
||||
new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace),
|
||||
configMapName);
|
||||
new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace), configMapName);
|
||||
|
||||
// no exception is thrown for unparseable content
|
||||
}
|
||||
@@ -175,21 +148,15 @@ public class ConfigMapsTest {
|
||||
public void testConfigMapFromMultipleApplicationProperties() {
|
||||
String configMapName = "app-multiple-properties-test";
|
||||
String namespace = "app-props";
|
||||
this.server.expect()
|
||||
.withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace,
|
||||
configMapName))
|
||||
this.server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName))
|
||||
.andReturn(200,
|
||||
new ConfigMapBuilder().withNewMetadata().withName(configMapName)
|
||||
.endMetadata()
|
||||
.addToData("application.properties",
|
||||
readResourceFile("application.properties"))
|
||||
.addToData("adhoc.properties",
|
||||
readResourceFile("adhoc.properties"))
|
||||
.build())
|
||||
new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata()
|
||||
.addToData("application.properties", readResourceFile("application.properties"))
|
||||
.addToData("adhoc.properties", readResourceFile("adhoc.properties")).build())
|
||||
.once();
|
||||
|
||||
ConfigMapPropertySource cmps = new ConfigMapPropertySource(
|
||||
this.server.getClient().inNamespace(namespace), configMapName);
|
||||
ConfigMapPropertySource cmps = new ConfigMapPropertySource(this.server.getClient().inNamespace(namespace),
|
||||
configMapName);
|
||||
|
||||
// application.properties should be read correctly
|
||||
assertThat(cmps.getProperty("dummy.property.string1")).isEqualTo("a");
|
||||
|
||||
@@ -41,9 +41,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Charles Moulliard
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class, properties = { "spring.application.name=configmap-example",
|
||||
"spring.cloud.kubernetes.reload.enabled=false" })
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
|
||||
properties = { "spring.application.name=configmap-example", "spring.cloud.kubernetes.reload.enabled=false" })
|
||||
@AutoConfigureWebTestClient
|
||||
public class ConfigMapsTests {
|
||||
|
||||
@@ -65,42 +64,38 @@ public class ConfigMapsTests {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
HashMap<String, String> data = new HashMap<>();
|
||||
data.put("bean.greeting", "Hello ConfigMap, %s!");
|
||||
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(APPLICATION_NAME).endMetadata().addToData(data).build())
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata()
|
||||
.addToData(data).build())
|
||||
.always();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfig() {
|
||||
assertThat(mockClient.getConfiguration().getMasterUrl())
|
||||
.isEqualTo(this.config.getMasterUrl());
|
||||
assertThat(mockClient.getConfiguration().getMasterUrl()).isEqualTo(this.config.getMasterUrl());
|
||||
assertThat(mockClient.getNamespace()).isEqualTo(this.config.getNamespace());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigMap() {
|
||||
ConfigMap configmap = mockClient.configMaps().inNamespace("test")
|
||||
.withName(APPLICATION_NAME).get();
|
||||
ConfigMap configmap = mockClient.configMaps().inNamespace("test").withName(APPLICATION_NAME).get();
|
||||
HashMap<String, String> keys = (HashMap<String, String>) configmap.getData();
|
||||
assertThat("Hello ConfigMap, %s!").isEqualTo(keys.get("bean.greeting"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGreetingEndpoint() {
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content").isEqualTo("Hello ConfigMap, World!");
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Hello ConfigMap, World!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,8 +43,7 @@ import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.read
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = App.class,
|
||||
properties = {
|
||||
"spring.application.name=configmap-with-active-profile-name-example",
|
||||
properties = { "spring.application.name=configmap-with-active-profile-name-example",
|
||||
"spring.cloud.kubernetes.reload.enabled=false" })
|
||||
@ActiveProfiles("development")
|
||||
@AutoConfigureWebTestClient
|
||||
@@ -68,46 +67,37 @@ public class ConfigMapsWithActiveProfilesNameTests {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
HashMap<String, String> data = new HashMap<>();
|
||||
data.put("application.yml", readResourceFile("application-with-profiles.yaml"));
|
||||
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(APPLICATION_NAME).endMetadata().addToData(data).build())
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata()
|
||||
.addToData(data).build())
|
||||
.always();
|
||||
|
||||
HashMap<String, String> dataWithName = new HashMap<>();
|
||||
dataWithName.put("application.yml",
|
||||
readResourceFile("application-with-active-profiles-name.yaml"));
|
||||
server.expect()
|
||||
.withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME
|
||||
+ "-development")
|
||||
.andReturn(200,
|
||||
new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(APPLICATION_NAME + "-development").endMetadata()
|
||||
.addToData(dataWithName).build())
|
||||
dataWithName.put("application.yml", readResourceFile("application-with-active-profiles-name.yaml"));
|
||||
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME + "-development")
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME + "-development")
|
||||
.endMetadata().addToData(dataWithName).build())
|
||||
.always();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGreetingEndpoint() {
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content")
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Hello ConfigMap Active Profile Name, World!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFarewellEndpoint() {
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content")
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Goodbye ConfigMap default, World!");
|
||||
}
|
||||
|
||||
|
||||
@@ -41,10 +41,8 @@ import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.read
|
||||
* Tests reading property from YAML document specified by profile expression.
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class,
|
||||
properties = { "spring.application.name=configmap-with-profile-example",
|
||||
"spring.cloud.kubernetes.reload.enabled=false" })
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = {
|
||||
"spring.application.name=configmap-with-profile-example", "spring.cloud.kubernetes.reload.enabled=false" })
|
||||
@ActiveProfiles({ "production", "us-east" })
|
||||
@AutoConfigureWebTestClient
|
||||
public class ConfigMapsWithProfileExpressionTests {
|
||||
@@ -62,27 +60,24 @@ public class ConfigMapsWithProfileExpressionTests {
|
||||
KubernetesClient 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
HashMap<String, String> data = new HashMap<>();
|
||||
data.put("application.yml", readResourceFile("application-with-profiles.yaml"));
|
||||
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(APPLICATION_NAME).endMetadata().addToData(data).build())
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata()
|
||||
.addToData(data).build())
|
||||
.always();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGreetingEndpoint() {
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content")
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Hello ConfigMap production and us-east, World!");
|
||||
}
|
||||
|
||||
|
||||
@@ -40,10 +40,8 @@ import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.read
|
||||
* @author Charles Moulliard
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class,
|
||||
properties = {
|
||||
"spring.application.name=configmap-with-profile-no-active-profiles-example",
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
|
||||
properties = { "spring.application.name=configmap-with-profile-no-active-profiles-example",
|
||||
"spring.cloud.kubernetes.reload.enabled=false" })
|
||||
@AutoConfigureWebTestClient
|
||||
public class ConfigMapsWithProfilesNoActiveProfileTests {
|
||||
@@ -63,34 +61,30 @@ public class ConfigMapsWithProfilesNoActiveProfileTests {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
HashMap<String, String> data = new HashMap<>();
|
||||
data.put("application.yml", readResourceFile("application-with-profiles.yaml"));
|
||||
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(APPLICATION_NAME).endMetadata().addToData(data).build())
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata()
|
||||
.addToData(data).build())
|
||||
.always();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGreetingEndpoint() {
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content")
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Hello ConfigMap default, World!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFarewellEndpoint() {
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content")
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Goodbye ConfigMap default, World!");
|
||||
}
|
||||
|
||||
|
||||
@@ -41,10 +41,8 @@ import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.read
|
||||
* @author Charles Moulliard
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class,
|
||||
properties = { "spring.application.name=configmap-with-profile-example",
|
||||
"spring.cloud.kubernetes.reload.enabled=false" })
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = {
|
||||
"spring.application.name=configmap-with-profile-example", "spring.cloud.kubernetes.reload.enabled=false" })
|
||||
@ActiveProfiles("development")
|
||||
@AutoConfigureWebTestClient
|
||||
public class ConfigMapsWithProfilesTests {
|
||||
@@ -67,34 +65,30 @@ public class ConfigMapsWithProfilesTests {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
HashMap<String, String> data = new HashMap<>();
|
||||
data.put("application.yml", readResourceFile("application-with-profiles.yaml"));
|
||||
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(APPLICATION_NAME).endMetadata().addToData(data).build())
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata()
|
||||
.addToData(data).build())
|
||||
.always();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGreetingEndpoint() {
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content")
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Hello ConfigMap dev, World!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFarewellEndpoint() {
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content")
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Goodbye ConfigMap default, World!");
|
||||
}
|
||||
|
||||
|
||||
@@ -38,10 +38,8 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import static org.springframework.cloud.kubernetes.config.ConfigMapTestUtil.readResourceFile;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class,
|
||||
properties = { "spring.application.name=configmap-without-profile-example",
|
||||
"spring.cloud.kubernetes.reload.enabled=false" })
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class, properties = {
|
||||
"spring.application.name=configmap-without-profile-example", "spring.cloud.kubernetes.reload.enabled=false" })
|
||||
@ActiveProfiles("development")
|
||||
@AutoConfigureWebTestClient
|
||||
public class ConfigMapsWithoutProfilesTests {
|
||||
@@ -61,34 +59,31 @@ public class ConfigMapsWithoutProfilesTests {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
HashMap<String, String> data = new HashMap<>();
|
||||
data.put("application.yml",
|
||||
readResourceFile("application-without-profiles.yaml"));
|
||||
data.put("application.yml", readResourceFile("application-without-profiles.yaml"));
|
||||
server.expect().withPath("/api/v1/namespaces/test/configmaps/" + APPLICATION_NAME)
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(APPLICATION_NAME).endMetadata().addToData(data).build())
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(APPLICATION_NAME).endMetadata()
|
||||
.addToData(data).build())
|
||||
.always();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGreetingEndpoint() {
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content").isEqualTo("Hello ConfigMap, World!");
|
||||
this.webClient.get().uri("/api/greeting").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Hello ConfigMap, World!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFarewellEndpoint() {
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk()
|
||||
.expectBody().jsonPath("content").isEqualTo("Goodbye ConfigMap, World!");
|
||||
this.webClient.get().uri("/api/farewell").exchange().expectStatus().isOk().expectBody().jsonPath("content")
|
||||
.isEqualTo("Goodbye ConfigMap, World!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,10 +37,8 @@ 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",
|
||||
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 {
|
||||
|
||||
@@ -63,39 +61,32 @@ public class CoreTest {
|
||||
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();
|
||||
.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();
|
||||
.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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void kubernetesClientConfigBeanShouldBeConfigurableViaSystemProperties() {
|
||||
assertThat(config).isNotNull();
|
||||
assertThat(config.getMasterUrl())
|
||||
.isEqualTo(mockClient.getConfiguration().getMasterUrl());
|
||||
assertThat(config.getMasterUrl()).isEqualTo(mockClient.getConfiguration().getMasterUrl());
|
||||
assertThat(config.getNamespace()).isEqualTo("testns");
|
||||
assertThat(config.isTrustCerts()).isTrue();
|
||||
}
|
||||
@@ -103,14 +94,12 @@ public class CoreTest {
|
||||
@Test
|
||||
public void kubernetesClientBeanShouldBeConfigurableViaSystemProperties() {
|
||||
assertThat(client).isNotNull();
|
||||
assertThat(client.getConfiguration().getMasterUrl())
|
||||
.isEqualTo(mockClient.getConfiguration().getMasterUrl());
|
||||
assertThat(client.getConfiguration().getMasterUrl()).isEqualTo(mockClient.getConfiguration().getMasterUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertiesShouldBeReadFromConfigMap() {
|
||||
assertThat(environment.getProperty("spring.kubernetes.test.value"))
|
||||
.isEqualTo("value1");
|
||||
assertThat(environment.getProperty("spring.kubernetes.test.value")).isEqualTo("value1");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -35,8 +35,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class,
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
|
||||
properties = { "management.endpoint.health.show-details=always" })
|
||||
public class HealthIndicatorTest {
|
||||
|
||||
@@ -56,12 +55,10 @@ public class HealthIndicatorTest {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
}
|
||||
@@ -69,8 +66,8 @@ public class HealthIndicatorTest {
|
||||
@Test
|
||||
public void healthEndpointShouldContainKubernetes() {
|
||||
this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port)
|
||||
.accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk()
|
||||
.expectBody(String.class).value(containsString("kubernetes"));
|
||||
.accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class)
|
||||
.value(containsString("kubernetes"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,8 +52,7 @@ public class KubernetesConfigConfigurationTest {
|
||||
|
||||
@Test
|
||||
public void kubernetesWhenKubernetesConfigDisabled() throws Exception {
|
||||
setup("spring.cloud.kubernetes.config.enabled=false",
|
||||
"spring.cloud.kubernetes.secrets.enabled=false");
|
||||
setup("spring.cloud.kubernetes.config.enabled=false", "spring.cloud.kubernetes.secrets.enabled=false");
|
||||
assertThat(this.context.containsBean("configMapPropertySourceLocator")).isFalse();
|
||||
assertThat(this.context.containsBean("secretsPropertySourceLocator")).isFalse();
|
||||
}
|
||||
@@ -66,11 +65,9 @@ public class KubernetesConfigConfigurationTest {
|
||||
}
|
||||
|
||||
private void setup(String... env) {
|
||||
this.context = new SpringApplicationBuilder(
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
this.context = new SpringApplicationBuilder(PropertyPlaceholderAutoConfiguration.class,
|
||||
KubernetesClientTestConfiguration.class, BootstrapConfiguration.class)
|
||||
.web(org.springframework.boot.WebApplicationType.NONE)
|
||||
.properties(env).run();
|
||||
.web(org.springframework.boot.WebApplicationType.NONE).properties(env).run();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
@@ -34,26 +34,23 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
// inspired by spring-cloud-commons: RefreshAutoConfigurationMoreClassPathTests
|
||||
|
||||
@RunWith(ModifiedClassPathRunner.class)
|
||||
@ClassPathExclusions({ "spring-boot-actuator-autoconfigure-*.jar",
|
||||
"spring-boot-starter-actuator-*.jar" })
|
||||
@ClassPathExclusions({ "spring-boot-actuator-autoconfigure-*.jar", "spring-boot-starter-actuator-*.jar" })
|
||||
public class MissingActuatorTest {
|
||||
|
||||
@Rule
|
||||
public OutputCaptureRule outputCapture = new OutputCaptureRule();
|
||||
|
||||
private static ConfigurableApplicationContext getApplicationContext(
|
||||
Class<?> configuration, String... properties) {
|
||||
return new SpringApplicationBuilder(configuration).web(WebApplicationType.NONE)
|
||||
.properties(properties).run();
|
||||
private static ConfigurableApplicationContext getApplicationContext(Class<?> configuration, String... properties) {
|
||||
return new SpringApplicationBuilder(configuration).web(WebApplicationType.NONE).properties(properties).run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unknownClassProtected() {
|
||||
try (ConfigurableApplicationContext context = getApplicationContext(Config.class,
|
||||
"debug=true")) {
|
||||
try (ConfigurableApplicationContext context = getApplicationContext(Config.class, "debug=true")) {
|
||||
String output = this.outputCapture.toString();
|
||||
assertThat(output).doesNotContain("Failed to introspect annotations on"
|
||||
+ " [class org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration")
|
||||
assertThat(output)
|
||||
.doesNotContain("Failed to introspect annotations on"
|
||||
+ " [class org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration")
|
||||
.doesNotContain("TypeNotPresentExceptionProxy");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
* @author Charles Moulliard
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = ExampleApp.class,
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = ExampleApp.class,
|
||||
properties = { "spring.cloud.bootstrap.name=multiplecms" })
|
||||
@AutoConfigureWebTestClient
|
||||
public class MultipleConfigMapsTests {
|
||||
@@ -58,12 +57,10 @@ public class MultipleConfigMapsTests {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
@@ -81,23 +78,20 @@ public class MultipleConfigMapsTests {
|
||||
}
|
||||
});
|
||||
|
||||
createConfigmap(server, "othername", "othernamespace",
|
||||
new HashMap<String, String>() {
|
||||
{
|
||||
put("bean.common-message", "c3");
|
||||
put("bean.message3", "m3");
|
||||
}
|
||||
});
|
||||
createConfigmap(server, "othername", "othernamespace", new HashMap<String, String>() {
|
||||
{
|
||||
put("bean.common-message", "c3");
|
||||
put("bean.message3", "m3");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void createConfigmap(KubernetesServer server, String configMapName,
|
||||
String namespace, Map<String, String> data) {
|
||||
private static void createConfigmap(KubernetesServer server, String configMapName, String namespace,
|
||||
Map<String, String> data) {
|
||||
|
||||
server.expect()
|
||||
.withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace,
|
||||
configMapName))
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(configMapName).endMetadata().addToData(data).build())
|
||||
server.expect().withPath(String.format("/api/v1/namespaces/%s/configmaps/%s", namespace, configMapName))
|
||||
.andReturn(200, new ConfigMapBuilder().withNewMetadata().withName(configMapName).endMetadata()
|
||||
.addToData(data).build())
|
||||
.always();
|
||||
}
|
||||
|
||||
@@ -124,8 +118,8 @@ public class MultipleConfigMapsTests {
|
||||
}
|
||||
|
||||
private void assertResponse(String path, String expectedMessage) {
|
||||
this.webClient.get().uri(path).exchange().expectStatus().isOk().expectBody()
|
||||
.jsonPath("message").isEqualTo(expectedMessage);
|
||||
this.webClient.get().uri(path).exchange().expectStatus().isOk().expectBody().jsonPath("message")
|
||||
.isEqualTo(expectedMessage);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,8 +41,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
* @author Haytham Mohamed
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = MultiSecretsApp.class,
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = MultiSecretsApp.class,
|
||||
properties = { "spring.cloud.bootstrap.name=multiple-secrets" })
|
||||
@AutoConfigureWebTestClient
|
||||
public class MultipleSecretsTests {
|
||||
@@ -68,14 +67,11 @@ public class MultipleSecretsTests {
|
||||
KubernetesClient 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_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_NAMESPACE_SYSTEM_PROPERTY,
|
||||
DEFAULT_NAMESPACE);
|
||||
System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, DEFAULT_NAMESPACE);
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
Map<String, String> metadata1 = new HashMap() {
|
||||
@@ -85,11 +81,8 @@ public class MultipleSecretsTests {
|
||||
}
|
||||
};
|
||||
|
||||
Secret secret1 = new SecretBuilder().withNewMetadata().withName("name1")
|
||||
.withLabels(metadata1).endMetadata()
|
||||
.addToData("secrets.secret1",
|
||||
Base64.getEncoder().encodeToString(SECRET_VALUE_1.getBytes()))
|
||||
.build();
|
||||
Secret secret1 = new SecretBuilder().withNewMetadata().withName("name1").withLabels(metadata1).endMetadata()
|
||||
.addToData("secrets.secret1", Base64.getEncoder().encodeToString(SECRET_VALUE_1.getBytes())).build();
|
||||
|
||||
mockClient.secrets().inNamespace(DEFAULT_NAMESPACE).create(secret1);
|
||||
|
||||
@@ -100,11 +93,8 @@ public class MultipleSecretsTests {
|
||||
}
|
||||
};
|
||||
|
||||
Secret secret2 = new SecretBuilder().withNewMetadata().withName("name2")
|
||||
.withLabels(metadata2).endMetadata()
|
||||
.addToData("secrets.secret2",
|
||||
Base64.getEncoder().encodeToString(SECRET_VALUE_2.getBytes()))
|
||||
.build();
|
||||
Secret secret2 = new SecretBuilder().withNewMetadata().withName("name2").withLabels(metadata2).endMetadata()
|
||||
.addToData("secrets.secret2", Base64.getEncoder().encodeToString(SECRET_VALUE_2.getBytes())).build();
|
||||
|
||||
mockClient.secrets().inNamespace(ANOTHER_NAMESPACE).create(secret2);
|
||||
}
|
||||
@@ -120,8 +110,8 @@ public class MultipleSecretsTests {
|
||||
}
|
||||
|
||||
private void assertResponse(String path, String expectedMessage) {
|
||||
this.webClient.get().uri(path).exchange().expectStatus().isOk().expectBody()
|
||||
.jsonPath("secret").isEqualTo(expectedMessage);
|
||||
this.webClient.get().uri(path).exchange().expectStatus().isOk().expectBody().jsonPath("secret")
|
||||
.isEqualTo(expectedMessage);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,8 +39,7 @@ import static java.util.Collections.singletonMap;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class)
|
||||
@TestPropertySource("classpath:/application-secrets.properties")
|
||||
public class SecretsPropertySourceTest {
|
||||
|
||||
@@ -62,20 +61,15 @@ public class SecretsPropertySourceTest {
|
||||
KubernetesClient 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, NAMESPACE);
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
|
||||
Secret secret = new SecretBuilder().withNewMetadata()
|
||||
.withLabels(singletonMap("foo", "bar")).endMetadata()
|
||||
.addToData("secretName",
|
||||
Base64.getEncoder().encodeToString(SECRET_VALUE.getBytes()))
|
||||
.build();
|
||||
Secret secret = new SecretBuilder().withNewMetadata().withLabels(singletonMap("foo", "bar")).endMetadata()
|
||||
.addToData("secretName", Base64.getEncoder().encodeToString(SECRET_VALUE.getBytes())).build();
|
||||
mockClient.secrets().inNamespace(NAMESPACE).create(secret);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,20 +35,17 @@ public class GreetingController {
|
||||
}
|
||||
|
||||
@RequestMapping("/api/greeting")
|
||||
public ResponseMessage greeting(
|
||||
@RequestParam(value = "name", defaultValue = "World") String name) {
|
||||
public ResponseMessage greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
|
||||
return new ResponseMessage(String.format(this.properties.getGreeting(), name));
|
||||
}
|
||||
|
||||
@RequestMapping("/api/farewell")
|
||||
public ResponseMessage farewell(
|
||||
@RequestParam(value = "name", defaultValue = "World") String name) {
|
||||
public ResponseMessage farewell(@RequestParam(value = "name", defaultValue = "World") String name) {
|
||||
return new ResponseMessage(String.format(this.properties.getFarewell(), name));
|
||||
}
|
||||
|
||||
@RequestMapping("/api/morning")
|
||||
public ResponseMessage morning(
|
||||
@RequestParam(value = "name", defaultValue = "World") String name) {
|
||||
public ResponseMessage morning(@RequestParam(value = "name", defaultValue = "World") String name) {
|
||||
return new ResponseMessage(String.format(this.properties.getMorning(), name));
|
||||
}
|
||||
|
||||
|
||||
@@ -27,8 +27,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
public class ExampleApp {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication
|
||||
.run(org.springframework.cloud.kubernetes.config.example.App.class, args);
|
||||
SpringApplication.run(org.springframework.cloud.kubernetes.config.example.App.class, args);
|
||||
}
|
||||
|
||||
@RestController
|
||||
|
||||
@@ -60,22 +60,15 @@ public class EventBasedConfigurationChangeDetectorTests {
|
||||
when(mixedOperation.withName(eq("myconfigmap"))).thenReturn(resource);
|
||||
when(k8sClient.configMaps()).thenReturn(mixedOperation);
|
||||
|
||||
ConfigMapPropertySource configMapPropertySource = new ConfigMapPropertySource(
|
||||
k8sClient, "myconfigmap");
|
||||
env.getPropertySources()
|
||||
.addFirst(new BootstrapPropertySource(configMapPropertySource));
|
||||
ConfigMapPropertySource configMapPropertySource = new ConfigMapPropertySource(k8sClient, "myconfigmap");
|
||||
env.getPropertySources().addFirst(new BootstrapPropertySource(configMapPropertySource));
|
||||
|
||||
ConfigurationUpdateStrategy configurationUpdateStrategy = mock(
|
||||
ConfigurationUpdateStrategy.class);
|
||||
ConfigMapPropertySourceLocator configMapLocator = mock(
|
||||
ConfigMapPropertySourceLocator.class);
|
||||
SecretsPropertySourceLocator secretsLocator = mock(
|
||||
SecretsPropertySourceLocator.class);
|
||||
EventBasedConfigurationChangeDetector detector = new EventBasedConfigurationChangeDetector(
|
||||
env, configReloadProperties, k8sClient, configurationUpdateStrategy,
|
||||
configMapLocator, secretsLocator);
|
||||
List<ConfigMapPropertySource> sources = detector
|
||||
.findPropertySources(ConfigMapPropertySource.class);
|
||||
ConfigurationUpdateStrategy configurationUpdateStrategy = mock(ConfigurationUpdateStrategy.class);
|
||||
ConfigMapPropertySourceLocator configMapLocator = mock(ConfigMapPropertySourceLocator.class);
|
||||
SecretsPropertySourceLocator secretsLocator = mock(SecretsPropertySourceLocator.class);
|
||||
EventBasedConfigurationChangeDetector detector = new EventBasedConfigurationChangeDetector(env,
|
||||
configReloadProperties, k8sClient, configurationUpdateStrategy, configMapLocator, secretsLocator);
|
||||
List<ConfigMapPropertySource> sources = detector.findPropertySources(ConfigMapPropertySource.class);
|
||||
assertThat(sources.size()).isEqualTo(1);
|
||||
assertThat(sources.get(0).getProperty("foo")).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@@ -35,45 +35,41 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class BusEventBasedConfigurationWatcherChangeDetector extends
|
||||
ConfigurationWatcherChangeDetector implements ApplicationEventPublisherAware {
|
||||
public class BusEventBasedConfigurationWatcherChangeDetector extends ConfigurationWatcherChangeDetector
|
||||
implements ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
private BusProperties busProperties;
|
||||
|
||||
public BusEventBasedConfigurationWatcherChangeDetector(
|
||||
AbstractEnvironment environment, ConfigReloadProperties properties,
|
||||
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
|
||||
public BusEventBasedConfigurationWatcherChangeDetector(AbstractEnvironment environment,
|
||||
ConfigReloadProperties properties, KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
|
||||
ConfigMapPropertySourceLocator configMapPropertySourceLocator,
|
||||
SecretsPropertySourceLocator secretsPropertySourceLocator,
|
||||
BusProperties busProperties,
|
||||
SecretsPropertySourceLocator secretsPropertySourceLocator, BusProperties busProperties,
|
||||
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
|
||||
ThreadPoolTaskExecutor threadPoolTaskExecutor) {
|
||||
super(environment, properties, kubernetesClient, strategy,
|
||||
configMapPropertySourceLocator, secretsPropertySourceLocator,
|
||||
k8SConfigurationProperties, threadPoolTaskExecutor);
|
||||
super(environment, properties, kubernetesClient, strategy, configMapPropertySourceLocator,
|
||||
secretsPropertySourceLocator, k8SConfigurationProperties, threadPoolTaskExecutor);
|
||||
|
||||
this.busProperties = busProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mono<Void> triggerRefresh(Secret secret) {
|
||||
this.applicationEventPublisher.publishEvent(new RefreshRemoteApplicationEvent(
|
||||
secret, busProperties.getId(), secret.getMetadata().getName()));
|
||||
this.applicationEventPublisher.publishEvent(
|
||||
new RefreshRemoteApplicationEvent(secret, busProperties.getId(), secret.getMetadata().getName()));
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mono<Void> triggerRefresh(ConfigMap configMap) {
|
||||
this.applicationEventPublisher.publishEvent(new RefreshRemoteApplicationEvent(
|
||||
configMap, busProperties.getId(), configMap.getMetadata().getName()));
|
||||
this.applicationEventPublisher.publishEvent(
|
||||
new RefreshRemoteApplicationEvent(configMap, busProperties.getId(), configMap.getMetadata().getName()));
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(
|
||||
ApplicationEventPublisher applicationEventPublisher) {
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ import org.springframework.context.annotation.Configuration;
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@SpringBootApplication(exclude = { ContextFunctionCatalogAutoConfiguration.class,
|
||||
RabbitHealthContributorAutoConfiguration.class })
|
||||
@SpringBootApplication(
|
||||
exclude = { ContextFunctionCatalogAutoConfiguration.class, RabbitHealthContributorAutoConfiguration.class })
|
||||
public class ConfigurationWatcherApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -55,40 +55,35 @@ public class ConfigurationWatcherAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ConfigurationWatcherChangeDetector.class)
|
||||
public ConfigurationWatcherChangeDetector httpBasedConfigurationWatchChangeDetector(
|
||||
AbstractEnvironment environment, KubernetesClient kubernetesClient,
|
||||
ConfigMapPropertySourceLocator configMapPropertySourceLocator,
|
||||
SecretsPropertySourceLocator secretsPropertySourceLocator,
|
||||
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
|
||||
public ConfigurationWatcherChangeDetector httpBasedConfigurationWatchChangeDetector(AbstractEnvironment environment,
|
||||
KubernetesClient kubernetesClient, ConfigMapPropertySourceLocator configMapPropertySourceLocator,
|
||||
SecretsPropertySourceLocator secretsPropertySourceLocator, ConfigReloadProperties properties,
|
||||
ConfigurationUpdateStrategy strategy,
|
||||
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
|
||||
ThreadPoolTaskExecutor threadFactory, WebClient webClient,
|
||||
KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient) {
|
||||
return new HttpBasedConfigurationWatchChangeDetector(environment, properties,
|
||||
kubernetesClient, strategy, configMapPropertySourceLocator,
|
||||
secretsPropertySourceLocator, k8SConfigurationProperties, threadFactory,
|
||||
return new HttpBasedConfigurationWatchChangeDetector(environment, properties, kubernetesClient, strategy,
|
||||
configMapPropertySourceLocator, secretsPropertySourceLocator, k8SConfigurationProperties, threadFactory,
|
||||
webClient, kubernetesReactiveDiscoveryClient);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Profile("bus")
|
||||
@Import({ ContextFunctionCatalogAutoConfiguration.class,
|
||||
RabbitHealthContributorAutoConfiguration.class })
|
||||
@Import({ ContextFunctionCatalogAutoConfiguration.class, RabbitHealthContributorAutoConfiguration.class })
|
||||
static class BusConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ConfigurationWatcherChangeDetector.class)
|
||||
public ConfigurationWatcherChangeDetector busPropertyChangeWatcher(
|
||||
BusProperties busProperties, AbstractEnvironment environment,
|
||||
KubernetesClient kubernetesClient,
|
||||
public ConfigurationWatcherChangeDetector busPropertyChangeWatcher(BusProperties busProperties,
|
||||
AbstractEnvironment environment, KubernetesClient kubernetesClient,
|
||||
ConfigMapPropertySourceLocator configMapPropertySourceLocator,
|
||||
SecretsPropertySourceLocator secretsPropertySourceLocator,
|
||||
ConfigReloadProperties properties, ConfigurationUpdateStrategy strategy,
|
||||
SecretsPropertySourceLocator secretsPropertySourceLocator, ConfigReloadProperties properties,
|
||||
ConfigurationUpdateStrategy strategy,
|
||||
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
|
||||
ThreadPoolTaskExecutor threadFactory) {
|
||||
return new BusEventBasedConfigurationWatcherChangeDetector(environment,
|
||||
properties, kubernetesClient, strategy,
|
||||
configMapPropertySourceLocator, secretsPropertySourceLocator,
|
||||
busProperties, k8SConfigurationProperties, threadFactory);
|
||||
return new BusEventBasedConfigurationWatcherChangeDetector(environment, properties, kubernetesClient,
|
||||
strategy, configMapPropertySourceLocator, secretsPropertySourceLocator, busProperties,
|
||||
k8SConfigurationProperties, threadFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,24 +36,22 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public abstract class ConfigurationWatcherChangeDetector
|
||||
extends EventBasedConfigurationChangeDetector {
|
||||
public abstract class ConfigurationWatcherChangeDetector extends EventBasedConfigurationChangeDetector {
|
||||
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
protected ConfigurationWatcherConfigurationProperties k8SConfigurationProperties;
|
||||
|
||||
public ConfigurationWatcherChangeDetector(AbstractEnvironment environment,
|
||||
ConfigReloadProperties properties, KubernetesClient kubernetesClient,
|
||||
ConfigurationUpdateStrategy strategy,
|
||||
public ConfigurationWatcherChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
|
||||
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
|
||||
ConfigMapPropertySourceLocator configMapPropertySourceLocator,
|
||||
SecretsPropertySourceLocator secretsPropertySourceLocator,
|
||||
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
|
||||
ThreadPoolTaskExecutor threadPoolTaskExecutor) {
|
||||
super(environment, properties, kubernetesClient, strategy,
|
||||
configMapPropertySourceLocator, secretsPropertySourceLocator);
|
||||
this.executorService = Executors.newScheduledThreadPool(
|
||||
k8SConfigurationProperties.getThreadPoolSize(), threadPoolTaskExecutor);
|
||||
super(environment, properties, kubernetesClient, strategy, configMapPropertySourceLocator,
|
||||
secretsPropertySourceLocator);
|
||||
this.executorService = Executors.newScheduledThreadPool(k8SConfigurationProperties.getThreadPoolSize(),
|
||||
threadPoolTaskExecutor);
|
||||
this.k8SConfigurationProperties = k8SConfigurationProperties;
|
||||
}
|
||||
|
||||
@@ -63,38 +61,33 @@ public abstract class ConfigurationWatcherChangeDetector
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Scheduling remote refresh event to be published for ConfigMap "
|
||||
+ configMap.getMetadata().getName() + " to be published in "
|
||||
+ k8SConfigurationProperties.getRefreshDelay().toMillis()
|
||||
+ " milliseconds");
|
||||
+ k8SConfigurationProperties.getRefreshDelay().toMillis() + " milliseconds");
|
||||
}
|
||||
executorService.schedule(() -> triggerRefresh(configMap).subscribe(),
|
||||
k8SConfigurationProperties.getRefreshDelay().toMillis(),
|
||||
TimeUnit.MILLISECONDS);
|
||||
k8SConfigurationProperties.getRefreshDelay().toMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Not publishing event. ConfigMap "
|
||||
+ configMap.getMetadata().getName()
|
||||
+ " does not contain the label "
|
||||
+ k8SConfigurationProperties.getConfigLabel());
|
||||
log.debug("Not publishing event. ConfigMap " + configMap.getMetadata().getName()
|
||||
+ " does not contain the label " + k8SConfigurationProperties.getConfigLabel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isSpringCloudKubernetesConfig(ConfigMap configMap) {
|
||||
if (configMap.getMetadata() == null
|
||||
|| configMap.getMetadata().getLabels() == null) {
|
||||
if (configMap.getMetadata() == null || configMap.getMetadata().getLabels() == null) {
|
||||
return false;
|
||||
}
|
||||
return Boolean.parseBoolean(configMap.getMetadata().getLabels()
|
||||
.getOrDefault(k8SConfigurationProperties.getConfigLabel(), "false"));
|
||||
return Boolean.parseBoolean(
|
||||
configMap.getMetadata().getLabels().getOrDefault(k8SConfigurationProperties.getConfigLabel(), "false"));
|
||||
}
|
||||
|
||||
protected boolean isSpringCloudKubernetesSecret(Secret secret) {
|
||||
if (secret.getMetadata() == null || secret.getMetadata().getLabels() == null) {
|
||||
return false;
|
||||
}
|
||||
return Boolean.parseBoolean(secret.getMetadata().getLabels()
|
||||
.getOrDefault(k8SConfigurationProperties.getSecretLabel(), "false"));
|
||||
return Boolean.parseBoolean(
|
||||
secret.getMetadata().getLabels().getOrDefault(k8SConfigurationProperties.getSecretLabel(), "false"));
|
||||
}
|
||||
|
||||
protected abstract Mono<Void> triggerRefresh(Secret secret);
|
||||
@@ -105,20 +98,17 @@ public abstract class ConfigurationWatcherChangeDetector
|
||||
protected void onEvent(Secret secret) {
|
||||
if (isSpringCloudKubernetesSecret(secret)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Scheduling remote refresh event to be published for Secret "
|
||||
+ secret.getMetadata().getName() + " to be published in "
|
||||
+ k8SConfigurationProperties.getRefreshDelay().toMillis()
|
||||
log.debug("Scheduling remote refresh event to be published for Secret " + secret.getMetadata().getName()
|
||||
+ " to be published in " + k8SConfigurationProperties.getRefreshDelay().toMillis()
|
||||
+ " milliseconds");
|
||||
}
|
||||
executorService.schedule(() -> triggerRefresh(secret).subscribe(),
|
||||
k8SConfigurationProperties.getRefreshDelay().toMillis(),
|
||||
TimeUnit.MILLISECONDS);
|
||||
k8SConfigurationProperties.getRefreshDelay().toMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Not publishing event. Secret " + secret.getMetadata().getName()
|
||||
+ " does not contain the label "
|
||||
+ k8SConfigurationProperties.getSecretLabel());
|
||||
+ " does not contain the label " + k8SConfigurationProperties.getSecretLabel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,7 @@ import org.springframework.web.util.UriComponentsBuilder;
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
*/
|
||||
public class HttpBasedConfigurationWatchChangeDetector
|
||||
extends ConfigurationWatcherChangeDetector {
|
||||
public class HttpBasedConfigurationWatchChangeDetector extends ConfigurationWatcherChangeDetector {
|
||||
|
||||
/**
|
||||
* Annotation key for actuator port and path.
|
||||
@@ -53,17 +52,15 @@ public class HttpBasedConfigurationWatchChangeDetector
|
||||
|
||||
private KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient;
|
||||
|
||||
public HttpBasedConfigurationWatchChangeDetector(AbstractEnvironment environment,
|
||||
ConfigReloadProperties properties, KubernetesClient kubernetesClient,
|
||||
ConfigurationUpdateStrategy strategy,
|
||||
public HttpBasedConfigurationWatchChangeDetector(AbstractEnvironment environment, ConfigReloadProperties properties,
|
||||
KubernetesClient kubernetesClient, ConfigurationUpdateStrategy strategy,
|
||||
ConfigMapPropertySourceLocator configMapPropertySourceLocator,
|
||||
SecretsPropertySourceLocator secretsPropertySourceLocator,
|
||||
ConfigurationWatcherConfigurationProperties k8SConfigurationProperties,
|
||||
ThreadPoolTaskExecutor threadPoolTaskExecutor, WebClient webClient,
|
||||
KubernetesReactiveDiscoveryClient k8sReactiveDiscoveryClient) {
|
||||
super(environment, properties, kubernetesClient, strategy,
|
||||
configMapPropertySourceLocator, secretsPropertySourceLocator,
|
||||
k8SConfigurationProperties, threadPoolTaskExecutor);
|
||||
super(environment, properties, kubernetesClient, strategy, configMapPropertySourceLocator,
|
||||
secretsPropertySourceLocator, k8SConfigurationProperties, threadPoolTaskExecutor);
|
||||
this.webClient = webClient;
|
||||
this.kubernetesReactiveDiscoveryClient = k8sReactiveDiscoveryClient;
|
||||
}
|
||||
@@ -73,8 +70,7 @@ public class HttpBasedConfigurationWatchChangeDetector
|
||||
return refresh(secret.getMetadata()).then();
|
||||
}
|
||||
|
||||
private void setActuatorUriFromAnnotation(UriComponentsBuilder actuatorUriBuilder,
|
||||
String metadataUri) {
|
||||
private void setActuatorUriFromAnnotation(UriComponentsBuilder actuatorUriBuilder, String metadataUri) {
|
||||
URI annotationUri = URI.create(metadataUri);
|
||||
actuatorUriBuilder.path(annotationUri.getPath() + "/refresh");
|
||||
|
||||
@@ -84,8 +80,7 @@ public class HttpBasedConfigurationWatchChangeDetector
|
||||
// 9090 in this case
|
||||
if (annotationUri.getPort() < 0) {
|
||||
if (annotationUri.getAuthority() != null) {
|
||||
actuatorUriBuilder
|
||||
.port(annotationUri.getAuthority().replaceFirst(":", ""));
|
||||
actuatorUriBuilder.port(annotationUri.getAuthority().replaceFirst(":", ""));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -99,8 +94,8 @@ public class HttpBasedConfigurationWatchChangeDetector
|
||||
log.debug("Metadata actuator uri is: " + metadataUri);
|
||||
}
|
||||
|
||||
UriComponentsBuilder actuatorUriBuilder = UriComponentsBuilder.newInstance()
|
||||
.scheme(si.getScheme()).host(si.getHost());
|
||||
UriComponentsBuilder actuatorUriBuilder = UriComponentsBuilder.newInstance().scheme(si.getScheme())
|
||||
.host(si.getHost());
|
||||
|
||||
if (!StringUtils.isEmpty(metadataUri)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -111,8 +106,7 @@ public class HttpBasedConfigurationWatchChangeDetector
|
||||
else {
|
||||
Integer port = k8SConfigurationProperties.getActuatorPort() < 0 ? si.getPort()
|
||||
: k8SConfigurationProperties.getActuatorPort();
|
||||
actuatorUriBuilder = actuatorUriBuilder
|
||||
.path(k8SConfigurationProperties.getActuatorPath() + "/refresh")
|
||||
actuatorUriBuilder = actuatorUriBuilder.path(k8SConfigurationProperties.getActuatorPath() + "/refresh")
|
||||
.port(port);
|
||||
}
|
||||
|
||||
@@ -121,28 +115,22 @@ public class HttpBasedConfigurationWatchChangeDetector
|
||||
|
||||
protected Flux<ResponseEntity<Void>> refresh(ObjectMeta objectMeta) {
|
||||
|
||||
return kubernetesReactiveDiscoveryClient.getInstances(objectMeta.getName())
|
||||
.flatMap(si -> {
|
||||
URI actuatorUri = getActuatorUri(si);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Sending refresh request for " + objectMeta.getName()
|
||||
+ " to URI " + actuatorUri.toString());
|
||||
}
|
||||
Mono<ResponseEntity<Void>> response = webClient.post()
|
||||
.uri(actuatorUri).retrieve().toBodilessEntity()
|
||||
.doOnSuccess(re -> {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Refresh sent to " + objectMeta.getName()
|
||||
+ " at URI address " + actuatorUri
|
||||
+ " returned a "
|
||||
+ re.getStatusCode().toString());
|
||||
}
|
||||
}).doOnError(t -> {
|
||||
log.warn("Refresh sent to " + objectMeta.getName()
|
||||
+ " failed", t);
|
||||
});
|
||||
return response;
|
||||
});
|
||||
return kubernetesReactiveDiscoveryClient.getInstances(objectMeta.getName()).flatMap(si -> {
|
||||
URI actuatorUri = getActuatorUri(si);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Sending refresh request for " + objectMeta.getName() + " to URI " + actuatorUri.toString());
|
||||
}
|
||||
Mono<ResponseEntity<Void>> response = webClient.post().uri(actuatorUri).retrieve().toBodilessEntity()
|
||||
.doOnSuccess(re -> {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Refresh sent to " + objectMeta.getName() + " at URI address " + actuatorUri
|
||||
+ " returned a " + re.getStatusCode().toString());
|
||||
}
|
||||
}).doOnError(t -> {
|
||||
log.warn("Refresh sent to " + objectMeta.getName() + " failed", t);
|
||||
});
|
||||
return response;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -76,11 +76,9 @@ public class BusEventBasedConfigurationWatcherChangeDetectorTests {
|
||||
ConfigReloadProperties configReloadProperties = new ConfigReloadProperties();
|
||||
configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties();
|
||||
busProperties = new BusProperties();
|
||||
changeDetector = new BusEventBasedConfigurationWatcherChangeDetector(
|
||||
mockEnvironment, configReloadProperties, client, updateStrategy,
|
||||
configMapPropertySourceLocator, secretsPropertySourceLocator,
|
||||
busProperties, configurationWatcherConfigurationProperties,
|
||||
threadPoolTaskExecutor);
|
||||
changeDetector = new BusEventBasedConfigurationWatcherChangeDetector(mockEnvironment, configReloadProperties,
|
||||
client, updateStrategy, configMapPropertySourceLocator, secretsPropertySourceLocator, busProperties,
|
||||
configurationWatcherConfigurationProperties, threadPoolTaskExecutor);
|
||||
changeDetector.setApplicationEventPublisher(applicationEventPublisher);
|
||||
}
|
||||
|
||||
@@ -95,8 +93,7 @@ public class BusEventBasedConfigurationWatcherChangeDetectorTests {
|
||||
.forClass(RefreshRemoteApplicationEvent.class);
|
||||
verify(applicationEventPublisher).publishEvent(argumentCaptor.capture());
|
||||
assertThat(argumentCaptor.getValue().getSource()).isEqualTo(configMap);
|
||||
assertThat(argumentCaptor.getValue().getOriginService())
|
||||
.isEqualTo(busProperties.getId());
|
||||
assertThat(argumentCaptor.getValue().getOriginService()).isEqualTo(busProperties.getId());
|
||||
assertThat(argumentCaptor.getValue().getDestinationService()).isEqualTo("foo:**");
|
||||
}
|
||||
|
||||
@@ -111,8 +108,7 @@ public class BusEventBasedConfigurationWatcherChangeDetectorTests {
|
||||
.forClass(RefreshRemoteApplicationEvent.class);
|
||||
verify(applicationEventPublisher).publishEvent(argumentCaptor.capture());
|
||||
assertThat(argumentCaptor.getValue().getSource()).isEqualTo(secret);
|
||||
assertThat(argumentCaptor.getValue().getOriginService())
|
||||
.isEqualTo(busProperties.getId());
|
||||
assertThat(argumentCaptor.getValue().getOriginService()).isEqualTo(busProperties.getId());
|
||||
assertThat(argumentCaptor.getValue().getDestinationService()).isEqualTo("foo:**");
|
||||
}
|
||||
|
||||
|
||||
@@ -98,21 +98,18 @@ public class HttpBasedConfigurationWatchChangeDetectorTests {
|
||||
EndpointPort fooEndpointPort = new EndpointPort();
|
||||
fooEndpointPort.setPort(wireMockRule.port());
|
||||
List<ServiceInstance> instances = new ArrayList<>();
|
||||
KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance(
|
||||
"foo", "foo", fooEndpointAddress.getIp(), fooEndpointPort.getPort(),
|
||||
new HashMap<>(), false);
|
||||
KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance("foo", "foo",
|
||||
fooEndpointAddress.getIp(), fooEndpointPort.getPort(), new HashMap<>(), false);
|
||||
instances.add(fooServiceInstance);
|
||||
when(reactiveDiscoveryClient.getInstances(eq("foo")))
|
||||
.thenReturn(Flux.fromIterable(instances));
|
||||
when(reactiveDiscoveryClient.getInstances(eq("foo"))).thenReturn(Flux.fromIterable(instances));
|
||||
MockEnvironment mockEnvironment = new MockEnvironment();
|
||||
ConfigReloadProperties configReloadProperties = new ConfigReloadProperties();
|
||||
configurationWatcherConfigurationProperties = new ConfigurationWatcherConfigurationProperties();
|
||||
WebClient webClient = WebClient.builder().build();
|
||||
changeDetector = new HttpBasedConfigurationWatchChangeDetector(mockEnvironment,
|
||||
configReloadProperties, client, updateStrategy,
|
||||
configMapPropertySourceLocator, secretsPropertySourceLocator,
|
||||
configurationWatcherConfigurationProperties, threadPoolTaskExecutor,
|
||||
webClient, reactiveDiscoveryClient);
|
||||
changeDetector = new HttpBasedConfigurationWatchChangeDetector(mockEnvironment, configReloadProperties, client,
|
||||
updateStrategy, configMapPropertySourceLocator, secretsPropertySourceLocator,
|
||||
configurationWatcherConfigurationProperties, threadPoolTaskExecutor, webClient,
|
||||
reactiveDiscoveryClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -122,8 +119,7 @@ public class HttpBasedConfigurationWatchChangeDetectorTests {
|
||||
objectMeta.setName("foo");
|
||||
configMap.setMetadata(objectMeta);
|
||||
WireMock.configureFor("localhost", wireMockRule.port());
|
||||
stubFor(post(WireMock.urlEqualTo("/actuator/refresh"))
|
||||
.willReturn(aResponse().withStatus(200)));
|
||||
stubFor(post(WireMock.urlEqualTo("/actuator/refresh")).willReturn(aResponse().withStatus(200)));
|
||||
StepVerifier.create(changeDetector.triggerRefresh(configMap)).verifyComplete();
|
||||
verify(postRequestedFor(urlEqualTo("/actuator/refresh")));
|
||||
}
|
||||
@@ -135,40 +131,33 @@ public class HttpBasedConfigurationWatchChangeDetectorTests {
|
||||
objectMeta.setName("foo");
|
||||
secret.setMetadata(objectMeta);
|
||||
WireMock.configureFor("localhost", wireMockRule.port());
|
||||
stubFor(post(WireMock.urlEqualTo("/actuator/refresh"))
|
||||
.willReturn(aResponse().withStatus(200)));
|
||||
stubFor(post(WireMock.urlEqualTo("/actuator/refresh")).willReturn(aResponse().withStatus(200)));
|
||||
StepVerifier.create(changeDetector.triggerRefresh(secret)).verifyComplete();
|
||||
verify(postRequestedFor(urlEqualTo("/actuator/refresh")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void triggerConfigMapRefreshWithPropertiesBasedActuatorPath()
|
||||
throws InterruptedException {
|
||||
configurationWatcherConfigurationProperties
|
||||
.setActuatorPath("/my/custom/actuator");
|
||||
public void triggerConfigMapRefreshWithPropertiesBasedActuatorPath() throws InterruptedException {
|
||||
configurationWatcherConfigurationProperties.setActuatorPath("/my/custom/actuator");
|
||||
ConfigMap configMap = new ConfigMap();
|
||||
ObjectMeta objectMeta = new ObjectMeta();
|
||||
objectMeta.setName("foo");
|
||||
configMap.setMetadata(objectMeta);
|
||||
WireMock.configureFor("localhost", wireMockRule.port());
|
||||
stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh"))
|
||||
.willReturn(aResponse().withStatus(200)));
|
||||
stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")).willReturn(aResponse().withStatus(200)));
|
||||
StepVerifier.create(changeDetector.triggerRefresh(configMap)).verifyComplete();
|
||||
verify(postRequestedFor(urlEqualTo("/my/custom/actuator/refresh")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void triggerSecretRefreshWithPropertiesBasedActuatorPath()
|
||||
throws InterruptedException {
|
||||
configurationWatcherConfigurationProperties
|
||||
.setActuatorPath("/my/custom/actuator");
|
||||
public void triggerSecretRefreshWithPropertiesBasedActuatorPath() throws InterruptedException {
|
||||
configurationWatcherConfigurationProperties.setActuatorPath("/my/custom/actuator");
|
||||
Secret secret = new Secret();
|
||||
ObjectMeta objectMeta = new ObjectMeta();
|
||||
objectMeta.setName("foo");
|
||||
secret.setMetadata(objectMeta);
|
||||
WireMock.configureFor("localhost", wireMockRule.port());
|
||||
stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh"))
|
||||
.willReturn(aResponse().withStatus(200)));
|
||||
stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")).willReturn(aResponse().withStatus(200)));
|
||||
StepVerifier.create(changeDetector.triggerRefresh(secret)).verifyComplete();
|
||||
verify(postRequestedFor(urlEqualTo("/my/custom/actuator/refresh")));
|
||||
}
|
||||
@@ -176,26 +165,22 @@ public class HttpBasedConfigurationWatchChangeDetectorTests {
|
||||
@Test
|
||||
public void triggerConfigMapRefreshWithAnnotationActuatorPath() {
|
||||
Map<String, String> metadata = new HashMap<>();
|
||||
metadata.put(ANNOTATION_KEY,
|
||||
"http://:" + wireMockRule.port() + "/my/custom/actuator");
|
||||
metadata.put(ANNOTATION_KEY, "http://:" + wireMockRule.port() + "/my/custom/actuator");
|
||||
EndpointAddress fooEndpointAddress = new EndpointAddress();
|
||||
fooEndpointAddress.setIp("127.0.0.1");
|
||||
fooEndpointAddress.setHostname("localhost");
|
||||
EndpointPort fooEndpointPort = new EndpointPort();
|
||||
fooEndpointPort.setPort(wireMockRule.port());
|
||||
List<ServiceInstance> instances = new ArrayList<>();
|
||||
KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance(
|
||||
"foo", "foo", fooEndpointAddress.getIp(), fooEndpointPort.getPort(),
|
||||
metadata, false);
|
||||
KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance("foo", "foo",
|
||||
fooEndpointAddress.getIp(), fooEndpointPort.getPort(), metadata, false);
|
||||
instances.add(fooServiceInstance);
|
||||
when(reactiveDiscoveryClient.getInstances(eq("foo")))
|
||||
.thenReturn(Flux.fromIterable(instances));
|
||||
when(reactiveDiscoveryClient.getInstances(eq("foo"))).thenReturn(Flux.fromIterable(instances));
|
||||
ConfigMap configMap = new ConfigMap();
|
||||
ObjectMeta objectMeta = new ObjectMeta();
|
||||
objectMeta.setName("foo");
|
||||
configMap.setMetadata(objectMeta);
|
||||
stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh"))
|
||||
.willReturn(aResponse().withStatus(200)));
|
||||
stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")).willReturn(aResponse().withStatus(200)));
|
||||
StepVerifier.create(changeDetector.triggerRefresh(configMap)).verifyComplete();
|
||||
verify(postRequestedFor(urlEqualTo("/my/custom/actuator/refresh")));
|
||||
}
|
||||
@@ -203,26 +188,22 @@ public class HttpBasedConfigurationWatchChangeDetectorTests {
|
||||
@Test
|
||||
public void triggerSecretRefreshWithAnnotationActuatorPath() {
|
||||
Map<String, String> metadata = new HashMap<>();
|
||||
metadata.put(ANNOTATION_KEY,
|
||||
"http://:" + wireMockRule.port() + "/my/custom/actuator");
|
||||
metadata.put(ANNOTATION_KEY, "http://:" + wireMockRule.port() + "/my/custom/actuator");
|
||||
EndpointAddress fooEndpointAddress = new EndpointAddress();
|
||||
fooEndpointAddress.setIp("127.0.0.1");
|
||||
fooEndpointAddress.setHostname("localhost");
|
||||
EndpointPort fooEndpointPort = new EndpointPort();
|
||||
fooEndpointPort.setPort(wireMockRule.port());
|
||||
List<ServiceInstance> instances = new ArrayList<>();
|
||||
KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance(
|
||||
"foo", "foo", fooEndpointAddress.getIp(), fooEndpointPort.getPort(),
|
||||
metadata, false);
|
||||
KubernetesServiceInstance fooServiceInstance = new KubernetesServiceInstance("foo", "foo",
|
||||
fooEndpointAddress.getIp(), fooEndpointPort.getPort(), metadata, false);
|
||||
instances.add(fooServiceInstance);
|
||||
when(reactiveDiscoveryClient.getInstances(eq("foo")))
|
||||
.thenReturn(Flux.fromIterable(instances));
|
||||
when(reactiveDiscoveryClient.getInstances(eq("foo"))).thenReturn(Flux.fromIterable(instances));
|
||||
Secret secret = new Secret();
|
||||
ObjectMeta objectMeta = new ObjectMeta();
|
||||
objectMeta.setName("foo");
|
||||
secret.setMetadata(objectMeta);
|
||||
stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh"))
|
||||
.willReturn(aResponse().withStatus(200)));
|
||||
stubFor(post(WireMock.urlEqualTo("/my/custom/actuator/refresh")).willReturn(aResponse().withStatus(200)));
|
||||
StepVerifier.create(changeDetector.triggerRefresh(secret)).verifyComplete();
|
||||
verify(postRequestedFor(urlEqualTo("/my/custom/actuator/refresh")));
|
||||
}
|
||||
|
||||
@@ -76,65 +76,41 @@ public class KubernetesAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(Config.class)
|
||||
public Config kubernetesClientConfig(
|
||||
KubernetesClientProperties kubernetesClientProperties) {
|
||||
public Config kubernetesClientConfig(KubernetesClientProperties kubernetesClientProperties) {
|
||||
Config base = Config.autoConfigure(null);
|
||||
Config properties = new ConfigBuilder(base)
|
||||
// Only set values that have been explicitly specified
|
||||
.withMasterUrl(or(kubernetesClientProperties.getMasterUrl(),
|
||||
base.getMasterUrl()))
|
||||
.withApiVersion(or(kubernetesClientProperties.getApiVersion(),
|
||||
base.getApiVersion()))
|
||||
.withNamespace(or(kubernetesClientProperties.getNamespace(),
|
||||
base.getNamespace()))
|
||||
.withUsername(
|
||||
or(kubernetesClientProperties.getUsername(), base.getUsername()))
|
||||
.withPassword(
|
||||
or(kubernetesClientProperties.getPassword(), base.getPassword()))
|
||||
.withMasterUrl(or(kubernetesClientProperties.getMasterUrl(), base.getMasterUrl()))
|
||||
.withApiVersion(or(kubernetesClientProperties.getApiVersion(), base.getApiVersion()))
|
||||
.withNamespace(or(kubernetesClientProperties.getNamespace(), base.getNamespace()))
|
||||
.withUsername(or(kubernetesClientProperties.getUsername(), base.getUsername()))
|
||||
.withPassword(or(kubernetesClientProperties.getPassword(), base.getPassword()))
|
||||
|
||||
.withCaCertFile(or(kubernetesClientProperties.getCaCertFile(),
|
||||
base.getCaCertFile()))
|
||||
.withCaCertData(or(kubernetesClientProperties.getCaCertData(),
|
||||
base.getCaCertData()))
|
||||
.withCaCertFile(or(kubernetesClientProperties.getCaCertFile(), base.getCaCertFile()))
|
||||
.withCaCertData(or(kubernetesClientProperties.getCaCertData(), base.getCaCertData()))
|
||||
|
||||
.withClientKeyFile(or(kubernetesClientProperties.getClientKeyFile(),
|
||||
base.getClientKeyFile()))
|
||||
.withClientKeyData(or(kubernetesClientProperties.getClientKeyData(),
|
||||
base.getClientKeyData()))
|
||||
.withClientKeyFile(or(kubernetesClientProperties.getClientKeyFile(), base.getClientKeyFile()))
|
||||
.withClientKeyData(or(kubernetesClientProperties.getClientKeyData(), base.getClientKeyData()))
|
||||
|
||||
.withClientCertFile(or(kubernetesClientProperties.getClientCertFile(),
|
||||
base.getClientCertFile()))
|
||||
.withClientCertData(or(kubernetesClientProperties.getClientCertData(),
|
||||
base.getClientCertData()))
|
||||
.withClientCertFile(or(kubernetesClientProperties.getClientCertFile(), base.getClientCertFile()))
|
||||
.withClientCertData(or(kubernetesClientProperties.getClientCertData(), base.getClientCertData()))
|
||||
|
||||
// No magic is done for the properties below so we leave them as is.
|
||||
.withClientKeyAlgo(or(kubernetesClientProperties.getClientKeyAlgo(),
|
||||
base.getClientKeyAlgo()))
|
||||
.withClientKeyAlgo(or(kubernetesClientProperties.getClientKeyAlgo(), base.getClientKeyAlgo()))
|
||||
.withClientKeyPassphrase(
|
||||
or(kubernetesClientProperties.getClientKeyPassphrase(),
|
||||
base.getClientKeyPassphrase()))
|
||||
or(kubernetesClientProperties.getClientKeyPassphrase(), base.getClientKeyPassphrase()))
|
||||
.withConnectionTimeout(
|
||||
orDurationInt(kubernetesClientProperties.getConnectionTimeout(),
|
||||
base.getConnectionTimeout()))
|
||||
orDurationInt(kubernetesClientProperties.getConnectionTimeout(), base.getConnectionTimeout()))
|
||||
.withRequestTimeout(
|
||||
orDurationInt(kubernetesClientProperties.getRequestTimeout(),
|
||||
base.getRequestTimeout()))
|
||||
orDurationInt(kubernetesClientProperties.getRequestTimeout(), base.getRequestTimeout()))
|
||||
.withRollingTimeout(
|
||||
orDurationLong(kubernetesClientProperties.getRollingTimeout(),
|
||||
base.getRollingTimeout()))
|
||||
.withTrustCerts(or(kubernetesClientProperties.isTrustCerts(),
|
||||
base.isTrustCerts()))
|
||||
.withHttpProxy(or(kubernetesClientProperties.getHttpProxy(),
|
||||
base.getHttpProxy()))
|
||||
.withHttpsProxy(or(kubernetesClientProperties.getHttpsProxy(),
|
||||
base.getHttpsProxy()))
|
||||
.withProxyUsername(or(kubernetesClientProperties.getProxyUsername(),
|
||||
base.getProxyUsername()))
|
||||
.withProxyPassword(or(kubernetesClientProperties.getProxyPassword(),
|
||||
base.getProxyPassword()))
|
||||
.withNoProxy(
|
||||
or(kubernetesClientProperties.getNoProxy(), base.getNoProxy()))
|
||||
.build();
|
||||
orDurationLong(kubernetesClientProperties.getRollingTimeout(), base.getRollingTimeout()))
|
||||
.withTrustCerts(or(kubernetesClientProperties.isTrustCerts(), base.isTrustCerts()))
|
||||
.withHttpProxy(or(kubernetesClientProperties.getHttpProxy(), base.getHttpProxy()))
|
||||
.withHttpsProxy(or(kubernetesClientProperties.getHttpsProxy(), base.getHttpsProxy()))
|
||||
.withProxyUsername(or(kubernetesClientProperties.getProxyUsername(), base.getProxyUsername()))
|
||||
.withProxyPassword(or(kubernetesClientProperties.getProxyPassword(), base.getProxyPassword()))
|
||||
.withNoProxy(or(kubernetesClientProperties.getNoProxy(), base.getNoProxy())).build();
|
||||
|
||||
if (properties.getNamespace() == null || properties.getNamespace().isEmpty()) {
|
||||
LOG.warn("No namespace has been detected. Please specify "
|
||||
|
||||
@@ -40,12 +40,10 @@ public class KubernetesHealthIndicator extends AbstractHealthIndicator {
|
||||
try {
|
||||
Pod current = this.utils.currentPod().get();
|
||||
if (current != null) {
|
||||
builder.up().withDetail("inside", true)
|
||||
.withDetail("namespace", current.getMetadata().getNamespace())
|
||||
builder.up().withDetail("inside", true).withDetail("namespace", current.getMetadata().getNamespace())
|
||||
.withDetail("podName", current.getMetadata().getName())
|
||||
.withDetail("podIp", current.getStatus().getPodIP())
|
||||
.withDetail("serviceAccount",
|
||||
current.getSpec().getServiceAccountName())
|
||||
.withDetail("serviceAccount", current.getSpec().getServiceAccountName())
|
||||
.withDetail("nodeName", current.getSpec().getNodeName())
|
||||
.withDetail("hostIp", current.getStatus().getHostIP())
|
||||
.withDetail("labels", current.getMetadata().getLabels());
|
||||
|
||||
@@ -47,8 +47,7 @@ public class StandardPodUtils implements PodUtils {
|
||||
|
||||
public StandardPodUtils(KubernetesClient client) {
|
||||
if (client == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Must provide an instance of KubernetesClient");
|
||||
throw new IllegalArgumentException("Must provide an instance of KubernetesClient");
|
||||
}
|
||||
|
||||
this.client = client;
|
||||
@@ -76,10 +75,8 @@ public class StandardPodUtils implements PodUtils {
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
LOG.warn("Failed to get pod with name:[" + this.hostName
|
||||
+ "]. You should look into this if things aren't"
|
||||
+ " working as you expect. Are you missing serviceaccount permissions?",
|
||||
t);
|
||||
LOG.warn("Failed to get pod with name:[" + this.hostName + "]. You should look into this if things aren't"
|
||||
+ " working as you expect. Are you missing serviceaccount permissions?", t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -90,8 +87,7 @@ public class StandardPodUtils implements PodUtils {
|
||||
|
||||
private boolean isServiceAccountFound() {
|
||||
return Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH).toFile().exists()
|
||||
&& Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_CA_CRT_PATH).toFile()
|
||||
.exists();
|
||||
&& Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_CA_CRT_PATH).toFile().exists();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,11 +28,9 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
public class KubernetesProfileEnvironmentPostProcessor
|
||||
implements EnvironmentPostProcessor, Ordered {
|
||||
public class KubernetesProfileEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
|
||||
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(KubernetesProfileEnvironmentPostProcessor.class);
|
||||
private static final Log LOG = LogFactory.getLog(KubernetesProfileEnvironmentPostProcessor.class);
|
||||
|
||||
// Before ConfigFileApplicationListener so values there can use these ones
|
||||
private static final int ORDER = ConfigFileApplicationListener.DEFAULT_ORDER - 1;
|
||||
@@ -40,11 +38,10 @@ public class KubernetesProfileEnvironmentPostProcessor
|
||||
private static final String KUBERNETES_PROFILE = "kubernetes";
|
||||
|
||||
@Override
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment,
|
||||
SpringApplication application) {
|
||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||
|
||||
final boolean kubernetesEnabled = environment
|
||||
.getProperty("spring.cloud.kubernetes.enabled", Boolean.class, true);
|
||||
final boolean kubernetesEnabled = environment.getProperty("spring.cloud.kubernetes.enabled", Boolean.class,
|
||||
true);
|
||||
if (!kubernetesEnabled) {
|
||||
return;
|
||||
}
|
||||
@@ -64,8 +61,7 @@ public class KubernetesProfileEnvironmentPostProcessor
|
||||
}
|
||||
else {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.warn(
|
||||
"Not running inside kubernetes. Skipping 'kubernetes' profile activation.");
|
||||
LOG.warn("Not running inside kubernetes. Skipping 'kubernetes' profile activation.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@ import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class,
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
|
||||
properties = { "management.health.kubernetes.enabled=false" })
|
||||
public class HealthIndicatorDisabledTest {
|
||||
|
||||
@@ -57,20 +56,18 @@ public class HealthIndicatorDisabledTest {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void healthEndpointShouldContainKubernetes() {
|
||||
this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port)
|
||||
.accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk()
|
||||
.expectBody(String.class).value(not(containsString("kubernetes")));
|
||||
.accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class)
|
||||
.value(not(containsString("kubernetes")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,8 +35,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class,
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
|
||||
properties = { "management.endpoint.health.show-details=always" })
|
||||
public class HealthIndicatorTest {
|
||||
|
||||
@@ -56,12 +55,10 @@ public class HealthIndicatorTest {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
}
|
||||
@@ -69,8 +66,8 @@ public class HealthIndicatorTest {
|
||||
@Test
|
||||
public void healthEndpointShouldContainKubernetes() {
|
||||
this.webClient.get().uri("http://localhost:{port}/actuator/health", this.port)
|
||||
.accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk()
|
||||
.expectBody(String.class).value(containsString("kubernetes"));
|
||||
.accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk().expectBody(String.class)
|
||||
.value(containsString("kubernetes"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,8 +35,7 @@ import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class)
|
||||
public class InfoContributorTest {
|
||||
|
||||
@ClassRule
|
||||
@@ -55,21 +54,18 @@ public class InfoContributorTest {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void infoEndpointShouldContainKubernetes() {
|
||||
this.webClient.get().uri("http://localhost:{port}/actuator/info", this.port)
|
||||
.accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk()
|
||||
.expectBody(String.class).value(containsString("kubernetes"));
|
||||
this.webClient.get().uri("http://localhost:{port}/actuator/info", this.port).accept(MediaType.APPLICATION_JSON)
|
||||
.exchange().expectStatus().isOk().expectBody(String.class).value(containsString("kubernetes"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,8 +33,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
classes = App.class,
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
|
||||
properties = { "spring.cloud.kubernetes.client.password=mypassword",
|
||||
"spring.cloud.kubernetes.client.proxy-password=myproxypassword" })
|
||||
public class KubernetesAutoConfigurationTests {
|
||||
@@ -50,12 +49,10 @@ public class KubernetesAutoConfigurationTests {
|
||||
KubernetesClient 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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
}
|
||||
@@ -65,10 +62,8 @@ public class KubernetesAutoConfigurationTests {
|
||||
assertThat(context.getBeanNamesForType(Config.class)).hasSize(1);
|
||||
assertThat(context.getBeanNamesForType(KubernetesClient.class)).hasSize(1);
|
||||
assertThat(context.getBeanNamesForType(StandardPodUtils.class)).hasSize(1);
|
||||
assertThat(context.getBeanNamesForType(KubernetesHealthIndicator.class))
|
||||
.hasSize(1);
|
||||
assertThat(context.getBeanNamesForType(KubernetesInfoContributor.class))
|
||||
.hasSize(1);
|
||||
assertThat(context.getBeanNamesForType(KubernetesHealthIndicator.class)).hasSize(1);
|
||||
assertThat(context.getBeanNamesForType(KubernetesInfoContributor.class)).hasSize(1);
|
||||
|
||||
Config config = context.getBean(Config.class);
|
||||
assertThat(config.getPassword()).isEqualTo("mypassword");
|
||||
|
||||
@@ -53,8 +53,7 @@ public class LazilyInstantiateTest {
|
||||
|
||||
@Test
|
||||
public void factoryReturnsSingletonFromSupplier() {
|
||||
LazilyInstantiate<String> lazyStringFactory = LazilyInstantiate
|
||||
.using(this.mockSupplier);
|
||||
LazilyInstantiate<String> lazyStringFactory = LazilyInstantiate.using(this.mockSupplier);
|
||||
String singletonString = lazyStringFactory.get();
|
||||
|
||||
// verify
|
||||
@@ -63,8 +62,7 @@ public class LazilyInstantiateTest {
|
||||
|
||||
@Test
|
||||
public void factoryOnlyCallsSupplierOnce() {
|
||||
LazilyInstantiate<String> lazyStringFactory = LazilyInstantiate
|
||||
.using(this.mockSupplier);
|
||||
LazilyInstantiate<String> lazyStringFactory = LazilyInstantiate.using(this.mockSupplier);
|
||||
lazyStringFactory.get();
|
||||
|
||||
// mock will throw exception if it is called more than once
|
||||
|
||||
@@ -36,8 +36,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@ConditionalOnProperty(value = "spring.cloud.kubernetes.discovery.enabled",
|
||||
matchIfMissing = true)
|
||||
@ConditionalOnProperty(value = "spring.cloud.kubernetes.discovery.enabled", matchIfMissing = true)
|
||||
public @interface ConditionalOnKubernetesDiscoveryEnabled {
|
||||
|
||||
}
|
||||
|
||||
@@ -35,8 +35,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
*/
|
||||
class DefaultIsServicePortSecureResolver {
|
||||
|
||||
private static final Log log = LogFactory
|
||||
.getLog(DefaultIsServicePortSecureResolver.class);
|
||||
private static final Log log = LogFactory.getLog(DefaultIsServicePortSecureResolver.class);
|
||||
|
||||
private static final Set<String> TRUTHY_STRINGS = new HashSet<String>() {
|
||||
{
|
||||
@@ -54,33 +53,27 @@ class DefaultIsServicePortSecureResolver {
|
||||
}
|
||||
|
||||
boolean resolve(Input input) {
|
||||
final String securedLabelValue = input.getServiceLabels().getOrDefault("secured",
|
||||
"false");
|
||||
final String securedLabelValue = input.getServiceLabels().getOrDefault("secured", "false");
|
||||
if (TRUTHY_STRINGS.contains(securedLabelValue)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Considering service with name: " + input.getServiceName()
|
||||
+ " and port " + input.getPort()
|
||||
log.debug("Considering service with name: " + input.getServiceName() + " and port " + input.getPort()
|
||||
+ " is secure since the service contains a true value for the 'secured' label");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
final String securedAnnotationValue = input.getServiceAnnotations()
|
||||
.getOrDefault("secured", "false");
|
||||
final String securedAnnotationValue = input.getServiceAnnotations().getOrDefault("secured", "false");
|
||||
if (TRUTHY_STRINGS.contains(securedAnnotationValue)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Considering service with name: " + input.getServiceName()
|
||||
+ " and port " + input.getPort()
|
||||
log.debug("Considering service with name: " + input.getServiceName() + " and port " + input.getPort()
|
||||
+ " is secure since the service contains a true value for the 'secured' annotation");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input.getPort() != null
|
||||
&& this.properties.getKnownSecurePorts().contains(input.getPort())) {
|
||||
if (input.getPort() != null && this.properties.getKnownSecurePorts().contains(input.getPort())) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Considering service with name: " + input.getServiceName()
|
||||
+ " and port " + input.getPort()
|
||||
log.debug("Considering service with name: " + input.getServiceName() + " and port " + input.getPort()
|
||||
+ " is secure due to the port being a known https port");
|
||||
}
|
||||
return true;
|
||||
@@ -109,8 +102,7 @@ class DefaultIsServicePortSecureResolver {
|
||||
this.port = port;
|
||||
this.serviceName = serviceName;
|
||||
this.serviceLabels = serviceLabels == null ? new HashMap<>() : serviceLabels;
|
||||
this.serviceAnnotations = serviceAnnotations == null ? new HashMap<>()
|
||||
: serviceAnnotations;
|
||||
this.serviceAnnotations = serviceAnnotations == null ? new HashMap<>() : serviceAnnotations;
|
||||
}
|
||||
|
||||
public String getServiceName() {
|
||||
|
||||
@@ -40,8 +40,7 @@ import org.springframework.scheduling.annotation.Scheduled;
|
||||
*/
|
||||
public class KubernetesCatalogWatch implements ApplicationEventPublisherAware {
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(KubernetesCatalogWatch.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(KubernetesCatalogWatch.class);
|
||||
|
||||
private final KubernetesClient kubernetesClient;
|
||||
|
||||
@@ -51,8 +50,7 @@ public class KubernetesCatalogWatch implements ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher publisher;
|
||||
|
||||
public KubernetesCatalogWatch(KubernetesClient kubernetesClient,
|
||||
KubernetesDiscoveryProperties properties) {
|
||||
public KubernetesCatalogWatch(KubernetesClient kubernetesClient, KubernetesDiscoveryProperties properties) {
|
||||
this.kubernetesClient = kubernetesClient;
|
||||
this.properties = properties;
|
||||
}
|
||||
@@ -62,8 +60,7 @@ public class KubernetesCatalogWatch implements ApplicationEventPublisherAware {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@Scheduled(
|
||||
fixedDelayString = "${spring.cloud.kubernetes.discovery.catalogServicesWatchDelay:30000}")
|
||||
@Scheduled(fixedDelayString = "${spring.cloud.kubernetes.discovery.catalogServicesWatchDelay:30000}")
|
||||
public void catalogServicesWatch() {
|
||||
try {
|
||||
List<String> previousState = this.catalogEndpointsState.get();
|
||||
@@ -71,24 +68,21 @@ public class KubernetesCatalogWatch implements ApplicationEventPublisherAware {
|
||||
// not all pods participate in the service discovery. only those that have
|
||||
// endpoints.
|
||||
List<Endpoints> endpoints = this.properties.isAllNamespaces()
|
||||
? this.kubernetesClient.endpoints().inAnyNamespace()
|
||||
.withLabels(properties.getServiceLabels()).list().getItems()
|
||||
: this.kubernetesClient.endpoints()
|
||||
.withLabels(properties.getServiceLabels()).list().getItems();
|
||||
List<String> endpointsPodNames = endpoints.stream().map(Endpoints::getSubsets)
|
||||
.filter(Objects::nonNull).flatMap(Collection::stream)
|
||||
.map(EndpointSubset::getAddresses).filter(Objects::nonNull)
|
||||
.flatMap(Collection::stream).map(EndpointAddress::getTargetRef)
|
||||
.filter(Objects::nonNull).map(ObjectReference::getName) // pod name
|
||||
// unique in
|
||||
// namespace
|
||||
? this.kubernetesClient.endpoints().inAnyNamespace().withLabels(properties.getServiceLabels())
|
||||
.list().getItems()
|
||||
: this.kubernetesClient.endpoints().withLabels(properties.getServiceLabels()).list().getItems();
|
||||
List<String> endpointsPodNames = endpoints.stream().map(Endpoints::getSubsets).filter(Objects::nonNull)
|
||||
.flatMap(Collection::stream).map(EndpointSubset::getAddresses).filter(Objects::nonNull)
|
||||
.flatMap(Collection::stream).map(EndpointAddress::getTargetRef).filter(Objects::nonNull)
|
||||
.map(ObjectReference::getName) // pod name
|
||||
// unique in
|
||||
// namespace
|
||||
.sorted(String::compareTo).collect(Collectors.toList());
|
||||
|
||||
this.catalogEndpointsState.set(endpointsPodNames);
|
||||
|
||||
if (!endpointsPodNames.equals(previousState)) {
|
||||
logger.trace("Received endpoints update from kubernetesClient: {}",
|
||||
endpointsPodNames);
|
||||
logger.trace("Received endpoints update from kubernetesClient: {}", endpointsPodNames);
|
||||
this.publisher.publishEvent(new HeartbeatEvent(this, endpointsPodNames));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,7 @@ public class KubernetesCatalogWatchAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(
|
||||
name = "spring.cloud.kubernetes.discovery.catalog-services-watch.enabled",
|
||||
@ConditionalOnProperty(name = "spring.cloud.kubernetes.discovery.catalog-services-watch.enabled",
|
||||
matchIfMissing = true)
|
||||
public KubernetesCatalogWatch kubernetesCatalogWatch(KubernetesClient client,
|
||||
KubernetesDiscoveryProperties properties) {
|
||||
|
||||
@@ -60,8 +60,8 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
|
||||
private final SpelExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
private final SimpleEvaluationContext evalCtxt = SimpleEvaluationContext
|
||||
.forReadOnlyDataBinding().withInstanceMethods().build();
|
||||
private final SimpleEvaluationContext evalCtxt = SimpleEvaluationContext.forReadOnlyDataBinding()
|
||||
.withInstanceMethods().build();
|
||||
|
||||
private KubernetesClient client;
|
||||
|
||||
@@ -73,8 +73,7 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
new DefaultIsServicePortSecureResolver(kubernetesDiscoveryProperties));
|
||||
}
|
||||
|
||||
KubernetesDiscoveryClient(KubernetesClient client,
|
||||
KubernetesDiscoveryProperties kubernetesDiscoveryProperties,
|
||||
KubernetesDiscoveryClient(KubernetesClient client, KubernetesDiscoveryProperties kubernetesDiscoveryProperties,
|
||||
KubernetesClientServicesFunction kubernetesClientServicesFunction,
|
||||
DefaultIsServicePortSecureResolver isServicePortSecureResolver) {
|
||||
|
||||
@@ -99,12 +98,10 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getInstances(String serviceId) {
|
||||
Assert.notNull(serviceId,
|
||||
"[Assertion failed] - the object argument must not be null");
|
||||
Assert.notNull(serviceId, "[Assertion failed] - the object argument must not be null");
|
||||
|
||||
List<EndpointSubsetNS> subsetsNS = this.getEndPointsList(serviceId).stream()
|
||||
.map(endpoints -> getSubsetsFromEndpoints(endpoints))
|
||||
.collect(Collectors.toList());
|
||||
.map(endpoints -> getSubsetsFromEndpoints(endpoints)).collect(Collectors.toList());
|
||||
|
||||
List<ServiceInstance> instances = new ArrayList<>();
|
||||
if (!subsetsNS.isEmpty()) {
|
||||
@@ -118,24 +115,20 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
|
||||
public List<Endpoints> getEndPointsList(String serviceId) {
|
||||
return this.properties.isAllNamespaces()
|
||||
? this.client.endpoints().inAnyNamespace()
|
||||
.withField("metadata.name", serviceId)
|
||||
? this.client.endpoints().inAnyNamespace().withField("metadata.name", serviceId)
|
||||
.withLabels(properties.getServiceLabels()).list().getItems()
|
||||
: this.client.endpoints().withField("metadata.name", serviceId)
|
||||
.withLabels(properties.getServiceLabels()).list().getItems();
|
||||
}
|
||||
|
||||
private List<ServiceInstance> getNamespaceServiceInstances(EndpointSubsetNS es,
|
||||
String serviceId) {
|
||||
private List<ServiceInstance> getNamespaceServiceInstances(EndpointSubsetNS es, String serviceId) {
|
||||
String namespace = es.getNamespace();
|
||||
List<EndpointSubset> subsets = es.getEndpointSubset();
|
||||
List<ServiceInstance> instances = new ArrayList<>();
|
||||
if (!subsets.isEmpty()) {
|
||||
final Service service = this.client.services().inNamespace(namespace)
|
||||
.withName(serviceId).get();
|
||||
final Service service = this.client.services().inNamespace(namespace).withName(serviceId).get();
|
||||
final Map<String, String> serviceMetadata = this.getServiceMetadata(service);
|
||||
KubernetesDiscoveryProperties.Metadata metadataProps = this.properties
|
||||
.getMetadata();
|
||||
KubernetesDiscoveryProperties.Metadata metadataProps = this.properties.getMetadata();
|
||||
|
||||
for (EndpointSubset s : subsets) {
|
||||
// Extend the service metadata map with per-endpoint port information (if
|
||||
@@ -144,10 +137,8 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
if (metadataProps.isAddPorts()) {
|
||||
Map<String, String> ports = s.getPorts().stream()
|
||||
.filter(port -> !StringUtils.isEmpty(port.getName()))
|
||||
.collect(toMap(EndpointPort::getName,
|
||||
port -> Integer.toString(port.getPort())));
|
||||
Map<String, String> portMetadata = getMapWithPrefixedKeys(ports,
|
||||
metadataProps.getPortsPrefix());
|
||||
.collect(toMap(EndpointPort::getName, port -> Integer.toString(port.getPort())));
|
||||
Map<String, String> portMetadata = getMapWithPrefixedKeys(ports, metadataProps.getPortsPrefix());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Adding port metadata: " + portMetadata);
|
||||
}
|
||||
@@ -166,15 +157,11 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
}
|
||||
|
||||
EndpointPort endpointPort = findEndpointPort(s);
|
||||
instances.add(new KubernetesServiceInstance(instanceId, serviceId,
|
||||
endpointAddress.getIp(), endpointPort.getPort(),
|
||||
endpointMetadata,
|
||||
this.isServicePortSecureResolver
|
||||
.resolve(new DefaultIsServicePortSecureResolver.Input(
|
||||
endpointPort.getPort(),
|
||||
service.getMetadata().getName(),
|
||||
service.getMetadata().getLabels(),
|
||||
service.getMetadata().getAnnotations()))));
|
||||
instances.add(new KubernetesServiceInstance(instanceId, serviceId, endpointAddress.getIp(),
|
||||
endpointPort.getPort(), endpointMetadata,
|
||||
this.isServicePortSecureResolver.resolve(new DefaultIsServicePortSecureResolver.Input(
|
||||
endpointPort.getPort(), service.getMetadata().getName(),
|
||||
service.getMetadata().getLabels(), service.getMetadata().getAnnotations()))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,19 +171,17 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
|
||||
private Map<String, String> getServiceMetadata(Service service) {
|
||||
final Map<String, String> serviceMetadata = new HashMap<>();
|
||||
KubernetesDiscoveryProperties.Metadata metadataProps = this.properties
|
||||
.getMetadata();
|
||||
KubernetesDiscoveryProperties.Metadata metadataProps = this.properties.getMetadata();
|
||||
if (metadataProps.isAddLabels()) {
|
||||
Map<String, String> labelMetadata = getMapWithPrefixedKeys(
|
||||
service.getMetadata().getLabels(), metadataProps.getLabelsPrefix());
|
||||
Map<String, String> labelMetadata = getMapWithPrefixedKeys(service.getMetadata().getLabels(),
|
||||
metadataProps.getLabelsPrefix());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Adding label metadata: " + labelMetadata);
|
||||
}
|
||||
serviceMetadata.putAll(labelMetadata);
|
||||
}
|
||||
if (metadataProps.isAddAnnotations()) {
|
||||
Map<String, String> annotationMetadata = getMapWithPrefixedKeys(
|
||||
service.getMetadata().getAnnotations(),
|
||||
Map<String, String> annotationMetadata = getMapWithPrefixedKeys(service.getMetadata().getAnnotations(),
|
||||
metadataProps.getAnnotationsPrefix());
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Adding annotation metadata: " + annotationMetadata);
|
||||
@@ -216,14 +201,12 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
else {
|
||||
Predicate<EndpointPort> portPredicate;
|
||||
if (!StringUtils.isEmpty(properties.getPrimaryPortName())) {
|
||||
portPredicate = port -> properties.getPrimaryPortName()
|
||||
.equalsIgnoreCase(port.getName());
|
||||
portPredicate = port -> properties.getPrimaryPortName().equalsIgnoreCase(port.getName());
|
||||
}
|
||||
else {
|
||||
portPredicate = port -> true;
|
||||
}
|
||||
endpointPort = ports.stream().filter(portPredicate).findAny()
|
||||
.orElseThrow(IllegalStateException::new);
|
||||
endpointPort = ports.stream().filter(portPredicate).findAny().orElseThrow(IllegalStateException::new);
|
||||
}
|
||||
return endpointPort;
|
||||
}
|
||||
@@ -244,8 +227,7 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
// returns a new map that contain all the entries of the original map
|
||||
// but with the keys prefixed
|
||||
// if the prefix is null or empty, the map itself is returned (unchanged of course)
|
||||
private Map<String, String> getMapWithPrefixedKeys(Map<String, String> map,
|
||||
String prefix) {
|
||||
private Map<String, String> getMapWithPrefixedKeys(Map<String, String> map, String prefix) {
|
||||
if (map == null) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
@@ -271,8 +253,7 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
else {
|
||||
Expression filterExpr = this.parser.parseExpression(spelExpression);
|
||||
filteredServices = (Service instance) -> {
|
||||
Boolean include = filterExpr.getValue(this.evalCtxt, instance,
|
||||
Boolean.class);
|
||||
Boolean include = filterExpr.getValue(this.evalCtxt, instance, Boolean.class);
|
||||
if (include == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -283,9 +264,8 @@ public class KubernetesDiscoveryClient implements DiscoveryClient {
|
||||
}
|
||||
|
||||
public List<String> getServices(Predicate<Service> filter) {
|
||||
return this.kubernetesClientServicesFunction.apply(this.client).list().getItems()
|
||||
.stream().filter(filter).map(s -> s.getMetadata().getName())
|
||||
.collect(Collectors.toList());
|
||||
return this.kubernetesClientServicesFunction.apply(this.client).list().getItems().stream().filter(filter)
|
||||
.map(s -> s.getMetadata().getName()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -41,21 +41,18 @@ import org.springframework.context.annotation.Configuration;
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnDiscoveryEnabled
|
||||
@ConditionalOnKubernetesEnabled
|
||||
@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class,
|
||||
CommonsClientAutoConfiguration.class })
|
||||
@AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class })
|
||||
@AutoConfigureAfter({ KubernetesAutoConfiguration.class })
|
||||
public class KubernetesDiscoveryClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DefaultIsServicePortSecureResolver isServicePortSecureResolver(
|
||||
KubernetesDiscoveryProperties properties) {
|
||||
public DefaultIsServicePortSecureResolver isServicePortSecureResolver(KubernetesDiscoveryProperties properties) {
|
||||
return new DefaultIsServicePortSecureResolver(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KubernetesClientServicesFunction servicesFunction(
|
||||
KubernetesDiscoveryProperties properties) {
|
||||
public KubernetesClientServicesFunction servicesFunction(KubernetesDiscoveryProperties properties) {
|
||||
if (properties.getServiceLabels().isEmpty()) {
|
||||
if (properties.isAllNamespaces()) {
|
||||
return (client) -> client.services().inAnyNamespace();
|
||||
@@ -66,12 +63,10 @@ public class KubernetesDiscoveryClientAutoConfiguration {
|
||||
}
|
||||
else {
|
||||
if (properties.isAllNamespaces()) {
|
||||
return (client) -> client.services().inAnyNamespace()
|
||||
.withLabels(properties.getServiceLabels());
|
||||
return (client) -> client.services().inAnyNamespace().withLabels(properties.getServiceLabels());
|
||||
}
|
||||
else {
|
||||
return (client) -> client.services()
|
||||
.withLabels(properties.getServiceLabels());
|
||||
return (client) -> client.services().withLabels(properties.getServiceLabels());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,8 +77,7 @@ public class KubernetesDiscoveryClientAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KubernetesRegistration getRegistration(KubernetesClient client,
|
||||
KubernetesDiscoveryProperties properties) {
|
||||
public KubernetesRegistration getRegistration(KubernetesClient client, KubernetesDiscoveryProperties properties) {
|
||||
return new KubernetesRegistration(client, properties);
|
||||
}
|
||||
|
||||
@@ -99,12 +93,12 @@ public class KubernetesDiscoveryClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public KubernetesDiscoveryClient kubernetesDiscoveryClient(
|
||||
KubernetesClient client, KubernetesDiscoveryProperties properties,
|
||||
public KubernetesDiscoveryClient kubernetesDiscoveryClient(KubernetesClient client,
|
||||
KubernetesDiscoveryProperties properties,
|
||||
KubernetesClientServicesFunction kubernetesClientServicesFunction,
|
||||
DefaultIsServicePortSecureResolver isServicePortSecureResolver) {
|
||||
return new KubernetesDiscoveryClient(client, properties,
|
||||
kubernetesClientServicesFunction, isServicePortSecureResolver);
|
||||
return new KubernetesDiscoveryClient(client, properties, kubernetesClientServicesFunction,
|
||||
isServicePortSecureResolver);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,7 @@ import org.springframework.context.annotation.Import;
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty("spring.cloud.config.discovery.enabled")
|
||||
@Import({ KubernetesAutoConfiguration.class,
|
||||
KubernetesDiscoveryClientAutoConfiguration.class })
|
||||
@Import({ KubernetesAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class })
|
||||
public class KubernetesDiscoveryClientConfigClientBootstrapConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@@ -148,11 +148,9 @@ public class KubernetesDiscoveryProperties {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("enabled", this.enabled)
|
||||
.append("serviceName", this.serviceName).append("filter", this.filter)
|
||||
.append("knownSecurePorts", this.knownSecurePorts)
|
||||
.append("serviceLabels", this.serviceLabels)
|
||||
.append("metadata", this.metadata).toString();
|
||||
return new ToStringCreator(this).append("enabled", this.enabled).append("serviceName", this.serviceName)
|
||||
.append("filter", this.filter).append("knownSecurePorts", this.knownSecurePorts)
|
||||
.append("serviceLabels", this.serviceLabels).append("metadata", this.metadata).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,10 +245,8 @@ public class KubernetesDiscoveryProperties {
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("addLabels", this.addLabels)
|
||||
.append("labelsPrefix", this.labelsPrefix)
|
||||
.append("addAnnotations", this.addAnnotations)
|
||||
.append("annotationsPrefix", this.annotationsPrefix)
|
||||
.append("addPorts", this.addPorts)
|
||||
.append("labelsPrefix", this.labelsPrefix).append("addAnnotations", this.addAnnotations)
|
||||
.append("annotationsPrefix", this.annotationsPrefix).append("addPorts", this.addPorts)
|
||||
.append("portsPrefix", this.portsPrefix).toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -63,8 +63,8 @@ public class KubernetesServiceInstance implements ServiceInstance {
|
||||
* @param metadata a map containing metadata.
|
||||
* @param secure indicates whether or not the connection needs to be secure.
|
||||
*/
|
||||
public KubernetesServiceInstance(String instanceId, String serviceId, String host,
|
||||
int port, Map<String, String> metadata, Boolean secure) {
|
||||
public KubernetesServiceInstance(String instanceId, String serviceId, String host, int port,
|
||||
Map<String, String> metadata, Boolean secure) {
|
||||
this.instanceId = instanceId;
|
||||
this.serviceId = serviceId;
|
||||
this.host = host;
|
||||
@@ -115,8 +115,7 @@ public class KubernetesServiceInstance implements ServiceInstance {
|
||||
|
||||
private URI createUri(String scheme, String host, int port) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(scheme).append(COLON).append(DSL).append(host).append(COLON)
|
||||
.append(port);
|
||||
sb.append(scheme).append(COLON).append(DSL).append(host).append(COLON).append(port);
|
||||
return URI.create(sb.toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,7 @@ public class KubernetesReactiveDiscoveryClient implements ReactiveDiscoveryClien
|
||||
|
||||
private final KubernetesDiscoveryClient kubernetesDiscoveryClient;
|
||||
|
||||
public KubernetesReactiveDiscoveryClient(KubernetesClient client,
|
||||
KubernetesDiscoveryProperties properties,
|
||||
public KubernetesReactiveDiscoveryClient(KubernetesClient client, KubernetesDiscoveryProperties properties,
|
||||
KubernetesClientServicesFunction kubernetesClientServicesFunction) {
|
||||
this.kubernetesDiscoveryClient = new KubernetesDiscoveryClient(client, properties,
|
||||
kubernetesClientServicesFunction);
|
||||
@@ -51,18 +50,14 @@ public class KubernetesReactiveDiscoveryClient implements ReactiveDiscoveryClien
|
||||
|
||||
@Override
|
||||
public Flux<ServiceInstance> getInstances(String serviceId) {
|
||||
Assert.notNull(serviceId,
|
||||
"[Assertion failed] - the object argument must not be null");
|
||||
return Flux
|
||||
.defer(() -> Flux
|
||||
.fromIterable(kubernetesDiscoveryClient.getInstances(serviceId)))
|
||||
Assert.notNull(serviceId, "[Assertion failed] - the object argument must not be null");
|
||||
return Flux.defer(() -> Flux.fromIterable(kubernetesDiscoveryClient.getInstances(serviceId)))
|
||||
.subscribeOn(Schedulers.boundedElastic());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<String> getServices() {
|
||||
return Flux
|
||||
.defer(() -> Flux.fromIterable(kubernetesDiscoveryClient.getServices()))
|
||||
return Flux.defer(() -> Flux.fromIterable(kubernetesDiscoveryClient.getServices()))
|
||||
.subscribeOn(Schedulers.boundedElastic());
|
||||
}
|
||||
|
||||
|
||||
@@ -56,20 +56,17 @@ public class KubernetesReactiveDiscoveryClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient(
|
||||
KubernetesClient client, KubernetesDiscoveryProperties properties,
|
||||
public KubernetesReactiveDiscoveryClient kubernetesReactiveDiscoveryClient(KubernetesClient client,
|
||||
KubernetesDiscoveryProperties properties,
|
||||
KubernetesClientServicesFunction kubernetesClientServicesFunction) {
|
||||
return new KubernetesReactiveDiscoveryClient(client, properties,
|
||||
kubernetesClientServicesFunction);
|
||||
return new KubernetesReactiveDiscoveryClient(client, properties, kubernetesClientServicesFunction);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(
|
||||
name = "org.springframework.boot.actuate.health.ReactiveHealthIndicator")
|
||||
@ConditionalOnClass(name = "org.springframework.boot.actuate.health.ReactiveHealthIndicator")
|
||||
@ConditionalOnDiscoveryHealthIndicatorEnabled
|
||||
public ReactiveDiscoveryClientHealthIndicator kubernetesReactiveDiscoveryClientHealthIndicator(
|
||||
KubernetesReactiveDiscoveryClient client,
|
||||
DiscoveryClientHealthIndicatorProperties properties) {
|
||||
KubernetesReactiveDiscoveryClient client, DiscoveryClientHealthIndicatorProperties properties) {
|
||||
return new ReactiveDiscoveryClientHealthIndicator(client, properties);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,9 @@ import org.springframework.core.Ordered;
|
||||
*/
|
||||
@Deprecated
|
||||
// TODO Remove this class in 2.x as it is not used or necessary in Kubernetes
|
||||
public class KubernetesAutoServiceRegistration
|
||||
implements AutoServiceRegistration, SmartLifecycle, Ordered {
|
||||
public class KubernetesAutoServiceRegistration implements AutoServiceRegistration, SmartLifecycle, Ordered {
|
||||
|
||||
private static final Log log = LogFactory
|
||||
.getLog(KubernetesAutoServiceRegistration.class);
|
||||
private static final Log log = LogFactory.getLog(KubernetesAutoServiceRegistration.class);
|
||||
|
||||
private AtomicBoolean running = new AtomicBoolean(false);
|
||||
|
||||
@@ -56,8 +54,7 @@ public class KubernetesAutoServiceRegistration
|
||||
|
||||
private KubernetesRegistration registration;
|
||||
|
||||
public KubernetesAutoServiceRegistration(ApplicationContext context,
|
||||
KubernetesServiceRegistry serviceRegistry,
|
||||
public KubernetesAutoServiceRegistration(ApplicationContext context, KubernetesServiceRegistry serviceRegistry,
|
||||
KubernetesRegistration registration) {
|
||||
this.context = context;
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
@@ -79,8 +76,7 @@ public class KubernetesAutoServiceRegistration
|
||||
public void start() {
|
||||
this.serviceRegistry.register(this.registration);
|
||||
|
||||
this.context.publishEvent(
|
||||
new InstanceRegisteredEvent<>(this, this.registration.getProperties()));
|
||||
this.context.publishEvent(new InstanceRegisteredEvent<>(this, this.registration.getProperties()));
|
||||
this.running.set(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,7 @@ public class KubernetesRegistration implements Registration, Closeable {
|
||||
|
||||
private AtomicBoolean running = new AtomicBoolean(false);
|
||||
|
||||
public KubernetesRegistration(KubernetesClient client,
|
||||
KubernetesDiscoveryProperties properties) {
|
||||
public KubernetesRegistration(KubernetesClient client, KubernetesDiscoveryProperties properties) {
|
||||
this.client = client;
|
||||
this.properties = properties;
|
||||
}
|
||||
@@ -94,8 +93,8 @@ public class KubernetesRegistration implements Registration, Closeable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KubernetesRegistration{" + "client=" + this.client + ", properties="
|
||||
+ this.properties + ", running=" + this.running + '}';
|
||||
return "KubernetesRegistration{" + "client=" + this.client + ", properties=" + this.properties + ", running="
|
||||
+ this.running + '}';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@ import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
|
||||
*
|
||||
* @author Mauricio Salatino
|
||||
*/
|
||||
public class KubernetesServiceRegistry
|
||||
implements ServiceRegistry<KubernetesRegistration> {
|
||||
public class KubernetesServiceRegistry implements ServiceRegistry<KubernetesRegistration> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(KubernetesServiceRegistry.class);
|
||||
|
||||
|
||||
@@ -29,28 +29,15 @@ public class DefaultIsServicePortSecureResolverTest {
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
properties.getKnownSecurePorts().add(12345);
|
||||
|
||||
final DefaultIsServicePortSecureResolver sut = new DefaultIsServicePortSecureResolver(
|
||||
properties);
|
||||
final DefaultIsServicePortSecureResolver sut = new DefaultIsServicePortSecureResolver(properties);
|
||||
|
||||
assertThat(
|
||||
sut.resolve(new DefaultIsServicePortSecureResolver.Input(null, "dummy")))
|
||||
.isFalse();
|
||||
assertThat(
|
||||
sut.resolve(new DefaultIsServicePortSecureResolver.Input(8080, "dummy")))
|
||||
.isFalse();
|
||||
assertThat(
|
||||
sut.resolve(new DefaultIsServicePortSecureResolver.Input(1234, "dummy")))
|
||||
.isFalse();
|
||||
assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(null, "dummy"))).isFalse();
|
||||
assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(8080, "dummy"))).isFalse();
|
||||
assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(1234, "dummy"))).isFalse();
|
||||
|
||||
assertThat(
|
||||
sut.resolve(new DefaultIsServicePortSecureResolver.Input(443, "dummy")))
|
||||
.isTrue();
|
||||
assertThat(
|
||||
sut.resolve(new DefaultIsServicePortSecureResolver.Input(8443, "dummy")))
|
||||
.isTrue();
|
||||
assertThat(
|
||||
sut.resolve(new DefaultIsServicePortSecureResolver.Input(12345, "dummy")))
|
||||
.isTrue();
|
||||
assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(443, "dummy"))).isTrue();
|
||||
assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(8443, "dummy"))).isTrue();
|
||||
assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(12345, "dummy"))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -58,22 +45,22 @@ public class DefaultIsServicePortSecureResolverTest {
|
||||
final DefaultIsServicePortSecureResolver sut = new DefaultIsServicePortSecureResolver(
|
||||
new KubernetesDiscoveryProperties());
|
||||
|
||||
assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(8080, "dummy",
|
||||
new HashMap<String, String>() {
|
||||
assertThat(
|
||||
sut.resolve(new DefaultIsServicePortSecureResolver.Input(8080, "dummy", new HashMap<String, String>() {
|
||||
{
|
||||
put("secured", "true");
|
||||
put("other", "value");
|
||||
}
|
||||
}, new HashMap<>()))).isTrue();
|
||||
assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(1234, "dummy",
|
||||
new HashMap<String, String>() {
|
||||
assertThat(
|
||||
sut.resolve(new DefaultIsServicePortSecureResolver.Input(1234, "dummy", new HashMap<String, String>() {
|
||||
{
|
||||
put("other", "value");
|
||||
put("secured", "1");
|
||||
}
|
||||
}, new HashMap<>()))).isTrue();
|
||||
assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(4321, "dummy",
|
||||
new HashMap<>(), new HashMap<String, String>() {
|
||||
assertThat(sut.resolve(new DefaultIsServicePortSecureResolver.Input(4321, "dummy", new HashMap<>(),
|
||||
new HashMap<String, String>() {
|
||||
{
|
||||
put("other1", "value1");
|
||||
put("secured", "yes");
|
||||
|
||||
@@ -70,12 +70,9 @@ public class KubernetesCatalogServicesWatchConfigurationTest {
|
||||
}
|
||||
|
||||
private void setup(String... env) {
|
||||
this.context = new SpringApplicationBuilder(
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
KubernetesClientTestConfiguration.class,
|
||||
KubernetesCatalogWatchAutoConfiguration.class,
|
||||
KubernetesDiscoveryClientAutoConfiguration.class)
|
||||
.web(WebApplicationType.NONE).properties(env).run();
|
||||
this.context = new SpringApplicationBuilder(PropertyPlaceholderAutoConfiguration.class,
|
||||
KubernetesClientTestConfiguration.class, KubernetesCatalogWatchAutoConfiguration.class,
|
||||
KubernetesDiscoveryClientAutoConfiguration.class).web(WebApplicationType.NONE).properties(env).run();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
@@ -84,13 +84,10 @@ public class KubernetesCatalogWatchTest {
|
||||
@Test
|
||||
public void testRandomOrderChangePods() throws Exception {
|
||||
when(this.endpointsOperation.list())
|
||||
.thenReturn(
|
||||
createSingleEndpointEndpointListByPodName("api-pod", "other-pod"))
|
||||
.thenReturn(createSingleEndpointEndpointListByPodName("other-pod",
|
||||
"api-pod"));
|
||||
.thenReturn(createSingleEndpointEndpointListByPodName("api-pod", "other-pod"))
|
||||
.thenReturn(createSingleEndpointEndpointListByPodName("other-pod", "api-pod"));
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation);
|
||||
|
||||
this.underTest.catalogServicesWatch();
|
||||
// second execution on shuffleServices
|
||||
@@ -102,13 +99,10 @@ public class KubernetesCatalogWatchTest {
|
||||
@Test
|
||||
public void testRandomOrderChangePodsAllNamespaces() throws Exception {
|
||||
when(this.endpointsOperation.list())
|
||||
.thenReturn(
|
||||
createSingleEndpointEndpointListByPodName("api-pod", "other-pod"))
|
||||
.thenReturn(createSingleEndpointEndpointListByPodName("other-pod",
|
||||
"api-pod"));
|
||||
.thenReturn(createSingleEndpointEndpointListByPodName("api-pod", "other-pod"))
|
||||
.thenReturn(createSingleEndpointEndpointListByPodName("other-pod", "api-pod"));
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace())
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
|
||||
@@ -122,13 +116,10 @@ public class KubernetesCatalogWatchTest {
|
||||
@Test
|
||||
public void testRandomOrderChangeServices() throws Exception {
|
||||
when(this.endpointsOperation.list())
|
||||
.thenReturn(
|
||||
createEndpointsListByServiceName("api-service", "other-service"))
|
||||
.thenReturn(
|
||||
createEndpointsListByServiceName("other-service", "api-service"));
|
||||
.thenReturn(createEndpointsListByServiceName("api-service", "other-service"))
|
||||
.thenReturn(createEndpointsListByServiceName("other-service", "api-service"));
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation);
|
||||
|
||||
this.underTest.catalogServicesWatch();
|
||||
// second execution on shuffleServices
|
||||
@@ -140,13 +131,10 @@ public class KubernetesCatalogWatchTest {
|
||||
@Test
|
||||
public void testRandomOrderChangeServicesAllNamespaces() throws Exception {
|
||||
when(this.endpointsOperation.list())
|
||||
.thenReturn(
|
||||
createEndpointsListByServiceName("api-service", "other-service"))
|
||||
.thenReturn(
|
||||
createEndpointsListByServiceName("other-service", "api-service"));
|
||||
.thenReturn(createEndpointsListByServiceName("api-service", "other-service"))
|
||||
.thenReturn(createEndpointsListByServiceName("other-service", "api-service"));
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace())
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
|
||||
@@ -159,16 +147,14 @@ public class KubernetesCatalogWatchTest {
|
||||
|
||||
@Test
|
||||
public void testEventBody() throws Exception {
|
||||
when(this.endpointsOperation.list()).thenReturn(
|
||||
createSingleEndpointEndpointListByPodName("api-pod", "other-pod"));
|
||||
when(this.endpointsOperation.list())
|
||||
.thenReturn(createSingleEndpointEndpointListByPodName("api-pod", "other-pod"));
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation);
|
||||
|
||||
this.underTest.catalogServicesWatch();
|
||||
|
||||
verify(this.applicationEventPublisher)
|
||||
.publishEvent(this.heartbeatEventArgumentCaptor.capture());
|
||||
verify(this.applicationEventPublisher).publishEvent(this.heartbeatEventArgumentCaptor.capture());
|
||||
|
||||
HeartbeatEvent event = this.heartbeatEventArgumentCaptor.getValue();
|
||||
assertThat(event.getValue()).isInstanceOf(List.class);
|
||||
@@ -179,18 +165,16 @@ public class KubernetesCatalogWatchTest {
|
||||
|
||||
@Test
|
||||
public void testEventBodyAllNamespaces() throws Exception {
|
||||
when(this.endpointsOperation.list()).thenReturn(
|
||||
createSingleEndpointEndpointListByPodName("api-pod", "other-pod"));
|
||||
when(this.endpointsOperation.list())
|
||||
.thenReturn(createSingleEndpointEndpointListByPodName("api-pod", "other-pod"));
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace())
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
|
||||
this.underTest.catalogServicesWatch();
|
||||
|
||||
verify(this.applicationEventPublisher)
|
||||
.publishEvent(this.heartbeatEventArgumentCaptor.capture());
|
||||
verify(this.applicationEventPublisher).publishEvent(this.heartbeatEventArgumentCaptor.capture());
|
||||
|
||||
HeartbeatEvent event = this.heartbeatEventArgumentCaptor.getValue();
|
||||
assertThat(event.getValue()).isInstanceOf(List.class);
|
||||
@@ -206,8 +190,7 @@ public class KubernetesCatalogWatchTest {
|
||||
|
||||
when(this.endpointsOperation.list()).thenReturn(endpoints);
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation);
|
||||
|
||||
this.underTest.catalogServicesWatch();
|
||||
// second execution on shuffleServices
|
||||
@@ -223,8 +206,7 @@ public class KubernetesCatalogWatchTest {
|
||||
|
||||
when(this.endpointsOperation.list()).thenReturn(endpoints);
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace())
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
|
||||
@@ -243,8 +225,7 @@ public class KubernetesCatalogWatchTest {
|
||||
|
||||
when(this.endpointsOperation.list()).thenReturn(endpoints);
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation);
|
||||
|
||||
this.underTest.catalogServicesWatch();
|
||||
// second execution on shuffleServices
|
||||
@@ -261,8 +242,7 @@ public class KubernetesCatalogWatchTest {
|
||||
|
||||
when(this.endpointsOperation.list()).thenReturn(endpoints);
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace())
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
|
||||
@@ -277,13 +257,11 @@ public class KubernetesCatalogWatchTest {
|
||||
public void testEndpointsWithoutTargetRefs() {
|
||||
|
||||
EndpointsList endpoints = createSingleEndpointEndpointListByPodName("api-pod");
|
||||
endpoints.getItems().get(0).getSubsets().get(0).getAddresses().get(0)
|
||||
.setTargetRef(null);
|
||||
endpoints.getItems().get(0).getSubsets().get(0).getAddresses().get(0).setTargetRef(null);
|
||||
|
||||
when(this.endpointsOperation.list()).thenReturn(endpoints);
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().withLabels(anyMap())).thenReturn(this.endpointsOperation);
|
||||
|
||||
this.underTest.catalogServicesWatch();
|
||||
// second execution on shuffleServices
|
||||
@@ -296,13 +274,11 @@ public class KubernetesCatalogWatchTest {
|
||||
public void testEndpointsWithoutTargetRefsAllNamespaces() {
|
||||
|
||||
EndpointsList endpoints = createSingleEndpointEndpointListByPodName("api-pod");
|
||||
endpoints.getItems().get(0).getSubsets().get(0).getAddresses().get(0)
|
||||
.setTargetRef(null);
|
||||
endpoints.getItems().get(0).getSubsets().get(0).getAddresses().get(0).setTargetRef(null);
|
||||
|
||||
when(this.endpointsOperation.list()).thenReturn(endpoints);
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace())
|
||||
.thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace()).thenReturn(this.endpointsOperation);
|
||||
when(this.kubernetesClient.endpoints().inAnyNamespace().withLabels(anyMap()))
|
||||
.thenReturn(this.endpointsOperation);
|
||||
|
||||
@@ -314,8 +290,7 @@ public class KubernetesCatalogWatchTest {
|
||||
}
|
||||
|
||||
private EndpointsList createEndpointsListByServiceName(String... serviceNames) {
|
||||
List<Endpoints> endpoints = stream(serviceNames)
|
||||
.map(s -> createEndpointsByPodName(s + "-singlePodUniqueId"))
|
||||
List<Endpoints> endpoints = stream(serviceNames).map(s -> createEndpointsByPodName(s + "-singlePodUniqueId"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
EndpointsList endpointsList = new EndpointsList();
|
||||
|
||||
@@ -48,38 +48,31 @@ public class KubernetesDiscoveryClientAutoConfigurationPropertiesTests {
|
||||
public void kubernetesDiscoveryDisabled() throws Exception {
|
||||
setup("spring.cloud.kubernetes.discovery.enabled=false",
|
||||
"spring.cloud.kubernetes.discovery.catalog-services-watch.enabled=false");
|
||||
assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class))
|
||||
.isEmpty();
|
||||
assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void kubernetesDiscoveryWhenKubernetesDisabled() throws Exception {
|
||||
setup("spring.cloud.kubernetes.enabled=false");
|
||||
assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class))
|
||||
.isEmpty();
|
||||
assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void kubernetesDiscoveryWhenDiscoveryDisabled() throws Exception {
|
||||
setup("spring.cloud.discovery.enabled=false");
|
||||
assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class))
|
||||
.isEmpty();
|
||||
assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void kubernetesDiscoveryDefaultEnabled() throws Exception {
|
||||
setup("spring.cloud.kubernetes.enabled=true");
|
||||
assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class))
|
||||
.hasSize(1);
|
||||
assertThat(this.context.getBeanNamesForType(KubernetesDiscoveryClient.class)).hasSize(1);
|
||||
}
|
||||
|
||||
private void setup(String... env) {
|
||||
this.context = new SpringApplicationBuilder(
|
||||
PropertyPlaceholderAutoConfiguration.class,
|
||||
KubernetesClientTestConfiguration.class,
|
||||
KubernetesDiscoveryClientAutoConfiguration.class)
|
||||
.web(org.springframework.boot.WebApplicationType.NONE)
|
||||
.properties(env).run();
|
||||
this.context = new SpringApplicationBuilder(PropertyPlaceholderAutoConfiguration.class,
|
||||
KubernetesClientTestConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class)
|
||||
.web(org.springframework.boot.WebApplicationType.NONE).properties(env).run();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
@@ -39,12 +39,11 @@ public class KubernetesDiscoveryClientAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void kubernetesDiscoveryClientCreated() {
|
||||
assertThat(this.discoveryClient).isNotNull()
|
||||
.isInstanceOf(CompositeDiscoveryClient.class);
|
||||
assertThat(this.discoveryClient).isNotNull().isInstanceOf(CompositeDiscoveryClient.class);
|
||||
|
||||
CompositeDiscoveryClient composite = (CompositeDiscoveryClient) this.discoveryClient;
|
||||
assertThat(composite.getDiscoveryClients().stream()
|
||||
.anyMatch(dc -> dc instanceof KubernetesDiscoveryClient)).isTrue();
|
||||
assertThat(composite.getDiscoveryClients().stream().anyMatch(dc -> dc instanceof KubernetesDiscoveryClient))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
|
||||
@@ -60,31 +60,25 @@ public class KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests {
|
||||
@Test
|
||||
public void onWhenRequested() throws Exception {
|
||||
setup("server.port=7000", "spring.cloud.config.discovery.enabled=true",
|
||||
"spring.cloud.kubernetes.discovery.enabled:true",
|
||||
"spring.cloud.kubernetes.enabled:true", "spring.application.name:test",
|
||||
"spring.cloud.config.discovery.service-id:configserver");
|
||||
assertEquals(1, this.context.getParent()
|
||||
.getBeanNamesForType(DiscoveryClient.class).length);
|
||||
"spring.cloud.kubernetes.discovery.enabled:true", "spring.cloud.kubernetes.enabled:true",
|
||||
"spring.application.name:test", "spring.cloud.config.discovery.service-id:configserver");
|
||||
assertEquals(1, this.context.getParent().getBeanNamesForType(DiscoveryClient.class).length);
|
||||
DiscoveryClient client = this.context.getParent().getBean(DiscoveryClient.class);
|
||||
verify(client, atLeast(2)).getInstances("configserver");
|
||||
ConfigClientProperties locator = this.context
|
||||
.getBean(ConfigClientProperties.class);
|
||||
ConfigClientProperties locator = this.context.getBean(ConfigClientProperties.class);
|
||||
assertEquals("http://fake:8888/", locator.getUri()[0]);
|
||||
}
|
||||
|
||||
private void setup(String... env) {
|
||||
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
|
||||
TestPropertyValues.of(env).applyTo(parent);
|
||||
parent.register(UtilAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, EnvironmentKnobbler.class,
|
||||
KubernetesDiscoveryClientConfigClientBootstrapConfiguration.class,
|
||||
DiscoveryClientConfigServiceBootstrapConfiguration.class,
|
||||
ConfigClientProperties.class);
|
||||
parent.register(UtilAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
|
||||
EnvironmentKnobbler.class, KubernetesDiscoveryClientConfigClientBootstrapConfiguration.class,
|
||||
DiscoveryClientConfigServiceBootstrapConfiguration.class, ConfigClientProperties.class);
|
||||
parent.refresh();
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.setParent(parent);
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class,
|
||||
KubernetesAutoConfiguration.class,
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class, KubernetesAutoConfiguration.class,
|
||||
KubernetesDiscoveryClientAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
}
|
||||
@@ -95,10 +89,8 @@ public class KubernetesDiscoveryClientConfigClientBootstrapConfigurationTests {
|
||||
@Bean
|
||||
public KubernetesDiscoveryClient kubernetesDiscoveryClient() {
|
||||
KubernetesDiscoveryClient client = mock(KubernetesDiscoveryClient.class);
|
||||
ServiceInstance instance = new DefaultServiceInstance("configserver1",
|
||||
"configserver", "fake", 8888, false);
|
||||
given(client.getInstances("configserver"))
|
||||
.willReturn(Collections.singletonList(instance));
|
||||
ServiceInstance instance = new DefaultServiceInstance("configserver1", "configserver", "fake", 8888, false);
|
||||
given(client.getInstances("configserver")).willReturn(Collections.singletonList(instance));
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,21 +100,20 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
when(this.metadata.isAddAnnotations()).thenReturn(false);
|
||||
when(this.metadata.isAddPorts()).thenReturn(false);
|
||||
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns",
|
||||
new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "lab");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "lab");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "lab");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "lab");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
|
||||
final List<ServiceInstance> instances = this.underTest.getInstances(serviceId);
|
||||
assertThat(instances).hasSize(1);
|
||||
@@ -130,27 +129,25 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
when(this.metadata.isAddAnnotations()).thenReturn(false);
|
||||
when(this.metadata.isAddPorts()).thenReturn(false);
|
||||
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns",
|
||||
new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
put("l2", "v2");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "lab");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
put("l2", "v2");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "lab");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
|
||||
final List<ServiceInstance> instances = this.underTest.getInstances(serviceId);
|
||||
assertThat(instances).hasSize(1);
|
||||
assertThat(instances.get(0).getMetadata()).containsOnly(entry("l1", "v1"),
|
||||
entry("l2", "v2"));
|
||||
assertThat(instances.get(0).getMetadata()).containsOnly(entry("l1", "v1"), entry("l2", "v2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -163,27 +160,25 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
when(this.metadata.isAddAnnotations()).thenReturn(false);
|
||||
when(this.metadata.isAddPorts()).thenReturn(false);
|
||||
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns",
|
||||
new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
put("l2", "v2");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "lab");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
put("l2", "v2");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "lab");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
|
||||
final List<ServiceInstance> instances = this.underTest.getInstances(serviceId);
|
||||
assertThat(instances).hasSize(1);
|
||||
assertThat(instances.get(0).getMetadata()).containsOnly(entry("l_l1", "v1"),
|
||||
entry("l_l2", "v2"));
|
||||
assertThat(instances.get(0).getMetadata()).containsOnly(entry("l_l1", "v1"), entry("l_l2", "v2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -195,27 +190,25 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
when(this.metadata.isAddAnnotations()).thenReturn(true);
|
||||
when(this.metadata.isAddPorts()).thenReturn(false);
|
||||
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns",
|
||||
new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("a1", "v1");
|
||||
put("a2", "v2");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("a1", "v1");
|
||||
put("a2", "v2");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
|
||||
final List<ServiceInstance> instances = this.underTest.getInstances(serviceId);
|
||||
assertThat(instances).hasSize(1);
|
||||
assertThat(instances.get(0).getMetadata()).containsOnly(entry("a1", "v1"),
|
||||
entry("a2", "v2"));
|
||||
assertThat(instances.get(0).getMetadata()).containsOnly(entry("a1", "v1"), entry("a2", "v2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -228,27 +221,25 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
when(this.metadata.getAnnotationsPrefix()).thenReturn("a_");
|
||||
when(this.metadata.isAddPorts()).thenReturn(false);
|
||||
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns",
|
||||
new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("a1", "v1");
|
||||
put("a2", "v2");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("a1", "v1");
|
||||
put("a2", "v2");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
|
||||
final List<ServiceInstance> instances = this.underTest.getInstances(serviceId);
|
||||
assertThat(instances).hasSize(1);
|
||||
assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "v1"),
|
||||
entry("a_a2", "v2"));
|
||||
assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "v1"), entry("a_a2", "v2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -260,22 +251,21 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
when(this.metadata.isAddAnnotations()).thenReturn(false);
|
||||
when(this.metadata.isAddPorts()).thenReturn(true);
|
||||
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns",
|
||||
new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("a1", "v1");
|
||||
put("a2", "v2");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("a1", "v1");
|
||||
put("a2", "v2");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
|
||||
final List<ServiceInstance> instances = this.underTest.getInstances(serviceId);
|
||||
assertThat(instances).hasSize(1);
|
||||
@@ -292,22 +282,21 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
when(this.metadata.isAddPorts()).thenReturn(true);
|
||||
when(this.metadata.getPortsPrefix()).thenReturn("p_");
|
||||
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns",
|
||||
new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("a1", "v1");
|
||||
put("a2", "v2");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "v1");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("a1", "v1");
|
||||
put("a2", "v2");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
|
||||
final List<ServiceInstance> instances = this.underTest.getInstances(serviceId);
|
||||
assertThat(instances).hasSize(1);
|
||||
@@ -326,58 +315,51 @@ public class KubernetesDiscoveryClientFilterMetadataTest {
|
||||
when(this.metadata.isAddPorts()).thenReturn(true);
|
||||
when(this.metadata.getPortsPrefix()).thenReturn("p_");
|
||||
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns",
|
||||
new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "la1");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("a1", "an1");
|
||||
put("a2", "an2");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
setupServiceWithLabelsAndAnnotationsAndPorts(serviceId, "ns", new HashMap<String, String>() {
|
||||
{
|
||||
put("l1", "la1");
|
||||
}
|
||||
}, new HashMap<String, String>() {
|
||||
{
|
||||
put("a1", "an1");
|
||||
put("a2", "an2");
|
||||
}
|
||||
}, new HashMap<Integer, String>() {
|
||||
{
|
||||
put(80, "http");
|
||||
put(5555, "");
|
||||
}
|
||||
});
|
||||
|
||||
final List<ServiceInstance> instances = this.underTest.getInstances(serviceId);
|
||||
assertThat(instances).hasSize(1);
|
||||
assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "an1"),
|
||||
entry("a_a2", "an2"), entry("l_l1", "la1"), entry("p_http", "80"));
|
||||
assertThat(instances.get(0).getMetadata()).containsOnly(entry("a_a1", "an1"), entry("a_a2", "an2"),
|
||||
entry("l_l1", "la1"), entry("p_http", "80"));
|
||||
}
|
||||
|
||||
private void setupServiceWithLabelsAndAnnotationsAndPorts(String serviceId,
|
||||
String namespace, Map<String, String> labels, Map<String, String> annotations,
|
||||
Map<Integer, String> ports) {
|
||||
final Service service = new ServiceBuilder().withNewMetadata()
|
||||
.withNamespace(namespace).withLabels(labels).withAnnotations(annotations)
|
||||
.endMetadata().withNewSpec().withPorts(getServicePorts(ports)).endSpec()
|
||||
private void setupServiceWithLabelsAndAnnotationsAndPorts(String serviceId, String namespace,
|
||||
Map<String, String> labels, Map<String, String> annotations, Map<Integer, String> ports) {
|
||||
final Service service = new ServiceBuilder().withNewMetadata().withNamespace(namespace).withLabels(labels)
|
||||
.withAnnotations(annotations).endMetadata().withNewSpec().withPorts(getServicePorts(ports)).endSpec()
|
||||
.build();
|
||||
when(this.serviceOperation.withName(serviceId)).thenReturn(this.serviceResource);
|
||||
when(this.serviceResource.get()).thenReturn(service);
|
||||
when(this.kubernetesClient.services()).thenReturn(this.serviceOperation);
|
||||
when(this.kubernetesClient.services().inNamespace(anyString()))
|
||||
.thenReturn(this.serviceOperation);
|
||||
when(this.kubernetesClient.services().inNamespace(anyString())).thenReturn(this.serviceOperation);
|
||||
|
||||
ObjectMeta objectMeta = new ObjectMeta();
|
||||
objectMeta.setNamespace(namespace);
|
||||
|
||||
final Endpoints endpoints = new EndpointsBuilder().withMetadata(objectMeta)
|
||||
.addNewSubset().addAllToPorts(getEndpointPorts(ports)).addNewAddress()
|
||||
.endAddress().endSubset().build();
|
||||
final Endpoints endpoints = new EndpointsBuilder().withMetadata(objectMeta).addNewSubset()
|
||||
.addAllToPorts(getEndpointPorts(ports)).addNewAddress().endAddress().endSubset().build();
|
||||
|
||||
when(this.kubernetesClient.endpoints()).thenReturn(this.endpointsOperation);
|
||||
|
||||
EndpointsList endpointsList = new EndpointsList(null,
|
||||
Collections.singletonList(endpoints), null, null);
|
||||
EndpointsList endpointsList = new EndpointsList(null, Collections.singletonList(endpoints), null, null);
|
||||
when(filter.list()).thenReturn(endpointsList);
|
||||
when(filter.withLabels(anyMap())).thenReturn(filter);
|
||||
|
||||
when(this.kubernetesClient.endpoints().withField(eq("metadata.name"),
|
||||
eq(serviceId))).thenReturn(filter);
|
||||
when(this.kubernetesClient.endpoints().withField(eq("metadata.name"), eq(serviceId))).thenReturn(filter);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,8 @@ public class KubernetesDiscoveryClientFilterTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.underTest = new KubernetesDiscoveryClient(this.kubernetesClient,
|
||||
this.properties, this.kubernetesClientServicesFunction);
|
||||
this.underTest = new KubernetesDiscoveryClient(this.kubernetesClient, this.properties,
|
||||
this.kubernetesClientServicesFunction);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -75,8 +75,7 @@ public class KubernetesDiscoveryClientFilterTest {
|
||||
when(this.serviceOperation.list()).thenReturn(serviceList);
|
||||
when(this.kubernetesClient.services()).thenReturn(this.serviceOperation);
|
||||
|
||||
when(this.properties.getFilter())
|
||||
.thenReturn("metadata.additionalProperties['spring-boot']");
|
||||
when(this.properties.getFilter()).thenReturn("metadata.additionalProperties['spring-boot']");
|
||||
|
||||
List<String> filteredServices = this.underTest.getServices();
|
||||
|
||||
@@ -87,8 +86,7 @@ public class KubernetesDiscoveryClientFilterTest {
|
||||
|
||||
@Test
|
||||
public void testFilteredServicesByPrefix() {
|
||||
List<String> springBootServiceNames = Arrays.asList("serviceA", "serviceB",
|
||||
"serviceC");
|
||||
List<String> springBootServiceNames = Arrays.asList("serviceA", "serviceB", "serviceC");
|
||||
List<Service> services = createSpringBootServiceByName(springBootServiceNames);
|
||||
|
||||
// Add non spring boot service
|
||||
@@ -103,8 +101,7 @@ public class KubernetesDiscoveryClientFilterTest {
|
||||
when(this.serviceOperation.list()).thenReturn(serviceList);
|
||||
when(this.kubernetesClient.services()).thenReturn(this.serviceOperation);
|
||||
|
||||
when(this.properties.getFilter())
|
||||
.thenReturn("metadata.name.startsWith('service')");
|
||||
when(this.properties.getFilter()).thenReturn("metadata.name.startsWith('service')");
|
||||
|
||||
List<String> filteredServices = this.underTest.getServices();
|
||||
|
||||
@@ -115,8 +112,7 @@ public class KubernetesDiscoveryClientFilterTest {
|
||||
|
||||
@Test
|
||||
public void testNoExpression() {
|
||||
List<String> springBootServiceNames = Arrays.asList("serviceA", "serviceB",
|
||||
"serviceC");
|
||||
List<String> springBootServiceNames = Arrays.asList("serviceA", "serviceB", "serviceC");
|
||||
List<Service> services = createSpringBootServiceByName(springBootServiceNames);
|
||||
|
||||
ServiceList serviceList = new ServiceList();
|
||||
|
||||
@@ -52,12 +52,10 @@ public class KubernetesDiscoveryClientTest {
|
||||
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_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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
}
|
||||
|
||||
@@ -66,11 +64,10 @@ public class KubernetesDiscoveryClientTest {
|
||||
Map<String, String> labels = new HashMap();
|
||||
labels.put("l", "v");
|
||||
|
||||
Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint")
|
||||
.withNamespace("test").withLabels(labels).endMetadata().addNewSubset()
|
||||
.addNewAddress().withIp("ip1").withNewTargetRef().withUid("10")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP")
|
||||
.endSubset().build();
|
||||
Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.withLabels(labels).endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef()
|
||||
.withUid("10").endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset()
|
||||
.build();
|
||||
|
||||
List<Endpoints> endpointsList = new ArrayList<>();
|
||||
endpointsList.add(endPoint);
|
||||
@@ -78,37 +75,34 @@ public class KubernetesDiscoveryClientTest {
|
||||
EndpointsList endpoints = new EndpointsList();
|
||||
endpoints.setItems(endpointsList);
|
||||
|
||||
mockServer.expect().get().withPath(
|
||||
"/api/v1/namespaces/test/endpoints?labelSelector=l%3Dv&fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, endpoints).once();
|
||||
|
||||
mockServer.expect().get()
|
||||
.withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dendpoint")
|
||||
.withPath(
|
||||
"/api/v1/namespaces/test/endpoints?labelSelector=l%3Dv&fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, endpoints).once();
|
||||
|
||||
mockServer.expect().get().withPath(
|
||||
"/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint")
|
||||
mockServer.expect().get().withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, endpoints).once();
|
||||
|
||||
Service service = new ServiceBuilder().withNewMetadata().withName("endpoint")
|
||||
.withNamespace("test").withLabels(labels).endMetadata().build();
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, endpoints).once();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint")
|
||||
.andReturn(200, service).always();
|
||||
Service service = new ServiceBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.withLabels(labels).endMetadata().build();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint").andReturn(200, service)
|
||||
.always();
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
properties.setServiceLabels(labels);
|
||||
properties.getMetadata().setAddLabels(false);
|
||||
properties.getMetadata().setAddAnnotations(false);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
|
||||
properties, KubernetesClient::services,
|
||||
new DefaultIsServicePortSecureResolver(properties));
|
||||
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)
|
||||
assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1)
|
||||
.filteredOn(s -> s.getInstanceId().equals("10")).hasSize(1);
|
||||
}
|
||||
|
||||
@@ -117,11 +111,9 @@ public class KubernetesDiscoveryClientTest {
|
||||
Map<String, String> labels = new HashMap();
|
||||
labels.put("l2", "v2");
|
||||
|
||||
Endpoints endPoint1 = new EndpointsBuilder().withNewMetadata()
|
||||
.withName("endpoint").withNamespace("test").withLabels(labels)
|
||||
.endMetadata().addNewSubset().addNewAddress().withIp("ip1")
|
||||
.withNewTargetRef().withUid("20").endTargetRef().endAddress()
|
||||
.addNewPort("mgmt", "mgmt_tcp", 900, "TCP")
|
||||
Endpoints endPoint1 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.withLabels(labels).endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef()
|
||||
.withUid("20").endTargetRef().endAddress().addNewPort("mgmt", "mgmt_tcp", 900, "TCP")
|
||||
.addNewPort("http", "http_tcp", 80, "TCP").endSubset().build();
|
||||
|
||||
List<Endpoints> endpointsList = new ArrayList<>();
|
||||
@@ -134,30 +126,26 @@ public class KubernetesDiscoveryClientTest {
|
||||
"/api/v1/namespaces/test/endpoints?labelSelector=l2%3Dv2&fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, endpoints).once();
|
||||
|
||||
mockServer.expect().get().withPath(
|
||||
"/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint")
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, endpoints).once();
|
||||
|
||||
Service service = new ServiceBuilder().withNewMetadata().withName("endpoint")
|
||||
.withNamespace("test").withLabels(labels).withAnnotations(labels)
|
||||
.endMetadata().build();
|
||||
Service service = new ServiceBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.withLabels(labels).withAnnotations(labels).endMetadata().build();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint")
|
||||
.andReturn(200, service).always();
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint").andReturn(200, service)
|
||||
.always();
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
properties.setPrimaryPortName("http_tcp");
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
|
||||
properties, KubernetesClient::services,
|
||||
new DefaultIsServicePortSecureResolver(properties));
|
||||
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)
|
||||
.filteredOn(s -> s.getInstanceId().equals("20")).hasSize(1)
|
||||
.filteredOn(s -> 80 == s.getPort()).hasSize(1);
|
||||
assertThat(instances).hasSize(1).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1)
|
||||
.filteredOn(s -> s.getInstanceId().equals("20")).hasSize(1).filteredOn(s -> 80 == s.getPort())
|
||||
.hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -165,11 +153,10 @@ public class KubernetesDiscoveryClientTest {
|
||||
Map<String, String> labels = new HashMap();
|
||||
labels.put("l", "v");
|
||||
|
||||
Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint")
|
||||
.withNamespace("test").withLabels(labels).endMetadata().addNewSubset()
|
||||
.addNewAddress().withIp("ip1").withNewTargetRef().withUid("30")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP")
|
||||
.endSubset().build();
|
||||
Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.withLabels(labels).endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef()
|
||||
.withUid("30").endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset()
|
||||
.build();
|
||||
|
||||
List<Endpoints> endpointsList = new ArrayList<>();
|
||||
endpointsList.add(endPoint);
|
||||
@@ -177,19 +164,18 @@ public class KubernetesDiscoveryClientTest {
|
||||
EndpointsList endpoints = new EndpointsList();
|
||||
endpoints.setItems(endpointsList);
|
||||
|
||||
mockServer.expect().get().withPath(
|
||||
"/api/v1/namespaces/test/endpoints?labelSelector=l%3Dv&fieldSelector=metadata.name%3Dendpoint")
|
||||
mockServer.expect().get()
|
||||
.withPath(
|
||||
"/api/v1/namespaces/test/endpoints?labelSelector=l%3Dv&fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, endpoints).once();
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
properties.setServiceLabels(labels);
|
||||
|
||||
final KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(
|
||||
mockClient, properties, KubernetesClient::services,
|
||||
new DefaultIsServicePortSecureResolver(properties));
|
||||
final KubernetesDiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new DefaultIsServicePortSecureResolver(properties));
|
||||
|
||||
final List<Endpoints> result_endpoints = discoveryClient
|
||||
.getEndPointsList("endpoint");
|
||||
final List<Endpoints> result_endpoints = discoveryClient.getEndPointsList("endpoint");
|
||||
|
||||
assertThat(result_endpoints).hasSize(1);
|
||||
}
|
||||
@@ -199,12 +185,11 @@ public class KubernetesDiscoveryClientTest {
|
||||
Map<String, String> labels = new HashMap();
|
||||
labels.put("l1", "v1");
|
||||
|
||||
Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint")
|
||||
.withNamespace("test").withLabels(labels).endMetadata().addNewSubset()
|
||||
.addNewAddress().withIp("ip1").withNewTargetRef().withUid("40")
|
||||
.endTargetRef().endAddress().addNewAddress().withIp("ip2")
|
||||
.withNewTargetRef().withUid("50").endTargetRef().endAddress()
|
||||
.addNewPort("https", "https_tcp", 443, "TCP").endSubset().build();
|
||||
Endpoints endPoint = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.withLabels(labels).endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef()
|
||||
.withUid("40").endTargetRef().endAddress().addNewAddress().withIp("ip2").withNewTargetRef()
|
||||
.withUid("50").endTargetRef().endAddress().addNewPort("https", "https_tcp", 443, "TCP").endSubset()
|
||||
.build();
|
||||
|
||||
List<Endpoints> endpointsList = new ArrayList<>();
|
||||
endpointsList.add(endPoint);
|
||||
@@ -216,53 +201,48 @@ public class KubernetesDiscoveryClientTest {
|
||||
"/api/v1/namespaces/test/endpoints?labelSelector=l1%3Dv1&fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, endpoints).once();
|
||||
|
||||
mockServer.expect().get().withPath(
|
||||
"/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint")
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints?fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, endpoints).once();
|
||||
|
||||
Service service = new ServiceBuilder().withNewMetadata().withName("endpoint")
|
||||
.withNamespace("test").withLabels(labels).endMetadata().build();
|
||||
Service service = new ServiceBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.withLabels(labels).endMetadata().build();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint")
|
||||
.andReturn(200, service).always();
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint").andReturn(200, service)
|
||||
.always();
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
properties.setServiceLabels(labels);
|
||||
properties.getMetadata().setAddAnnotations(false);
|
||||
properties.getMetadata().setAddLabels(false);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
|
||||
properties, KubernetesClient::services,
|
||||
new DefaultIsServicePortSecureResolver(properties));
|
||||
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");
|
||||
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();
|
||||
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 DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new DefaultIsServicePortSecureResolver(properties));
|
||||
|
||||
final List<String> services = discoveryClient.getServices();
|
||||
|
||||
@@ -271,15 +251,14 @@ public class KubernetesDiscoveryClientTest {
|
||||
|
||||
@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>() {
|
||||
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>() {
|
||||
}).endMetadata().endItem().addNewItem().withNewMetadata().withName("s2")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
put("label2", "value2");
|
||||
@@ -288,8 +267,7 @@ public class KubernetesDiscoveryClientTest {
|
||||
.once();
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
|
||||
properties,
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
client -> client.services().withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
@@ -303,17 +281,13 @@ public class KubernetesDiscoveryClientTest {
|
||||
|
||||
@Test
|
||||
public void getInstancesShouldBeAbleToHandleEndpointsFromMultipleNamespaces() {
|
||||
Endpoints endPoints1 = new EndpointsBuilder().withNewMetadata()
|
||||
.withName("endpoint").withNamespace("test").endMetadata().addNewSubset()
|
||||
.addNewAddress().withIp("ip1").withNewTargetRef().withUid("60")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP")
|
||||
.endSubset().build();
|
||||
Endpoints endPoints1 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef().withUid("60")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset().build();
|
||||
|
||||
Endpoints endpoints2 = new EndpointsBuilder().withNewMetadata()
|
||||
.withName("endpoint").withNamespace("test2").endMetadata().addNewSubset()
|
||||
.addNewAddress().withIp("ip2").withNewTargetRef().withUid("70")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP")
|
||||
.endSubset().build();
|
||||
Endpoints endpoints2 = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test2")
|
||||
.endMetadata().addNewSubset().addNewAddress().withIp("ip2").withNewTargetRef().withUid("70")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset().build();
|
||||
|
||||
List<Endpoints> endpointsList = new ArrayList<>();
|
||||
endpointsList.add(endPoints1);
|
||||
@@ -322,25 +296,24 @@ public class KubernetesDiscoveryClientTest {
|
||||
EndpointsList endpoints = new EndpointsList();
|
||||
endpoints.setItems(endpointsList);
|
||||
|
||||
mockServer.expect().get()
|
||||
.withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dendpoint")
|
||||
mockServer.expect().get().withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, endpoints).once();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint")
|
||||
.andReturn(200, endPoints1).once();
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/endpoint").andReturn(200, endPoints1)
|
||||
.once();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test2/endpoints/endpoint")
|
||||
.andReturn(200, endpoints2).once();
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test2/endpoints/endpoint").andReturn(200, endpoints2)
|
||||
.once();
|
||||
|
||||
Service service1 = new ServiceBuilder().withNewMetadata().withName("endpoint")
|
||||
.withNamespace("test").withLabels(new HashMap<String, String>() {
|
||||
Service service1 = new ServiceBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("l", "v");
|
||||
}
|
||||
}).endMetadata().build();
|
||||
|
||||
Service service2 = new ServiceBuilder().withNewMetadata().withName("endpoint")
|
||||
.withNamespace("test2").withLabels(new HashMap<String, String>() {
|
||||
Service service2 = new ServiceBuilder().withNewMetadata().withName("endpoint").withNamespace("test2")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("l", "v");
|
||||
}
|
||||
@@ -353,38 +326,30 @@ public class KubernetesDiscoveryClientTest {
|
||||
ServiceList services = new ServiceList();
|
||||
services.setItems(servicesList);
|
||||
|
||||
mockServer.expect().get()
|
||||
.withPath("/api/v1/services?fieldSelector=metadata.name%3Dendpoint")
|
||||
mockServer.expect().get().withPath("/api/v1/services?fieldSelector=metadata.name%3Dendpoint")
|
||||
.andReturn(200, services).once();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint")
|
||||
.andReturn(200, service1).always();
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test/services/endpoint").andReturn(200, service1)
|
||||
.always();
|
||||
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test2/services/endpoint")
|
||||
.andReturn(200, service2).always();
|
||||
mockServer.expect().get().withPath("/api/v1/namespaces/test2/services/endpoint").andReturn(200, service2)
|
||||
.always();
|
||||
|
||||
final KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
properties.setAllNamespaces(true);
|
||||
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient,
|
||||
properties, KubernetesClient::services,
|
||||
new DefaultIsServicePortSecureResolver(properties));
|
||||
final DiscoveryClient discoveryClient = new KubernetesDiscoveryClient(mockClient, properties,
|
||||
KubernetesClient::services, new DefaultIsServicePortSecureResolver(properties));
|
||||
|
||||
final List<ServiceInstance> instances = discoveryClient.getInstances("endpoint");
|
||||
|
||||
assertThat(instances).hasSize(2);
|
||||
assertThat(instances).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure())
|
||||
.hasSize(1);
|
||||
assertThat(instances).filteredOn(s -> s.getHost().equals("ip2") && !s.isSecure())
|
||||
.hasSize(1);
|
||||
assertThat(instances)
|
||||
.filteredOn(s -> s.getServiceId().contains("endpoint")
|
||||
&& ((KubernetesServiceInstance) s).getNamespace().equals("test"))
|
||||
.hasSize(1);
|
||||
assertThat(instances)
|
||||
.filteredOn(s -> s.getServiceId().contains("endpoint")
|
||||
&& ((KubernetesServiceInstance) s).getNamespace().equals("test2"))
|
||||
.hasSize(1);
|
||||
assertThat(instances).filteredOn(s -> s.getHost().equals("ip1") && !s.isSecure()).hasSize(1);
|
||||
assertThat(instances).filteredOn(s -> s.getHost().equals("ip2") && !s.isSecure()).hasSize(1);
|
||||
assertThat(instances).filteredOn(s -> s.getServiceId().contains("endpoint")
|
||||
&& ((KubernetesServiceInstance) s).getNamespace().equals("test")).hasSize(1);
|
||||
assertThat(instances).filteredOn(s -> s.getServiceId().contains("endpoint")
|
||||
&& ((KubernetesServiceInstance) s).getNamespace().equals("test2")).hasSize(1);
|
||||
assertThat(instances).filteredOn(s -> s.getInstanceId().equals("60")).hasSize(1);
|
||||
assertThat(instances).filteredOn(s -> s.getInstanceId().equals("70")).hasSize(1);
|
||||
}
|
||||
|
||||
@@ -36,9 +36,8 @@ public class KubernetesServiceInstanceTests {
|
||||
address.setIp("1.2.3.4");
|
||||
EndpointPort port = new EndpointPort();
|
||||
port.setPort(8080);
|
||||
KubernetesServiceInstance instance = new KubernetesServiceInstance("123",
|
||||
"myservice", address.getIp(), port.getPort(), Collections.emptyMap(),
|
||||
secure);
|
||||
KubernetesServiceInstance instance = new KubernetesServiceInstance("123", "myservice", address.getIp(),
|
||||
port.getPort(), Collections.emptyMap(), secure);
|
||||
|
||||
assertThat(instance.getInstanceId()).isEqualTo("123");
|
||||
assertThat(instance.getServiceId()).isEqualTo("myservice");
|
||||
|
||||
@@ -35,93 +35,69 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class KubernetesReactiveDiscoveryClientAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(UtilAutoConfiguration.class,
|
||||
ReactiveCommonsClientAutoConfiguration.class,
|
||||
KubernetesAutoConfiguration.class,
|
||||
KubernetesDiscoveryClientAutoConfiguration.class,
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(UtilAutoConfiguration.class, ReactiveCommonsClientAutoConfiguration.class,
|
||||
KubernetesAutoConfiguration.class, KubernetesDiscoveryClientAutoConfiguration.class,
|
||||
KubernetesReactiveDiscoveryClientAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
public void shouldWorkWithDefaults() {
|
||||
contextRunner.run(context -> {
|
||||
assertThat(context).hasSingleBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context)
|
||||
.hasSingleBean(ReactiveDiscoveryClientHealthIndicator.class);
|
||||
assertThat(context).hasSingleBean(ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotHaveDiscoveryClientWhenDiscoveryDisabled() {
|
||||
contextRunner.withPropertyValues("spring.cloud.discovery.enabled=false")
|
||||
.run(context -> {
|
||||
assertThat(context)
|
||||
.doesNotHaveBean("kubernetesReactiveDiscoveryClient");
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(
|
||||
ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
contextRunner.withPropertyValues("spring.cloud.discovery.enabled=false").run(context -> {
|
||||
assertThat(context).doesNotHaveBean("kubernetesReactiveDiscoveryClient");
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotHaveDiscoveryClientWhenReactiveDiscoveryDisabled() {
|
||||
contextRunner.withPropertyValues("spring.cloud.discovery.reactive.enabled=false")
|
||||
.run(context -> {
|
||||
assertThat(context)
|
||||
.doesNotHaveBean("kubernetesReactiveDiscoveryClient");
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(
|
||||
ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
contextRunner.withPropertyValues("spring.cloud.discovery.reactive.enabled=false").run(context -> {
|
||||
assertThat(context).doesNotHaveBean("kubernetesReactiveDiscoveryClient");
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotHaveDiscoveryClientWhenKubernetesDisabled() {
|
||||
contextRunner.withPropertyValues("spring.cloud.kubernetes.enabled=false")
|
||||
.run(context -> {
|
||||
assertThat(context)
|
||||
.doesNotHaveBean("kubernetesReactiveDiscoveryClient");
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(
|
||||
ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
contextRunner.withPropertyValues("spring.cloud.kubernetes.enabled=false").run(context -> {
|
||||
assertThat(context).doesNotHaveBean("kubernetesReactiveDiscoveryClient");
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotHaveDiscoveryClientWhenKubernetesDiscoveryDisabled() {
|
||||
contextRunner
|
||||
.withPropertyValues("spring.cloud.kubernetes.discovery.enabled=false")
|
||||
.run(context -> {
|
||||
assertThat(context)
|
||||
.doesNotHaveBean("kubernetesReactiveDiscoveryClient");
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(
|
||||
ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
contextRunner.withPropertyValues("spring.cloud.kubernetes.discovery.enabled=false").run(context -> {
|
||||
assertThat(context).doesNotHaveBean("kubernetesReactiveDiscoveryClient");
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void worksWithoutWebflux() {
|
||||
contextRunner
|
||||
.withClassLoader(
|
||||
new FilteredClassLoader("org.springframework.web.reactive"))
|
||||
.run(context -> {
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(
|
||||
ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
contextRunner.withClassLoader(new FilteredClassLoader("org.springframework.web.reactive")).run(context -> {
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void worksWithoutActuator() {
|
||||
contextRunner
|
||||
.withClassLoader(
|
||||
new FilteredClassLoader("org.springframework.boot.actuate"))
|
||||
.run(context -> {
|
||||
assertThat(context).hasSingleBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(
|
||||
ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
contextRunner.withClassLoader(new FilteredClassLoader("org.springframework.boot.actuate")).run(context -> {
|
||||
assertThat(context).hasSingleBean(ReactiveDiscoveryClient.class);
|
||||
assertThat(context).doesNotHaveBean(ReactiveDiscoveryClientHealthIndicator.class);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,18 +56,16 @@ class KubernetesReactiveDiscoveryClientTests {
|
||||
kubernetesClient.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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyDefaults(@Client KubernetesClient kubernetesClient) {
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(
|
||||
kubernetesClient, properties, KubernetesClient::services);
|
||||
assertThat(client.description())
|
||||
.isEqualTo("Kubernetes Reactive Discovery Client");
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties,
|
||||
KubernetesClient::services);
|
||||
assertThat(client.description()).isEqualTo("Kubernetes Reactive Discovery Client");
|
||||
assertThat(client.getOrder()).isEqualTo(ReactiveDiscoveryClient.DEFAULT_ORDER);
|
||||
}
|
||||
|
||||
@@ -75,165 +73,141 @@ class KubernetesReactiveDiscoveryClientTests {
|
||||
public void shouldReturnFluxOfServices(@Client KubernetesClient kubernetesClient,
|
||||
@Server KubernetesServer kubernetesServer) {
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services")
|
||||
.andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata()
|
||||
.withName("s1").withLabels(new HashMap<String, String>() {
|
||||
.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>() {
|
||||
}).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())
|
||||
}).endMetadata().endItem().addNewItem().withNewMetadata().withName("s3").endMetadata().endItem()
|
||||
.build())
|
||||
.once();
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(
|
||||
kubernetesClient, properties, KubernetesClient::services);
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties,
|
||||
KubernetesClient::services);
|
||||
Flux<String> services = client.getServices();
|
||||
StepVerifier.create(services).expectNext("s1", "s2", "s3").expectComplete()
|
||||
.verify();
|
||||
StepVerifier.create(services).expectNext("s1", "s2", "s3").expectComplete().verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnEmptyFluxOfServicesWhenNoInstancesFound(
|
||||
@Client KubernetesClient kubernetesClient,
|
||||
public void shouldReturnEmptyFluxOfServicesWhenNoInstancesFound(@Client KubernetesClient kubernetesClient,
|
||||
@Server KubernetesServer kubernetesServer) {
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services")
|
||||
.andReturn(200, new ServiceListBuilder().build()).once();
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(
|
||||
kubernetesClient, properties, KubernetesClient::services);
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties,
|
||||
KubernetesClient::services);
|
||||
Flux<String> services = client.getServices();
|
||||
StepVerifier.create(services).expectNextCount(0).expectComplete().verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // see gh-603
|
||||
public void shouldReturnEmptyFluxForNonExistingService(
|
||||
@Client KubernetesClient kubernetesClient) {
|
||||
public void shouldReturnEmptyFluxForNonExistingService(@Client KubernetesClient kubernetesClient) {
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(
|
||||
kubernetesClient, properties, KubernetesClient::services);
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties,
|
||||
KubernetesClient::services);
|
||||
Flux<ServiceInstance> instances = client.getInstances("nonexistent-service");
|
||||
StepVerifier.create(instances).expectNextCount(0).expectComplete().verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // see gh-603
|
||||
public void shouldReturnEmptyFluxWhenServiceHasNoSubsets(
|
||||
@Client KubernetesClient kubernetesClient,
|
||||
public void shouldReturnEmptyFluxWhenServiceHasNoSubsets(@Client KubernetesClient kubernetesClient,
|
||||
@Server KubernetesServer kubernetesServer) {
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services")
|
||||
.andReturn(200,
|
||||
new ServiceListBuilder().addNewItem().withNewMetadata()
|
||||
.withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.once();
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(
|
||||
kubernetesClient, properties, KubernetesClient::services);
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties,
|
||||
KubernetesClient::services);
|
||||
Flux<ServiceInstance> instances = client.getInstances("existing-service");
|
||||
StepVerifier.create(instances).expectNextCount(0).expectComplete().verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // see gh-603
|
||||
public void shouldReturnFlux(@Client KubernetesClient kubernetesClient,
|
||||
@Server KubernetesServer kubernetesServer) {
|
||||
public void shouldReturnFlux(@Client KubernetesClient kubernetesClient, @Server KubernetesServer kubernetesServer) {
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services")
|
||||
.andReturn(200,
|
||||
new ServiceListBuilder().addNewItem().withNewMetadata()
|
||||
.withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.once();
|
||||
|
||||
Endpoints endPoints = new EndpointsBuilder().withNewMetadata()
|
||||
.withName("endpoint").withNamespace("test").endMetadata().addNewSubset()
|
||||
.addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP")
|
||||
.endSubset().build();
|
||||
Endpoints endPoints = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset().build();
|
||||
|
||||
kubernetesServer.expect().get()
|
||||
.withPath("/api/v1/namespaces/test/endpoints/existing-service")
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/existing-service")
|
||||
.andReturn(200, endPoints).once();
|
||||
|
||||
kubernetesServer.expect().get()
|
||||
.withPath("/api/v1/namespaces/test/services/existing-service")
|
||||
.andReturn(200,
|
||||
new ServiceBuilder().withNewMetadata()
|
||||
.withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().build())
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services/existing-service")
|
||||
.andReturn(200, new ServiceBuilder().withNewMetadata().withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().build())
|
||||
.once();
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(
|
||||
kubernetesClient, properties, KubernetesClient::services);
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties,
|
||||
KubernetesClient::services);
|
||||
Flux<ServiceInstance> instances = client.getInstances("existing-service");
|
||||
StepVerifier.create(instances).expectNextCount(1).expectComplete().verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled // see gh-603
|
||||
public void shouldReturnFluxWithPrefixedMetadata(
|
||||
@Client KubernetesClient kubernetesClient,
|
||||
public void shouldReturnFluxWithPrefixedMetadata(@Client KubernetesClient kubernetesClient,
|
||||
@Server KubernetesServer kubernetesServer) {
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services")
|
||||
.andReturn(200,
|
||||
new ServiceListBuilder().addNewItem().withNewMetadata()
|
||||
.withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.once();
|
||||
|
||||
Endpoints endPoints = new EndpointsBuilder().withNewMetadata()
|
||||
.withName("endpoint").withNamespace("test").endMetadata().addNewSubset()
|
||||
.addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP")
|
||||
.endSubset().build();
|
||||
Endpoints endPoints = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP").endSubset().build();
|
||||
|
||||
kubernetesServer.expect().get()
|
||||
.withPath("/api/v1/namespaces/test/endpoints/existing-service")
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/existing-service")
|
||||
.andReturn(200, endPoints).once();
|
||||
|
||||
kubernetesServer.expect().get()
|
||||
.withPath("/api/v1/namespaces/test/services/existing-service")
|
||||
.andReturn(200,
|
||||
new ServiceBuilder().withNewMetadata()
|
||||
.withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().build())
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services/existing-service")
|
||||
.andReturn(200, new ServiceBuilder().withNewMetadata().withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().build())
|
||||
.once();
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
properties.getMetadata().setAnnotationsPrefix("annotation.");
|
||||
properties.getMetadata().setLabelsPrefix("label.");
|
||||
properties.getMetadata().setPortsPrefix("port.");
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(
|
||||
kubernetesClient, properties, KubernetesClient::services);
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties,
|
||||
KubernetesClient::services);
|
||||
Flux<ServiceInstance> instances = client.getInstances("existing-service");
|
||||
StepVerifier.create(instances).expectNextCount(1).expectComplete().verify();
|
||||
}
|
||||
@@ -241,93 +215,77 @@ class KubernetesReactiveDiscoveryClientTests {
|
||||
@Test
|
||||
@Disabled // see gh-603
|
||||
public void shouldReturnFluxWhenServiceHasMultiplePortsAndPrimaryPortNameIsSet(
|
||||
@Client KubernetesClient kubernetesClient,
|
||||
@Server KubernetesServer kubernetesServer) {
|
||||
@Client KubernetesClient kubernetesClient, @Server KubernetesServer kubernetesServer) {
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services")
|
||||
.andReturn(200,
|
||||
new ServiceListBuilder().addNewItem().withNewMetadata()
|
||||
.withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.once();
|
||||
|
||||
Endpoints endPoints = new EndpointsBuilder().withNewMetadata()
|
||||
.withName("endpoint").withNamespace("test").endMetadata().addNewSubset()
|
||||
.addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1")
|
||||
Endpoints endPoints = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP")
|
||||
.addNewPort("https", "https_tcp", 443, "TCP").endSubset().build();
|
||||
|
||||
kubernetesServer.expect().get()
|
||||
.withPath("/api/v1/namespaces/test/endpoints/existing-service")
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/endpoints/existing-service")
|
||||
.andReturn(200, endPoints).once();
|
||||
|
||||
kubernetesServer.expect().get()
|
||||
.withPath("/api/v1/namespaces/test/services/existing-service")
|
||||
.andReturn(200,
|
||||
new ServiceBuilder().withNewMetadata()
|
||||
.withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().build())
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services/existing-service")
|
||||
.andReturn(200, new ServiceBuilder().withNewMetadata().withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().build())
|
||||
.once();
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
properties.setPrimaryPortName("https");
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(
|
||||
kubernetesClient, properties, KubernetesClient::services);
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties,
|
||||
KubernetesClient::services);
|
||||
Flux<ServiceInstance> instances = client.getInstances("existing-service");
|
||||
StepVerifier.create(instances).expectNextCount(1).expectComplete().verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFluxOfServicesAcrossAllNamespaces(
|
||||
@Client KubernetesClient kubernetesClient,
|
||||
public void shouldReturnFluxOfServicesAcrossAllNamespaces(@Client KubernetesClient kubernetesClient,
|
||||
@Server KubernetesServer kubernetesServer) {
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services")
|
||||
.andReturn(200,
|
||||
new ServiceListBuilder().addNewItem().withNewMetadata()
|
||||
.withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.andReturn(200, new ServiceListBuilder().addNewItem().withNewMetadata().withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().endItem().build())
|
||||
.once();
|
||||
|
||||
Endpoints endpoints = new EndpointsBuilder().withNewMetadata()
|
||||
.withName("endpoint").withNamespace("test").endMetadata().addNewSubset()
|
||||
.addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1")
|
||||
Endpoints endpoints = new EndpointsBuilder().withNewMetadata().withName("endpoint").withNamespace("test")
|
||||
.endMetadata().addNewSubset().addNewAddress().withIp("ip1").withNewTargetRef().withUid("uid1")
|
||||
.endTargetRef().endAddress().addNewPort("http", "http_tcp", 80, "TCP")
|
||||
.addNewPort("https", "https_tcp", 443, "TCP").endSubset().build();
|
||||
|
||||
EndpointsList endpointsList = new EndpointsList();
|
||||
endpointsList.setItems(singletonList(endpoints));
|
||||
|
||||
kubernetesServer.expect().get().withPath(
|
||||
"/api/v1/endpoints?fieldSelector=metadata.name%3Dexisting-service")
|
||||
kubernetesServer.expect().get().withPath("/api/v1/endpoints?fieldSelector=metadata.name%3Dexisting-service")
|
||||
.andReturn(200, endpointsList).once();
|
||||
|
||||
kubernetesServer.expect().get()
|
||||
.withPath("/api/v1/namespaces/test/services/existing-service")
|
||||
.andReturn(200,
|
||||
new ServiceBuilder().withNewMetadata()
|
||||
.withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().build())
|
||||
kubernetesServer.expect().get().withPath("/api/v1/namespaces/test/services/existing-service")
|
||||
.andReturn(200, new ServiceBuilder().withNewMetadata().withName("existing-service")
|
||||
.withLabels(new HashMap<String, String>() {
|
||||
{
|
||||
put("label", "value");
|
||||
}
|
||||
}).endMetadata().build())
|
||||
.once();
|
||||
|
||||
KubernetesDiscoveryProperties properties = new KubernetesDiscoveryProperties();
|
||||
properties.setAllNamespaces(true);
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(
|
||||
kubernetesClient, properties, KubernetesClient::services);
|
||||
ReactiveDiscoveryClient client = new KubernetesReactiveDiscoveryClient(kubernetesClient, properties,
|
||||
KubernetesClient::services);
|
||||
Flux<ServiceInstance> instances = client.getInstances("existing-service");
|
||||
StepVerifier.create(instances).expectNextCount(1).expectComplete().verify();
|
||||
}
|
||||
|
||||
@@ -33,20 +33,16 @@ import org.junit.jupiter.api.extension.ParameterResolver;
|
||||
/**
|
||||
* @author Tim Ysewyn
|
||||
*/
|
||||
public class KubernetesExtension
|
||||
implements ParameterResolver, BeforeEachCallback, AfterEachCallback {
|
||||
public class KubernetesExtension implements ParameterResolver, BeforeEachCallback, AfterEachCallback {
|
||||
|
||||
private final KubernetesServer mockServer = new KubernetesServer();
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(ParameterContext parameterContext,
|
||||
ExtensionContext context) {
|
||||
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext context) {
|
||||
return (parameterContext.getParameter().isAnnotationPresent(Server.class)
|
||||
&& KubernetesServer.class
|
||||
.isAssignableFrom(parameterContext.getParameter().getType()))
|
||||
&& KubernetesServer.class.isAssignableFrom(parameterContext.getParameter().getType()))
|
||||
|| (parameterContext.getParameter().isAnnotationPresent(Client.class)
|
||||
&& KubernetesClient.class.isAssignableFrom(
|
||||
parameterContext.getParameter().getType()));
|
||||
&& KubernetesClient.class.isAssignableFrom(parameterContext.getParameter().getType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,8 +56,8 @@ public class KubernetesExtension
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveParameter(ParameterContext parameterContext,
|
||||
ExtensionContext extensionContext) throws ParameterResolutionException {
|
||||
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
|
||||
throws ParameterResolutionException {
|
||||
if (parameterContext.getParameter().isAnnotationPresent(Client.class)) {
|
||||
return mockServer.getClient();
|
||||
}
|
||||
|
||||
@@ -50,12 +50,10 @@ public class LeaderController {
|
||||
@GetMapping
|
||||
public String getInfo() {
|
||||
if (this.context == null) {
|
||||
return String.format("I am '%s' but I am not a leader of the '%s'", this.host,
|
||||
this.role);
|
||||
return String.format("I am '%s' but I am not a leader of the '%s'", this.host, this.role);
|
||||
}
|
||||
|
||||
return String.format("I am '%s' and I am the leader of the '%s'", this.host,
|
||||
this.role);
|
||||
return String.format("I am '%s' and I am the leader of the '%s'", this.host, this.role);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,8 +66,7 @@ public class LeaderController {
|
||||
@PutMapping
|
||||
public ResponseEntity<String> revokeLeadership() {
|
||||
if (this.context == null) {
|
||||
String message = String.format(
|
||||
"Cannot revoke leadership because '%s' is not a leader", this.host);
|
||||
String message = String.format("Cannot revoke leadership because '%s' is not a leader", this.host);
|
||||
return ResponseEntity.badRequest().body(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +60,7 @@ public class LeaderControllerTest {
|
||||
|
||||
@Test
|
||||
public void shouldGetNonLeaderInfo() {
|
||||
String message = String.format("I am '%s' but I am not a leader of the 'null'",
|
||||
this.host);
|
||||
String message = String.format("I am '%s' but I am not a leader of the 'null'", this.host);
|
||||
assertThat(this.leaderController.getInfo()).isEqualTo(message);
|
||||
}
|
||||
|
||||
@@ -71,8 +70,7 @@ public class LeaderControllerTest {
|
||||
|
||||
this.leaderController.handleEvent(this.mockOnGrantedEvent);
|
||||
|
||||
String message = String.format("I am '%s' and I am the leader of the 'null'",
|
||||
this.host);
|
||||
String message = String.format("I am '%s' and I am the leader of the 'null'", this.host);
|
||||
assertThat(this.leaderController.getInfo()).isEqualTo(message);
|
||||
}
|
||||
|
||||
@@ -83,8 +81,7 @@ public class LeaderControllerTest {
|
||||
this.leaderController.handleEvent(this.mockOnGrantedEvent);
|
||||
this.leaderController.handleEvent(this.mockOnRevokedEvent);
|
||||
|
||||
String message = String.format("I am '%s' but I am not a leader of the 'null'",
|
||||
this.host);
|
||||
String message = String.format("I am '%s' but I am not a leader of the 'null'", this.host);
|
||||
assertThat(this.leaderController.getInfo()).isEqualTo(message);
|
||||
}
|
||||
|
||||
@@ -105,8 +102,7 @@ public class LeaderControllerTest {
|
||||
public void shouldNotRevokeLeadershipIfNotLeader() {
|
||||
ResponseEntity<String> responseEntity = this.leaderController.revokeLeadership();
|
||||
|
||||
String message = String.format(
|
||||
"Cannot revoke leadership because '%s' is not a leader", this.host);
|
||||
String message = String.format("Cannot revoke leadership because '%s' is not a leader", this.host);
|
||||
assertThat(responseEntity.getBody()).isEqualTo(message);
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
|
||||
verify(this.mockContext, times(0)).yield();
|
||||
|
||||
@@ -50,10 +50,8 @@ public class GreetingController {
|
||||
* @return Greeting string.
|
||||
*/
|
||||
@GetMapping("/greeting")
|
||||
public Mono<String> getGreeting(
|
||||
@RequestParam(value = "delay", defaultValue = "0") int delay) {
|
||||
return nameService.getName(delay)
|
||||
.map(name -> String.format("Hello from %s!", name));
|
||||
public Mono<String> getGreeting(@RequestParam(value = "delay", defaultValue = "0") int delay) {
|
||||
return nameService.getName(delay).map(name -> String.format("Hello from %s!", name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,8 +37,7 @@ public class NameService {
|
||||
}
|
||||
|
||||
public Mono<String> getName(int delay) {
|
||||
return webClient.get()
|
||||
.uri(String.format("http://name-service/name?delay=%d", delay)).retrieve()
|
||||
return webClient.get().uri(String.format("http://name-service/name?delay=%d", delay)).retrieve()
|
||||
.bodyToMono(String.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,10 +50,8 @@ public class NameController {
|
||||
* @return Host name.
|
||||
*/
|
||||
@GetMapping("/name")
|
||||
public Mono<String> getName(
|
||||
@RequestParam(value = "delay", defaultValue = "0") int delayValue) {
|
||||
LOG.info(String.format("Returning a name '%s' with a delay '%d'", hostName,
|
||||
delayValue));
|
||||
public Mono<String> getName(@RequestParam(value = "delay", defaultValue = "0") int delayValue) {
|
||||
LOG.info(String.format("Returning a name '%s' with a delay '%d'", hostName, delayValue));
|
||||
delay(delayValue);
|
||||
return Mono.just(hostName);
|
||||
}
|
||||
|
||||
@@ -32,16 +32,15 @@ public class ServicesIT {
|
||||
|
||||
private static final String HOST = System.getProperty("service.host");
|
||||
|
||||
private static final Integer PORT = Integer
|
||||
.valueOf(System.getProperty("service.port"));
|
||||
private static final Integer PORT = Integer.valueOf(System.getProperty("service.port"));
|
||||
|
||||
private static final String PROTOCOL = "true"
|
||||
.equalsIgnoreCase(System.getProperty("service.secure")) ? "https" : "http";
|
||||
private static final String PROTOCOL = "true".equalsIgnoreCase(System.getProperty("service.secure")) ? "https"
|
||||
: "http";
|
||||
|
||||
@Test
|
||||
public void testServicesEndpoint() {
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("services")
|
||||
.then().statusCode(200).body(new StringContains(false, "service-a") {
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("services").then().statusCode(200)
|
||||
.body(new StringContains(false, "service-a") {
|
||||
@Override
|
||||
protected boolean evalSubstringOf(String s) {
|
||||
return s.contains("service-a") && s.contains("service-b");
|
||||
@@ -51,9 +50,8 @@ public class ServicesIT {
|
||||
|
||||
@Test
|
||||
public void testInstancesEndpoint() {
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT))
|
||||
.get("services/discovery-service-a/instances").then().statusCode(200)
|
||||
.body("instanceId", hasSize(1))
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("services/discovery-service-a/instances")
|
||||
.then().statusCode(200).body("instanceId", hasSize(1))
|
||||
.body("serviceId", hasItems("discovery-service-a"));
|
||||
}
|
||||
|
||||
|
||||
@@ -46,12 +46,10 @@ class LoadBalancerAllNamespacesTests {
|
||||
|
||||
@BeforeAll
|
||||
static void setup() {
|
||||
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY,
|
||||
client.getConfiguration().getMasterUrl());
|
||||
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, client.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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
}
|
||||
@@ -59,23 +57,21 @@ class LoadBalancerAllNamespacesTests {
|
||||
@Test
|
||||
void testLoadBalancerDifferentNamespace() {
|
||||
createTestData("service-b", "b");
|
||||
String response = restTemplate.getForObject("http://service-b/greeting",
|
||||
String.class);
|
||||
String response = restTemplate.getForObject("http://service-b/greeting", String.class);
|
||||
Assertions.assertNotNull(response);
|
||||
Assertions.assertEquals("greeting", response);
|
||||
}
|
||||
|
||||
private void createTestData(String name, String namespace) {
|
||||
client.services().inNamespace(namespace).createNew().withNewMetadata()
|
||||
.withName(name).withNamespace(namespace).endMetadata()
|
||||
.withSpec(new ServiceSpecBuilder().withPorts(new ServicePortBuilder()
|
||||
.withProtocol("TCP").withPort(randomServerPort).build()).build())
|
||||
client.services().inNamespace(namespace).createNew().withNewMetadata().withName(name).withNamespace(namespace)
|
||||
.endMetadata()
|
||||
.withSpec(new ServiceSpecBuilder()
|
||||
.withPorts(new ServicePortBuilder().withProtocol("TCP").withPort(randomServerPort).build())
|
||||
.build())
|
||||
.done();
|
||||
client.endpoints().inNamespace(namespace).createNew().withNewMetadata()
|
||||
.withName("service-a").withNamespace(namespace).endMetadata()
|
||||
.addNewSubset().addNewAddress().withIp("localhost").endAddress()
|
||||
.addNewPort().withName("http").withPort(randomServerPort).endPort()
|
||||
.endSubset().done();
|
||||
client.endpoints().inNamespace(namespace).createNew().withNewMetadata().withName("service-a")
|
||||
.withNamespace(namespace).endMetadata().addNewSubset().addNewAddress().withIp("localhost").endAddress()
|
||||
.addNewPort().withName("http").withPort(randomServerPort).endPort().endSubset().done();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,12 +44,10 @@ class LoadBalancerTests {
|
||||
|
||||
@BeforeAll
|
||||
static void setup() {
|
||||
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY,
|
||||
client.getConfiguration().getMasterUrl());
|
||||
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, client.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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
}
|
||||
@@ -57,8 +55,7 @@ class LoadBalancerTests {
|
||||
@Test
|
||||
void testLoadBalancerSameNamespace() {
|
||||
createTestData("service-a", "test");
|
||||
String response = restTemplate.getForObject("http://service-a/greeting",
|
||||
String.class);
|
||||
String response = restTemplate.getForObject("http://service-a/greeting", String.class);
|
||||
Assertions.assertNotNull(response);
|
||||
Assertions.assertEquals("greeting", response);
|
||||
}
|
||||
@@ -66,19 +63,18 @@ class LoadBalancerTests {
|
||||
@Test
|
||||
void testLoadBalancerDifferentNamespace() {
|
||||
createTestData("service-b", "b");
|
||||
Assertions.assertThrows(IllegalStateException.class, () -> restTemplate
|
||||
.getForObject("http://service-b/greeting", String.class));
|
||||
Assertions.assertThrows(IllegalStateException.class,
|
||||
() -> restTemplate.getForObject("http://service-b/greeting", String.class));
|
||||
}
|
||||
|
||||
private void createTestData(String name, String namespace) {
|
||||
client.services().inNamespace(namespace).createNew().withNewMetadata()
|
||||
.withName(name).endMetadata()
|
||||
.withSpec(new ServiceSpecBuilder().withPorts(new ServicePortBuilder()
|
||||
.withProtocol("TCP").withPort(randomServerPort).build()).build())
|
||||
client.services().inNamespace(namespace).createNew().withNewMetadata().withName(name).endMetadata()
|
||||
.withSpec(new ServiceSpecBuilder()
|
||||
.withPorts(new ServicePortBuilder().withProtocol("TCP").withPort(randomServerPort).build())
|
||||
.build())
|
||||
.done();
|
||||
client.endpoints().inNamespace(namespace).createNew().withNewMetadata()
|
||||
.withName("service-a").endMetadata().addNewSubset().addNewAddress()
|
||||
.withIp("localhost").endAddress().addNewPort().withName("http")
|
||||
client.endpoints().inNamespace(namespace).createNew().withNewMetadata().withName("service-a").endMetadata()
|
||||
.addNewSubset().addNewAddress().withIp("localhost").endAddress().addNewPort().withName("http")
|
||||
.withPort(randomServerPort).endPort().endSubset().done();
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,7 @@ import static io.specto.hoverfly.junit.dsl.ResponseCreators.success;
|
||||
@ExtendWith(HoverflyExtension.class)
|
||||
class LoadBalancerWithServiceTests {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory
|
||||
.getLogger(LoadBalancerWithServiceTests.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoadBalancerWithServiceTests.class);
|
||||
|
||||
@Autowired
|
||||
RestTemplate restTemplate;
|
||||
@@ -60,8 +59,7 @@ class LoadBalancerWithServiceTests {
|
||||
static void setup() {
|
||||
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_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
|
||||
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
|
||||
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
|
||||
}
|
||||
@@ -70,23 +68,19 @@ class LoadBalancerWithServiceTests {
|
||||
void testLoadBalancerInServiceMode(Hoverfly hoverfly) {
|
||||
LOGGER.info("Master URL: {}", client.getConfiguration().getMasterUrl());
|
||||
hoverfly.simulate(
|
||||
dsl(service("http://service-a.test.svc.cluster.local:8080")
|
||||
.get("/greeting").willReturn(success().body("greeting"))),
|
||||
dsl(service(client.getConfiguration().getMasterUrl().replace("/", "")
|
||||
.replace("https:", ""))
|
||||
.get("/api/v1/namespaces/test/services/service-a")
|
||||
.willReturn(success().body(
|
||||
json(buildService("service-a", 8080, "test"))))));
|
||||
String response = restTemplate.getForObject("http://service-a/greeting",
|
||||
String.class);
|
||||
dsl(service("http://service-a.test.svc.cluster.local:8080").get("/greeting")
|
||||
.willReturn(success().body("greeting"))),
|
||||
dsl(service(client.getConfiguration().getMasterUrl().replace("/", "").replace("https:", ""))
|
||||
.get("/api/v1/namespaces/test/services/service-a")
|
||||
.willReturn(success().body(json(buildService("service-a", 8080, "test"))))));
|
||||
String response = restTemplate.getForObject("http://service-a/greeting", String.class);
|
||||
Assertions.assertNotNull(response);
|
||||
Assertions.assertEquals("greeting", response);
|
||||
}
|
||||
|
||||
private Service buildService(String name, int port, String namespace) {
|
||||
return new ServiceBuilder().withNewMetadata().withName(name)
|
||||
.withNamespace(namespace).withLabels(new HashMap<>())
|
||||
.withAnnotations(new HashMap<>()).endMetadata().withNewSpec().addNewPort()
|
||||
return new ServiceBuilder().withNewMetadata().withName(name).withNamespace(namespace)
|
||||
.withLabels(new HashMap<>()).withAnnotations(new HashMap<>()).endMetadata().withNewSpec().addNewPort()
|
||||
.withPort(port).endPort().endSpec().build();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,16 +34,15 @@ public class GreetingIT {
|
||||
|
||||
private static final String HOST = System.getProperty("service.host");
|
||||
|
||||
private static final Integer PORT = Integer
|
||||
.valueOf(System.getProperty("service.port"));
|
||||
private static final Integer PORT = Integer.valueOf(System.getProperty("service.port"));
|
||||
|
||||
private static final String PROTOCOL = "true"
|
||||
.equalsIgnoreCase(System.getProperty("service.secure")) ? "https" : "http";
|
||||
private static final String PROTOCOL = "true".equalsIgnoreCase(System.getProperty("service.secure")) ? "https"
|
||||
: "http";
|
||||
|
||||
@Test
|
||||
public void firstTestThatTheDefaultMessageIsReturned() {
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting")
|
||||
.then().statusCode(200).body("message", is("This is a dummy message"));
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting").then().statusCode(200)
|
||||
.body("message", is("This is a dummy message"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -51,8 +50,7 @@ public class GreetingIT {
|
||||
public void thenApplyAConfigMapAndEnsureThatTheMessageIsUpdated() {
|
||||
waitForApplicationToReload();
|
||||
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting")
|
||||
.then().statusCode(200)
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting").then().statusCode(200)
|
||||
.body("message", is("Hello from Spring Cloud Kubernetes!"));
|
||||
}
|
||||
|
||||
|
||||
@@ -30,23 +30,21 @@ public class GreetingAndHealthIT {
|
||||
|
||||
private static final String HOST = System.getProperty("service.host");
|
||||
|
||||
private static final Integer PORT = Integer
|
||||
.valueOf(System.getProperty("service.port"));
|
||||
private static final Integer PORT = Integer.valueOf(System.getProperty("service.port"));
|
||||
|
||||
private static final String PROTOCOL = "true"
|
||||
.equalsIgnoreCase(System.getProperty("service.secure")) ? "https" : "http";
|
||||
private static final String PROTOCOL = "true".equalsIgnoreCase(System.getProperty("service.secure")) ? "https"
|
||||
: "http";
|
||||
|
||||
@Test
|
||||
public void testGreetingEndpoint() {
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting")
|
||||
.then().statusCode(200).body("message", is("Hello from k8s"));
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).get("greeting").then().statusCode(200)
|
||||
.body("message", is("Hello from k8s"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHealthEndpoint() {
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT))
|
||||
.contentType("application/json").get("actuator/health").then()
|
||||
.statusCode(200).body("components.kubernetes.details.inside", is(true));
|
||||
given().baseUri(String.format("%s://%s:%d", PROTOCOL, HOST, PORT)).contentType("application/json")
|
||||
.get("actuator/health").then().statusCode(200).body("components.kubernetes.details.inside", is(true));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,8 +59,7 @@ public class IstioBootstrapConfiguration {
|
||||
|
||||
private final ConfigurableEnvironment environment;
|
||||
|
||||
public IstioDetectionConfiguration(MeshUtils utils,
|
||||
ConfigurableEnvironment environment) {
|
||||
public IstioDetectionConfiguration(MeshUtils utils, ConfigurableEnvironment environment) {
|
||||
this.utils = utils;
|
||||
this.environment = environment;
|
||||
}
|
||||
@@ -86,15 +85,13 @@ public class IstioBootstrapConfiguration {
|
||||
}
|
||||
else {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug(
|
||||
"Not running inside kubernetes with istio enabled. Skipping 'istio' profile activation.");
|
||||
LOG.debug("Not running inside kubernetes with istio enabled. Skipping 'istio' profile activation.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasIstioProfile(Environment environment) {
|
||||
return Arrays.stream(environment.getActiveProfiles())
|
||||
.anyMatch(ISTIO_PROFILE::equalsIgnoreCase);
|
||||
return Arrays.stream(environment.getActiveProfiles()).anyMatch(ISTIO_PROFILE::equalsIgnoreCase);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,26 +50,21 @@ public class MeshUtils {
|
||||
// Check if Istio Envoy proxy is installed. Notice that the check is done to
|
||||
// localhost.
|
||||
// TODO: We can improve this initial detection if better methods are found.
|
||||
String resource = "http://localhost:"
|
||||
+ this.istioClientProperties.getEnvoyPort();
|
||||
ResponseEntity<String> response = this.restTemplate.getForEntity(
|
||||
resource + "/" + this.istioClientProperties.getTestPath(),
|
||||
String.class);
|
||||
String resource = "http://localhost:" + this.istioClientProperties.getEnvoyPort();
|
||||
ResponseEntity<String> response = this.restTemplate
|
||||
.getForEntity(resource + "/" + this.istioClientProperties.getTestPath(), String.class);
|
||||
if (response.getStatusCode().is2xxSuccessful()) {
|
||||
LOG.info("Istio Resources Found.");
|
||||
return true;
|
||||
}
|
||||
LOG.warn("Although Envoy proxy did respond at port"
|
||||
+ this.istioClientProperties.getEnvoyPort()
|
||||
+ ", it did not respond with HTTP 200 to path: "
|
||||
+ this.istioClientProperties.getTestPath()
|
||||
LOG.warn("Although Envoy proxy did respond at port" + this.istioClientProperties.getEnvoyPort()
|
||||
+ ", it did not respond with HTTP 200 to path: " + this.istioClientProperties.getTestPath()
|
||||
+ ". You may need to tweak the test path in order to get proper Istio support");
|
||||
return false;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Envoy proxy could not be located at port: "
|
||||
+ this.istioClientProperties.getEnvoyPort()
|
||||
LOG.debug("Envoy proxy could not be located at port: " + this.istioClientProperties.getEnvoyPort()
|
||||
+ ". Assuming that the application is not running inside the Istio Service Mesh");
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -47,8 +47,7 @@ public class Leader {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(this.role, candidate.getRole())
|
||||
&& Objects.equals(this.id, candidate.getId());
|
||||
return Objects.equals(this.role, candidate.getRole()) && Objects.equals(this.id, candidate.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,8 +62,7 @@ public class Leader {
|
||||
|
||||
Leader leader = (Leader) o;
|
||||
|
||||
return Objects.equals(this.role, leader.role)
|
||||
&& Objects.equals(this.id, leader.id);
|
||||
return Objects.equals(this.role, leader.role) && Objects.equals(this.id, leader.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -41,20 +41,17 @@ import org.springframework.integration.leader.event.LeaderEventPublisher;
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(LeaderProperties.class)
|
||||
@ConditionalOnBean(KubernetesClient.class)
|
||||
@ConditionalOnProperty(value = "spring.cloud.kubernetes.leader.enabled",
|
||||
matchIfMissing = true)
|
||||
@ConditionalOnProperty(value = "spring.cloud.kubernetes.leader.enabled", matchIfMissing = true)
|
||||
public class LeaderAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(LeaderEventPublisher.class)
|
||||
public LeaderEventPublisher defaultLeaderEventPublisher(
|
||||
ApplicationEventPublisher applicationEventPublisher) {
|
||||
public LeaderEventPublisher defaultLeaderEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
|
||||
return new DefaultLeaderEventPublisher(applicationEventPublisher);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Candidate candidate(LeaderProperties leaderProperties)
|
||||
throws UnknownHostException {
|
||||
public Candidate candidate(LeaderProperties leaderProperties) throws UnknownHostException {
|
||||
String id = Inet4Address.getLocalHost().getHostName();
|
||||
String role = leaderProperties.getRole();
|
||||
|
||||
@@ -62,41 +59,32 @@ public class LeaderAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LeadershipController leadershipController(Candidate candidate,
|
||||
LeaderProperties leaderProperties, LeaderEventPublisher leaderEventPublisher,
|
||||
KubernetesClient kubernetesClient) {
|
||||
return new LeadershipController(candidate, leaderProperties, leaderEventPublisher,
|
||||
kubernetesClient);
|
||||
public LeadershipController leadershipController(Candidate candidate, LeaderProperties leaderProperties,
|
||||
LeaderEventPublisher leaderEventPublisher, KubernetesClient kubernetesClient) {
|
||||
return new LeadershipController(candidate, leaderProperties, leaderEventPublisher, kubernetesClient);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LeaderRecordWatcher leaderRecordWatcher(LeaderProperties leaderProperties,
|
||||
LeadershipController leadershipController,
|
||||
KubernetesClient kubernetesClient) {
|
||||
return new LeaderRecordWatcher(leaderProperties, leadershipController,
|
||||
kubernetesClient);
|
||||
LeadershipController leadershipController, KubernetesClient kubernetesClient) {
|
||||
return new LeaderRecordWatcher(leaderProperties, leadershipController, kubernetesClient);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PodReadinessWatcher hostPodWatcher(Candidate candidate,
|
||||
KubernetesClient kubernetesClient,
|
||||
public PodReadinessWatcher hostPodWatcher(Candidate candidate, KubernetesClient kubernetesClient,
|
||||
LeadershipController leadershipController) {
|
||||
return new PodReadinessWatcher(candidate.getId(), kubernetesClient,
|
||||
leadershipController);
|
||||
return new PodReadinessWatcher(candidate.getId(), kubernetesClient, leadershipController);
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "stop")
|
||||
public LeaderInitiator leaderInitiator(LeaderProperties leaderProperties,
|
||||
LeadershipController leadershipController,
|
||||
public LeaderInitiator leaderInitiator(LeaderProperties leaderProperties, LeadershipController leadershipController,
|
||||
LeaderRecordWatcher leaderRecordWatcher, PodReadinessWatcher hostPodWatcher) {
|
||||
return new LeaderInitiator(leaderProperties, leadershipController,
|
||||
leaderRecordWatcher, hostPodWatcher);
|
||||
return new LeaderInitiator(leaderProperties, leadershipController, leaderRecordWatcher, hostPodWatcher);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(InfoContributor.class)
|
||||
public LeaderInfoContributor leaderInfoContributor(
|
||||
LeadershipController leadershipController, Candidate candidate) {
|
||||
public LeaderInfoContributor leaderInfoContributor(LeadershipController leadershipController, Candidate candidate) {
|
||||
return new LeaderInfoContributor(leadershipController, candidate);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,7 @@ public class LeaderContext implements Context {
|
||||
|
||||
@Override
|
||||
public boolean isLeader() {
|
||||
return this.leadershipController.getLocalLeader()
|
||||
.filter(l -> l.isCandidate(this.candidate)).isPresent();
|
||||
return this.leadershipController.getLocalLeader().filter(l -> l.isCandidate(this.candidate)).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -30,8 +30,7 @@ public class LeaderInfoContributor implements InfoContributor {
|
||||
|
||||
private final Candidate candidate;
|
||||
|
||||
public LeaderInfoContributor(LeadershipController leadershipController,
|
||||
Candidate candidate) {
|
||||
public LeaderInfoContributor(LeadershipController leadershipController, Candidate candidate) {
|
||||
this.leadershipController = leadershipController;
|
||||
this.candidate = candidate;
|
||||
}
|
||||
|
||||
@@ -44,8 +44,7 @@ public class LeaderInitiator implements SmartLifecycle {
|
||||
|
||||
private boolean isRunning;
|
||||
|
||||
public LeaderInitiator(LeaderProperties leaderProperties,
|
||||
LeadershipController leadershipController,
|
||||
public LeaderInitiator(LeaderProperties leaderProperties, LeadershipController leadershipController,
|
||||
LeaderRecordWatcher leaderRecordWatcher, PodReadinessWatcher hostPodWatcher) {
|
||||
this.leaderProperties = leaderProperties;
|
||||
this.leadershipController = leadershipController;
|
||||
@@ -65,11 +64,9 @@ public class LeaderInitiator implements SmartLifecycle {
|
||||
this.leaderRecordWatcher.start();
|
||||
this.hostPodWatcher.start();
|
||||
this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
|
||||
this.scheduledExecutorService.scheduleAtFixedRate(
|
||||
this.leadershipController::update,
|
||||
this.scheduledExecutorService.scheduleAtFixedRate(this.leadershipController::update,
|
||||
this.leaderProperties.getUpdatePeriod().toMillis(),
|
||||
this.leaderProperties.getUpdatePeriod().toMillis(),
|
||||
TimeUnit.MILLISECONDS);
|
||||
this.leaderProperties.getUpdatePeriod().toMillis(), TimeUnit.MILLISECONDS);
|
||||
this.isRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public class LeaderRecordWatcher implements Watcher<ConfigMap> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory
|
||||
.getLogger(LeaderRecordWatcher.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LeaderRecordWatcher.class);
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
@@ -42,8 +41,7 @@ public class LeaderRecordWatcher implements Watcher<ConfigMap> {
|
||||
|
||||
private Watch watch;
|
||||
|
||||
public LeaderRecordWatcher(LeaderProperties leaderProperties,
|
||||
LeadershipController leadershipController,
|
||||
public LeaderRecordWatcher(LeaderProperties leaderProperties, LeadershipController leadershipController,
|
||||
KubernetesClient kubernetesClient) {
|
||||
this.leadershipController = leadershipController;
|
||||
this.leaderProperties = leaderProperties;
|
||||
@@ -56,10 +54,8 @@ public class LeaderRecordWatcher implements Watcher<ConfigMap> {
|
||||
if (this.watch == null) {
|
||||
LOGGER.debug("Starting leader record watcher");
|
||||
this.watch = this.kubernetesClient.configMaps()
|
||||
.inNamespace(this.leaderProperties
|
||||
.getNamespace(this.kubernetesClient.getNamespace()))
|
||||
.withName(this.leaderProperties.getConfigMapName())
|
||||
.watch(this);
|
||||
.inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace()))
|
||||
.withName(this.leaderProperties.getConfigMapName()).watch(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +45,7 @@ public class LeadershipController {
|
||||
|
||||
private static final String KIND = "leaders";
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory
|
||||
.getLogger(LeadershipController.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LeadershipController.class);
|
||||
|
||||
private final Candidate candidate;
|
||||
|
||||
@@ -61,8 +60,7 @@ public class LeadershipController {
|
||||
private PodReadinessWatcher leaderReadinessWatcher;
|
||||
|
||||
public LeadershipController(Candidate candidate, LeaderProperties leaderProperties,
|
||||
LeaderEventPublisher leaderEventPublisher,
|
||||
KubernetesClient kubernetesClient) {
|
||||
LeaderEventPublisher leaderEventPublisher, KubernetesClient kubernetesClient) {
|
||||
this.candidate = candidate;
|
||||
this.leaderProperties = leaderProperties;
|
||||
this.leaderEventPublisher = leaderEventPublisher;
|
||||
@@ -109,8 +107,7 @@ public class LeadershipController {
|
||||
handleLeaderChange(null);
|
||||
}
|
||||
catch (KubernetesClientException e) {
|
||||
LOGGER.warn("Failure when revoking leadership for '{}': {}", this.candidate,
|
||||
e.getMessage());
|
||||
LOGGER.warn("Failure when revoking leadership for '{}': {}", this.candidate, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,9 +115,7 @@ public class LeadershipController {
|
||||
LOGGER.debug("Trying to acquire leadership for '{}'", this.candidate);
|
||||
|
||||
if (!isPodReady(this.candidate.getId())) {
|
||||
LOGGER.debug(
|
||||
"Pod of '{}' is not ready at the moment, cannot acquire leadership",
|
||||
this.candidate);
|
||||
LOGGER.debug("Pod of '{}' is not ready at the moment, cannot acquire leadership", this.candidate);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -133,13 +128,11 @@ public class LeadershipController {
|
||||
updateConfigMapEntry(configMap, data);
|
||||
}
|
||||
|
||||
Leader newLeader = new Leader(this.candidate.getRole(),
|
||||
this.candidate.getId());
|
||||
Leader newLeader = new Leader(this.candidate.getRole(), this.candidate.getId());
|
||||
handleLeaderChange(newLeader);
|
||||
}
|
||||
catch (KubernetesClientException e) {
|
||||
LOGGER.warn("Failure when acquiring leadership for '{}': {}", this.candidate,
|
||||
e.getMessage());
|
||||
LOGGER.warn("Failure when acquiring leadership for '{}': {}", this.candidate, e.getMessage());
|
||||
notifyOnFailedToAcquire();
|
||||
}
|
||||
}
|
||||
@@ -169,8 +162,7 @@ public class LeadershipController {
|
||||
LOGGER.debug("Leadership has been granted for '{}'", this.candidate);
|
||||
|
||||
Context context = new LeaderContext(this.candidate, this);
|
||||
this.leaderEventPublisher.publishOnGranted(this, context,
|
||||
this.candidate.getRole());
|
||||
this.leaderEventPublisher.publishOnGranted(this, context, this.candidate.getRole());
|
||||
try {
|
||||
this.candidate.onGranted(context);
|
||||
}
|
||||
@@ -184,16 +176,14 @@ public class LeadershipController {
|
||||
LOGGER.debug("Leadership has been revoked for '{}'", this.candidate);
|
||||
|
||||
Context context = new LeaderContext(this.candidate, this);
|
||||
this.leaderEventPublisher.publishOnRevoked(this, context,
|
||||
this.candidate.getRole());
|
||||
this.leaderEventPublisher.publishOnRevoked(this, context, this.candidate.getRole());
|
||||
this.candidate.onRevoked(context);
|
||||
}
|
||||
|
||||
private void notifyOnFailedToAcquire() {
|
||||
if (this.leaderProperties.isPublishFailedEvents()) {
|
||||
Context context = new LeaderContext(this.candidate, this);
|
||||
this.leaderEventPublisher.publishOnFailedToAcquire(this, context,
|
||||
this.candidate.getRole());
|
||||
this.leaderEventPublisher.publishOnFailedToAcquire(this, context, this.candidate.getRole());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,8 +194,8 @@ public class LeadershipController {
|
||||
}
|
||||
|
||||
if (this.localLeader != null && !this.localLeader.isCandidate(this.candidate)) {
|
||||
this.leaderReadinessWatcher = new PodReadinessWatcher(
|
||||
this.localLeader.getId(), this.kubernetesClient, this);
|
||||
this.leaderReadinessWatcher = new PodReadinessWatcher(this.localLeader.getId(), this.kubernetesClient,
|
||||
this);
|
||||
this.leaderReadinessWatcher.start();
|
||||
}
|
||||
}
|
||||
@@ -240,8 +230,7 @@ public class LeadershipController {
|
||||
|
||||
private ConfigMap getConfigMap() {
|
||||
return this.kubernetesClient.configMaps()
|
||||
.inNamespace(this.leaderProperties
|
||||
.getNamespace(this.kubernetesClient.getNamespace()))
|
||||
.inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace()))
|
||||
.withName(this.leaderProperties.getConfigMapName()).get();
|
||||
}
|
||||
|
||||
@@ -249,21 +238,18 @@ public class LeadershipController {
|
||||
LOGGER.debug("Creating new config map with data: {}", data);
|
||||
|
||||
ConfigMap newConfigMap = new ConfigMapBuilder().withNewMetadata()
|
||||
.withName(this.leaderProperties.getConfigMapName())
|
||||
.addToLabels(PROVIDER_KEY, PROVIDER).addToLabels(KIND_KEY, KIND)
|
||||
.endMetadata().addToData(data).build();
|
||||
.withName(this.leaderProperties.getConfigMapName()).addToLabels(PROVIDER_KEY, PROVIDER)
|
||||
.addToLabels(KIND_KEY, KIND).endMetadata().addToData(data).build();
|
||||
|
||||
this.kubernetesClient.configMaps()
|
||||
.inNamespace(this.leaderProperties
|
||||
.getNamespace(this.kubernetesClient.getNamespace()))
|
||||
.inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace()))
|
||||
.create(newConfigMap);
|
||||
}
|
||||
|
||||
private void updateConfigMapEntry(ConfigMap configMap, Map<String, String> newData) {
|
||||
LOGGER.debug("Adding new data to config map: {}", newData);
|
||||
|
||||
ConfigMap newConfigMap = new ConfigMapBuilder(configMap).addToData(newData)
|
||||
.build();
|
||||
ConfigMap newConfigMap = new ConfigMapBuilder(configMap).addToData(newData).build();
|
||||
|
||||
updateConfigMap(configMap, newConfigMap);
|
||||
}
|
||||
@@ -271,19 +257,16 @@ public class LeadershipController {
|
||||
private void removeConfigMapEntry(ConfigMap configMap, String key) {
|
||||
LOGGER.debug("Removing config map entry '{}'", key);
|
||||
|
||||
ConfigMap newConfigMap = new ConfigMapBuilder(configMap).removeFromData(key)
|
||||
.build();
|
||||
ConfigMap newConfigMap = new ConfigMapBuilder(configMap).removeFromData(key).build();
|
||||
|
||||
updateConfigMap(configMap, newConfigMap);
|
||||
}
|
||||
|
||||
private void updateConfigMap(ConfigMap oldConfigMap, ConfigMap newConfigMap) {
|
||||
this.kubernetesClient.configMaps()
|
||||
.inNamespace(this.leaderProperties
|
||||
.getNamespace(this.kubernetesClient.getNamespace()))
|
||||
.inNamespace(this.leaderProperties.getNamespace(this.kubernetesClient.getNamespace()))
|
||||
.withName(this.leaderProperties.getConfigMapName())
|
||||
.lockResourceVersion(oldConfigMap.getMetadata().getResourceVersion())
|
||||
.replace(newConfigMap);
|
||||
.lockResourceVersion(oldConfigMap.getMetadata().getResourceVersion()).replace(newConfigMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,8 +32,7 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public class PodReadinessWatcher implements Watcher<Pod> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory
|
||||
.getLogger(PodReadinessWatcher.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PodReadinessWatcher.class);
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
@@ -59,8 +58,7 @@ public class PodReadinessWatcher implements Watcher<Pod> {
|
||||
synchronized (this.lock) {
|
||||
if (this.watch == null) {
|
||||
LOGGER.debug("Starting pod readiness watcher for '{}'", this.podName);
|
||||
PodResource<Pod, DoneablePod> podResource = this.kubernetesClient
|
||||
.pods().withName(this.podName);
|
||||
PodResource<Pod, DoneablePod> podResource = this.kubernetesClient.pods().withName(this.podName);
|
||||
this.previousState = podResource.isReady();
|
||||
this.watch = podResource.watch(this);
|
||||
}
|
||||
@@ -86,9 +84,8 @@ public class PodReadinessWatcher implements Watcher<Pod> {
|
||||
if (this.previousState != currentState) {
|
||||
synchronized (this.lock) {
|
||||
if (this.previousState != currentState) {
|
||||
LOGGER.debug(
|
||||
"'{}' readiness status changed to '{}', triggering leadership update",
|
||||
this.podName, currentState);
|
||||
LOGGER.debug("'{}' readiness status changed to '{}', triggering leadership update", this.podName,
|
||||
currentState);
|
||||
this.previousState = currentState;
|
||||
this.leadershipController.update();
|
||||
}
|
||||
|
||||
@@ -48,9 +48,8 @@ public class LeaderAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void infoEndpointShouldContainLeaderElection() {
|
||||
this.webClient.get().uri("http://localhost:{port}/actuator/info", this.port)
|
||||
.accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk()
|
||||
.expectBody(String.class).value(containsString("kubernetes"));
|
||||
this.webClient.get().uri("http://localhost:{port}/actuator/info", this.port).accept(MediaType.APPLICATION_JSON)
|
||||
.exchange().expectStatus().isOk().expectBody(String.class).value(containsString("kubernetes"));
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
|
||||
@@ -49,14 +49,12 @@ public class LeaderContextTest {
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
this.leaderContext = new LeaderContext(this.mockCandidate,
|
||||
this.mockLeadershipController);
|
||||
this.leaderContext = new LeaderContext(this.mockCandidate, this.mockLeadershipController);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsLeaderWithoutLeader() {
|
||||
given(this.mockLeadershipController.getLocalLeader())
|
||||
.willReturn(Optional.empty());
|
||||
given(this.mockLeadershipController.getLocalLeader()).willReturn(Optional.empty());
|
||||
|
||||
boolean result = this.leaderContext.isLeader();
|
||||
|
||||
@@ -65,8 +63,7 @@ public class LeaderContextTest {
|
||||
|
||||
@Test
|
||||
public void testIsLeaderWithAnotherLeader() {
|
||||
given(this.mockLeadershipController.getLocalLeader())
|
||||
.willReturn(Optional.of(this.mockLeader));
|
||||
given(this.mockLeadershipController.getLocalLeader()).willReturn(Optional.of(this.mockLeader));
|
||||
|
||||
boolean result = this.leaderContext.isLeader();
|
||||
|
||||
@@ -75,8 +72,7 @@ public class LeaderContextTest {
|
||||
|
||||
@Test
|
||||
public void testIsLeaderWhenLeader() {
|
||||
given(this.mockLeadershipController.getLocalLeader())
|
||||
.willReturn(Optional.of(this.mockLeader));
|
||||
given(this.mockLeadershipController.getLocalLeader()).willReturn(Optional.of(this.mockLeader));
|
||||
given(this.mockLeader.isCandidate(this.mockCandidate)).willReturn(true);
|
||||
|
||||
boolean result = this.leaderContext.isLeader();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user