You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by gr...@apache.org on 2014/08/21 18:01:18 UTC
[03/11] git commit: Initial NodeJS entity
Initial NodeJS entity
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/a9ad442d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/a9ad442d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/a9ad442d
Branch: refs/heads/master
Commit: a9ad442de4d5576df24cf81bb4b07d66de3e46ed
Parents: f56233a
Author: Andrew Kennedy <an...@cloudsoftcorp.com>
Authored: Tue Jun 3 22:43:42 2014 +0100
Committer: Andrew Kennedy <gr...@apache.org>
Committed: Thu Aug 21 14:50:26 2014 +0100
----------------------------------------------------------------------
.../webapp/JavaWebAppSoftwareProcessImpl.java | 31 -----
.../entity/webapp/WebAppServiceMethods.java | 52 ++++++--
.../entity/webapp/jboss/JBoss7ServerImpl.java | 5 +-
.../webapp/nodejs/NodeJsWebAppDriver.java | 9 ++
.../webapp/nodejs/NodeJsWebAppService.java | 19 +++
.../nodejs/NodeJsWebAppSoftwareProcess.java | 15 +++
.../nodejs/NodeJsWebAppSoftwareProcessImpl.java | 54 ++++++++
.../webapp/nodejs/NodeJsWebAppSshDriver.java | 125 +++++++++++++++++++
8 files changed, 269 insertions(+), 41 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a9ad442d/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcessImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcessImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcessImpl.java
index 2ea3f48..5c89497 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcessImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcessImpl.java
@@ -34,11 +34,9 @@ import brooklyn.entity.annotation.Effector;
import brooklyn.entity.annotation.EffectorParam;
import brooklyn.entity.basic.SoftwareProcessImpl;
import brooklyn.entity.java.JavaAppUtils;
-import brooklyn.location.access.BrooklynAccessUtils;
import com.google.common.base.Throwables;
import com.google.common.collect.Sets;
-import com.google.common.net.HostAndPort;
public abstract class JavaWebAppSoftwareProcessImpl extends SoftwareProcessImpl implements JavaWebAppService, JavaWebAppSoftwareProcess {
@@ -178,33 +176,4 @@ public abstract class JavaWebAppSoftwareProcessImpl extends SoftwareProcessImpl
setAttribute(REQUESTS_PER_SECOND_LAST, 0D);
setAttribute(REQUESTS_PER_SECOND_IN_WINDOW, 0D);
}
-
- protected Set<String> getEnabledProtocols() {
- return getAttribute(JavaWebAppSoftwareProcess.ENABLED_PROTOCOLS);
- }
-
- protected boolean isProtocolEnabled(String protocol) {
- for (String contender : getEnabledProtocols()) {
- if (protocol.equalsIgnoreCase(contender)) {
- return true;
- }
- }
- return false;
- }
-
- protected String inferBrooklynAccessibleRootUrl() {
- if (isProtocolEnabled("https")) {
- Integer rawPort = getAttribute(HTTPS_PORT);
- checkNotNull(rawPort, "HTTPS_PORT sensors not set for %s; is an acceptable port available?", this);
- HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(this, rawPort);
- return String.format("https://%s:%s/", hp.getHostText(), hp.getPort());
- } else if (isProtocolEnabled("http")) {
- Integer rawPort = getAttribute(HTTP_PORT);
- checkNotNull(rawPort, "HTTP_PORT sensors not set for %s; is an acceptable port available?", this);
- HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(this, rawPort);
- return String.format("http://%s:%s/", hp.getHostText(), hp.getPort());
- } else {
- throw new IllegalStateException("HTTP and HTTPS protocols not enabled for "+this+"; enabled protocols are "+getEnabledProtocols());
- }
- }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a9ad442d/software/webapp/src/main/java/brooklyn/entity/webapp/WebAppServiceMethods.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/WebAppServiceMethods.java b/software/webapp/src/main/java/brooklyn/entity/webapp/WebAppServiceMethods.java
index 7104830..c6fbe29 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/WebAppServiceMethods.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/WebAppServiceMethods.java
@@ -18,36 +18,72 @@
*/
package brooklyn.entity.webapp;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import brooklyn.enricher.RollingTimeWindowMeanEnricher;
import brooklyn.enricher.TimeFractionDeltaEnricher;
import brooklyn.enricher.TimeWeightedDeltaEnricher;
+import brooklyn.entity.Entity;
import brooklyn.entity.basic.EntityLocal;
+import brooklyn.location.access.BrooklynAccessUtils;
import brooklyn.util.time.Duration;
+import com.google.common.net.HostAndPort;
+
public class WebAppServiceMethods implements WebAppServiceConstants {
-
+
public static final Duration DEFAULT_WINDOW_DURATION = Duration.TEN_SECONDS;
-
+
public static void connectWebAppServerPolicies(EntityLocal entity) {
connectWebAppServerPolicies(entity, DEFAULT_WINDOW_DURATION);
}
-
+
public static void connectWebAppServerPolicies(EntityLocal entity, Duration windowPeriod) {
entity.addEnricher(TimeWeightedDeltaEnricher.<Integer>getPerSecondDeltaEnricher(entity, REQUEST_COUNT, REQUESTS_PER_SECOND_LAST));
-
+
if (windowPeriod!=null) {
- entity.addEnricher(new RollingTimeWindowMeanEnricher<Double>(entity, REQUESTS_PER_SECOND_LAST,
+ entity.addEnricher(new RollingTimeWindowMeanEnricher<Double>(entity, REQUESTS_PER_SECOND_LAST,
REQUESTS_PER_SECOND_IN_WINDOW, windowPeriod));
}
-
+
entity.addEnricher(new TimeFractionDeltaEnricher<Integer>(entity, TOTAL_PROCESSING_TIME, PROCESSING_TIME_FRACTION_LAST, TimeUnit.MILLISECONDS));
-
+
if (windowPeriod!=null) {
- entity.addEnricher(new RollingTimeWindowMeanEnricher<Double>(entity, PROCESSING_TIME_FRACTION_LAST,
+ entity.addEnricher(new RollingTimeWindowMeanEnricher<Double>(entity, PROCESSING_TIME_FRACTION_LAST,
PROCESSING_TIME_FRACTION_IN_WINDOW, windowPeriod));
}
}
+
+ public static Set<String> getEnabledProtocols(Entity entity) {
+ return entity.getAttribute(WebAppService.ENABLED_PROTOCOLS);
+ }
+
+ public static boolean isProtocolEnabled(Entity entity, String protocol) {
+ for (String contender : getEnabledProtocols(entity)) {
+ if (protocol.equalsIgnoreCase(contender)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static String inferBrooklynAccessibleRootUrl(Entity entity) {
+ if (isProtocolEnabled(entity, "https")) {
+ Integer rawPort = entity.getAttribute(HTTPS_PORT);
+ checkNotNull(rawPort, "HTTPS_PORT sensors not set for %s; is an acceptable port available?", entity);
+ HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, rawPort);
+ return String.format("https://%s:%s/", hp.getHostText(), hp.getPort());
+ } else if (isProtocolEnabled(entity, "http")) {
+ Integer rawPort = entity.getAttribute(HTTP_PORT);
+ checkNotNull(rawPort, "HTTP_PORT sensors not set for %s; is an acceptable port available?", entity);
+ HostAndPort hp = BrooklynAccessUtils.getBrooklynAccessibleAddress(entity, rawPort);
+ return String.format("http://%s:%s/", hp.getHostText(), hp.getPort());
+ } else {
+ throw new IllegalStateException("HTTP and HTTPS protocols not enabled for "+entity+"; enabled protocols are "+getEnabledProtocols(entity));
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a9ad442d/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
index df59259..2cb1303 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/jboss/JBoss7ServerImpl.java
@@ -27,6 +27,7 @@ import brooklyn.enricher.Enrichers;
import brooklyn.entity.Entity;
import brooklyn.entity.webapp.HttpsSslConfig;
import brooklyn.entity.webapp.JavaWebAppSoftwareProcessImpl;
+import brooklyn.entity.webapp.WebAppServiceMethods;
import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
import brooklyn.event.feed.http.HttpValueFunctions;
@@ -173,11 +174,11 @@ public class JBoss7ServerImpl extends JavaWebAppSoftwareProcessImpl implements J
}
public boolean isHttpEnabled() {
- return isProtocolEnabled("HTTP");
+ return WebAppServiceMethods.isProtocolEnabled(this, "HTTP");
}
public boolean isHttpsEnabled() {
- return isProtocolEnabled("HTTPS");
+ return WebAppServiceMethods.isProtocolEnabled(this, "HTTPS");
}
public Integer getHttpPort() {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a9ad442d/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppDriver.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppDriver.java b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppDriver.java
new file mode 100644
index 0000000..00c908d
--- /dev/null
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppDriver.java
@@ -0,0 +1,9 @@
+package brooklyn.entity.webapp.nodejs;
+
+import brooklyn.entity.basic.SoftwareProcessDriver;
+
+public interface NodeJsWebAppDriver extends SoftwareProcessDriver {
+
+ Integer getHttpPort();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a9ad442d/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java
new file mode 100644
index 0000000..19c8c3e
--- /dev/null
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java
@@ -0,0 +1,19 @@
+package brooklyn.entity.webapp.nodejs;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.webapp.WebAppService;
+import brooklyn.util.flags.SetFromFlag;
+
+public interface NodeJsWebAppService extends WebAppService {
+
+ @SetFromFlag("gitRepoUrl")
+ ConfigKey<String> APP_GIT_REPOSITORY_URL = ConfigKeys.newStringConfigKey("nodejs.gitRepo.url", "The Git repository where the application is hosted");
+
+ @SetFromFlag("appFileName")
+ ConfigKey<String> APP_FILE = ConfigKeys.newStringConfigKey("nodejs.app.fileName", "The NodeJS application file to start", "app.js");
+
+ @SetFromFlag("appName")
+ ConfigKey<String> APP_NAME = ConfigKeys.newStringConfigKey("nodejs.app.name", "The name of the NodeJS application");
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a9ad442d/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSoftwareProcess.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSoftwareProcess.java b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSoftwareProcess.java
new file mode 100644
index 0000000..999440d
--- /dev/null
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSoftwareProcess.java
@@ -0,0 +1,15 @@
+package brooklyn.entity.webapp.nodejs;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.util.flags.SetFromFlag;
+
+public interface NodeJsWebAppSoftwareProcess extends SoftwareProcess, NodeJsWebAppService {
+
+ ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "stable");
+
+ @SetFromFlag("appUser")
+ ConfigKey<String> APP_USER = ConfigKeys.newStringConfigKey("nodejs.app.user", "The user to run the NodeJS application as", "webapp");
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a9ad442d/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSoftwareProcessImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSoftwareProcessImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSoftwareProcessImpl.java
new file mode 100644
index 0000000..d0d2207
--- /dev/null
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSoftwareProcessImpl.java
@@ -0,0 +1,54 @@
+package brooklyn.entity.webapp.nodejs;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.annotation.Effector;
+import brooklyn.entity.annotation.EffectorParam;
+import brooklyn.entity.basic.SoftwareProcessImpl;
+import brooklyn.entity.java.JavaAppUtils;
+import brooklyn.entity.webapp.WebAppServiceMethods;
+import brooklyn.location.access.BrooklynAccessUtils;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Sets;
+import com.google.common.net.HostAndPort;
+
+public abstract class NodeJsWebAppSoftwareProcessImpl extends SoftwareProcessImpl implements NodeJsWebAppSoftwareProcess {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NodeJsWebAppSoftwareProcessImpl.class);
+
+ public NodeJsWebAppSoftwareProcessImpl() {
+ super();
+ }
+
+ @Override
+ protected void connectSensors() {
+ super.connectSensors();
+
+ WebAppServiceMethods.connectWebAppServerPolicies(this);
+ }
+
+ public NodeJsWebAppDriver getDriver() {
+ return (NodeJsWebAppDriver) super.getDriver();
+ }
+
+ @Override
+ protected void doStop() {
+ super.doStop();
+ // zero our workrate derived workrates.
+ // TODO might not be enough, as policy may still be executing and have a record of historic vals; should remove policies
+ // (also not sure we want this; implies more generally a responsibility for sensors to announce things when disconnected,
+ // vs them just showing the last known value...)
+ setAttribute(REQUESTS_PER_SECOND_LAST, 0D);
+ setAttribute(REQUESTS_PER_SECOND_IN_WINDOW, 0D);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a9ad442d/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java
new file mode 100644
index 0000000..611b3b7
--- /dev/null
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java
@@ -0,0 +1,125 @@
+package brooklyn.entity.webapp.nodejs;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.webapp.WebAppService;
+import brooklyn.entity.webapp.WebAppServiceMethods;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.os.Os;
+import brooklyn.util.ssh.BashCommands;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+public abstract class NodeJsWebAppSshDriver extends AbstractSoftwareProcessSshDriver implements NodeJsWebAppDriver {
+
+ public NodeJsWebAppSshDriver(NodeJsWebAppSoftwareProcessImpl entity, SshMachineLocation machine) {
+ super(entity, machine);
+ }
+
+ public NodeJsWebAppSoftwareProcessImpl getEntity() {
+ return (NodeJsWebAppSoftwareProcessImpl) super.getEntity();
+ }
+
+ @Override
+ public Integer getHttpPort() {
+ return entity.getAttribute(Attributes.HTTP_PORT);
+ }
+
+ protected String inferRootUrl() {
+ return WebAppServiceMethods.inferBrooklynAccessibleRootUrl(getEntity());
+ }
+
+ @Override
+ public void postLaunch() {
+ String rootUrl = inferRootUrl();
+ entity.setAttribute(WebAppService.ROOT_URL, rootUrl);
+ }
+
+ protected Map<String, Integer> getPortMap() {
+ return ImmutableMap.of("httpPort", entity.getAttribute(WebAppService.HTTP_PORT));
+ }
+
+ @Override
+ public Set<Integer> getPortsUsed() {
+ return ImmutableSet.<Integer>builder()
+ .addAll(super.getPortsUsed())
+ .addAll(getPortMap().values())
+ .build();
+ }
+
+ @Override
+ public void install() {
+ log.debug("Installing {}", getEntity());
+
+ List<String> commands = ImmutableList.<String>builder()
+ .add(BashCommands.installPackage(MutableMap.of("yum", "git nodejs npm"), null))
+ .add(BashCommands.sudo("npm install -g n"))
+ .add(BashCommands.sudo("n " + getEntity().getConfig(SoftwareProcess.SUGGESTED_VERSION)))
+ .add(BashCommands.sudo("useradd -mrU " + getEntity().getConfig(NodeJsWebAppSoftwareProcess.APP_USER)))
+ .build();
+
+ newScript(INSTALLING)
+ .body.append(commands)
+ .execute();
+ }
+
+ @Override
+ public void customize() {
+ log.debug("Customising {}", getEntity());
+
+ String appUser = getEntity().getConfig(NodeJsWebAppSoftwareProcess.APP_USER);
+ String appName = getEntity().getConfig(NodeJsWebAppService.APP_NAME);
+
+ List<String> commands = ImmutableList.<String>builder()
+ .add(String.format("git clone %s %s", getEntity().getConfig(NodeJsWebAppService.APP_GIT_REPOSITORY_URL), appName))
+ .add(BashCommands.sudo(String.format("chown -R %1$s:%1$s %2$s", appUser, appName)))
+ .build();
+
+ newScript(CUSTOMIZING)
+ .body.append(commands)
+ .execute();
+ }
+
+ @Override
+ public void launch() {
+ log.debug("Launching {}", getEntity());
+
+ String appUser = getEntity().getConfig(NodeJsWebAppSoftwareProcess.APP_USER);
+ String appName = getEntity().getConfig(NodeJsWebAppService.APP_NAME);
+
+ List<String> commands = ImmutableList.<String>builder()
+ .add(String.format("cd %s", Os.mergePathsUnix(getRunDir(), appName)))
+ .add(BashCommands.sudoAsUser(appUser, "nohup node " + getEntity().getConfig(NodeJsWebAppService.APP_FILE) + " &"))
+ .build();
+
+ newScript(LAUNCHING)
+ .body.append(commands)
+ .execute();
+ }
+
+ @Override
+ public boolean isRunning() {
+ return newScript(CHECK_RUNNING).execute() == 0;
+ }
+
+ @Override
+ public void stop() {
+ newScript(STOPPING).execute();
+ }
+
+ @Override
+ public Map<String, String> getShellEnvironment() {
+ return MutableMap.<String, String>builder().putAll(super.getShellEnvironment())
+ .put("PORT", Integer.toString(getHttpPort()))
+ .build();
+ }
+
+}