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:17 UTC
[02/11] git commit: Updated NodeJS entity
Updated 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/ef23cc19
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/ef23cc19
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/ef23cc19
Branch: refs/heads/master
Commit: ef23cc19395d8f9b0bf1129635e79a091b7abf5b
Parents: a9ad442
Author: Andrew Kennedy <gr...@apache.org>
Authored: Thu Jul 24 16:49:50 2014 +0100
Committer: Andrew Kennedy <gr...@apache.org>
Committed: Thu Aug 21 14:50:26 2014 +0100
----------------------------------------------------------------------
.../webapp/nodejs/NodeJsWebAppService.java | 26 +++++-
.../webapp/nodejs/NodeJsWebAppServiceImpl.java | 67 ++++++++++++++++
.../nodejs/NodeJsWebAppSoftwareProcess.java | 15 ----
.../nodejs/NodeJsWebAppSoftwareProcessImpl.java | 54 -------------
.../webapp/nodejs/NodeJsWebAppSshDriver.java | 84 ++++++++++++--------
5 files changed, 143 insertions(+), 103 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ef23cc19/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
index 19c8c3e..6ed2580 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppService.java
@@ -1,19 +1,43 @@
package brooklyn.entity.webapp.nodejs;
+import java.util.List;
+
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.proxying.ImplementedBy;
import brooklyn.entity.webapp.WebAppService;
import brooklyn.util.flags.SetFromFlag;
-public interface NodeJsWebAppService extends WebAppService {
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.TypeToken;
+
+@ImplementedBy(NodeJsWebAppServiceImpl.class)
+public interface NodeJsWebAppService extends SoftwareProcess, WebAppService {
+
+ ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "stable");
@SetFromFlag("gitRepoUrl")
ConfigKey<String> APP_GIT_REPOSITORY_URL = ConfigKeys.newStringConfigKey("nodejs.gitRepo.url", "The Git repository where the application is hosted");
+ @SetFromFlag("archiveUrl")
+ ConfigKey<String> APP_ARCHIVE_URL = ConfigKeys.newStringConfigKey("nodejs.archive.url", "The URL where the application archive 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");
+ @SetFromFlag("appCommand")
+ ConfigKey<String> APP_COMMAND = ConfigKeys.newStringConfigKey("nodejs.app.command", "Command to start the NodeJS application", "node");
+
+ @SetFromFlag("nodePackages")
+ ConfigKey<List<String>> NODE_PACKAGE_LIST = ConfigKeys.newConfigKey(new TypeToken<List<String>>() { },
+ "nodejs.packages", "The NPM packages to install", ImmutableList.<String>of());
+
+ ConfigKey<String> SERVICE_UP_PATH = ConfigKeys.newStringConfigKey("nodejs.serviceUp.path", "Path to use when checking the NodeJS application is running", "/");
+
+ Integer getHttpPort();
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ef23cc19/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppServiceImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppServiceImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppServiceImpl.java
new file mode 100644
index 0000000..802727e
--- /dev/null
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppServiceImpl.java
@@ -0,0 +1,67 @@
+package brooklyn.entity.webapp.nodejs;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.SoftwareProcessImpl;
+import brooklyn.entity.webapp.WebAppServiceMethods;
+import brooklyn.event.feed.http.HttpFeed;
+import brooklyn.event.feed.http.HttpPollConfig;
+import brooklyn.event.feed.http.HttpValueFunctions;
+
+import com.google.common.base.Predicates;
+
+public class NodeJsWebAppServiceImpl extends SoftwareProcessImpl implements NodeJsWebAppService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NodeJsWebAppService.class);
+
+ private transient HttpFeed httpFeed;
+
+ @Override
+ public Class<?> getDriverInterface() {
+ return NodeJsWebAppDriver.class;
+ }
+
+ @Override
+ public NodeJsWebAppDriver getDriver() {
+ return (NodeJsWebAppDriver) super.getDriver();
+ }
+
+ @Override
+ protected void connectSensors() {
+ super.connectSensors();
+
+ String nodeJsUrl = WebAppServiceMethods.inferBrooklynAccessibleRootUrl(this);
+ LOG.info("Connecting to {}", nodeJsUrl);
+
+ httpFeed = HttpFeed.builder()
+ .entity(this)
+ .baseUri(nodeJsUrl)
+ .poll(new HttpPollConfig<Boolean>(SERVICE_UP)
+ .suburl(getConfig(NodeJsWebAppService.SERVICE_UP_PATH))
+ .checkSuccess(Predicates.alwaysTrue())
+ .onSuccess(HttpValueFunctions.responseCodeEquals(200))
+ .setOnException(false))
+ .build();
+
+ WebAppServiceMethods.connectWebAppServerPolicies(this);
+ }
+
+ @Override
+ public void disconnectSensors() {
+ if (httpFeed != null) httpFeed.stop();
+ super.disconnectSensors();
+ }
+
+ @Override
+ protected void doStop() {
+ super.doStop();
+
+ setAttribute(REQUESTS_PER_SECOND_LAST, 0D);
+ setAttribute(REQUESTS_PER_SECOND_IN_WINDOW, 0D);
+ }
+
+ @Override
+ public Integer getHttpPort() { return getAttribute(HTTP_PORT); }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ef23cc19/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
deleted file mode 100644
index 999440d..0000000
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSoftwareProcess.java
+++ /dev/null
@@ -1,15 +0,0 @@
-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/ef23cc19/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
deleted file mode 100644
index d0d2207..0000000
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSoftwareProcessImpl.java
+++ /dev/null
@@ -1,54 +0,0 @@
-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/ef23cc19/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
index 611b3b7..f653976 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/nodejs/NodeJsWebAppSshDriver.java
@@ -4,47 +4,52 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
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.MutableList;
import brooklyn.util.collections.MutableMap;
+import brooklyn.util.file.ArchiveUtils;
import brooklyn.util.os.Os;
import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.text.Strings;
-import com.google.common.collect.ImmutableList;
+import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+public class NodeJsWebAppSshDriver extends AbstractSoftwareProcessSshDriver implements NodeJsWebAppDriver {
-public abstract class NodeJsWebAppSshDriver extends AbstractSoftwareProcessSshDriver implements NodeJsWebAppDriver {
+ private static final Logger LOG = LoggerFactory.getLogger(NodeJsWebAppService.class);
- public NodeJsWebAppSshDriver(NodeJsWebAppSoftwareProcessImpl entity, SshMachineLocation machine) {
+ public NodeJsWebAppSshDriver(NodeJsWebAppServiceImpl entity, SshMachineLocation machine) {
super(entity, machine);
}
- public NodeJsWebAppSoftwareProcessImpl getEntity() {
- return (NodeJsWebAppSoftwareProcessImpl) super.getEntity();
+ public NodeJsWebAppServiceImpl getEntity() {
+ return (NodeJsWebAppServiceImpl) super.getEntity();
}
@Override
public Integer getHttpPort() {
- return entity.getAttribute(Attributes.HTTP_PORT);
- }
-
- protected String inferRootUrl() {
- return WebAppServiceMethods.inferBrooklynAccessibleRootUrl(getEntity());
+ return getEntity().getAttribute(Attributes.HTTP_PORT);
}
@Override
public void postLaunch() {
- String rootUrl = inferRootUrl();
+ String rootUrl = String.format("http://%s:%d/", getHostname(), getHttpPort());
entity.setAttribute(WebAppService.ROOT_URL, rootUrl);
}
protected Map<String, Integer> getPortMap() {
- return ImmutableMap.of("httpPort", entity.getAttribute(WebAppService.HTTP_PORT));
+ return ImmutableMap.of("http", getEntity().getAttribute(WebAppService.HTTP_PORT));
}
@Override
@@ -57,15 +62,23 @@ public abstract class NodeJsWebAppSshDriver extends AbstractSoftwareProcessSshDr
@Override
public void install() {
- log.debug("Installing {}", getEntity());
-
- List<String> commands = ImmutableList.<String>builder()
- .add(BashCommands.installPackage(MutableMap.of("yum", "git nodejs npm"), null))
+ List<String> packages = getEntity().getConfig(NodeJsWebAppService.NODE_PACKAGE_LIST);
+ LOG.info("Installing Node.JS {} {}", getEntity().getConfig(SoftwareProcess.SUGGESTED_VERSION), Iterables.toString(packages));
+
+ List<String> commands = MutableList.<String>builder()
+ .add(BashCommands.INSTALL_CURL)
+ .add(BashCommands.ifExecutableElse0("apt-get", BashCommands.chain(
+ BashCommands.installPackage("python-software-properties python g++ make"),
+ BashCommands.sudo("add-apt-repository ppa:chris-lea/node.js"))))
+ .add(BashCommands.installPackage(MutableMap.of("yum", "git nodejs npm", "apt", "git-core nodejs"), 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();
+ if (packages != null && packages.size() > 0) {
+ commands.add(BashCommands.sudo("npm install -g " + Joiner.on(' ').join(packages)));
+ }
+
newScript(INSTALLING)
.body.append(commands)
.execute();
@@ -73,15 +86,21 @@ public abstract class NodeJsWebAppSshDriver extends AbstractSoftwareProcessSshDr
@Override
public void customize() {
- log.debug("Customising {}", getEntity());
+ List<String> commands = Lists.newLinkedList();
- String appUser = getEntity().getConfig(NodeJsWebAppSoftwareProcess.APP_USER);
+ String gitRepoUrl = getEntity().getConfig(NodeJsWebAppService.APP_GIT_REPOSITORY_URL);
+ String archiveUrl = getEntity().getConfig(NodeJsWebAppService.APP_ARCHIVE_URL);
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();
+ if (Strings.isNonBlank(gitRepoUrl) && Strings.isNonBlank(archiveUrl)) {
+ throw new IllegalStateException("Only one of Git or archive URL must be set");
+ } else if (Strings.isNonBlank(gitRepoUrl)) {
+ commands.add(String.format("git clone %s %s", gitRepoUrl, appName));
+ } else if (Strings.isNonBlank(archiveUrl)) {
+ ArchiveUtils.deploy(archiveUrl, getMachine(), getRunDir());
+ } else {
+ throw new IllegalStateException("At least one of Git or archive URL must be set");
+ }
newScript(CUSTOMIZING)
.body.append(commands)
@@ -90,29 +109,28 @@ public abstract class NodeJsWebAppSshDriver extends AbstractSoftwareProcessSshDr
@Override
public void launch() {
- log.debug("Launching {}", getEntity());
+ List<String> commands = Lists.newLinkedList();
- String appUser = getEntity().getConfig(NodeJsWebAppSoftwareProcess.APP_USER);
String appName = getEntity().getConfig(NodeJsWebAppService.APP_NAME);
+ String appFile = getEntity().getConfig(NodeJsWebAppService.APP_FILE);
+ String appCommand = getEntity().getConfig(NodeJsWebAppService.APP_COMMAND);
- 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();
+ commands.add(String.format("cd %s", Os.mergePathsUnix(getRunDir(), appName)));
+ commands.add(BashCommands.sudo("nohup " + appCommand + " " + appFile + " &"));
- newScript(LAUNCHING)
+ newScript(MutableMap.of(USE_PID_FILE, true), LAUNCHING)
.body.append(commands)
.execute();
}
@Override
public boolean isRunning() {
- return newScript(CHECK_RUNNING).execute() == 0;
+ return newScript(MutableMap.of(USE_PID_FILE, true), CHECK_RUNNING).execute() == 0;
}
@Override
public void stop() {
- newScript(STOPPING).execute();
+ newScript(MutableMap.of(USE_PID_FILE, true), STOPPING).execute();
}
@Override