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 a88d8ec6ce003afba46b482f6c6bd9d065187041 Author: Duncan Grant <[email protected]> AuthorDate: Tue Jun 16 11:34:51 2020 +0100 Deploy basic Helm based cluster --- .../brooklyn/container/entity/helm/HelmDriver.java | 25 ++++ .../brooklyn/container/entity/helm/HelmEntity.java | 49 +++++++ .../container/entity/helm/HelmEntityImpl.java | 71 ++++++++++ .../container/entity/helm/HelmSshDriver.java | 156 +++++++++++++++++++++ .../container/entity/helm/HelmEntityLiveTest.java | 62 ++++++++ 5 files changed, 363 insertions(+) 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 new file mode 100644 index 0000000..52dbbc8 --- /dev/null +++ b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmDriver.java @@ -0,0 +1,25 @@ +/* * 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. + */ +package org.apache.brooklyn.container.entity.helm; + +import org.apache.brooklyn.entity.software.base.SoftwareProcessDriver; + +import java.util.concurrent.Callable; + +public interface HelmDriver extends SoftwareProcessDriver { + Callable getCallable(String command); +} 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 new file mode 100644 index 0000000..e34499f --- /dev/null +++ b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmEntity.java @@ -0,0 +1,49 @@ +/* + * 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. + */ +package org.apache.brooklyn.container.entity.helm; + +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; + +@ImplementedBy(HelmEntityImpl.class) +public interface HelmEntity extends SoftwareProcess { + + public static final ConfigKey<String> REPO_NAME = ConfigKeys.newStringConfigKey( + "repo.name", + "Name to add repo under"); + + public static final ConfigKey<String> REPO_URL = ConfigKeys.newStringConfigKey( + "repo.url", + "Repo url"); + + public static final ConfigKey<String> HELM_TEMPLATE = ConfigKeys.newStringConfigKey( + "helm.template", + "Template name or url"); + + public static final ConfigKey<String> HELM_TEMPLATE_INSTALL_NAME = ConfigKeys.newStringConfigKey( + "helm.template.install.name", + "Kuberentes deployment name"); + + AttributeSensor<String> STATUS = Sensors.newStringSensor("helm.status", + "The results of a status call"); +} 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 new file mode 100644 index 0000000..72ed9f5 --- /dev/null +++ b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmEntityImpl.java @@ -0,0 +1,71 @@ +/* + * 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. + */ +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.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 { + @Override + public Class getDriverInterface() { + return HelmDriver.class; + } + + @Override + public void init() { + super.init(); + } + + @Override + protected void connectSensors() { + super.connectSensors(); + connectServiceUpIsRunning(); + + HelmDriver driver = getDriver(); + Callable status = driver.getCallable("status"); + FunctionPollConfig pollConfig = new FunctionPollConfig<Object, String>(STATUS) + .callable(status); + + addFeed(FunctionFeed.builder() + .entity(this) + .poll(pollConfig) + .period(Duration.FIVE_SECONDS) + .build()); + } + + @Override + protected void disconnectSensors() { + super.disconnectSensors(); + disconnectServiceUpIsRunning(); + } + + @Override + public HelmDriver getDriver() { + return (HelmDriver) super.getDriver(); + } +} 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 new file mode 100644 index 0000000..c8c6728 --- /dev/null +++ b/locations/container/src/main/java/org/apache/brooklyn/container/entity/helm/HelmSshDriver.java @@ -0,0 +1,156 @@ +/* + * 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. + */ +package org.apache.brooklyn.container.entity.helm; + +import com.google.common.collect.ImmutableList; +import org.apache.brooklyn.api.entity.EntityLocal; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.core.entity.EntityInternal; +import org.apache.brooklyn.entity.java.JavaSoftwareProcessSshDriver; +import org.apache.brooklyn.entity.software.base.AbstractSoftwareProcessDriver; +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 java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; +import java.util.concurrent.Callable; + +public class HelmSshDriver extends AbstractSoftwareProcessDriver implements HelmDriver{ + + public HelmSshDriver(EntityLocal entity, Location location) { + super(entity, location); + } + + @Override + public boolean isRunning() { + String helm_name_install_name = getEntity().getConfig(HelmEntity.HELM_TEMPLATE_INSTALL_NAME); + ImmutableList<String> command = ImmutableList.<String>of(String.format("helm status %s", helm_name_install_name)); + OutputStream out = new ByteArrayOutputStream(); + OutputStream err = new ByteArrayOutputStream(); + return 0 == ProcessTool.execProcesses(command, null, null, out, err,";",false, this); + } + + @Override + public void stop() { + String helm_name_install_name = getEntity().getConfig(HelmEntity.HELM_TEMPLATE_INSTALL_NAME); + ImmutableList<String> command = ImmutableList.<String>of(String.format("helm delete %s", helm_name_install_name)); + OutputStream out = new ByteArrayOutputStream(); + OutputStream err = new ByteArrayOutputStream(); + ProcessTool.execProcesses(command, null, null, out, err,";",false, this); + + //TODO Do something with output + } + + @Override + public void runPreInstallCommand() { + + } + + @Override + public void setup() { + + } + + @Override + public void install() { + String repo_name = getEntity().getConfig(HelmEntity.REPO_NAME); + String repo_url = getEntity().getConfig(HelmEntity.REPO_URL); + + String helm_template = getEntity().getConfig(HelmEntity.HELM_TEMPLATE); + String helm_name_install_name = getEntity().getConfig(HelmEntity.HELM_TEMPLATE_INSTALL_NAME); + //TODO Fix string formating + ImmutableList<String> installHelmTemplateCommand = + ImmutableList.<String>of(String.format("helm repo add %s %s", repo_name, repo_url), + String.format("helm install %s %s", helm_name_install_name, helm_template)); + OutputStream out = new ByteArrayOutputStream(); + OutputStream err = new ByteArrayOutputStream(); + ProcessTool.execProcesses(installHelmTemplateCommand, null, null, out, err,";", false, this); + + //TODO Do something with output + } + + @Override + public void runPostInstallCommand() { + + } + + @Override + public void runPreCustomizeCommand() { + + } + + @Override + public void customize() { + + } + + @Override + public void runPostCustomizeCommand() { + + } + + @Override + public void runPreLaunchCommand() { + + } + + @Override + public void launch() { + + } + + @Override + public void runPostLaunchCommand() { + + } + + @Override + protected void createDirectory(String directoryName, String summaryForLogging) { + + } + + @Override + public int copyResource(Map<Object, Object> sshFlags, String sourceUrl, String target, boolean createParentDir) { + return 0; + } + + @Override + public int copyResource(Map<Object, Object> sshFlags, InputStream source, String target, boolean createParentDir) { + return 0; + } + + @Override + public Callable<String> getCallable(String command) { + return new Callable() { + @Override + public Object call() throws Exception { + String helm_name_install_name = getEntity().getConfig(HelmEntity.HELM_TEMPLATE_INSTALL_NAME); + ImmutableList<String> installHelmTemplateCommand = + 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); + } + }; + } +} 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 new file mode 100644 index 0000000..ffd021b --- /dev/null +++ b/locations/container/src/test/java/org/apache/brooklyn/container/entity/helm/HelmEntityLiveTest.java @@ -0,0 +1,62 @@ +/* + * 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. + */ +package org.apache.brooklyn.container.entity.helm; + +import com.google.common.collect.ImmutableList; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.container.location.kubernetes.KubernetesLocation; +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.testng.annotations.Test; + +import java.util.Map; + +import static org.apache.brooklyn.core.entity.EntityAsserts.assertAttributeEqualsEventually; +import static org.testng.Assert.*; + +public class HelmEntityLiveTest extends BrooklynAppLiveTestSupport { + + @Test + public void testSimpleDeploy() throws Exception { + 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(ImmutableList.<Location>of(app.newLocalhostProvisioningLocation())); + + assertAttributeEqualsEventually(andManageChild, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING); + 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); + } +} \ No newline at end of file
