Bumping versions

This commit is contained in:
buildmaster
2020-09-18 11:47:22 +00:00
parent 3126157493
commit 7f6ddf69c5
111 changed files with 1272 additions and 2007 deletions

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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));
}
}

View File

@@ -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));

View File

@@ -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() + ")");
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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()));
}
}

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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");

View File

@@ -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);
}
}

View File

@@ -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 = "";

View File

@@ -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!");
}
}

View File

@@ -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");
}

View File

@@ -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");

View File

@@ -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!");
}
}

View File

@@ -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!");
}

View File

@@ -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!");
}

View File

@@ -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!");
}

View File

@@ -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!");
}

View File

@@ -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!");
}
}

View File

@@ -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

View File

@@ -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"));
}
}

View File

@@ -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)

View File

@@ -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");
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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));
}

View File

@@ -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

View File

@@ -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");
}

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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());
}
}
}

View File

@@ -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

View File

@@ -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:**");
}

View File

@@ -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")));
}

View File

@@ -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 "

View File

@@ -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());

View File

@@ -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();
}
}

View File

@@ -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.");
}
}
}

View File

@@ -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")));
}
}

View File

@@ -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"));
}
}

View File

@@ -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"));
}
}

View File

@@ -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");

View File

@@ -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

View File

@@ -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 {
}

View File

@@ -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() {

View File

@@ -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));
}
}

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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 {
}

View File

@@ -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();
}

View File

@@ -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());
}

View File

@@ -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());
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 + '}';
}
}

View File

@@ -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);

View File

@@ -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");

View File

@@ -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)

View File

@@ -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();

View File

@@ -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)

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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");

View File

@@ -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);
});
}
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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));
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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"));
}

View File

@@ -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();
}
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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!"));
}

View File

@@ -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));
}
}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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