Merge pull request #70 from Jahia/blacklist-optimization
Slightly optimized code for group configuration
diff --git a/.asf.yaml b/.asf.yaml
new file mode 100644
index 0000000..9420e0a
--- /dev/null
+++ b/.asf.yaml
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+notifications:
+ pullrequests: commits@karaf.apache.org
diff --git a/assembly/src/main/resources/groups.cfg b/assembly/src/main/resources/groups.cfg
index bb3b700..b2687e8 100644
--- a/assembly/src/main/resources/groups.cfg
+++ b/assembly/src/main/resources/groups.cfg
@@ -22,16 +22,16 @@
org.ops4j.pax.web, \
org.apache.aries.transaction, \
org.ops4j.pax.logging, \
- org.apache.karaf.cellar.node.cfg, \
- org.apache.karaf.cellar.groups.cfg
+ org.apache.karaf.cellar.node, \
+ org.apache.karaf.cellar.groups
default.config.blacklist.outbound=org.apache.felix.fileinstall*, \
org.apache.karaf.management, \
org.apache.karaf.shell, \
org.ops4j.pax.web, \
org.apache.aries.transaction, \
org.ops4j.pax.logging, \
- org.apache.karaf.cellar.node.cfg, \
- org.apache.karaf.cellar.groups.cfg
+ org.apache.karaf.cellar.node, \
+ org.apache.karaf.cellar.groups
#
# Filtering of the features in the default cluster group
diff --git a/assembly/src/main/resources/hazelcast.xml b/assembly/src/main/resources/hazelcast.xml
index 860e3e1..866f0ca 100644
--- a/assembly/src/main/resources/hazelcast.xml
+++ b/assembly/src/main/resources/hazelcast.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<hazelcast xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.hazelcast.com/schema/config http://www.hazelcast.com/schema/config/hazelcast-config-3.6.xsd">
+ xsi:schemaLocation="http://www.hazelcast.com/schema/config http://www.hazelcast.com/schema/config/hazelcast-config-3.12.xsd">
<group>
<name>cellar</name>
<password>pass</password>
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
index 2e78fe4..d24bbae 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/BundleSynchronizer.java
@@ -19,6 +19,7 @@
import org.apache.karaf.cellar.core.control.SwitchStatus;
import org.apache.karaf.cellar.core.event.EventProducer;
import org.apache.karaf.cellar.core.event.EventType;
+import org.apache.karaf.cellar.core.utils.CellarUtils;
import org.apache.karaf.features.BootFinished;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -32,10 +33,7 @@
import org.slf4j.LoggerFactory;
import java.io.IOException;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
/**
* The BundleSynchronizer is called when Cellar starts or a node joins a cluster group.
@@ -128,6 +126,8 @@
try {
// get the bundles on the cluster to update local bundles
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+
+ List<String> bundleToStart = new ArrayList<String>();
for (Map.Entry<String, BundleState> entry : clusterBundles.entrySet()) {
String id = entry.getKey();
BundleState state = entry.getValue();
@@ -153,8 +153,9 @@
installBundleFromLocation(state.getLocation(), state.getStartLevel());
}
if (!isStarted(state.getLocation())) {
- LOGGER.debug("CELLAR BUNDLE: starting bundle {}/{} on node", symbolicName, version);
- startBundle(symbolicName, version);
+ // Store the id in a list so we can install all bundles before trying to start them,
+ // this way if a bundle depend on another one that is not install yet but is part of the same update, the start won't fail.
+ bundleToStart.add(id);
} else {
LOGGER.debug("CELLAR BUNDLE: bundle located {} already started on node", state.getLocation());
}
@@ -177,19 +178,34 @@
}
}
} catch (BundleException e) {
- LOGGER.error("CELLAR BUNDLE: failed to pull bundle {}", id, e);
+ resolveBundleException(id, e);
}
} else LOGGER.trace("CELLAR BUNDLE: bundle {} is marked BLOCKED INBOUND for cluster group {}", bundleLocation, groupName);
}
}
}
+
+ for (String id : bundleToStart) {
+ String[] tokens = id.split("/");
+ String symbolicName = tokens[0];
+ String version = tokens[1];
+
+ try {
+ LOGGER.debug("CELLAR BUNDLE: starting bundle {}/{} on node", symbolicName, version);
+ startBundle(symbolicName, version);
+ } catch (BundleException e) {
+ resolveBundleException(id, e);
+ }
+ }
+
// cleanup the local bundles not present on the cluster if the node is not the first one in the cluster group
- if (clusterManager.listNodesByGroup(group).size() > 1) {
+ if (CellarUtils.doCleanupResourcesNotPresentInCluster(configurationAdmin) && getSynchronizerMap().containsKey(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName)) {
for (Bundle bundle : bundleContext.getBundles()) {
String id = getId(bundle);
if (!clusterBundles.containsKey(id) && isAllowed(group, Constants.CATEGORY, bundle.getLocation(), EventType.INBOUND)) {
// the bundle is not present on the cluster, so it has to be uninstalled locally
try {
+ LOGGER.debug("CELLAR BUNDLE: uninstalling local bundle {} which is not present in cluster", id);
bundle.uninstall();
} catch (Exception e) {
LOGGER.warn("Can't uninstall {}", id, e);
@@ -268,12 +284,12 @@
} else {
BundleState bundleState = clusterBundles.get(id);
if (bundleState.getStatus() != status) {
- LOGGER.debug("CELLAR BUNDLE: updating bundle {} on the cluster", id);
+ LOGGER.debug("CELLAR BUNDLE: updating bundle id: {}, name: {}, location: {} status: {} on the cluster", id, symbolicName, bundleLocation, status);
// update cluster state
bundleState.setStatus(status);
clusterBundles.put(id, bundleState);
// send cluster event
- ClusterBundleEvent clusterEvent = new ClusterBundleEvent(symbolicName, version, bundleLocation, null, status);
+ ClusterBundleEvent clusterEvent = new ClusterBundleEvent(symbolicName, version, bundleLocation, level, status);
clusterEvent.setSourceGroup(group);
clusterEvent.setSourceNode(clusterManager.getNode());
clusterEvent.setLocal(clusterManager.getNode());
@@ -301,6 +317,7 @@
}
}
}
+ getSynchronizerMap().putIfAbsent(Constants.BUNDLE_MAP + Configurations.SEPARATOR + groupName, true);
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
@@ -344,4 +361,15 @@
return null;
}
+ private void resolveBundleException(String id, BundleException e) {
+ if (BundleException.RESOLVE_ERROR == e.getType()) {
+ // we log unresolved dependencies in DEBUG
+ LOGGER.warn("CELLAR BUNDLE: Bundle {} has unresolved dependencies and won't be started now", id);
+ LOGGER.debug("CELLAR BUNDLE: Error while starting bundle {}.", id, e);
+ } else {
+ LOGGER.error("CELLAR BUNDLE: failed to pull bundle {}", id, e);
+ }
+ }
+
+
}
diff --git a/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/internal/CellarBundleMBeanImpl.java b/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/internal/CellarBundleMBeanImpl.java
index a8c03c7..9bcaa20 100644
--- a/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/internal/CellarBundleMBeanImpl.java
+++ b/bundle/src/main/java/org/apache/karaf/cellar/bundle/management/internal/CellarBundleMBeanImpl.java
@@ -149,6 +149,7 @@
state.setSymbolicName(symbolicName);
state.setVersion(version);
state.setId(clusterBundles.size());
+ state.setStartLevel(level);
state.setLocation(location);
if (start) {
state.setStatus(Bundle.ACTIVE);
@@ -273,7 +274,8 @@
// broadcast the cluster event
String[] split = bundle.split("/");
- ClusterBundleEvent event = new ClusterBundleEvent(split[0], split[1], location, null, Bundle.ACTIVE);
+
+ ClusterBundleEvent event = new ClusterBundleEvent(split[0], split[1], location, state.getStartLevel(), Bundle.ACTIVE);
event.setSourceGroup(group);
event.setSourceNode(clusterManager.getNode());
eventProducer.produce(event);
@@ -327,7 +329,7 @@
// broadcast the cluster event
String[] split = bundle.split("/");
- ClusterBundleEvent event = new ClusterBundleEvent(split[0], split[1], location, null, Bundle.RESOLVED);
+ ClusterBundleEvent event = new ClusterBundleEvent(split[0], split[1], location, state.getStartLevel(), Bundle.RESOLVED);
event.setSourceGroup(group);
event.setSourceNode(clusterManager.getNode());
eventProducer.produce(event);
diff --git a/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java b/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java
index e02040c..613ce4c 100644
--- a/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java
+++ b/config/src/main/java/org/apache/karaf/cellar/config/ConfigurationSynchronizer.java
@@ -19,6 +19,7 @@
import org.apache.karaf.cellar.core.control.SwitchStatus;
import org.apache.karaf.cellar.core.event.EventProducer;
import org.apache.karaf.cellar.core.event.EventType;
+import org.apache.karaf.cellar.core.utils.CellarUtils;
import org.apache.karaf.features.BootFinished;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
@@ -148,7 +149,7 @@
} else LOGGER.trace("CELLAR CONFIG: configuration with PID {} is marked BLOCKED INBOUND for cluster group {}", pid, groupName);
}
// cleanup the local configurations not present on the cluster if the node is not the first one in the cluster
- if (clusterManager.listNodesByGroup(group).size() > 1) {
+ if (CellarUtils.doCleanupResourcesNotPresentInCluster(configurationAdmin) && getSynchronizerMap().containsKey(Constants.CONFIGURATION_MAP + Configurations.SEPARATOR + groupName)) {
try {
Set<String> filenames = new HashSet();
for (Properties configuration : clusterConfigurations.values()) {
@@ -241,6 +242,7 @@
}
}
}
+ getSynchronizerMap().putIfAbsent(Constants.CONFIGURATION_MAP + Configurations.SEPARATOR + groupName, true);
} catch (IOException ex) {
LOGGER.error("CELLAR CONFIG: failed to read configuration (IO error)", ex);
} catch (InvalidSyntaxException ex) {
diff --git a/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java b/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java
index 586bc5e..965e09c 100644
--- a/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java
+++ b/core/src/main/java/org/apache/karaf/cellar/core/CellarSupport.java
@@ -249,4 +249,8 @@
this.groupManager = groupManager;
}
+ @SuppressWarnings("unchecked")
+ protected Map<String, Boolean> getSynchronizerMap() {
+ return clusterManager.getMap("org.apache.karaf.cellar.synchronizers");
+ }
}
diff --git a/core/src/main/java/org/apache/karaf/cellar/core/event/EventHandlerRegistryDispatcher.java b/core/src/main/java/org/apache/karaf/cellar/core/event/EventHandlerRegistryDispatcher.java
index 6e4a087..7dd7b54 100644
--- a/core/src/main/java/org/apache/karaf/cellar/core/event/EventHandlerRegistryDispatcher.java
+++ b/core/src/main/java/org/apache/karaf/cellar/core/event/EventHandlerRegistryDispatcher.java
@@ -16,17 +16,27 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* Event handler service registry dispatcher.
*/
public class EventHandlerRegistryDispatcher<E extends Event> implements EventDispatcher<E> {
+ private static final transient Logger LOGGER = LoggerFactory.getLogger(EventHandlerRegistryDispatcher.class);
private ExecutorService threadPool;
private EventHandlerRegistry handlerRegistry;
public void init() {
if (threadPool == null) {
- threadPool = Executors.newCachedThreadPool();
+ if (Boolean.getBoolean(this.getClass().getName() + ".threadPool.singleThreadExecutor")) {
+ LOGGER.info("Will use an Executor that uses a single worker thread");
+ threadPool = Executors.newSingleThreadExecutor();
+ } else {
+ LOGGER.info("Will use an Executor with a pool of threads");
+ threadPool = Executors.newCachedThreadPool();
+ }
}
}
@@ -56,4 +66,10 @@
this.threadPool = threadPool;
}
+ public void destroy() {
+ if (threadPool != null) {
+ threadPool.shutdown();
+ }
+ }
+
}
diff --git a/core/src/main/java/org/apache/karaf/cellar/core/utils/CellarUtils.java b/core/src/main/java/org/apache/karaf/cellar/core/utils/CellarUtils.java
index 28e57d7..8ba5973 100644
--- a/core/src/main/java/org/apache/karaf/cellar/core/utils/CellarUtils.java
+++ b/core/src/main/java/org/apache/karaf/cellar/core/utils/CellarUtils.java
@@ -13,13 +13,21 @@
*/
package org.apache.karaf.cellar.core.utils;
+import java.io.IOException;
import java.util.Collection;
+import java.util.Dictionary;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.karaf.cellar.core.Configurations;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
* Generic Cellar utils class.
*/
@@ -29,6 +37,8 @@
MERGA
}
+ private static final transient Logger LOGGER = LoggerFactory.getLogger(CellarUtils.class);
+
public static final String MERGABLE = "MERGABLE[%s]";
public static final String MERGABLE_REGEX = "MERGABLE\\[([^\\s]+[\\,]*[\\s]*)*\\]";
@@ -129,4 +139,51 @@
return true;
}
}
+
+ /**
+ * Retrieves the value of the configuration property from the specified configuration. If the property is not found or there is an error
+ * retrieving it, return the provided default value.
+ *
+ * @param configurationAdmin
+ * the config admin service instance
+ * @param configurationId
+ * the configuration PID to be retrieved
+ * @param propertyKey
+ * the key of the property entry to look up
+ * @param defaultValue
+ * a value to be returned, if the property is not present in the configuration or there is an error retrieving it
+ * @return the value of the configuration property from the specified configuration. If the property is not found or there is an error
+ * retrieving it, return the provided default value
+ */
+ public static String getConfigurationProperty(ConfigurationAdmin configurationAdmin, String configurationId,
+ String propertyKey, String defaultValue) {
+ String propertyValue = null;
+ try {
+ Configuration configuration = configurationAdmin.getConfiguration(configurationId, null);
+ Dictionary<String, Object> properties = configuration.getProperties();
+ if (properties != null) {
+ propertyValue = (String) properties.get(propertyKey);
+ }
+ } catch (IOException e) {
+ LOGGER.warn("Error while retrieving the " + propertyKey + " entry from coonfiguration " + configurationId,
+ e);
+ }
+
+ return propertyValue != null ? propertyValue : defaultValue;
+ }
+
+ /**
+ * Returns the flag value, indicating if the resources (bundles, configuration, features), not present on cluster, should be uninstalled
+ * on cluster sync by corresponding synchronizers.
+ *
+ * @param configurationAdmin
+ * the config admin service instance
+ * @return the flag value, indicating if the resources (bundles, configuration, features), not present on cluster, should be uninstalled
+ * on cluster sync by corresponding synchronizers
+ */
+ public static boolean doCleanupResourcesNotPresentInCluster(ConfigurationAdmin configurationAdmin) {
+ return Boolean.parseBoolean(getConfigurationProperty(configurationAdmin, Configurations.NODE,
+ "org.apache.karaf.cellar.cleanupResourcesNotPresentInCluster", "true"));
+ }
+
}
diff --git a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java
index 487b780..daf8961 100644
--- a/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java
+++ b/features/src/main/java/org/apache/karaf/cellar/features/FeaturesSynchronizer.java
@@ -19,6 +19,7 @@
import org.apache.karaf.cellar.core.control.SwitchStatus;
import org.apache.karaf.cellar.core.event.EventProducer;
import org.apache.karaf.cellar.core.event.EventType;
+import org.apache.karaf.cellar.core.utils.CellarUtils;
import org.apache.karaf.features.*;
import org.osgi.framework.BundleContext;
import org.osgi.service.cm.Configuration;
@@ -122,6 +123,7 @@
Map<String, String> clusterRepositories = clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);
Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
+ Map<String, Boolean> synchronizers = getSynchronizerMap();
if (clusterRepositories != null && !clusterRepositories.isEmpty()) {
// get the features repositories from the cluster to update locally
@@ -138,7 +140,8 @@
}
}
// cleanup the local features repositories not present on the cluster if the node is not the first one in the cluster group
- if (clusterManager.listNodesByGroup(group).size() > 1) {
+
+ if (synchronizers.containsKey(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName)) {
try {
for (Repository repository : featuresService.listRepositories()) {
URI uri = repository.getURI();
@@ -161,6 +164,7 @@
}
if (clusterFeatures != null && !clusterFeatures.isEmpty()) {
+ boolean doUninstallFeaturesNotPresentInCluster = CellarUtils.doCleanupResourcesNotPresentInCluster(configurationAdmin) && synchronizers.containsKey(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
// get the features from the cluster group and update locally
for (FeatureState state : clusterFeatures.values()) {
String name = state.getName();
@@ -187,7 +191,7 @@
}
}
// if feature has to be uninstalled locally (and node is not the first one in the cluster group)
- if (clusterManager.listNodesByGroup(group).size() > 1 && !clusterInstalled && locallyInstalled) {
+ if (doUninstallFeaturesNotPresentInCluster && !clusterInstalled && locallyInstalled) {
try {
LOGGER.debug("CELLAR FEATURE: uninstalling feature {}/{}", state.getName(), state.getVersion());
featuresService.uninstallFeature(state.getName(), state.getVersion());
@@ -227,6 +231,7 @@
Map<String, String> clusterRepositories = clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);
Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
+ Map<String, Boolean> synchronizers = getSynchronizerMap();
Repository[] repositoryList = new Repository[0];
Feature[] featuresList = new Feature[0];
@@ -260,6 +265,7 @@
}
}
}
+ synchronizers.put(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName, true);
// push features to the cluster group
if (featuresList != null && featuresList.length > 0) {
@@ -312,6 +318,7 @@
}
}
}
+ synchronizers.put(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName, true);
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
diff --git a/hazelcast/src/main/java/org/apache/karaf/cellar/hazelcast/internal/osgi/Activator.java b/hazelcast/src/main/java/org/apache/karaf/cellar/hazelcast/internal/osgi/Activator.java
index 3de5799..87593c1 100644
--- a/hazelcast/src/main/java/org/apache/karaf/cellar/hazelcast/internal/osgi/Activator.java
+++ b/hazelcast/src/main/java/org/apache/karaf/cellar/hazelcast/internal/osgi/Activator.java
@@ -98,6 +98,8 @@
private HashMap updatedConfig;
+ private EventHandlerRegistryDispatcher dispatcher;
+
@Override
public void doStart() throws Exception {
@@ -144,7 +146,7 @@
extender.init();
LOGGER.debug("CELLAR HAZELCAST: init dispatcher");
- EventHandlerRegistryDispatcher dispatcher = new EventHandlerRegistryDispatcher();
+ dispatcher = new EventHandlerRegistryDispatcher();
dispatcher.setHandlerRegistry(eventHandlerRegistry);
dispatcher.init();
@@ -402,6 +404,10 @@
combinedClassLoader.destroy();
combinedClassLoader = null;
}
+ if (dispatcher != null) {
+ dispatcher.destroy();
+ dispatcher = null;
+ }
}
@Override
diff --git a/itests/pom.xml b/itests/pom.xml
index 8362d95..2789962 100644
--- a/itests/pom.xml
+++ b/itests/pom.xml
@@ -69,13 +69,13 @@
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
- <version>4.7.0</version>
+ <version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-karaf</artifactId>
- <version>4.7.0</version>
+ <version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
diff --git a/kubernetes/pom.xml b/kubernetes/pom.xml
index 1892ce1..0b3b894 100644
--- a/kubernetes/pom.xml
+++ b/kubernetes/pom.xml
@@ -47,6 +47,18 @@
<artifactId>kubernetes-client</artifactId>
</dependency>
+ <!-- Testing -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+
<!-- OSGi -->
<dependency>
<groupId>org.apache.karaf</groupId>
diff --git a/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/ConfigKey.java b/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/ConfigKey.java
new file mode 100644
index 0000000..c26c5b8
--- /dev/null
+++ b/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/ConfigKey.java
@@ -0,0 +1,62 @@
+package org.apache.karaf.cellar.kubernetes;
+
+import io.fabric8.kubernetes.client.Config;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Dictionary;
+
+/**
+ * Constant names must be the same as the envvar names specified on
+ * <a href="https://github.com/fabric8io/kubernetes-client">GitHub</a>
+ */
+public enum ConfigKey {
+ KUBERNETES_MASTER(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY),
+ KUBERNETES_API_VERSION(Config.KUBERNETES_API_VERSION_SYSTEM_PROPERTY),
+ KUBERNETES_TRUST_CERTIFICATES(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY),
+ KUBERNETES_DISABLE_HOSTNAME_VERIFICATION(Config.KUBERNETES_DISABLE_HOSTNAME_VERIFICATION_SYSTEM_PROPERTY),
+ KUBERNETES_CERTS_CA_FILE(Config.KUBERNETES_CA_CERTIFICATE_FILE_SYSTEM_PROPERTY),
+ KUBERNETES_CERTS_CA_DATA(Config.KUBERNETES_CA_CERTIFICATE_DATA_SYSTEM_PROPERTY),
+ KUBERNETES_CERTS_CLIENT_FILE(Config.KUBERNETES_CLIENT_CERTIFICATE_FILE_SYSTEM_PROPERTY),
+ KUBERNETES_CERTS_CLIENT_DATA(Config.KUBERNETES_CLIENT_CERTIFICATE_DATA_SYSTEM_PROPERTY),
+ KUBERNETES_CERTS_CLIENT_KEY_FILE(Config.KUBERNETES_CLIENT_KEY_FILE_SYSTEM_PROPERTY),
+ KUBERNETES_CERTS_CLIENT_KEY_DATA(Config.KUBERNETES_CLIENT_KEY_DATA_SYSTEM_PROPERTY),
+ KUBERNETES_CERTS_CLIENT_KEY_ALGO(Config.KUBERNETES_CLIENT_KEY_ALGO_SYSTEM_PROPERTY),
+ KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE(Config.KUBERNETES_CLIENT_KEY_PASSPHRASE_SYSTEM_PROPERTY),
+ KUBERNETES_AUTH_BASIC_USERNAME(Config.KUBERNETES_AUTH_BASIC_USERNAME_SYSTEM_PROPERTY),
+ KUBERNETES_AUTH_BASIC_PASSWORD(Config.KUBERNETES_AUTH_BASIC_PASSWORD_SYSTEM_PROPERTY),
+ KUBERNETES_AUTH_TOKEN(Config.KUBERNETES_OAUTH_TOKEN_SYSTEM_PROPERTY),
+ KUBERNETES_WATCH_RECONNECTINTERVAL(Config.KUBERNETES_WATCH_RECONNECT_INTERVAL_SYSTEM_PROPERTY),
+ KUBERNETES_WATCH_RECONNECTLIMIT(Config.KUBERNETES_WATCH_RECONNECT_LIMIT_SYSTEM_PROPERTY),
+ KUBERNETES_USER_AGENT(Config.KUBERNETES_USER_AGENT),
+ KUBERNETES_TLS_VERSIONS(Config.KUBERNETES_TLS_VERSIONS),
+ KUBERNETES_TRUSTSTORE_FILE(Config.KUBERNETES_TRUSTSTORE_FILE_PROPERTY),
+ KUBERNETES_TRUSTSTORE_PASSPHRASE(Config.KUBERNETES_TRUSTSTORE_PASSPHRASE_PROPERTY),
+ KUBERNETES_KEYSTORE_FILE(Config.KUBERNETES_KEYSTORE_FILE_PROPERTY),
+ KUBERNETES_KEYSTORE_PASSPHRASE(Config.KUBERNETES_KEYSTORE_PASSPHRASE_PROPERTY);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConfigKey.class);
+ String propertyName;
+
+ ConfigKey(String propertyName) {
+ this.propertyName = propertyName;
+ }
+
+ public String getValue(Dictionary properties) {
+ // Highest priority
+ String value = (String)properties.get(propertyName);
+ LOGGER.debug("Properties : {}", value);
+
+ if (value == null) {
+ // Second priority
+ value = System.getProperty(propertyName);
+ LOGGER.debug("System properties : {}", value);
+
+ if (value == null) {
+ value = System.getenv(name());
+ LOGGER.debug("Environment variables : {}", value);
+ }
+ }
+
+ return value;
+ }
+}
diff --git a/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryService.java b/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryService.java
index e4f0890..bed2dcb 100644
--- a/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryService.java
+++ b/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryService.java
@@ -13,13 +13,13 @@
*/
package org.apache.karaf.cellar.kubernetes;
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.api.model.PodList;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
-import io.fabric8.kubernetes.api.model.Pod;
-import io.fabric8.kubernetes.api.model.PodList;
-
+import okhttp3.TlsVersion;
import org.apache.karaf.cellar.core.discovery.DiscoveryService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,8 +35,29 @@
private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesDiscoveryService.class);
- private String kubernetesHost;
- private String kubernetesPort;
+ private String kubernetesMaster;
+ private String kubernetesApiVersion;
+ private boolean kubernetesTrustCertificates;
+ private boolean kubernetesDisableHostnameVerification;
+ private String kubernetesCertsCaFile;
+ private String kubernetesCertsCaData;
+ private String kubernetesCertsClientFile;
+ private String kubernetesCertsClientData;
+ private String kubernetesCertsClientKeyFile;
+ private String kubernetesCertsClientKeyData;
+ private String kubernetesCertsClientKeyAlgo;
+ private String kubernetesCertsClientKeyPassphrase;
+ private String kubernetesAuthBasicUsername;
+ private String kubernetesAuthBasicPassword;
+ private String kubernetesOauthToken;
+ private int kubernetesWatchReconnectInterval;
+ private int kubernetesWatchReconnectLimit;
+ private String kubernetesUserAgent;
+ private String kubernetesTlsVersion;
+ private String kubernetesTruststoreFile;
+ private String kubernetesTruststorePassphrase;
+ private String kubernetesKeystoreFile;
+ private String kubernetesKeystorePassphrase;
private String kubernetesPodLabelKey;
private String kubernetesPodLabelValue;
@@ -46,11 +67,38 @@
LOGGER.debug("CELLAR KUBERNETES: create discovery service");
}
+ Config createConfig() {
+ return new ConfigBuilder()
+ .withMasterUrl(kubernetesMaster)
+ .withApiVersion(kubernetesApiVersion)
+ .withTrustCerts(kubernetesTrustCertificates)
+ .withDisableHostnameVerification(kubernetesDisableHostnameVerification)
+ .withCaCertFile(kubernetesCertsCaFile)
+ .withCaCertData(kubernetesCertsCaData)
+ .withClientCertFile(kubernetesCertsClientFile)
+ .withClientCertData(kubernetesCertsClientData)
+ .withClientKeyFile(kubernetesCertsClientKeyFile)
+ .withClientKeyData(kubernetesCertsClientKeyData)
+ .withClientKeyAlgo(kubernetesCertsClientKeyAlgo)
+ .withClientKeyPassphrase(kubernetesCertsClientKeyPassphrase)
+ .withUsername(kubernetesAuthBasicUsername)
+ .withPassword(kubernetesAuthBasicPassword)
+ .withOauthToken(kubernetesOauthToken)
+ .withWatchReconnectInterval(kubernetesWatchReconnectInterval)
+ .withWatchReconnectLimit(kubernetesWatchReconnectLimit)
+ .withUserAgent(kubernetesUserAgent)
+ .withTlsVersions(TlsVersion.forJavaName(kubernetesTlsVersion))
+ .withTrustStoreFile(kubernetesTruststoreFile)
+ .withTrustStorePassphrase(kubernetesTruststorePassphrase)
+ .withKeyStoreFile(kubernetesKeystoreFile)
+ .withKeyStorePassphrase(kubernetesKeystorePassphrase)
+ .build();
+ }
+
public void init() {
try {
- String kubernetesUrl = "http://" + kubernetesHost + ":" + kubernetesPort;
- LOGGER.debug("CELLAR KUBERNETES: query API at {} ...", kubernetesUrl);
- Config config = new ConfigBuilder().withMasterUrl(kubernetesUrl).build();
+ LOGGER.debug("CELLAR KUBERNETES: query API at {} ...", kubernetesMaster);
+ Config config = createConfig();
kubernetesClient = new DefaultKubernetesClient(config);
LOGGER.debug("CELLAR KUBERNETES: discovery service initialized");
} catch (Exception e) {
@@ -99,20 +147,8 @@
// nothing to do for Kubernetes
}
- public String getKubernetesHost() {
- return kubernetesHost;
- }
-
- public void setKubernetesHost(String kubernetesHost) {
- this.kubernetesHost = kubernetesHost;
- }
-
- public String getKubernetesPort() {
- return kubernetesPort;
- }
-
- public void setKubernetesPort(String kubernetesPort) {
- this.kubernetesPort = kubernetesPort;
+ void setKubernetesClient(KubernetesClient kubernetesClient) {
+ this.kubernetesClient = kubernetesClient;
}
public String getKubernetesPodLabelKey() {
@@ -131,4 +167,195 @@
this.kubernetesPodLabelValue = kubernetesPodLabelValue;
}
+ public String getKubernetesMaster() {
+ return kubernetesMaster;
+ }
+
+ public void setKubernetesMaster(String kubernetesMaster) {
+ this.kubernetesMaster = kubernetesMaster;
+ }
+
+ public String getKubernetesApiVersion() {
+ return kubernetesApiVersion;
+ }
+
+ public void setKubernetesApiVersion(String kubernetesApiVersion) {
+ this.kubernetesApiVersion = kubernetesApiVersion;
+ }
+
+ public boolean isKubernetesTrustCertificates() {
+ return kubernetesTrustCertificates;
+ }
+
+ public void setKubernetesTrustCertificates(String kubernetesTrustCertificates) {
+ if (kubernetesTrustCertificates != null) {
+ this.kubernetesTrustCertificates = Boolean.parseBoolean(kubernetesTrustCertificates);
+ }
+ }
+
+ public boolean isKubernetesDisableHostnameVerification() {
+ return kubernetesDisableHostnameVerification;
+ }
+
+ public void setKubernetesDisableHostnameVerification(String kubernetesDisableHostnameVerification) {
+ if (kubernetesDisableHostnameVerification != null) {
+ this.kubernetesDisableHostnameVerification = Boolean.parseBoolean(kubernetesDisableHostnameVerification);
+ }
+ }
+
+ public String getKubernetesCertsCaFile() {
+ return kubernetesCertsCaFile;
+ }
+
+ public void setKubernetesCertsCaFile(String kubernetesCertsCaFile) {
+ this.kubernetesCertsCaFile = kubernetesCertsCaFile;
+ }
+
+ public String getKubernetesCertsCaData() {
+ return kubernetesCertsCaData;
+ }
+
+ public void setKubernetesCertsCaData(String kubernetesCertsCaData) {
+ this.kubernetesCertsCaData = kubernetesCertsCaData;
+ }
+
+ public String getKubernetesCertsClientFile() {
+ return kubernetesCertsClientFile;
+ }
+
+ public void setKubernetesCertsClientFile(String kubernetesCertsClientFile) {
+ this.kubernetesCertsClientFile = kubernetesCertsClientFile;
+ }
+
+ public String getKubernetesCertsClientData() {
+ return kubernetesCertsClientData;
+ }
+
+ public void setKubernetesCertsClientData(String kubernetesCertsClientData) {
+ this.kubernetesCertsClientData = kubernetesCertsClientData;
+ }
+
+ public String getKubernetesCertsClientKeyFile() {
+ return kubernetesCertsClientKeyFile;
+ }
+
+ public void setKubernetesCertsClientKeyFile(String kubernetesCertsClientKeyFile) {
+ this.kubernetesCertsClientKeyFile = kubernetesCertsClientKeyFile;
+ }
+
+ public String getKubernetesCertsClientKeyData() {
+ return kubernetesCertsClientKeyData;
+ }
+
+ public void setKubernetesCertsClientKeyData(String kubernetesCertsClientKeyData) {
+ this.kubernetesCertsClientKeyData = kubernetesCertsClientKeyData;
+ }
+
+ public String getKubernetesCertsClientKeyAlgo() {
+ return kubernetesCertsClientKeyAlgo;
+ }
+
+ public void setKubernetesCertsClientKeyAlgo(String kubernetesCertsClientKeyAlgo) {
+ this.kubernetesCertsClientKeyAlgo = kubernetesCertsClientKeyAlgo;
+ }
+
+ public String getKubernetesCertsClientKeyPassphrase() {
+ return kubernetesCertsClientKeyPassphrase;
+ }
+
+ public void setKubernetesCertsClientKeyPassphrase(String kubernetesCertsClientKeyPassphrase) {
+ this.kubernetesCertsClientKeyPassphrase = kubernetesCertsClientKeyPassphrase;
+ }
+
+ public String getKubernetesAuthBasicUsername() {
+ return kubernetesAuthBasicUsername;
+ }
+
+ public void setKubernetesAuthBasicUsername(String kubernetesAuthBasicUsername) {
+ this.kubernetesAuthBasicUsername = kubernetesAuthBasicUsername;
+ }
+
+ public String getKubernetesAuthBasicPassword() {
+ return kubernetesAuthBasicPassword;
+ }
+
+ public void setKubernetesAuthBasicPassword(String kubernetesAuthBasicPassword) {
+ this.kubernetesAuthBasicPassword = kubernetesAuthBasicPassword;
+ }
+
+ public String getKubernetesOauthToken() {
+ return kubernetesOauthToken;
+ }
+
+ public void setKubernetesOauthToken(String kubernetesOauthToken) {
+ this.kubernetesOauthToken = kubernetesOauthToken;
+ }
+
+ public int getKubernetesWatchReconnectInterval() {
+ return kubernetesWatchReconnectInterval;
+ }
+
+ public void setKubernetesWatchReconnectInterval(String kubernetesWatchReconnectInterval) {
+ if (kubernetesWatchReconnectInterval != null) {
+ this.kubernetesWatchReconnectInterval = Integer.parseInt(kubernetesWatchReconnectInterval);
+ }
+ }
+
+ public int getKubernetesWatchReconnectLimit() {
+ return kubernetesWatchReconnectLimit;
+ }
+
+ public void setKubernetesWatchReconnectLimit(String kubernetesWatchReconnectLimit) {
+ if (kubernetesWatchReconnectLimit != null) {
+ this.kubernetesWatchReconnectLimit = Integer.parseInt(kubernetesWatchReconnectLimit);
+ }
+ }
+
+ public String getKubernetesUserAgent() {
+ return kubernetesUserAgent;
+ }
+
+ public void setKubernetesUserAgent(String kubernetesUserAgent) {
+ this.kubernetesUserAgent = kubernetesUserAgent;
+ }
+
+ public String getKubernetesTlsVersion() {
+ return kubernetesTlsVersion;
+ }
+
+ public void setKubernetesTlsVersion(String kubernetesTlsVersion) {
+ this.kubernetesTlsVersion = kubernetesTlsVersion;
+ }
+
+ public String getKubernetesTruststoreFile() {
+ return kubernetesTruststoreFile;
+ }
+
+ public void setKubernetesTruststoreFile(String kubernetesTruststoreFile) {
+ this.kubernetesTruststoreFile = kubernetesTruststoreFile;
+ }
+
+ public String getKubernetesTruststorePassphrase() {
+ return kubernetesTruststorePassphrase;
+ }
+
+ public void setKubernetesTruststorePassphrase(String kubernetesTruststorePassphrase) {
+ this.kubernetesTruststorePassphrase = kubernetesTruststorePassphrase;
+ }
+
+ public String getKubernetesKeystoreFile() {
+ return kubernetesKeystoreFile;
+ }
+
+ public void setKubernetesKeystoreFile(String kubernetesKeystoreFile) {
+ this.kubernetesKeystoreFile = kubernetesKeystoreFile;
+ }
+
+ public String getKubernetesKeystorePassphrase() {
+ return kubernetesKeystorePassphrase;
+ }
+
+ public void setKubernetesKeystorePassphrase(String kubernetesKeystorePassphrase) {
+ this.kubernetesKeystorePassphrase = kubernetesKeystorePassphrase;
+ }
}
diff --git a/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryServiceFactory.java b/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryServiceFactory.java
index 0eb7aae..44b73dc 100644
--- a/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryServiceFactory.java
+++ b/kubernetes/src/main/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryServiceFactory.java
@@ -27,6 +27,30 @@
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_API_VERSION;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_AUTH_BASIC_PASSWORD;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_AUTH_BASIC_USERNAME;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_AUTH_TOKEN;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CA_DATA;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CA_FILE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_DATA;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_FILE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_KEY_ALGO;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_KEY_DATA;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_KEY_FILE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_DISABLE_HOSTNAME_VERIFICATION;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_KEYSTORE_FILE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_KEYSTORE_PASSPHRASE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_MASTER;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_TLS_VERSIONS;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_TRUSTSTORE_FILE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_TRUSTSTORE_PASSPHRASE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_TRUST_CERTIFICATES;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_USER_AGENT;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_WATCH_RECONNECTINTERVAL;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_WATCH_RECONNECTLIMIT;
+
/**
* A factory for Kubernetes discovery services.
*/
@@ -39,10 +63,16 @@
private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesDiscoveryServiceFactory.class);
- private static final String KUBERNETES_HOST = "host";
- private static final String KUBERNETES_PORT = "port";
- private static final String KUBERNETES_POD_LABEL_KEY = "pod.label.key";
- private static final String KUBERNETES_POD_LABEL_VALUE = "pod.label.value";
+ // Deprecated constants, use the fabric8 default ones -> see io.fabric8.kubernetes.client.Config
+ @Deprecated
+ static final String KUBERNETES_HOST = "host";
+ @Deprecated
+ static final String KUBERNETES_PORT = "port";
+
+ static final String KUBERNETES_POD_LABEL_KEY = "pod.label.key";
+ static final String KUBERNETES_POD_LABEL_VALUE = "pod.label.value";
+ static final String DEFAULT_POD_LABEL_KEY = "name";
+ static final String DEFAULT_POD_LABEL_VALUE = "cellar";
private final Map<String, ServiceRegistration> registrations = new ConcurrentHashMap<String, ServiceRegistration>();
@@ -86,15 +116,44 @@
}
String kubernetesPodLabelKey = (String) properties.get(KUBERNETES_POD_LABEL_KEY);
if (kubernetesPodLabelKey == null) {
- kubernetesPodLabelKey = "name";
+ kubernetesPodLabelKey = DEFAULT_POD_LABEL_KEY;
}
String kubernetesPodLabelValue = (String) properties.get(KUBERNETES_POD_LABEL_VALUE);
if (kubernetesPodLabelValue == null) {
- kubernetesPodLabelValue = "cellar";
+ kubernetesPodLabelValue = DEFAULT_POD_LABEL_VALUE;
}
- kubernetesDiscoveryService.setKubernetesHost(kubernetesHost);
- kubernetesDiscoveryService.setKubernetesPort(kubernetesPort);
+
+ String kubernetesMaster = KUBERNETES_MASTER.getValue(properties);
+
+ // Keep compatibility with old configuration scheme
+ if (kubernetesMaster == null) {
+ kubernetesMaster = "http://" + kubernetesHost + ":" + kubernetesPort;
+ }
+
+ kubernetesDiscoveryService.setKubernetesMaster(kubernetesMaster);
+ kubernetesDiscoveryService.setKubernetesApiVersion(KUBERNETES_API_VERSION.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesTrustCertificates(KUBERNETES_TRUST_CERTIFICATES.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesDisableHostnameVerification(KUBERNETES_DISABLE_HOSTNAME_VERIFICATION.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesCertsCaFile(KUBERNETES_CERTS_CA_FILE.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesCertsCaData(KUBERNETES_CERTS_CA_DATA.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesCertsClientFile(KUBERNETES_CERTS_CLIENT_FILE.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesCertsClientData(KUBERNETES_CERTS_CLIENT_DATA.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesCertsClientKeyFile(KUBERNETES_CERTS_CLIENT_KEY_FILE.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesCertsClientKeyData(KUBERNETES_CERTS_CLIENT_KEY_DATA.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesCertsClientKeyAlgo(KUBERNETES_CERTS_CLIENT_KEY_ALGO.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesCertsClientKeyPassphrase(KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesAuthBasicUsername(KUBERNETES_AUTH_BASIC_USERNAME.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesAuthBasicPassword(KUBERNETES_AUTH_BASIC_PASSWORD.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesOauthToken(KUBERNETES_AUTH_TOKEN.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesWatchReconnectInterval(KUBERNETES_WATCH_RECONNECTINTERVAL.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesWatchReconnectLimit(KUBERNETES_WATCH_RECONNECTLIMIT.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesUserAgent(KUBERNETES_USER_AGENT.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesTlsVersion(KUBERNETES_TLS_VERSIONS.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesTruststoreFile(KUBERNETES_TRUSTSTORE_FILE.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesTruststorePassphrase(KUBERNETES_TRUSTSTORE_PASSPHRASE.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesKeystoreFile(KUBERNETES_KEYSTORE_FILE.getValue(properties));
+ kubernetesDiscoveryService.setKubernetesKeystorePassphrase(KUBERNETES_KEYSTORE_PASSPHRASE.getValue(properties));
kubernetesDiscoveryService.setKubernetesPodLabelKey(kubernetesPodLabelKey);
kubernetesDiscoveryService.setKubernetesPodLabelValue(kubernetesPodLabelValue);
diff --git a/kubernetes/src/test/java/org/apache/karaf/cellar/kubernetes/ConfigKeyTest.java b/kubernetes/src/test/java/org/apache/karaf/cellar/kubernetes/ConfigKeyTest.java
new file mode 100644
index 0000000..48a9f68
--- /dev/null
+++ b/kubernetes/src/test/java/org/apache/karaf/cellar/kubernetes/ConfigKeyTest.java
@@ -0,0 +1,129 @@
+package org.apache.karaf.cellar.kubernetes;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ConfigKeyTest {
+ private static final String EXPECTED_PROP_VALUE = "properties value";
+ private static final String EXPECTED_SYSPROP_VALUE = "system properties value";
+ private static final String EXPECTED_ENVVAR_VALUE = "envvar value";
+ private Properties originalProperties = new Properties();
+
+ public static class GetValueTestRun {
+
+ public static void main(String[] args) {
+ if (args.length == 0) {
+ System.exit(1);
+ }
+
+ String constantName = args[0];
+ String expectedValue = args[1];
+ ConfigKey key = ConfigKey.valueOf(constantName);
+
+ if (!expectedValue.equals(key.getValue(new Hashtable<>()))) {
+ System.exit(2);
+ }
+ }
+
+ }
+
+ @Before
+ public void setup() {
+ originalProperties.putAll(System.getProperties());
+ }
+
+ @After
+ public void tearDown() {
+ System.setProperties(originalProperties);
+ }
+
+ private void verifyEnvvar(ConfigKey key) throws Exception {
+ startTestProc(key, EXPECTED_ENVVAR_VALUE, null);
+ }
+
+ private void verifySysProp(ConfigKey key) throws Exception {
+ startTestProc(key, EXPECTED_ENVVAR_VALUE, EXPECTED_SYSPROP_VALUE);
+ }
+
+ private void startTestProc(ConfigKey key, String expectedEnvvarValue, String expectedSyspropValue) throws Exception {
+ String expectedValue = expectedSyspropValue == null ? expectedEnvvarValue : expectedSyspropValue;
+
+ String javaHome = System.getProperty("java.home");
+ String extension = System.getProperty("os.name").toLowerCase().contains("windows") ? ".exe" : "";
+ String javaBin = String.format("%s%sbin%sjava%s", javaHome, File.separator, File.separator, extension);
+ String classpath = System.getProperty("java.class.path");
+ List<String> command = new LinkedList<>();
+ command.add(javaBin);
+
+ if (expectedSyspropValue != null) {
+ command.add(String.format("-D%s=%s", key.propertyName, expectedSyspropValue));
+ }
+
+ command.add("-cp");
+ command.add(classpath);
+ command.add(GetValueTestRun.class.getName());
+ command.add(key.name());
+ command.add(expectedValue);
+
+ ProcessBuilder builder = new ProcessBuilder(command);
+ builder.inheritIO();
+ Map<String, String> env = builder.environment();
+ env.put(key.name(), expectedEnvvarValue);
+ Process proc = builder.start();
+ int rc = proc.waitFor();
+
+ if (rc == 1) {
+ Assert.fail("An unexpected exception occurred!");
+ }
+ if (rc == 2) {
+ Assert.fail(String.format("Actual value differs from %s", expectedValue));
+ }
+ }
+
+ @Test
+ public void valueFromEnvvar() throws Exception {
+ for (ConfigKey key : ConfigKey.values()) {
+ verifyEnvvar(key);
+ }
+ }
+
+ @Test
+ public void valueFromSystemProps() throws Exception {
+ for (ConfigKey key : ConfigKey.values()) {
+ verifySysProp(key);
+ }
+ }
+
+ @Test
+ public void valueFromProperties() {
+ for (ConfigKey key : ConfigKey.values()) {
+ System.setProperty(key.propertyName, EXPECTED_SYSPROP_VALUE);
+ Dictionary<String, String> properties = new Hashtable<>();
+ properties.put(key.propertyName, EXPECTED_PROP_VALUE);
+ assertEquals(EXPECTED_PROP_VALUE, key.getValue(properties));
+ }
+ }
+
+ @Test
+ public void verifyConfigKeyUniquelyAssignedToEnvvar() {
+ Set<String> configKeys = new HashSet<>();
+ for (ConfigKey key : ConfigKey.values()) {
+ assertTrue(configKeys.add(key.propertyName));
+ }
+ }
+}
diff --git a/kubernetes/src/test/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryServiceFactoryTest.java b/kubernetes/src/test/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryServiceFactoryTest.java
new file mode 100644
index 0000000..01899c3
--- /dev/null
+++ b/kubernetes/src/test/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryServiceFactoryTest.java
@@ -0,0 +1,175 @@
+package org.apache.karaf.cellar.kubernetes;
+
+import org.apache.karaf.cellar.core.discovery.DiscoveryService;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_API_VERSION;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_AUTH_BASIC_PASSWORD;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_AUTH_BASIC_USERNAME;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_AUTH_TOKEN;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CA_DATA;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CA_FILE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_DATA;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_FILE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_KEY_ALGO;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_KEY_DATA;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_KEY_FILE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_DISABLE_HOSTNAME_VERIFICATION;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_KEYSTORE_FILE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_KEYSTORE_PASSPHRASE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_TLS_VERSIONS;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_TRUSTSTORE_FILE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_TRUSTSTORE_PASSPHRASE;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_TRUST_CERTIFICATES;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_USER_AGENT;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_WATCH_RECONNECTINTERVAL;
+import static org.apache.karaf.cellar.kubernetes.ConfigKey.KUBERNETES_WATCH_RECONNECTLIMIT;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_API_VERSION;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_AUTH_BASIC_PASSWORD;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_AUTH_BASIC_USERNAME;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_CERTS_CA_DATA;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_CERTS_CA_FILE;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_CERTS_CLIENT_DATA;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_CERTS_CLIENT_FILE;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_ALGO;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_DATA;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_FILE;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_DISABLE_HOSTNAME_VERIFICATION;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_KEYSTORE_FILE;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_KEYSTORE_PASSPHRASE;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_MASTER;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_OAUTH_TOKEN;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_TLS_VERSION;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_TRUSTSTORE_FILE;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_TRUSTSTORE_PASSPHRASE;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_TRUST_CERTIFICATES;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_USER_AGENT;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_WATCH_RECONNECT_INTERVAL;
+import static org.apache.karaf.cellar.kubernetes.KubernetesDiscoveryServiceTest.EXPECTED_KUBERNETES_WATCH_RECONNECT_LIMIT;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.newCapture;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertEquals;
+
+public class KubernetesDiscoveryServiceFactoryTest {
+ private static final String ANY_PID = "anyPid";
+ private static final String EXPECTED_POD_LABEL_KEY = "expectedPodLabelKey";
+ private static final String EXPECTED_POD_LABEL_VALUE = "expectedPodLabelValue";
+ private final ServiceRegistration registration = EasyMock.mock(ServiceRegistration.class);
+ private final BundleContext bundleContext = EasyMock.mock(BundleContext.class);
+ private final KubernetesDiscoveryServiceFactory serviceFactory = new KubernetesDiscoveryServiceFactory(bundleContext);
+ private final Dictionary<String, String> properties = new Hashtable<>();
+ private final Capture<Object> serviceCapture = newCapture();
+ private final Capture<Dictionary<String, ?>> servicePropertiesCapture = newCapture();
+ private Dictionary<String, ?> serviceProperties;
+ private KubernetesDiscoveryService registeredService;
+
+ @Before
+ public void setup() throws Exception {
+ expect(bundleContext.registerService(
+ eq(DiscoveryService.class.getName()),
+ capture(serviceCapture),
+ capture(servicePropertiesCapture))).andReturn(registration);
+ replay(bundleContext);
+ }
+
+ private void update() throws Exception {
+ serviceFactory.updated(ANY_PID, properties);
+ this.registeredService = (KubernetesDiscoveryService) serviceCapture.getValue();
+ this.serviceProperties = servicePropertiesCapture.getValue();
+ }
+
+ @Test
+ public void verifyUpdatedOldConfigScheme() throws Exception {
+ properties.put(KubernetesDiscoveryServiceFactory.KUBERNETES_HOST, "foo");
+ properties.put(KubernetesDiscoveryServiceFactory.KUBERNETES_PORT, "55555");
+ update();
+ assertEquals("http://foo:55555", registeredService.getKubernetesMaster());
+ }
+
+ @Test
+ public void verifyUpdatedNewMasterHasPrecedence() throws Exception {
+ properties.put(KubernetesDiscoveryServiceFactory.KUBERNETES_HOST, "foo");
+ properties.put(KubernetesDiscoveryServiceFactory.KUBERNETES_PORT, "55555");
+ properties.put(ConfigKey.KUBERNETES_MASTER.propertyName, EXPECTED_KUBERNETES_MASTER);
+ update();
+ assertEquals(EXPECTED_KUBERNETES_MASTER, registeredService.getKubernetesMaster());
+ }
+
+ @Test
+ public void verifyUpdatedDefaultPodKeyAndLabel() throws Exception {
+ update();
+ assertEquals(KubernetesDiscoveryServiceFactory.DEFAULT_POD_LABEL_KEY, registeredService.getKubernetesPodLabelKey());
+ assertEquals(KubernetesDiscoveryServiceFactory.DEFAULT_POD_LABEL_VALUE, registeredService.getKubernetesPodLabelValue());
+ }
+
+ @Test
+ public void verifyUpdatedPodKeyAndLabel() throws Exception {
+ properties.put(KubernetesDiscoveryServiceFactory.KUBERNETES_POD_LABEL_KEY, EXPECTED_POD_LABEL_KEY);
+ properties.put(KubernetesDiscoveryServiceFactory.KUBERNETES_POD_LABEL_VALUE, EXPECTED_POD_LABEL_VALUE);
+ update();
+ assertEquals(EXPECTED_POD_LABEL_KEY, registeredService.getKubernetesPodLabelKey());
+ assertEquals(EXPECTED_POD_LABEL_VALUE, registeredService.getKubernetesPodLabelValue());
+ }
+
+ @Test
+ public void verifyUpdateKubernetesConfig() throws Exception {
+ properties.put(KUBERNETES_API_VERSION.propertyName, EXPECTED_KUBERNETES_API_VERSION);
+ properties.put(KUBERNETES_TRUST_CERTIFICATES.propertyName, EXPECTED_KUBERNETES_TRUST_CERTIFICATES);
+ properties.put(KUBERNETES_DISABLE_HOSTNAME_VERIFICATION.propertyName, EXPECTED_KUBERNETES_DISABLE_HOSTNAME_VERIFICATION);
+ properties.put(KUBERNETES_CERTS_CA_FILE.propertyName, EXPECTED_KUBERNETES_CERTS_CA_FILE);
+ properties.put(KUBERNETES_CERTS_CA_DATA.propertyName, EXPECTED_KUBERNETES_CERTS_CA_DATA);
+ properties.put(KUBERNETES_CERTS_CLIENT_FILE.propertyName, EXPECTED_KUBERNETES_CERTS_CLIENT_FILE);
+ properties.put(KUBERNETES_CERTS_CLIENT_DATA.propertyName, EXPECTED_KUBERNETES_CERTS_CLIENT_DATA);
+ properties.put(KUBERNETES_CERTS_CLIENT_KEY_FILE.propertyName, EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_FILE);
+ properties.put(KUBERNETES_CERTS_CLIENT_KEY_DATA.propertyName, EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_DATA);
+ properties.put(KUBERNETES_CERTS_CLIENT_KEY_ALGO.propertyName, EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_ALGO);
+ properties.put(KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE.propertyName, EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE);
+ properties.put(KUBERNETES_AUTH_BASIC_USERNAME.propertyName, EXPECTED_KUBERNETES_AUTH_BASIC_USERNAME);
+ properties.put(KUBERNETES_AUTH_BASIC_PASSWORD.propertyName, EXPECTED_KUBERNETES_AUTH_BASIC_PASSWORD);
+ properties.put(KUBERNETES_AUTH_TOKEN.propertyName, EXPECTED_KUBERNETES_OAUTH_TOKEN);
+ properties.put(KUBERNETES_WATCH_RECONNECTINTERVAL.propertyName, EXPECTED_KUBERNETES_WATCH_RECONNECT_INTERVAL);
+ properties.put(KUBERNETES_WATCH_RECONNECTLIMIT.propertyName, EXPECTED_KUBERNETES_WATCH_RECONNECT_LIMIT);
+ properties.put(KUBERNETES_USER_AGENT.propertyName, EXPECTED_KUBERNETES_USER_AGENT);
+ properties.put(KUBERNETES_TLS_VERSIONS.propertyName, EXPECTED_KUBERNETES_TLS_VERSION);
+ properties.put(KUBERNETES_TRUSTSTORE_FILE.propertyName, EXPECTED_KUBERNETES_TRUSTSTORE_FILE);
+ properties.put(KUBERNETES_TRUSTSTORE_PASSPHRASE.propertyName, EXPECTED_KUBERNETES_TRUSTSTORE_PASSPHRASE);
+ properties.put(KUBERNETES_KEYSTORE_FILE.propertyName, EXPECTED_KUBERNETES_KEYSTORE_FILE);
+ properties.put(KUBERNETES_KEYSTORE_PASSPHRASE.propertyName, EXPECTED_KUBERNETES_KEYSTORE_PASSPHRASE);
+ update();
+ assertEquals(EXPECTED_KUBERNETES_API_VERSION, registeredService.getKubernetesApiVersion());
+ assertEquals(Boolean.parseBoolean(EXPECTED_KUBERNETES_TRUST_CERTIFICATES), registeredService.isKubernetesTrustCertificates());
+ assertEquals(Boolean.parseBoolean(EXPECTED_KUBERNETES_DISABLE_HOSTNAME_VERIFICATION), registeredService.isKubernetesDisableHostnameVerification());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CA_FILE, registeredService.getKubernetesCertsCaFile());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CA_DATA, registeredService.getKubernetesCertsCaData());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_FILE, registeredService.getKubernetesCertsClientFile());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_DATA, registeredService.getKubernetesCertsClientData());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_FILE, registeredService.getKubernetesCertsClientKeyFile());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_DATA, registeredService.getKubernetesCertsClientKeyData());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_ALGO, registeredService.getKubernetesCertsClientKeyAlgo());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE, registeredService.getKubernetesCertsClientKeyPassphrase());
+ assertEquals(EXPECTED_KUBERNETES_AUTH_BASIC_USERNAME, registeredService.getKubernetesAuthBasicUsername());
+ assertEquals(EXPECTED_KUBERNETES_AUTH_BASIC_PASSWORD, registeredService.getKubernetesAuthBasicPassword());
+ assertEquals(EXPECTED_KUBERNETES_OAUTH_TOKEN, registeredService.getKubernetesOauthToken());
+ assertEquals(Integer.parseInt(EXPECTED_KUBERNETES_WATCH_RECONNECT_INTERVAL), registeredService.getKubernetesWatchReconnectInterval());
+ assertEquals(Integer.parseInt(EXPECTED_KUBERNETES_WATCH_RECONNECT_LIMIT), registeredService.getKubernetesWatchReconnectLimit());
+ assertEquals(EXPECTED_KUBERNETES_USER_AGENT, registeredService.getKubernetesUserAgent());
+ assertEquals(EXPECTED_KUBERNETES_TLS_VERSION, registeredService.getKubernetesTlsVersion());
+ assertEquals(EXPECTED_KUBERNETES_TRUSTSTORE_FILE, registeredService.getKubernetesTruststoreFile());
+ assertEquals(EXPECTED_KUBERNETES_TRUSTSTORE_PASSPHRASE, registeredService.getKubernetesTruststorePassphrase());
+ assertEquals(EXPECTED_KUBERNETES_KEYSTORE_FILE, registeredService.getKubernetesKeystoreFile());
+ assertEquals(EXPECTED_KUBERNETES_KEYSTORE_PASSPHRASE, registeredService.getKubernetesKeystorePassphrase());
+ }
+}
diff --git a/kubernetes/src/test/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryServiceTest.java b/kubernetes/src/test/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryServiceTest.java
new file mode 100644
index 0000000..e6e792e
--- /dev/null
+++ b/kubernetes/src/test/java/org/apache/karaf/cellar/kubernetes/KubernetesDiscoveryServiceTest.java
@@ -0,0 +1,167 @@
+package org.apache.karaf.cellar.kubernetes;
+
+import io.fabric8.kubernetes.api.model.DoneablePod;
+import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.api.model.PodList;
+import io.fabric8.kubernetes.api.model.PodStatus;
+import io.fabric8.kubernetes.client.Config;
+import io.fabric8.kubernetes.client.KubernetesClient;
+import io.fabric8.kubernetes.client.dsl.MixedOperation;
+import io.fabric8.kubernetes.client.dsl.PodResource;
+import okhttp3.TlsVersion;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.mock;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class KubernetesDiscoveryServiceTest {
+ static final String EXPECTED_KUBERNETES_MASTER = "http://master/";
+ static final String EXPECTED_KUBERNETES_API_VERSION = "api version";
+ static final String EXPECTED_KUBERNETES_TRUST_CERTIFICATES = "true";
+ static final String EXPECTED_KUBERNETES_DISABLE_HOSTNAME_VERIFICATION = "true";
+ static final String EXPECTED_KUBERNETES_CERTS_CA_FILE = "certs ca file";
+ static final String EXPECTED_KUBERNETES_CERTS_CA_DATA = "certs ca data";
+ static final String EXPECTED_KUBERNETES_CERTS_CLIENT_FILE = "certs client file";
+ static final String EXPECTED_KUBERNETES_CERTS_CLIENT_DATA = "certs client data";
+ static final String EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_FILE = "certs client key file";
+ static final String EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_DATA = "certs client key data";
+ static final String EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_ALGO = "certs client key algo";
+ static final String EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE = "certs client key passphrase";
+ static final String EXPECTED_KUBERNETES_AUTH_BASIC_USERNAME = "auth basic username";
+ static final String EXPECTED_KUBERNETES_AUTH_BASIC_PASSWORD = "auth basic password";
+ static final String EXPECTED_KUBERNETES_OAUTH_TOKEN = "oauth token";
+ static final String EXPECTED_KUBERNETES_WATCH_RECONNECT_INTERVAL = "10";
+ static final String EXPECTED_KUBERNETES_WATCH_RECONNECT_LIMIT = "20";
+ static final String EXPECTED_KUBERNETES_USER_AGENT = "user agent";
+ static final String EXPECTED_KUBERNETES_TLS_VERSION = "TLSv1.3";
+ static final String EXPECTED_KUBERNETES_TRUSTSTORE_FILE = "truststore file";
+ static final String EXPECTED_KUBERNETES_TRUSTSTORE_PASSPHRASE = "truststore passphrase";
+ static final String EXPECTED_KUBERNETES_KEYSTORE_FILE = "keystore file";
+ static final String EXPECTED_KUBERNETES_KEYSTORE_PASSPHRASE = "keystore passphrase";
+ static final String EXPECTED_KUBERNETES_POD_LABEL_KEY = "pod label key";
+ static final String EXPECTED_KUBERNETES_POD_LABEL_VALUE = "pod label value";
+ static final String EXPECTED_POD_ID = "192.168.0.1";
+ private KubernetesClient kubernetesClient = mock(KubernetesClient.class);
+ private final MixedOperation<Pod, PodList, DoneablePod, PodResource<Pod, DoneablePod>> pods = mock(MixedOperation.class);
+ private final PodList podList = new PodList();
+ private final KubernetesDiscoveryService service = new KubernetesDiscoveryService();
+ private final Pod pod = new Pod();
+ private final ObjectMeta metadata = new ObjectMeta();
+ private final PodStatus status = new PodStatus();
+ private final List<Pod> items = Arrays.asList(pod);
+ private final Map<String, String> labels = new HashMap<>();
+
+ @Before
+ public void setup() {
+ labels.put(EXPECTED_KUBERNETES_POD_LABEL_KEY, EXPECTED_KUBERNETES_POD_LABEL_VALUE);
+ service.setKubernetesPodLabelKey(EXPECTED_KUBERNETES_POD_LABEL_KEY);
+ service.setKubernetesPodLabelValue(EXPECTED_KUBERNETES_POD_LABEL_VALUE);
+ service.setKubernetesClient(kubernetesClient);
+
+ expect(kubernetesClient.pods()).andReturn(pods);
+ expect(pods.list()).andReturn(podList);
+ podList.setItems(items);
+ pod.setMetadata(metadata);
+ pod.setStatus(status);
+ metadata.setLabels(labels);
+ status.setPodIP(EXPECTED_POD_ID);
+ replay(kubernetesClient, pods);
+ }
+
+ @Test
+ public void createConfig() {
+ service.setKubernetesMaster(EXPECTED_KUBERNETES_MASTER);
+ service.setKubernetesApiVersion(EXPECTED_KUBERNETES_API_VERSION);
+ service.setKubernetesTrustCertificates(EXPECTED_KUBERNETES_TRUST_CERTIFICATES);
+ service.setKubernetesDisableHostnameVerification(EXPECTED_KUBERNETES_DISABLE_HOSTNAME_VERIFICATION);
+ service.setKubernetesCertsCaFile(EXPECTED_KUBERNETES_CERTS_CA_FILE);
+ service.setKubernetesCertsCaData(EXPECTED_KUBERNETES_CERTS_CA_DATA);
+ service.setKubernetesCertsClientFile(EXPECTED_KUBERNETES_CERTS_CLIENT_FILE);
+ service.setKubernetesCertsClientData(EXPECTED_KUBERNETES_CERTS_CLIENT_DATA);
+ service.setKubernetesCertsClientKeyFile(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_FILE);
+ service.setKubernetesCertsClientKeyData(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_DATA);
+ service.setKubernetesCertsClientKeyAlgo(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_ALGO);
+ service.setKubernetesCertsClientKeyPassphrase(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE);
+ service.setKubernetesAuthBasicUsername(EXPECTED_KUBERNETES_AUTH_BASIC_USERNAME);
+ service.setKubernetesAuthBasicPassword(EXPECTED_KUBERNETES_AUTH_BASIC_PASSWORD);
+ service.setKubernetesOauthToken(EXPECTED_KUBERNETES_OAUTH_TOKEN);
+ service.setKubernetesWatchReconnectInterval(EXPECTED_KUBERNETES_WATCH_RECONNECT_INTERVAL);
+ service.setKubernetesWatchReconnectLimit(EXPECTED_KUBERNETES_WATCH_RECONNECT_LIMIT);
+ service.setKubernetesUserAgent(EXPECTED_KUBERNETES_USER_AGENT);
+ service.setKubernetesTlsVersion(EXPECTED_KUBERNETES_TLS_VERSION);
+ service.setKubernetesTruststoreFile(EXPECTED_KUBERNETES_TRUSTSTORE_FILE);
+ service.setKubernetesTruststorePassphrase(EXPECTED_KUBERNETES_TRUSTSTORE_PASSPHRASE);
+ service.setKubernetesKeystoreFile(EXPECTED_KUBERNETES_KEYSTORE_FILE);
+ service.setKubernetesKeystorePassphrase(EXPECTED_KUBERNETES_KEYSTORE_PASSPHRASE);
+
+ Config config = service.createConfig();
+ assertEquals(EXPECTED_KUBERNETES_MASTER, config.getMasterUrl());
+ assertEquals(EXPECTED_KUBERNETES_API_VERSION, config.getApiVersion());
+ assertTrue(config.isTrustCerts());
+ assertTrue(config.isDisableHostnameVerification());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CA_FILE, config.getCaCertFile());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CA_DATA, config.getCaCertData());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_FILE, config.getClientCertFile());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_DATA, config.getClientCertData());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_FILE, config.getClientKeyFile());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_DATA, config.getClientKeyData());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_ALGO, config.getClientKeyAlgo());
+ assertEquals(EXPECTED_KUBERNETES_CERTS_CLIENT_KEY_PASSPHRASE, config.getClientKeyPassphrase());
+ assertEquals(EXPECTED_KUBERNETES_AUTH_BASIC_USERNAME, config.getUsername());
+ assertEquals(EXPECTED_KUBERNETES_AUTH_BASIC_PASSWORD, config.getPassword());
+ assertEquals(EXPECTED_KUBERNETES_OAUTH_TOKEN, config.getOauthToken());
+ assertEquals(Integer.parseInt(EXPECTED_KUBERNETES_WATCH_RECONNECT_INTERVAL), config.getWatchReconnectInterval());
+ assertEquals(Integer.parseInt(EXPECTED_KUBERNETES_WATCH_RECONNECT_LIMIT), config.getWatchReconnectLimit());
+ assertEquals(EXPECTED_KUBERNETES_USER_AGENT, config.getUserAgent());
+
+ TlsVersion[] tlsVersions = config.getTlsVersions();
+ assertEquals(1, tlsVersions.length);
+ assertEquals(TlsVersion.TLS_1_3, tlsVersions[0]);
+
+ assertEquals(EXPECTED_KUBERNETES_TRUSTSTORE_FILE, config.getTrustStoreFile());
+ assertEquals(EXPECTED_KUBERNETES_TRUSTSTORE_PASSPHRASE, config.getTrustStorePassphrase());
+ assertEquals(EXPECTED_KUBERNETES_KEYSTORE_FILE, config.getKeyStoreFile());
+ assertEquals(EXPECTED_KUBERNETES_KEYSTORE_PASSPHRASE, config.getKeyStorePassphrase());
+ }
+
+ @Test
+ public void discoverMembers() {
+ Set<String> memberIps = service.discoverMembers();
+ assertEquals(1, memberIps.size());
+ assertEquals(EXPECTED_POD_ID, memberIps.iterator().next());
+ }
+
+ @Test
+ public void discoverMembersUnexpectedPodLabelKey() {
+ service.setKubernetesPodLabelKey("unexpected");
+ assertTrue(service.discoverMembers().isEmpty());
+ }
+
+ @Test
+ public void discoverMembersUnexpectedPodLabelValue() {
+ service.setKubernetesPodLabelValue("unexpected");
+ assertTrue(service.discoverMembers().isEmpty());
+ }
+
+ @Test
+ public void discoverMembersLogException() {
+ reset(kubernetesClient);
+ expect(kubernetesClient.pods()).andThrow(new RuntimeException("Test exception"));
+ replay(kubernetesClient);
+
+ // Should return empty set because exception was caught and logged
+ assertTrue(service.discoverMembers().isEmpty());
+ }
+}
diff --git a/pom.xml b/pom.xml
index de45bd9..54b4e3e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
- <version>21</version>
+ <version>23</version>
<relativePath />
</parent>
@@ -37,15 +37,15 @@
<properties>
<commons-lang3.version>3.8.1</commons-lang3.version>
<easymock.version>3.4</easymock.version>
- <fabric8.kubernetes-client.version>4.0.5</fabric8.kubernetes-client.version>
+ <fabric8.kubernetes-client.version>4.6.2</fabric8.kubernetes-client.version>
<felix.bundlerepository.version>2.0.10</felix.bundlerepository.version>
<felix.utils.version>1.11.0</felix.utils.version>
<felix.webconsole.version>4.2.14</felix.webconsole.version>
- <hazelcast.version>3.9.4</hazelcast.version>
+ <hazelcast.version>3.12.8</hazelcast.version>
<jclouds.version>1.9.1</jclouds.version>
<joda-time.version>2.10</joda-time.version>
- <junit.version>4.12</junit.version>
- <karaf.version>4.2.1</karaf.version>
+ <junit.version>4.13</junit.version>
+ <karaf.version>4.2.8</karaf.version>
<osgi.version>6.0.0</osgi.version>
<osgi.compendium.version>5.0.0</osgi.compendium.version>
<slf4j.version>1.7.7</slf4j.version>