You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2020/07/08 13:18:13 UTC
[brooklyn-server] 03/20: Add kube sensors
This is an automated email from the ASF dual-hosted git repository.
heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit 0bbafedf754d4c1acf812679bdc9bfdaa3e4419c
Author: Duncan Grant <du...@cloudsoft.io>
AuthorDate: Thu Jun 18 08:47:18 2020 +0100
Add kube sensors
---
.../brooklyn/container/entity/helm/HelmDriver.java | 2 +
.../brooklyn/container/entity/helm/HelmEntity.java | 3 ++
.../container/entity/helm/HelmEntityImpl.java | 33 +++++++++----
.../container/entity/helm/HelmSshDriver.java | 47 +++++++++++++++++-
.../container/entity/helm/HelmEntityLiveTest.java | 55 ++++++++++++++++++----
5 files changed, 121 insertions(+), 19 deletions(-)
diff --git a/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmDriver.java b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmDriver.java
index 52dbbc8..4224f7a 100644
--- a/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmDriver.java
+++ b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmDriver.java
@@ -22,4 +22,6 @@ import java.util.concurrent.Callable;
public interface HelmDriver extends SoftwareProcessDriver {
Callable getCallable(String command);
+
+ Callable getKubeCallable();
}
diff --git a/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmEntity.java b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmEntity.java
index e34499f..0daa865 100644
--- a/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmEntity.java
+++ b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmEntity.java
@@ -46,4 +46,7 @@ public interface HelmEntity extends SoftwareProcess {
AttributeSensor<String> STATUS = Sensors.newStringSensor("helm.status",
"The results of a status call");
+
+ AttributeSensor<Boolean> DEPLOYMENT_READY = Sensors.newBooleanSensor("kube.deployment.status",
+ "The status of the deploymeny");
}
diff --git a/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmEntityImpl.java b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmEntityImpl.java
index 72ed9f5..451d4c1 100644
--- a/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmEntityImpl.java
+++ b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmEntityImpl.java
@@ -18,16 +18,12 @@
*/
package org.apache.brooklyn.container.entity.helm;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.entity.brooklynnode.BrooklynClusterImpl;
-import org.apache.brooklyn.entity.brooklynnode.BrooklynNode;
-import org.apache.brooklyn.entity.software.base.SoftwareProcessDriver;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.entity.software.base.SoftwareProcessImpl;
import org.apache.brooklyn.feed.function.FunctionFeed;
import org.apache.brooklyn.feed.function.FunctionPollConfig;
import org.apache.brooklyn.util.time.Duration;
-import javax.annotation.Nullable;
import java.util.concurrent.Callable;
public class HelmEntityImpl extends SoftwareProcessImpl implements HelmEntity {
@@ -46,10 +42,30 @@ public class HelmEntityImpl extends SoftwareProcessImpl implements HelmEntity {
super.connectSensors();
connectServiceUpIsRunning();
+ addHelmFeed("status", STATUS);
+ addKubernetesFeed();
+ }
+
+ private void addKubernetesFeed() {
+ HelmDriver driver = getDriver();
+ Callable status = driver.getKubeCallable();
+ FunctionPollConfig pollConfig = new FunctionPollConfig<String, Boolean>(DEPLOYMENT_READY)
+ .callable(status)
+ ;
+
+ addFeed(FunctionFeed.builder()
+ .entity(this)
+ .poll(pollConfig)
+ .period(Duration.FIVE_SECONDS)
+ .build());
+ }
+
+ private void addHelmFeed(String command, AttributeSensor<String> sensor) {
HelmDriver driver = getDriver();
- Callable status = driver.getCallable("status");
- FunctionPollConfig pollConfig = new FunctionPollConfig<Object, String>(STATUS)
- .callable(status);
+ Callable status = driver.getCallable(command);
+ FunctionPollConfig pollConfig = new FunctionPollConfig<String, String>(sensor)
+ .callable(status)
+ ;
addFeed(FunctionFeed.builder()
.entity(this)
@@ -58,6 +74,7 @@ public class HelmEntityImpl extends SoftwareProcessImpl implements HelmEntity {
.build());
}
+
@Override
protected void disconnectSensors() {
super.disconnectSensors();
diff --git a/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmSshDriver.java b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmSshDriver.java
index c8c6728..931534f 100644
--- a/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmSshDriver.java
+++ b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmSshDriver.java
@@ -19,8 +19,16 @@
package org.apache.brooklyn.container.entity.helm;
import com.google.common.collect.ImmutableList;
+import io.fabric8.kubernetes.api.model.apps.Deployment;
+import io.fabric8.kubernetes.api.model.apps.DoneableDeployment;
+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.client.dsl.RollableScalableResource;
import org.apache.brooklyn.api.entity.EntityLocal;
import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.container.location.kubernetes.KubernetesLocation;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.entity.java.JavaSoftwareProcessSshDriver;
import org.apache.brooklyn.entity.software.base.AbstractSoftwareProcessDriver;
@@ -28,10 +36,15 @@ import org.apache.brooklyn.entity.software.base.SoftwareProcess;
import org.apache.brooklyn.entity.software.base.SoftwareProcessDriver;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.util.core.internal.ssh.process.ProcessTool;
+import org.apache.brooklyn.util.exceptions.Exceptions;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.Callable;
@@ -149,8 +162,40 @@ public class HelmSshDriver extends AbstractSoftwareProcessDriver implements Helm
ImmutableList.<String>of(String.format("helm %s %s", command, helm_name_install_name));
OutputStream out = new ByteArrayOutputStream();
OutputStream err = new ByteArrayOutputStream();
- return ProcessTool.execProcesses(installHelmTemplateCommand, null, null, out, err,";", false, this);
+ ProcessTool.execProcesses(installHelmTemplateCommand, null, null, out, err,";", false, this);
+ return out.toString();
}
};
}
+
+ @Override
+ public Callable getKubeCallable() {
+ return new Callable() {
+ @Override
+ public Object call() throws Exception {
+ String helm_name_install_name = getEntity().getConfig(HelmEntity.HELM_TEMPLATE_INSTALL_NAME);
+ String config = getLocation().getConfig(KubernetesLocation.KUBECONFIG);
+ KubernetesClient client = getClient(config);
+
+ Deployment deploy = client.apps().deployments().inNamespace("default").withName(helm_name_install_name).get();
+ Integer availableReplicas = deploy.getStatus().getAvailableReplicas();
+ Integer replicas = deploy.getStatus().getReplicas();
+ Boolean ready = availableReplicas.equals(replicas);
+ return ready;
+ } ;
+ };
+ }
+
+ KubernetesClient getClient(String configFile) {
+ Path configPath = Paths.get(configFile);
+ try {
+ Config clientConfig = Config.fromKubeconfig(new String(Files.readAllBytes(configPath)));
+ ConfigBuilder configBuilder = new ConfigBuilder(clientConfig);
+ return new DefaultKubernetesClient(configBuilder.build());
+ }catch (IOException ioe) {
+ Exceptions.propagate(ioe);
+ return null;
+ }
+ }
+
}
diff --git a/locations/container/src/test/java/org/apache/brooklyn/container/entity/helm/HelmEntityLiveTest.java b/locations/container/src/test/java/org/apache/brooklyn/container/entity/helm/HelmEntityLiveTest.java
index ffd021b..7d9a9b8 100644
--- a/locations/container/src/test/java/org/apache/brooklyn/container/entity/helm/HelmEntityLiveTest.java
+++ b/locations/container/src/test/java/org/apache/brooklyn/container/entity/helm/HelmEntityLiveTest.java
@@ -18,7 +18,9 @@
*/
package org.apache.brooklyn.container.entity.helm;
+import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.container.location.kubernetes.KubernetesLocation;
@@ -26,11 +28,14 @@ import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.test.BrooklynAppLiveTestSupport;
import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.time.Duration;
import org.testng.annotations.Test;
+import javax.annotation.Nullable;
import java.util.Map;
import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEqualsEventually;
+import static org.apache.brooklyn.core.entity.EntityAsserts.assertPredicateEventuallyTrue;
import static org.testng.Assert.*;
public class HelmEntityLiveTest extends BrooklynAppLiveTestSupport {
@@ -43,20 +48,50 @@ public class HelmEntityLiveTest extends BrooklynAppLiveTestSupport {
.configure(HelmEntity.HELM_TEMPLATE_INSTALL_NAME, "wordpress-test")
.configure(HelmEntity.HELM_TEMPLATE, "bitnami/wordpress"));
- app.start(ImmutableList.<Location>of(app.newLocalhostProvisioningLocation()));
+ app.start(newLocalhostLocation());
assertAttributeEqualsEventually(andManageChild, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+ assertAttributeEqualsEventually(andManageChild, Attributes.SERVICE_UP, true);
app.stop();
}
- protected KubernetesLocation newKubernetesLocation(Map<String, ?> flags) throws Exception {
- Map<String, ?> allFlags = MutableMap.<String, Object>builder()
- .put("kubeconfig", "/Users/duncangrant/.kube/config")
- .put("image", "cloudsoft/centos:7")
- .put("loginUser", "root")
- .put("loginUser.password", "p4ssw0rd")
- .putAll(flags)
- .build();
- return (KubernetesLocation) mgmt.getLocationRegistry().getLocationManaged("kubernetes", allFlags);
+ @Test
+ public void testCanSenseHelmStatus() {
+ HelmEntity andManageChild = app.createAndManageChild(EntitySpec.create(HelmEntity.class)
+ .configure(HelmEntity.REPO_NAME, "bitnami")
+ .configure(HelmEntity.REPO_URL, "https://charts.bitnami.com/bitnami")
+ .configure(HelmEntity.HELM_TEMPLATE_INSTALL_NAME, "wordpress-test")
+ .configure(HelmEntity.HELM_TEMPLATE, "bitnami/wordpress"));
+
+ app.start(newLocalhostLocation());
+
+ assertPredicateEventuallyTrue(andManageChild, new Predicate<HelmEntity>() {
+ @Override
+ public boolean apply(@Nullable HelmEntity input) {
+ String status = input.getAttribute(HelmEntity.STATUS);
+ return status == null? false : status.contains("STATUS: deployed");
+ }
+ });
+ app.stop();
+ }
+
+ @Test
+ public void testCanSenseDeploymentStatus() {
+ HelmEntity andManageChild = app.createAndManageChild(EntitySpec.create(HelmEntity.class)
+ .configure(HelmEntity.REPO_NAME, "bitnami")
+ .configure(HelmEntity.REPO_URL, "https://charts.bitnami.com/bitnami")
+ .configure(HelmEntity.HELM_TEMPLATE_INSTALL_NAME, "nginx-test")
+ .configure(HelmEntity.HELM_TEMPLATE, "bitnami/nginx"));
+
+ app.start(newLocalhostLocation());
+
+ assertAttributeEqualsEventually(andManageChild, HelmEntity.DEPLOYMENT_READY, true);
+ app.stop();
+ }
+
+ private ImmutableList<Location> newLocalhostLocation() {
+ return ImmutableList.<Location>of(
+ app.newLocalhostProvisioningLocation(
+ ImmutableMap.of(KubernetesLocation.KUBECONFIG, "/Users/duncangrant/.kube/config")));
}
}
\ No newline at end of file