You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by dr...@apache.org on 2017/06/29 15:36:06 UTC
[24/50] [abbrv] brooklyn-server git commit: no_entry: Move kubernetes
classes to new location
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesEmptyMachineLocation.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesEmptyMachineLocation.java b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesEmptyMachineLocation.java
new file mode 100644
index 0000000..8875ef3
--- /dev/null
+++ b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesEmptyMachineLocation.java
@@ -0,0 +1,68 @@
+package io.cloudsoft.amp.containerservice.kubernetes.location.machine;
+
+import java.net.InetAddress;
+import java.util.Set;
+
+import org.apache.brooklyn.api.location.MachineDetails;
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.net.Networking;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * A {@link MachineLocation} represemnting a Kubernetes resource that does not support SSH access.
+ *
+ * @see {@link KubernetesSshMachineLocation}
+ */
+public class KubernetesEmptyMachineLocation extends SshMachineLocation implements KubernetesMachineLocation {
+
+ @Override
+ public String getHostname() {
+ return getResourceName();
+ }
+
+ @Override
+ public Set<String> getPublicAddresses() {
+ return ImmutableSet.of("0.0.0.0");
+ }
+
+ @Override
+ public Set<String> getPrivateAddresses() {
+ return ImmutableSet.of("0.0.0.0");
+ }
+
+ @Override
+ public InetAddress getAddress() {
+ return Networking.getInetAddressWithFixedName("0.0.0.0");
+ }
+
+ @Override
+ public OsDetails getOsDetails() {
+ return null;
+ // throw new UnsupportedOperationException("No OS details for empty KubernetesMachineLocation");
+ }
+
+ @Override
+ public MachineDetails getMachineDetails() {
+ return null;
+ // throw new UnsupportedOperationException("No machine details for empty KubernetesMachineLocation");
+ }
+
+ @Override
+ public String getResourceName() {
+ return config().get(KUBERNETES_RESOURCE_NAME);
+ }
+
+ @Override
+ public String getResourceType() {
+ return config().get(KUBERNETES_RESOURCE_TYPE);
+ }
+
+ @Override
+ public String getNamespace() {
+ return config().get(KUBERNETES_NAMESPACE);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesMachineLocation.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesMachineLocation.java b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesMachineLocation.java
new file mode 100644
index 0000000..6d8838b
--- /dev/null
+++ b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesMachineLocation.java
@@ -0,0 +1,27 @@
+package io.cloudsoft.amp.containerservice.kubernetes.location.machine;
+
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+
+public interface KubernetesMachineLocation extends MachineLocation {
+
+ ConfigKey<String> KUBERNETES_NAMESPACE = ConfigKeys.builder(String.class, "kubernetes.namespace")
+ .description("Namespace for the KubernetesMachineLocation")
+ .build();
+
+ ConfigKey<String> KUBERNETES_RESOURCE_NAME = ConfigKeys.builder(String.class, "kubernetes.name")
+ .description("Name of the resource represented by the KubernetesMachineLocation")
+ .build();
+
+ ConfigKey<String> KUBERNETES_RESOURCE_TYPE = ConfigKeys.builder(String.class, "kubernetes.type")
+ .description("Type of the resource represented by the KubernetesMachineLocation")
+ .build();
+
+ public String getResourceName();
+
+ public String getResourceType();
+
+ public String getNamespace();
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesSshMachineLocation.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesSshMachineLocation.java b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesSshMachineLocation.java
new file mode 100644
index 0000000..ad83f8f
--- /dev/null
+++ b/brooklyn-server/locations/container/src/main/java/org/apache/brooklyn/container/location/kubernetes/machine/KubernetesSshMachineLocation.java
@@ -0,0 +1,28 @@
+package io.cloudsoft.amp.containerservice.kubernetes.location.machine;
+
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+
+/**
+ * A {@link MachineLocation} represemnting a Kubernetes resource that allows SSH access.
+ *
+ * @see {@link KubernetesSshMachineLocation}
+ */
+public class KubernetesSshMachineLocation extends SshMachineLocation implements KubernetesMachineLocation {
+
+ @Override
+ public String getResourceName() {
+ return config().get(KUBERNETES_RESOURCE_NAME);
+ }
+
+ @Override
+ public String getResourceType() {
+ return config().get(KUBERNETES_RESOURCE_TYPE);
+ }
+
+ @Override
+ public String getNamespace() {
+ return config().get(KUBERNETES_NAMESPACE);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/ImageChooserTest.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/ImageChooserTest.java b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/ImageChooserTest.java
new file mode 100644
index 0000000..8f28929
--- /dev/null
+++ b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/ImageChooserTest.java
@@ -0,0 +1,67 @@
+package io.cloudsoft.amp.containerservice.kubernetes.location;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class ImageChooserTest {
+
+ private ImageChooser chooser;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() {
+ chooser = new ImageChooser();
+ }
+
+ @Test
+ public void testDefault() throws Exception {
+ assertEquals(chooser.chooseImage((String)null, null).get(), "cloudsoft/centos:7");
+ }
+
+ @Test
+ public void testCentos() throws Exception {
+ assertEquals(chooser.chooseImage("cEnToS", null).get(), "cloudsoft/centos:7");
+ }
+
+ @Test
+ public void testCentos7() throws Exception {
+ assertEquals(chooser.chooseImage("cEnToS", "7").get(), "cloudsoft/centos:7");
+ }
+
+ @Test
+ public void testUbnutu() throws Exception {
+ assertEquals(chooser.chooseImage("uBuNtU", null).get(), "cloudsoft/ubuntu:14.04");
+ }
+
+ @Test
+ public void testUbnutu14() throws Exception {
+ assertEquals(chooser.chooseImage("uBuNtU", "14.*").get(), "cloudsoft/ubuntu:14.04");
+ }
+
+ @Test
+ public void testUbnutu16() throws Exception {
+ assertEquals(chooser.chooseImage("uBuNtU", "16.*").get(), "cloudsoft/ubuntu:16.04");
+ }
+
+ @Test
+ public void testAbsentForCentos6() throws Exception {
+ assertFalse(chooser.chooseImage("cEnToS", "6").isPresent());
+ }
+
+ @Test
+ public void testAbsentForUbuntu15() throws Exception {
+ assertFalse(chooser.chooseImage("uBuNtU", "15").isPresent());
+ }
+
+ @Test
+ public void testAbsentForDebian() throws Exception {
+ assertFalse(chooser.chooseImage("debian", null).isPresent());
+ }
+
+ @Test
+ public void testAbsentForWrongOsFamily() throws Exception {
+ assertFalse(chooser.chooseImage("weirdOsFamily", null).isPresent());
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesCertsTest.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesCertsTest.java b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesCertsTest.java
new file mode 100644
index 0000000..27c1b79
--- /dev/null
+++ b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesCertsTest.java
@@ -0,0 +1,146 @@
+package io.cloudsoft.amp.containerservice.kubernetes.location;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import java.io.File;
+import java.util.List;
+
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.test.LogWatcher;
+import org.apache.brooklyn.test.LogWatcher.EventPredicates;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.text.Identifiers;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+
+public class KubernetesCertsTest {
+
+ private List<File> tempFiles;
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ tempFiles = Lists.newArrayList();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ if (tempFiles != null) {
+ for (File tempFile : tempFiles) {
+ tempFile.delete();
+ }
+ }
+ }
+
+ @Test
+ public void testCertsAbsent() throws Exception {
+ ConfigBag config = ConfigBag.newInstance();
+ KubernetesCerts certs = new KubernetesCerts(config);
+
+ assertFalse(certs.caCertData.isPresent());
+ assertFalse(certs.clientCertData.isPresent());
+ assertFalse(certs.clientKeyData.isPresent());
+ assertFalse(certs.clientKeyAlgo.isPresent());
+ assertFalse(certs.clientKeyPassphrase.isPresent());
+ }
+
+ @Test
+ public void testCertsFromData() throws Exception {
+ ConfigBag config = ConfigBag.newInstance(ImmutableMap.builder()
+ .put(KubernetesLocationConfig.CA_CERT_DATA, "myCaCertData")
+ .put(KubernetesLocationConfig.CLIENT_CERT_DATA, "myClientCertData")
+ .put(KubernetesLocationConfig.CLIENT_KEY_DATA, "myClientKeyData")
+ .put(KubernetesLocationConfig.CLIENT_KEY_ALGO, "myClientKeyAlgo")
+ .put(KubernetesLocationConfig.CLIENT_KEY_PASSPHRASE, "myClientKeyPassphrase")
+ .build());
+ KubernetesCerts certs = new KubernetesCerts(config);
+
+ assertEquals(certs.caCertData.get(), "myCaCertData");
+ assertEquals(certs.clientCertData.get(), "myClientCertData");
+ assertEquals(certs.clientKeyData.get(), "myClientKeyData");
+ assertEquals(certs.clientKeyAlgo.get(), "myClientKeyAlgo");
+ assertEquals(certs.clientKeyPassphrase.get(), "myClientKeyPassphrase");
+ }
+
+ @Test
+ public void testCertsFromFile() throws Exception {
+ ConfigBag config = ConfigBag.newInstance(ImmutableMap.builder()
+ .put(KubernetesLocationConfig.CA_CERT_FILE, newTempFile("myCaCertData").getAbsolutePath())
+ .put(KubernetesLocationConfig.CLIENT_CERT_FILE, newTempFile("myClientCertData").getAbsolutePath())
+ .put(KubernetesLocationConfig.CLIENT_KEY_FILE, newTempFile("myClientKeyData").getAbsolutePath())
+ .build());
+ KubernetesCerts certs = new KubernetesCerts(config);
+
+ assertEquals(certs.caCertData.get(), "myCaCertData");
+ assertEquals(certs.clientCertData.get(), "myClientCertData");
+ assertEquals(certs.clientKeyData.get(), "myClientKeyData");
+ }
+
+ @Test
+ public void testCertsFailsIfConflictingConfig() throws Exception {
+ ConfigBag config = ConfigBag.newInstance(ImmutableMap.builder()
+ .put(KubernetesLocationConfig.CA_CERT_DATA, "myCaCertData")
+ .put(KubernetesLocationConfig.CA_CERT_FILE, newTempFile("differentCaCertData").getAbsolutePath())
+ .build());
+ try {
+ new KubernetesCerts(config);
+ Asserts.shouldHaveFailedPreviously();
+ } catch (Exception e) {
+ Asserts.expectedFailureContains(e, "Duplicate conflicting configuration for caCertData and caCertFile");
+ }
+ }
+
+ @Test
+ public void testCertsWarnsIfConflictingConfig() throws Exception {
+ ConfigBag config = ConfigBag.newInstance(ImmutableMap.builder()
+ .put(KubernetesLocationConfig.CA_CERT_DATA, "myCaCertData")
+ .put(KubernetesLocationConfig.CA_CERT_FILE, newTempFile("myCaCertData").getAbsolutePath())
+ .build());
+
+ String loggerName = KubernetesCerts.class.getName();
+ ch.qos.logback.classic.Level logLevel = ch.qos.logback.classic.Level.WARN;
+ Predicate<ILoggingEvent> filter = EventPredicates.containsMessage("Duplicate (matching) configuration for "
+ + "caCertData and caCertFile (continuing)");
+ LogWatcher watcher = new LogWatcher(loggerName, logLevel, filter);
+
+ watcher.start();
+ KubernetesCerts certs;
+ try {
+ certs = new KubernetesCerts(config);
+ watcher.assertHasEvent();
+ } finally {
+ watcher.close();
+ }
+
+ assertEquals(certs.caCertData.get(), "myCaCertData");
+ }
+
+ @Test
+ public void testCertsFailsIfFileNotFound() throws Exception {
+ ConfigBag config = ConfigBag.newInstance(ImmutableMap.builder()
+ .put(KubernetesLocationConfig.CA_CERT_FILE, "/path/to/fileDoesNotExist-"+Identifiers.makeRandomId(8))
+ .build());
+ try {
+ new KubernetesCerts(config);
+ Asserts.shouldHaveFailedPreviously();
+ } catch (Exception e) {
+ Asserts.expectedFailureContains(e, "not found on classpath or filesystem");
+ }
+ }
+
+ private File newTempFile(String contents) throws Exception {
+ File file = File.createTempFile("KubernetesCertsTest", ".txt");
+ tempFiles.add(file);
+ Files.write(contents, file, Charsets.UTF_8);
+ return file;
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationLiveTest.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationLiveTest.java b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationLiveTest.java
new file mode 100644
index 0000000..4fb416f
--- /dev/null
+++ b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationLiveTest.java
@@ -0,0 +1,226 @@
+package io.cloudsoft.amp.containerservice.kubernetes.location;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.api.location.MachineDetails;
+import org.apache.brooklyn.api.location.OsDetails;
+import org.apache.brooklyn.core.location.BasicMachineDetails;
+import org.apache.brooklyn.core.location.LocationConfigKeys;
+import org.apache.brooklyn.core.location.access.PortForwardManager;
+import org.apache.brooklyn.core.location.access.PortForwardManagerLocationResolver;
+import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.net.HostAndPort;
+
+import io.cloudsoft.amp.containerservice.kubernetes.location.machine.KubernetesMachineLocation;
+import io.cloudsoft.amp.containerservice.kubernetes.location.machine.KubernetesSshMachineLocation;
+
+/**
+/**
+ * Live tests for deploying simple containers. Particularly useful during dev, but not so useful
+ * after that (because assumes the existence of a kubernetes endpoint). It needs configured with
+ * something like:
+ *
+ * {@code -Dtest.amp.kubernetes.endpoint=http://10.104.2.206:8080}).
+ *
+ * The QA Framework is more important for that - hence these tests (trying to be) kept simple
+ * and focused.
+ */
+public class KubernetesLocationLiveTest extends BrooklynAppLiveTestSupport {
+
+ private static final Logger LOG = LoggerFactory.getLogger(KubernetesLocationLiveTest.class);
+
+ public static final String KUBERNETES_ENDPOINT = System.getProperty("test.amp.kubernetes.endpoint", "");
+ public static final String IDENTITY = System.getProperty("test.amp.kubernetes.identity", "");
+ public static final String CREDENTIAL = System.getProperty("test.amp.kubernetes.credential", "");
+
+ protected KubernetesLocation loc;
+ protected List<KubernetesMachineLocation> machines;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ machines = Lists.newCopyOnWriteArrayList();
+ }
+
+ // FIXME: Clear up properly: Test leaves deployment, replicas and pods behind if obtain fails.
+ @AfterMethod(alwaysRun=true)
+ @Override
+ public void tearDown() throws Exception {
+ for (KubernetesMachineLocation machine : machines) {
+ try {
+ loc.release(machine);
+ } catch (Exception e) {
+ LOG.error("Error releasing machine "+machine+" in location "+loc, e);
+ }
+ }
+ super.tearDown();
+ }
+
+ protected KubernetesLocation newKubernetesLocation(Map<String, ?> flags) throws Exception {
+ Map<String,?> allFlags = MutableMap.<String,Object>builder()
+ .put("identity", IDENTITY)
+ .put("credential", CREDENTIAL)
+ .put("endpoint", KUBERNETES_ENDPOINT)
+ .putAll(flags)
+ .build();
+ return (KubernetesLocation) mgmt.getLocationRegistry().getLocationManaged("kubernetes", allFlags);
+ }
+
+ @Test(groups={"Live"})
+ public void testDefault() throws Exception {
+ // Default is "cloudsoft/centos:7"
+ runImage(ImmutableMap.<String, Object>of(), "centos", "7");
+ }
+
+ @Test(groups={"Live"})
+ public void testMatchesCentos() throws Exception {
+ runImage(ImmutableMap.<String, Object>of(KubernetesLocationConfig.OS_FAMILY.getName(), "centos"), "centos", "7");
+ }
+
+ @Test(groups={"Live"})
+ public void testMatchesCentos7() throws Exception {
+ ImmutableMap<String, Object> conf = ImmutableMap.<String, Object>of(
+ KubernetesLocationConfig.OS_FAMILY.getName(), "centos",
+ KubernetesLocationConfig.OS_VERSION_REGEX.getName(), "7.*");
+ runImage(conf, "centos", "7");
+ }
+
+ @Test(groups={"Live"})
+ public void testMatchesUbuntu() throws Exception {
+ runImage(ImmutableMap.<String, Object>of(KubernetesLocationConfig.OS_FAMILY.getName(), "ubuntu"), "ubuntu", "14.04");
+ }
+
+ @Test(groups={"Live"})
+ public void testMatchesUbuntu16() throws Exception {
+ ImmutableMap<String, Object> conf = ImmutableMap.<String, Object>of(
+ KubernetesLocationConfig.OS_FAMILY.getName(), "ubuntu",
+ KubernetesLocationConfig.OS_VERSION_REGEX.getName(), "16.*");
+ runImage(conf, "ubuntu", "16.04");
+ }
+
+ @Test(groups={"Live"})
+ public void testCloudsoftCentos7() throws Exception {
+ runImage(ImmutableMap.of(KubernetesLocationConfig.IMAGE.getName(), "cloudsoft/centos:7"), "centos", "7");
+ }
+
+ @Test(groups={"Live"})
+ public void testCloudsoftUbuntu14() throws Exception {
+ runImage(ImmutableMap.of(KubernetesLocationConfig.IMAGE.getName(), "cloudsoft/ubuntu:14.04"), "ubuntu", "14.04");
+ }
+
+ @Test(groups={"Live"})
+ public void testCloudsoftUbuntu16() throws Exception {
+ runImage(ImmutableMap.of(KubernetesLocationConfig.IMAGE.getName(), "cloudsoft/ubuntu:16.04"), "ubuntu", "16.04");
+ }
+
+ @Test(groups={"Live"})
+ public void testFailsForNonMatching() throws Exception {
+ ImmutableMap<String, Object> conf = ImmutableMap.<String, Object>of(
+ KubernetesLocationConfig.OS_FAMILY.getName(), "weirdOsFamiliy");
+ try {
+ runImage(conf, null, null);
+ Asserts.shouldHaveFailedPreviously();
+ } catch (Exception e) {
+ Asserts.expectedFailureContains(e, "No matching image found");
+ }
+ }
+
+ protected void runImage(Map<String, ?> config, String expectedOs, String expectedVersion) throws Exception {
+ loc = newKubernetesLocation(ImmutableMap.<String, Object>of());
+ SshMachineLocation machine = newContainerMachine(loc, ImmutableMap.<String, Object>builder()
+ .putAll(config)
+ .put(LocationConfigKeys.CALLER_CONTEXT.getName(), app)
+ .build());
+
+ assertTrue(machine.isSshable(), "not sshable machine="+machine);
+ assertOsNameContains(machine, expectedOs, expectedVersion);
+ assertMachinePasswordSecure(machine);
+ }
+
+ @Test(groups={"Live"})
+ protected void testUsesSuppliedLoginPassword() throws Exception {
+ // Because defaulting to "cloudsoft/centos:7", it knows to set the loginUserPassword
+ // on container creation.
+ String password = "myCustomP4ssword";
+ loc = newKubernetesLocation(ImmutableMap.<String, Object>of());
+ SshMachineLocation machine = newContainerMachine(loc, ImmutableMap.<String, Object>builder()
+ .put(KubernetesLocationConfig.LOGIN_USER_PASSWORD.getName(), password)
+ .put(LocationConfigKeys.CALLER_CONTEXT.getName(), app)
+ .build());
+
+ assertTrue(machine.isSshable(), "not sshable machine="+machine);
+ assertEquals(machine.config().get(SshMachineLocation.PASSWORD), password);
+ }
+
+ @Test(groups={"Live"})
+ public void testOpenPorts() throws Exception {
+ List<Integer> inboundPorts = ImmutableList.of(22, 443, 8000, 8081);
+ loc = newKubernetesLocation(ImmutableMap.<String, Object>of());
+ SshMachineLocation machine = newContainerMachine(loc, ImmutableMap.<String, Object>builder()
+ .put(KubernetesLocationConfig.IMAGE.getName(), "cloudsoft/centos:7")
+ .put(KubernetesLocationConfig.LOGIN_USER_PASSWORD.getName(), "p4ssw0rd")
+ .put(KubernetesLocationConfig.INBOUND_PORTS.getName(), inboundPorts)
+ .put(LocationConfigKeys.CALLER_CONTEXT.getName(), app)
+ .build());
+ assertTrue(machine.isSshable());
+
+ String publicHostText = machine.getSshHostAndPort().getHostText();
+ PortForwardManager pfm = (PortForwardManager) mgmt.getLocationRegistry().getLocationManaged(PortForwardManagerLocationResolver.PFM_GLOBAL_SPEC);
+ for (int targetPort : inboundPorts) {
+ HostAndPort mappedPort = pfm.lookup(machine, targetPort);
+ assertNotNull(mappedPort, "no mapping for targetPort "+targetPort);
+ assertEquals(mappedPort.getHostText(), publicHostText);
+ assertTrue(mappedPort.hasPort(), "no port-part in "+mappedPort+" for targetPort "+targetPort);
+ }
+ }
+
+ protected void assertOsNameContains(SshMachineLocation machine, String expectedNamePart, String expectedVersionPart) {
+ MachineDetails machineDetails = app.getExecutionContext()
+ .submit(BasicMachineDetails.taskForSshMachineLocation(machine))
+ .getUnchecked();
+ OsDetails osDetails = machineDetails.getOsDetails();
+ String osName = osDetails.getName();
+ String osVersion = osDetails.getVersion();
+ assertTrue(osName != null && osName.toLowerCase().contains(expectedNamePart), "osDetails="+osDetails);
+ assertTrue(osVersion != null && osVersion.toLowerCase().contains(expectedVersionPart), "osDetails="+osDetails);
+ }
+
+ protected SshMachineLocation newContainerMachine(KubernetesLocation loc, Map<?, ?> flags) throws Exception {
+ KubernetesMachineLocation result = loc.obtain(flags);
+ machines.add(result);
+ assertTrue(result instanceof KubernetesSshMachineLocation);
+ return (SshMachineLocation) result;
+ }
+
+ protected void assertMachinePasswordSecure(SshMachineLocation machine) {
+ String password = machine.config().get(SshMachineLocation.PASSWORD);
+ assertTrue(password.length() > 10, "password="+password);
+ boolean hasUpper = false;
+ boolean hasLower = false;
+ boolean hasNonAlphabetic = false;
+ for (char c : password.toCharArray()) {
+ if (Character.isUpperCase(c)) hasUpper = true;
+ if (Character.isLowerCase(c)) hasLower = true;
+ if (!Character.isAlphabetic(c)) hasNonAlphabetic = true;
+ }
+ assertTrue(hasUpper && hasLower && hasNonAlphabetic, "password="+password);
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationResolverTest.java b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationResolverTest.java
new file mode 100644
index 0000000..acd366b
--- /dev/null
+++ b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationResolverTest.java
@@ -0,0 +1,84 @@
+package io.cloudsoft.amp.containerservice.kubernetes.location;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.core.internal.BrooklynProperties;
+import org.apache.brooklyn.core.test.BrooklynMgmtUnitTestSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class KubernetesLocationResolverTest extends BrooklynMgmtUnitTestSupport {
+
+ private static final Logger LOG = LoggerFactory.getLogger(KubernetesLocationResolverTest.class);
+
+ private BrooklynProperties brooklynProperties;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception {
+ super.setUp();
+ brooklynProperties = mgmt.getBrooklynProperties();
+
+ brooklynProperties.put("brooklyn.location.kubernetes.identity", "kubernetes-id");
+ brooklynProperties.put("brooklyn.location.kubernetes.credential", "kubernetes-cred");
+ }
+
+ @Test
+ public void testGivesCorrectLocationType() {
+ LocationSpec<?> spec = getLocationSpec("kubernetes");
+ assertEquals(spec.getType(), KubernetesLocation.class);
+
+ KubernetesLocation loc = resolve("kubernetes");
+ assertTrue(loc instanceof KubernetesLocation, "loc="+loc);
+ }
+
+ @Test
+ public void testParametersInSpecString() {
+ KubernetesLocation loc = resolve("kubernetes(endpoint=myMasterUrl)");
+ assertEquals(loc.getConfig(KubernetesLocation.MASTER_URL), "myMasterUrl");
+ }
+
+ @Test
+ public void testTakesDotSeparateProperty() {
+ brooklynProperties.put("brooklyn.location.kubernetes.endpoint", "myMasterUrl");
+ KubernetesLocation loc = resolve("kubernetes");
+ assertEquals(loc.getConfig(KubernetesLocation.MASTER_URL), "myMasterUrl");
+ }
+
+ @Test
+ public void testPropertiesPrecedence() {
+ // prefer those in "spec" over everything else
+ brooklynProperties.put("brooklyn.location.named.mykubernetes", "kubernetes:(loginUser=\"loginUser-inSpec\")");
+
+ brooklynProperties.put("brooklyn.location.named.mykubernetes.loginUser", "loginUser-inNamed");
+ brooklynProperties.put("brooklyn.location.kubernetes.loginUser", "loginUser-inDocker");
+
+ // prefer those in "named" over everything else
+ brooklynProperties.put("brooklyn.location.named.mykubernetes.privateKeyFile", "privateKeyFile-inNamed");
+ brooklynProperties.put("brooklyn.location.kubernetes.privateKeyFile", "privateKeyFile-inDocker");
+
+ // prefer those in kubernetes-specific
+ brooklynProperties.put("brooklyn.location.kubernetes.publicKeyFile", "publicKeyFile-inDocker");
+
+ Map<String, Object> conf = resolve("named:mykubernetes").config().getBag().getAllConfig();
+
+ assertEquals(conf.get("loginUser"), "loginUser-inSpec");
+ assertEquals(conf.get("privateKeyFile"), "privateKeyFile-inNamed");
+ assertEquals(conf.get("publicKeyFile"), "publicKeyFile-inDocker");
+ }
+
+ private LocationSpec<?> getLocationSpec(String spec) {
+ LOG.debug("Obtaining location spec '{}'", spec);
+ return mgmt.getLocationRegistry().getLocationSpec(spec).get();
+ }
+
+ private KubernetesLocation resolve(String spec) {
+ LOG.debug("Resolving location spec '{}'", spec);
+ return (KubernetesLocation) mgmt.getLocationRegistry().getLocationManaged(spec);
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationYamlLiveTest.java
----------------------------------------------------------------------
diff --git a/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationYamlLiveTest.java b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationYamlLiveTest.java
new file mode 100644
index 0000000..6c09b16
--- /dev/null
+++ b/brooklyn-server/locations/container/src/test/java/org/apache/brooklyn/container/location/kubernetes/KubernetesLocationYamlLiveTest.java
@@ -0,0 +1,518 @@
+package io.cloudsoft.amp.containerservice.kubernetes.location;
+
+import static com.google.common.base.Predicates.and;
+import static com.google.common.base.Predicates.equalTo;
+import static com.google.common.base.Predicates.not;
+import static com.google.common.base.Predicates.notNull;
+import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationLiveTest.CREDENTIAL;
+import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationLiveTest.IDENTITY;
+import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationLiveTest.KUBERNETES_ENDPOINT;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEquals;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEqualsEventually;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEventually;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEventuallyNonNull;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertEntityHealthy;
+import static org.apache.brooklyn.test.Asserts.succeedsEventually;
+import static org.apache.brooklyn.util.http.HttpAsserts.assertHttpStatusCodeEventuallyEquals;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.location.MachineLocation;
+import org.apache.brooklyn.api.location.MachineProvisioningLocation;
+import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.EntityPredicates;
+import org.apache.brooklyn.core.location.Machines;
+import org.apache.brooklyn.core.network.OnPublicNetworkEnricher;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess;
+import org.apache.brooklyn.entity.software.base.SoftwareProcess;
+import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess;
+import org.apache.brooklyn.entity.stock.BasicStartable;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.net.Networking;
+import org.apache.brooklyn.util.text.Identifiers;
+import org.apache.logging.log4j.util.Strings;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.net.HostAndPort;
+
+import io.cloudsoft.amp.containerservice.dockercontainer.DockerContainer;
+import io.cloudsoft.amp.containerservice.kubernetes.entity.KubernetesPod;
+import io.cloudsoft.amp.containerservice.kubernetes.entity.KubernetesResource;
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.KubernetesClient;
+
+/**
+ * Live tests for deploying simple blueprints. Particularly useful during dev, but not so useful
+ * after that (because assumes the existence of a kubernetes endpoint). It needs configured with
+ * something like:
+ *
+ * {@code -Dtest.amp.kubernetes.endpoint=http://10.104.2.206:8080}).
+ *
+ * The QA Framework is more important for that - hence these tests (trying to be) kept simple
+ * and focused.
+ */
+public class KubernetesLocationYamlLiveTest extends AbstractYamlTest {
+
+ protected KubernetesLocation loc;
+ protected List<MachineLocation> machines;
+ protected String locationYaml;
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ locationYaml = Joiner.on("\n").join(
+ "location:",
+ " kubernetes:",
+ " " + KubernetesLocationConfig.MASTER_URL.getName() + ": \"" + KUBERNETES_ENDPOINT + "\"",
+ " " + (Strings.isBlank(IDENTITY) ? "" : "identity: "+IDENTITY),
+ " " + (Strings.isBlank(CREDENTIAL) ? "" : "credential: "+CREDENTIAL));
+ }
+
+ @Test(groups={"Live"})
+ public void testLoginPasswordOverride() throws Exception {
+ String customPassword = "myDifferentPassword";
+
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + EmptySoftwareProcess.class.getName(),
+ " brooklyn.config:",
+ " provisioning.properties:",
+ " " + KubernetesLocationConfig.LOGIN_USER_PASSWORD.getName() + ": " + customPassword);
+
+ Entity app = createStartWaitAndLogApplication(yaml);
+ EmptySoftwareProcess entity = Iterables.getOnlyElement(Entities.descendantsAndSelf(app, EmptySoftwareProcess.class));
+
+ SshMachineLocation machine = Machines.findUniqueMachineLocation(entity.getLocations(), SshMachineLocation.class).get();
+ assertEquals(machine.config().get(SshMachineLocation.PASSWORD), customPassword);
+ assertTrue(machine.isSshable());
+ }
+
+ @Test(groups={"Live"})
+ public void testNetcatServer() throws Exception {
+ // Runs as root user (hence not `sudo yum install ...`)
+ // breaks if shell.env uses attributeWhenReady, so not doing that - see testNetcatServerWithDslInShellEnv()
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + VanillaSoftwareProcess.class.getName(),
+ " brooklyn.parameters:",
+ " - name: netcat.port",
+ " type: port",
+ " default: 8081",
+ " brooklyn.config:",
+ " install.command: |",
+ " yum install -y nc",
+ " launch.command: |",
+ " echo $MESSAGE | nc -l $NETCAT_PORT &",
+ " echo $! > $PID_FILE",
+ " shell.env:",
+ " MESSAGE: mymessage",
+ " NETCAT_PORT: $brooklyn:attributeWhenReady(\"netcat.port\")",
+ " brooklyn.enrichers:",
+ " - type: " + OnPublicNetworkEnricher.class.getName(),
+ " brooklyn.config:",
+ " " + OnPublicNetworkEnricher.SENSORS.getName() + ":",
+ " - netcat.port");
+
+ Entity app = createStartWaitAndLogApplication(yaml);
+ VanillaSoftwareProcess entity = Iterables.getOnlyElement(Entities.descendantsAndSelf(app, VanillaSoftwareProcess.class));
+
+ String publicMapped = assertAttributeEventuallyNonNull(entity, Sensors.newStringSensor("netcat.endpoint.mapped.public"));
+ HostAndPort publicPort = HostAndPort.fromString(publicMapped);
+
+ assertTrue(Networking.isReachable(publicPort), "publicPort="+publicPort);
+ }
+
+ @Test(groups={"Live"})
+ public void testInterContainerNetworking() throws Exception {
+ String message = "mymessage";
+ int netcatPort = 8081;
+
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + VanillaSoftwareProcess.class.getName(),
+ " name: server1",
+ " brooklyn.parameters:",
+ " - name: netcat.port",
+ " type: port",
+ " default: " + netcatPort,
+ " brooklyn.config:",
+ " install.command: |",
+ " yum install -y nc",
+ " launch.command: |",
+ " echo " + message + " | nc -l " + netcatPort + " > netcat.out &",
+ " echo $! > $PID_FILE",
+ " - type: " + VanillaSoftwareProcess.class.getName(),
+ " name: server2",
+ " brooklyn.config:",
+ " install.command: |",
+ " yum install -y nc",
+ " launch.command: true",
+ " checkRunning.command: true");
+
+ Entity app = createStartWaitAndLogApplication(yaml);
+ Entities.dumpInfo(app);
+
+ Entity server1 = Iterables.find(Entities.descendantsAndSelf(app), EntityPredicates.displayNameEqualTo("server1"));
+ Entity server2 = Iterables.find(Entities.descendantsAndSelf(app), EntityPredicates.displayNameEqualTo("server2"));
+
+ SshMachineLocation machine1 = Machines.findUniqueMachineLocation(server1.getLocations(), SshMachineLocation.class).get();
+ SshMachineLocation machine2 = Machines.findUniqueMachineLocation(server2.getLocations(), SshMachineLocation.class).get();
+
+ String addr1 = server1.sensors().get(Attributes.SUBNET_ADDRESS);
+ String addr2 = server2.sensors().get(Attributes.SUBNET_ADDRESS);
+
+ // Ping between containers
+ int result1 = machine1.execCommands("ping-server2", ImmutableList.of("ping -c 4 " + addr2));
+ int result2 = machine2.execCommands("ping-server1", ImmutableList.of("ping -c 4 " + addr1));
+
+ // Reach netcat port from other container
+ int result3 = machine2.execCommands("nc-to-server1", ImmutableList.of(
+ "echo \"fromServer2\" | nc " + addr1 + " " + netcatPort + " > netcat.out",
+ "cat netcat.out",
+ "grep " + message + " netcat.out"));
+
+ String errMsg = "result1="+result1+"; result2="+result2+"; result3="+result3;
+ assertEquals(result1, 0, errMsg);
+ assertEquals(result2, 0, errMsg);
+ assertEquals(result3, 0, errMsg);
+ }
+
+ @Test(groups={"Live"})
+ public void testTomcatPod() throws Exception {
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + KubernetesPod.class.getName(),
+ " brooklyn.config:",
+ " docker.container.imageName: tomcat",
+ " docker.container.inboundPorts: [ \"8080\" ]");
+
+ runTomcat(yaml, KubernetesPod.class);
+ }
+
+ @Test(groups={"Live"})
+ public void testTomcatPodExtras() throws Exception {
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + KubernetesPod.class.getName(),
+ " brooklyn.config:",
+ " docker.container.imageName: tomcat",
+ " docker.container.inboundPorts: [ \"8080\" ]",
+ " metadata:",
+ " extra: test");
+
+ KubernetesPod entity = runTomcat(yaml, KubernetesPod.class);
+
+ String namespace = entity.sensors().get(KubernetesPod.KUBERNETES_NAMESPACE);
+ String podName = entity.sensors().get(KubernetesPod.KUBERNETES_POD);
+ KubernetesClient client = getClient(entity);
+ Pod pod = client.pods().inNamespace(namespace).withName(podName).get();
+ Map<String, String> labels = pod.getMetadata().getLabels();
+ assertTrue(labels.containsKey("extra"));
+ assertEquals(labels.get("extra"), "test");
+ }
+
+ @Test(groups={"Live"})
+ public void testTomcatContainer() throws Exception {
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + DockerContainer.class.getName(),
+ " brooklyn.config:",
+ " docker.container.imageName: tomcat",
+ " docker.container.inboundPorts: [ \"8080\" ]");
+
+ runTomcat(yaml, DockerContainer.class);
+ }
+
+ /**
+ * Assumes that the container entity uses port 8080.
+ */
+ protected <T extends Entity> T runTomcat(String yaml, Class<T> type) throws Exception {
+ Entity app = createStartWaitAndLogApplication(yaml);
+ T entity = Iterables.getOnlyElement(Entities.descendantsAndSelf(app, type));
+
+ Entities.dumpInfo(app);
+ String publicMapped = assertAttributeEventuallyNonNull(entity, Sensors.newStringSensor("docker.port.8080.mapped.public"));
+ HostAndPort publicPort = HostAndPort.fromString(publicMapped);
+
+ assertReachableEventually(publicPort);
+ assertHttpStatusCodeEventuallyEquals("http://"+publicPort.getHostText()+":"+publicPort.getPort(), 200);
+
+ return entity;
+ }
+
+ @Test(groups={"Live"})
+ public void testWordpressInContainersWithStartableParent() throws Exception {
+ // TODO docker.container.inboundPorts doesn't accept list of ints - need to use quotes
+ String randomId = Identifiers.makeRandomLowercaseId(4);
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + BasicStartable.class.getName(),
+ " brooklyn.children:",
+ " - type: " + DockerContainer.class.getName(),
+ " id: wordpress-mysql",
+ " name: mysql",
+ " brooklyn.config:",
+ " docker.container.imageName: mysql:5.6",
+ " docker.container.inboundPorts:",
+ " - \"3306\"",
+ " docker.container.environment:",
+ " MYSQL_ROOT_PASSWORD: \"password\"",
+ " provisioning.properties:",
+ " deployment: wordpress-mysql-" + randomId,
+ " - type: " + DockerContainer.class.getName(),
+ " id: wordpress",
+ " name: wordpress",
+ " brooklyn.config:",
+ " docker.container.imageName: wordpress:4-apache",
+ " docker.container.inboundPorts:",
+ " - \"80\"",
+ " docker.container.environment:",
+ " WORDPRESS_DB_HOST: \"wordpress-mysql-" + randomId + "\"",
+ " WORDPRESS_DB_PASSWORD: \"password\"",
+ " provisioning.properties:",
+ " deployment: wordpress-" + randomId);
+
+ runWordpress(yaml, randomId);
+ }
+
+ @Test(groups={"Live"})
+ public void testWordpressInPodsWithStartableParent() throws Exception {
+ // TODO docker.container.inboundPorts doesn't accept list of ints - need to use quotes
+ String randomId = Identifiers.makeRandomLowercaseId(4);
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + BasicStartable.class.getName(),
+ " brooklyn.children:",
+ " - type: " + KubernetesPod.class.getName(),
+ " id: wordpress-mysql",
+ " name: mysql",
+ " brooklyn.config:",
+ " docker.container.imageName: mysql:5.6",
+ " docker.container.inboundPorts:",
+ " - \"3306\"",
+ " docker.container.environment:",
+ " MYSQL_ROOT_PASSWORD: \"password\"",
+ " deployment: wordpress-mysql-" + randomId,
+ " - type: " + KubernetesPod.class.getName(),
+ " id: wordpress",
+ " name: wordpress",
+ " brooklyn.config:",
+ " docker.container.imageName: wordpress:4-apache",
+ " docker.container.inboundPorts:",
+ " - \"80\"",
+ " docker.container.environment:",
+ " WORDPRESS_DB_HOST: \"wordpress-mysql-" + randomId + "\"",
+ " WORDPRESS_DB_PASSWORD: \"password\"",
+ " deployment: wordpress-" + randomId);
+
+ runWordpress(yaml, randomId);
+ }
+
+ @Test(groups={"Live"})
+ public void testWordpressInPods() throws Exception {
+ // TODO docker.container.inboundPorts doesn't accept list of ints - need to use quotes
+ String randomId = Identifiers.makeRandomLowercaseId(4);
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + KubernetesPod.class.getName(),
+ " id: wordpress-mysql",
+ " name: mysql",
+ " brooklyn.config:",
+ " docker.container.imageName: mysql:5.6",
+ " docker.container.inboundPorts:",
+ " - \"3306\"",
+ " docker.container.environment:",
+ " MYSQL_ROOT_PASSWORD: \"password\"",
+ " deployment: wordpress-mysql-" + randomId,
+ " - type: " + KubernetesPod.class.getName(),
+ " id: wordpress",
+ " name: wordpress",
+ " brooklyn.config:",
+ " docker.container.imageName: wordpress:4-apache",
+ " docker.container.inboundPorts:",
+ " - \"80\"",
+ " docker.container.environment:",
+ " WORDPRESS_DB_HOST: \"wordpress-mysql-" + randomId + "\"",
+ " WORDPRESS_DB_PASSWORD: \"password\"",
+ " deployment: wordpress-" + randomId);
+
+ runWordpress(yaml, randomId);
+ }
+
+ /**
+ * Assumes that the {@link DockerContainer} entities have display names of "mysql" and "wordpress",
+ * and that they use ports 3306 and 80 respectively.
+ */
+ protected void runWordpress(String yaml, String randomId) throws Exception {
+ Entity app = createStartWaitAndLogApplication(yaml);
+ Entities.dumpInfo(app);
+
+ Iterable<DockerContainer> containers = Entities.descendantsAndSelf(app, DockerContainer.class);
+ DockerContainer mysql = Iterables.find(containers, EntityPredicates.displayNameEqualTo("mysql"));
+ DockerContainer wordpress = Iterables.find(containers, EntityPredicates.displayNameEqualTo("wordpress"));
+
+ String mysqlPublicPort = assertAttributeEventuallyNonNull(mysql, Sensors.newStringSensor("docker.port.3306.mapped.public"));
+ assertReachableEventually(HostAndPort.fromString(mysqlPublicPort));
+ assertAttributeEquals(mysql, KubernetesPod.KUBERNETES_NAMESPACE, "amp");
+ assertAttributeEquals(mysql, KubernetesPod.KUBERNETES_SERVICE, "wordpress-mysql-" + randomId);
+
+ String wordpressPublicPort = assertAttributeEventuallyNonNull(wordpress, Sensors.newStringSensor("docker.port.80.mapped.public"));
+ assertReachableEventually(HostAndPort.fromString(wordpressPublicPort));
+ assertAttributeEquals(wordpress, KubernetesPod.KUBERNETES_NAMESPACE, "amp");
+ assertAttributeEquals(wordpress, KubernetesPod.KUBERNETES_SERVICE, "wordpress-" + randomId);
+
+ // TODO more assertions (e.g. wordpress can successfully reach the database)
+ }
+
+ @Test(groups={"Live"})
+ public void testPod() throws Exception {
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + KubernetesPod.class.getName(),
+ " brooklyn.config:",
+ " docker.container.imageName: tomcat",
+ " docker.container.inboundPorts:",
+ " - \"8080\"",
+ " shell.env:",
+ " CLUSTER_ID: \"id\"",
+ " CLUSTER_TOKEN: \"token\"");
+
+ Entity app = createStartWaitAndLogApplication(yaml);
+ checkPod(app, KubernetesPod.class);
+ }
+
+ /* Test disabled as QA framework AMP does not have catalog entries deployed yet */
+ @Test(groups={"Live"}, enabled=false)
+ public void testPodCatalogEntry() throws Exception {
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: kubernetes-pod-entity",
+ " brooklyn.config:",
+ " docker.container.imageName: tomcat",
+ " docker.container.inboundPorts:",
+ " - \"8080\"",
+ " shell.env:",
+ " CLUSTER_ID: \"id\"",
+ " CLUSTER_TOKEN: \"token\"");
+
+ Entity app = createStartWaitAndLogApplication(yaml);
+ checkPod(app, KubernetesPod.class);
+ }
+
+ protected <T extends Entity> void checkPod(Entity app, Class<T> type) {
+ T container = Iterables.getOnlyElement(Entities.descendantsAndSelf(app, type));
+
+ Entities.dumpInfo(app);
+
+ String publicMapped = assertAttributeEventuallyNonNull(container, Sensors.newStringSensor("docker.port.8080.mapped.public"));
+ HostAndPort publicPort = HostAndPort.fromString(publicMapped);
+
+ assertReachableEventually(publicPort);
+ assertHttpStatusCodeEventuallyEquals("http://"+publicPort.getHostText()+":"+publicPort.getPort(), 200);
+ }
+
+ @Test(groups={"Live"})
+ public void testNginxReplicationController() throws Exception {
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + KubernetesResource.class.getName(),
+ " id: nginx-replication-controller",
+ " name: \"nginx-replication-controller\"",
+ " brooklyn.config:",
+ " resource: classpath://nginx-replication-controller.yaml");
+
+ Entity app = createStartWaitAndLogApplication(yaml);
+ checkNginxResource(app, KubernetesResource.class);
+ }
+
+ protected <T extends Entity> void checkNginxResource(Entity app, Class<T> type) {
+ T entity = Iterables.getOnlyElement(Entities.descendantsAndSelf(app, type));
+
+ Entities.dumpInfo(app);
+
+ assertEntityHealthy(entity);
+ assertAttributeEqualsEventually(entity, KubernetesResource.RESOURCE_NAME, "nginx-replication-controller");
+ assertAttributeEqualsEventually(entity, KubernetesResource.RESOURCE_TYPE, "ReplicationController");
+ assertAttributeEqualsEventually(entity, KubernetesResource.KUBERNETES_NAMESPACE, "default");
+ assertAttributeEventually(entity, SoftwareProcess.ADDRESS, and(notNull(), not(equalTo("0.0.0.0"))));
+ assertAttributeEventually(entity, SoftwareProcess.SUBNET_ADDRESS, and(notNull(), not(equalTo("0.0.0.0"))));
+ }
+
+ @Test(groups={"Live"})
+ public void testNginxService() throws Exception {
+ String yaml = Joiner.on("\n").join(
+ locationYaml,
+ "services:",
+ " - type: " + KubernetesResource.class.getName(),
+ " id: nginx-replication-controller",
+ " name: \"nginx-replication-controller\"",
+ " brooklyn.config:",
+ " resource: classpath://nginx-replication-controller.yaml",
+ " - type: " + KubernetesResource.class.getName(),
+ " id: nginx-service",
+ " name: \"nginx-service\"",
+ " brooklyn.config:",
+ " resource: classpath://nginx-service.yaml");
+ Entity app = createStartWaitAndLogApplication(yaml);
+
+ Iterable<KubernetesResource> resources = Entities.descendantsAndSelf(app, KubernetesResource.class);
+ KubernetesResource nginxReplicationController = Iterables.find(resources, EntityPredicates.displayNameEqualTo("nginx-replication-controller"));
+ KubernetesResource nginxService = Iterables.find(resources, EntityPredicates.displayNameEqualTo("nginx-service"));
+
+ assertEntityHealthy(nginxReplicationController);
+ assertEntityHealthy(nginxService);
+
+ Entities.dumpInfo(app);
+
+ Integer httpPort = assertAttributeEventuallyNonNull(nginxService, Sensors.newIntegerSensor("kubernetes.http.port"));
+ assertEquals(httpPort, Integer.valueOf(80));
+ String httpPublicPort = assertAttributeEventuallyNonNull(nginxService, Sensors.newStringSensor("kubernetes.http.endpoint.mapped.public"));
+ assertReachableEventually(HostAndPort.fromString(httpPublicPort));
+ }
+
+ protected void assertReachableEventually(final HostAndPort hostAndPort) {
+ succeedsEventually(new Runnable() {
+ public void run() {
+ assertTrue(Networking.isReachable(hostAndPort), "publicPort="+hostAndPort);
+ }});
+ }
+
+ public KubernetesClient getClient(Entity entity) {
+ MachineProvisioningLocation location = entity.sensors().get(SoftwareProcess.PROVISIONING_LOCATION);
+ if (location instanceof KubernetesLocation) {
+ KubernetesLocation kubernetes = (KubernetesLocation) location;
+ ConfigBag config = kubernetes.config().getBag();
+ KubernetesClientRegistry registry = kubernetes.config().get(KubernetesLocationConfig.KUBERNETES_CLIENT_REGISTRY);
+ KubernetesClient client = registry.getKubernetesClient(config);
+ return client;
+ }
+ throw new IllegalStateException("Cannot find KubernetesLocation on entity: " + Iterables.toString(entity.getLocations()));
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesPod.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesPod.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesPod.java
deleted file mode 100644
index bf5444d..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesPod.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.entity;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.ImplementedBy;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.BasicConfigInheritance;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.config.MapConfigKey;
-import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.util.math.MathPredicates;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.reflect.TypeToken;
-
-import io.cloudsoft.amp.containerservice.dockercontainer.DockerContainer;
-import io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationConfig;
-
-@ImplementedBy(KubernetesPodImpl.class)
-public interface KubernetesPod extends DockerContainer {
-
- ConfigKey<String> NAMESPACE = KubernetesLocationConfig.NAMESPACE;
-
- ConfigKey<Boolean> PRIVILEGED = KubernetesLocationConfig.PRIVILEGED;
-
- @SuppressWarnings("serial")
- ConfigKey<List<String>> PERSISTENT_VOLUMES = ConfigKeys.builder(new TypeToken<List<String>>() {})
- .name("persistentVolumes")
- .description("Persistent volumes used by the pod")
- .build();
-
- ConfigKey<String> DEPLOYMENT = ConfigKeys.builder(String.class)
- .name("deployment")
- .description("The name of the service the deployed pod will use")
- .build();
-
- ConfigKey<Integer> REPLICAS = ConfigKeys.builder(Integer.class)
- .name("replicas")
- .description("Number of replicas in the pod")
- .constraint(MathPredicates.greaterThanOrEqual(1d))
- .defaultValue(1)
- .build();
-
- @SuppressWarnings("serial")
- ConfigKey<Map<String, String>> SECRETS = ConfigKeys.builder(new TypeToken<Map<String, String>>() {})
- .name("secrets")
- .description("Secrets to be added to the pod")
- .build();
-
- @SuppressWarnings("serial")
- ConfigKey<Map<String, String>> LIMITS = ConfigKeys.builder(new TypeToken<Map<String, String>>() {})
- .name("limits")
- .description("Container resource limits for the pod")
- .build();
-
- MapConfigKey<Object> METADATA = new MapConfigKey.Builder<Object>(Object.class, "metadata")
- .description("Metadata to set on the pod")
- .defaultValue(ImmutableMap.<String, Object>of())
- .typeInheritance(BasicConfigInheritance.DEEP_MERGE)
- .runtimeInheritance(BasicConfigInheritance.NOT_REINHERITED_ELSE_DEEP_MERGE)
- .build();
-
- AttributeSensor<String> KUBERNETES_DEPLOYMENT = Sensors.builder(String.class, "kubernetes.deployment")
- .description("Deployment resources run in")
- .build();
-
- AttributeSensor<String> KUBERNETES_NAMESPACE = Sensors.builder(String.class, "kubernetes.namespace")
- .description("Namespace that resources run in")
- .build();
-
- AttributeSensor<String> KUBERNETES_SERVICE = Sensors.builder(String.class, "kubernetes.service")
- .description("Service that exposes the deployment")
- .build();
-
- AttributeSensor<String> KUBERNETES_POD = Sensors.builder(String.class, "kubernetes.pod")
- .description("Pod running the deployment")
- .build();
-
- String EMPTY = "Empty";
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesPodImpl.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesPodImpl.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesPodImpl.java
deleted file mode 100644
index 2acf734..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesPodImpl.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.entity;
-
-import io.cloudsoft.amp.containerservice.dockercontainer.DockerContainerImpl;
-
-public class KubernetesPodImpl extends DockerContainerImpl implements KubernetesPod {
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesResource.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesResource.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesResource.java
deleted file mode 100644
index 320c924..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesResource.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.entity;
-
-import org.apache.brooklyn.api.entity.ImplementedBy;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.entity.software.base.SoftwareProcess;
-import org.apache.brooklyn.util.core.ResourcePredicates;
-
-@ImplementedBy(KubernetesResourceImpl.class)
-public interface KubernetesResource extends SoftwareProcess {
-
- ConfigKey<String> RESOURCE_FILE = ConfigKeys.builder(String.class)
- .name("resource")
- .description("Kubernetes resource YAML file URI")
- .constraint(ResourcePredicates.urlExists())
- .build();
-
- AttributeSensor<String> RESOURCE_TYPE = Sensors.builder(String.class, "kubernetes.resource.type")
- .description("Kubernetes resource type")
- .build();
-
- AttributeSensor<String> RESOURCE_NAME = Sensors.builder(String.class, "kubernetes.resource.name")
- .description("Kubernetes resource name")
- .build();
-
- AttributeSensor<String> KUBERNETES_NAMESPACE = KubernetesPod.KUBERNETES_NAMESPACE;
-
- String POD = "Pod";
- String DEPLOYMENT = "Deployment";
- String REPLICA_SET = "ReplicaSet";
- String CONFIG_MAP = "ConfigMap";
- String PERSISTENT_VOLUME = "PersistentVolume";
- String SECRET = "Secret";
- String SERVICE = "Service";
- String REPLICATION_CONTROLLER = "ReplicationController";
- String NAMESPACE = "Namespace";
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesResourceImpl.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesResourceImpl.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesResourceImpl.java
deleted file mode 100644
index 3e7dad3..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/entity/KubernetesResourceImpl.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.entity;
-
-import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
-import org.apache.brooklyn.entity.software.base.EmptySoftwareProcessImpl;
-
-public class KubernetesResourceImpl extends EmptySoftwareProcessImpl implements KubernetesResource {
-
- @Override
- public void init() {
- super.init();
-
- config().set(BrooklynConfigKeys.SKIP_ON_BOX_BASE_DIR_RESOLUTION, true);
- config().set(PROVISIONING_PROPERTIES.subKey("useJcloudsSshInit"), false);
- config().set(PROVISIONING_PROPERTIES.subKey("waitForSshable"), false);
- config().set(PROVISIONING_PROPERTIES.subKey("pollForFirstReachableAddress"), false);
- config().set(EmptySoftwareProcessImpl.USE_SSH_MONITORING, false);
- }
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/ImageChooser.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/ImageChooser.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/ImageChooser.java
deleted file mode 100644
index 1bda432..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/ImageChooser.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-import org.jclouds.compute.domain.OsFamily;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-
-public class ImageChooser {
-
- private static final Logger LOG = LoggerFactory.getLogger(ImageChooser.class);
-
- public static class ImageMetadata {
- private final OsFamily osFamily;
- private final String osVersion;
- private final String imageName;
-
- public ImageMetadata(OsFamily osFamily, String osVersion, String imageName) {
- this.osFamily = checkNotNull(osFamily, "osFamily");
- this.osVersion = checkNotNull(osVersion, "osVersion");
- this.imageName = checkNotNull(imageName, "imageName");
- }
-
- public boolean matches(@Nullable OsFamily osFamily, @Nullable String osVersionRegex) {
- if (osFamily != null && osFamily != this.osFamily) return false;
- if (osVersionRegex != null && !osVersion.matches(osVersionRegex)) return false;
- return true;
- }
-
- public String getImageName() {
- return imageName;
- }
- }
-
- private static final List<ImageMetadata> DEFAULT_IMAGES = ImmutableList.of(
- new ImageMetadata(OsFamily.CENTOS, "7", "cloudsoft/centos:7"),
- new ImageMetadata(OsFamily.UBUNTU, "14.04", "cloudsoft/ubuntu:14.04"),
- new ImageMetadata(OsFamily.UBUNTU, "16.04", "cloudsoft/ubuntu:16.04"));
-
- private final List<ImageMetadata> images;
-
- public ImageChooser() {
- this.images = DEFAULT_IMAGES;
- }
-
- public ImageChooser(List<? extends ImageMetadata> images) {
- this.images = ImmutableList.copyOf(images);
- }
-
- public Optional<String> chooseImage(String osFamily, String osVersionRegex) {
- return chooseImage((osFamily == null ? (OsFamily)null : OsFamily.fromValue(osFamily)), osVersionRegex);
- }
-
- public Optional<String> chooseImage(OsFamily osFamily, String osVersionRegex) {
- for (ImageMetadata imageMetadata : images) {
- if (imageMetadata.matches(osFamily, osVersionRegex)) {
- String imageName = imageMetadata.getImageName();
- LOG.debug("Choosing container image {}, for osFamily={} and osVersionRegex={}", new Object[] {imageName, osFamily, osVersionRegex});
- return Optional.of(imageName);
- }
- }
- return Optional.absent();
- }
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesCerts.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesCerts.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesCerts.java
deleted file mode 100644
index 9bb840f..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesCerts.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location;
-
-import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationConfig.CA_CERT_DATA;
-import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationConfig.CA_CERT_FILE;
-import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationConfig.CLIENT_CERT_DATA;
-import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationConfig.CLIENT_CERT_FILE;
-import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationConfig.CLIENT_KEY_ALGO;
-import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationConfig.CLIENT_KEY_DATA;
-import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationConfig.CLIENT_KEY_FILE;
-import static io.cloudsoft.amp.containerservice.kubernetes.location.KubernetesLocationConfig.CLIENT_KEY_PASSPHRASE;
-
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.util.core.ResourceUtils;
-import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.text.Strings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-
-class KubernetesCerts {
-
- private static final Logger LOG = LoggerFactory.getLogger(KubernetesCerts.class);
-
- public final Optional<String> caCertData;
- public final Optional<String> clientCertData;
- public final Optional<String> clientKeyData;
- public final Optional<String> clientKeyAlgo;
- public final Optional<String> clientKeyPassphrase;
-
- public KubernetesCerts(ConfigBag config) {
- caCertData = getData(CA_CERT_DATA, CA_CERT_FILE, config);
- clientCertData = getData(CLIENT_CERT_DATA, CLIENT_CERT_FILE, config);
- clientKeyData = getData(CLIENT_KEY_DATA, CLIENT_KEY_FILE, config);
- clientKeyAlgo = getNonBlankOptional(CLIENT_KEY_ALGO, config);
- clientKeyPassphrase = getNonBlankOptional(CLIENT_KEY_PASSPHRASE, config);
- }
-
- protected Optional<String> getData(ConfigKey<String> dataKey, ConfigKey<String> fileKey, ConfigBag config) {
- String data = Strings.isNonBlank(config.get(dataKey)) ? config.get(dataKey).trim() : null;
- String file = config.get(fileKey);
- String fileData = Strings.isNonBlank(file) ? getFileContents(file).trim() : null;
-
- if (Strings.isNonBlank(data) && Strings.isNonBlank(fileData)) {
- if (data.equals(fileData)) {
- LOG.warn("Duplicate (matching) configuration for " + dataKey.getName() + " and " + fileKey.getName() + " (continuing)");
- } else {
- throw new IllegalStateException("Duplicate conflicting configuration for " + dataKey.getName() + " and " + fileKey.getName());
- }
- }
-
- String result = Strings.isNonBlank(data) ? data : (Strings.isNonBlank(fileData) ? fileData : null);
- return Optional.fromNullable(result);
- }
-
- protected Optional<String> getNonBlankOptional(ConfigKey<? extends String> key, ConfigBag config) {
- String result = config.get(key);
- return Optional.fromNullable(Strings.isNonBlank(result) ? result : null);
- }
-
- protected String getFileContents(String file) {
- return ResourceUtils.create(this).getResourceAsString(file);
- }
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesClientRegistry.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesClientRegistry.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesClientRegistry.java
deleted file mode 100644
index c240378..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesClientRegistry.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location;
-
-import org.apache.brooklyn.util.core.config.ConfigBag;
-
-import io.fabric8.kubernetes.client.KubernetesClient;
-
-public interface KubernetesClientRegistry {
-
- KubernetesClient getKubernetesClient(ConfigBag conf);
-
-}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/445884b1/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesClientRegistryImpl.java
----------------------------------------------------------------------
diff --git a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesClientRegistryImpl.java b/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesClientRegistryImpl.java
deleted file mode 100644
index 32bfee6..0000000
--- a/kubernetes-location/src/main/java/io/cloudsoft/amp/containerservice/kubernetes/location/KubernetesClientRegistryImpl.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package io.cloudsoft.amp.containerservice.kubernetes.location;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.text.Strings;
-import org.apache.brooklyn.util.time.Duration;
-
-import com.google.common.base.Throwables;
-import com.google.common.io.BaseEncoding;
-
-import io.fabric8.kubernetes.client.ConfigBuilder;
-import io.fabric8.kubernetes.client.DefaultKubernetesClient;
-import io.fabric8.kubernetes.client.KubernetesClient;
-
-public class KubernetesClientRegistryImpl implements KubernetesClientRegistry {
-
- public static final KubernetesClientRegistryImpl INSTANCE = new KubernetesClientRegistryImpl();
-
- @Override
- public KubernetesClient getKubernetesClient(ConfigBag conf) {
- String masterUrl = checkNotNull(conf.get(KubernetesLocationConfig.MASTER_URL), "master url must not be null");
-
- URL url;
- try {
- url = new URL(masterUrl);
- } catch (MalformedURLException e) {
- throw Throwables.propagate(e);
- }
-
- ConfigBuilder configBuilder = new ConfigBuilder()
- .withMasterUrl(masterUrl)
- .withTrustCerts(false);
-
- if (url.getProtocol().equals("https")) {
- KubernetesCerts certs = new KubernetesCerts(conf);
- if (certs.caCertData.isPresent()) configBuilder.withCaCertData(toBase64Encoding(certs.caCertData.get()));
- if (certs.clientCertData.isPresent()) configBuilder.withClientCertData(toBase64Encoding(certs.clientCertData.get()));
- if (certs.clientKeyData.isPresent()) configBuilder.withClientKeyData(toBase64Encoding(certs.clientKeyData.get()));
- if (certs.clientKeyAlgo.isPresent()) configBuilder.withClientKeyAlgo(certs.clientKeyAlgo.get());
- if (certs.clientKeyPassphrase.isPresent()) configBuilder.withClientKeyPassphrase(certs.clientKeyPassphrase.get());
- // TODO Should we also set configBuilder.withTrustCerts(true) here?
- }
-
- String username = conf.get(KubernetesLocationConfig.ACCESS_IDENTITY);
- if (Strings.isNonBlank(username)) configBuilder.withUsername(username);
-
- String password = conf.get(KubernetesLocationConfig.ACCESS_CREDENTIAL);
- if (Strings.isNonBlank(password)) configBuilder.withPassword(password);
-
- String token = conf.get(KubernetesLocationConfig.OAUTH_TOKEN);
- if (Strings.isNonBlank(token)) configBuilder.withOauthToken(token);
-
- Duration clientTimeout = conf.get(KubernetesLocationConfig.CLIENT_TIMEOUT);
- if (clientTimeout.isPositive()) {
- configBuilder.withConnectionTimeout((int) clientTimeout.toMilliseconds());
- configBuilder.withRequestTimeout((int) clientTimeout.toMilliseconds());
- } else {
- throw new IllegalArgumentException("Kubernetes client timeout should be a positive duration: " + clientTimeout.toString());
- }
- Duration actionTimeout = conf.get(KubernetesLocationConfig.ACTION_TIMEOUT);
- if (actionTimeout.isPositive()) {
- configBuilder.withRollingTimeout(actionTimeout.toMilliseconds());
- configBuilder.withScaleTimeout(actionTimeout.toMilliseconds());
- } else {
- throw new IllegalArgumentException("Kubernetes action timeout should be a positive duration: " + actionTimeout.toString());
- }
-
- return new DefaultKubernetesClient(configBuilder.build());
- }
-
- private String toBase64Encoding(String val) {
- return BaseEncoding.base64().encode(val.getBytes());
- }
-}