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 2014/07/29 21:31:58 UTC
[03/31] git commit: tidy initial pull request from @bmwshop,
as per code review, plus some todo comments
tidy initial pull request from @bmwshop, as per code review, plus some todo comments
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/dbf26e3a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/dbf26e3a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/dbf26e3a
Branch: refs/heads/master
Commit: dbf26e3a46afa7a7b25374043a0e0969052d049f
Parents: 9c9f037
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Jul 18 15:38:37 2014 -0400
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Jul 29 10:41:10 2014 -0400
----------------------------------------------------------------------
.../webapp/ControlledDynamicWebAppCluster.java | 25 ++--
.../ControlledDynamicWebAppClusterImpl.java | 114 ++++++++++---------
.../entity/webapp/DynamicWebAppClusterImpl.java | 2 +
.../entity/webapp/JavaWebAppService.java | 66 +++++++++++
.../webapp/JavaWebAppSoftwareProcess.java | 52 +--------
5 files changed, 134 insertions(+), 125 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dbf26e3a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java b/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
index 17fc569..0c263d9 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppCluster.java
@@ -21,8 +21,6 @@ package brooklyn.entity.webapp;
import brooklyn.config.ConfigKey;
import brooklyn.entity.Entity;
import brooklyn.entity.Group;
-import brooklyn.entity.annotation.Effector;
-import brooklyn.entity.annotation.EffectorParam;
import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.ConfigurableEntityFactory;
@@ -59,8 +57,8 @@ import brooklyn.util.flags.SetFromFlag;
* members has no effect on the members of the underlying DynamicCluster - treat this as a read-only view.
*/
@ImplementedBy(ControlledDynamicWebAppClusterImpl.class)
-public interface ControlledDynamicWebAppCluster extends DynamicGroup, Entity, Startable, Resizable, MemberReplaceable, Group, ElasticJavaWebAppService, JavaWebAppSoftwareProcess {
-
+public interface ControlledDynamicWebAppCluster extends DynamicGroup, Entity, Startable, Resizable, MemberReplaceable, Group, ElasticJavaWebAppService, JavaWebAppService.CanDeployAndUndeploy, JavaWebAppService.CanRedeployAll {
+
@SetFromFlag("initialSize")
public static ConfigKey<Integer> INITIAL_SIZE = ConfigKeys.newConfigKeyWithDefault(Cluster.INITIAL_SIZE, 1);
@@ -68,20 +66,24 @@ public interface ControlledDynamicWebAppCluster extends DynamicGroup, Entity, St
public static BasicAttributeSensorAndConfigKey<LoadBalancer> CONTROLLER = new BasicAttributeSensorAndConfigKey<LoadBalancer>(
LoadBalancer.class, "controlleddynamicwebappcluster.controller", "Controller for the cluster; if null a default will created (using controllerSpec)");
+ @SuppressWarnings({ "unchecked", "rawtypes" })
@SetFromFlag("controllerSpec")
public static BasicAttributeSensorAndConfigKey<EntitySpec<? extends LoadBalancer>> CONTROLLER_SPEC = new BasicAttributeSensorAndConfigKey(
EntitySpec.class, "controlleddynamicwebappcluster.controllerSpec", "Spec for creating the controller (if one not supplied explicitly); if null an NGINX instance will be created");
+ @SuppressWarnings({ "unchecked", "rawtypes", "deprecation" })
/** factory (or closure) to create the web server, given flags */
@SetFromFlag("factory")
public static BasicAttributeSensorAndConfigKey<ConfigurableEntityFactory<? extends WebAppService>> FACTORY = new BasicAttributeSensorAndConfigKey(
ConfigurableEntityFactory.class, DynamicCluster.FACTORY.getName(), "factory (or closure) to create the web server");
+ @SuppressWarnings({ "unchecked", "rawtypes" })
/** Spec for web server entiites to be created */
@SetFromFlag("memberSpec")
public static BasicAttributeSensorAndConfigKey<EntitySpec<? extends WebAppService>> MEMBER_SPEC = new BasicAttributeSensorAndConfigKey(
EntitySpec.class, DynamicCluster.MEMBER_SPEC.getName(), "Spec for web server entiites to be created");
+ @SuppressWarnings({ "unchecked", "rawtypes" })
@SetFromFlag("webClusterSpec")
public static BasicAttributeSensorAndConfigKey<EntitySpec<? extends DynamicWebAppCluster>> WEB_CLUSTER_SPEC = new BasicAttributeSensorAndConfigKey(
EntitySpec.class, "controlleddynamicwebappcluster.webClusterSpec", "Spec for creating the cluster; if null a DynamicWebAppCluster will be created");
@@ -93,24 +95,11 @@ public interface ControlledDynamicWebAppCluster extends DynamicGroup, Entity, St
public static final AttributeSensor<Lifecycle> SERVICE_STATE = Attributes.SERVICE_STATE;
+
public LoadBalancer getController();
public ConfigurableEntityFactory<WebAppService> getFactory();
public DynamicWebAppCluster getCluster();
- @Effector(description="Deploys the given artifact, from a source URL, to a given deployment filename/context")
- public void deploy(
- @EffectorParam(name="url", description="URL of WAR file") String url,
- @EffectorParam(name="targetName", description="context path where WAR should be deployed (/ for ROOT)") String targetName);
-
- @Effector(description="Undeploys the given context/artifact")
- public void undeploy(
- @EffectorParam(name="targetName") String targetName);
-
- @Effector(description="Updates the given context/artifact")
- public void update(
- @EffectorParam(name="url", description="URL of NEW WAR file") String url,
- @EffectorParam(name="targetName") String targetName);
-
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dbf26e3a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
index 262f9f8..ac70f3a 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/ControlledDynamicWebAppClusterImpl.java
@@ -18,6 +18,8 @@
*/
package brooklyn.entity.webapp;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
@@ -50,17 +52,14 @@ import brooklyn.event.feed.ConfigToAttributes;
import brooklyn.location.Location;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.MutableSet;
import brooklyn.util.exceptions.Exceptions;
import com.google.common.base.Predicate;
-import com.google.common.base.Throwables;
+import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
-import brooklyn.entity.webapp.FilenameToWebContextMapper;
-import static com.google.common.base.Preconditions.checkNotNull;
public class ControlledDynamicWebAppClusterImpl extends DynamicGroupImpl implements ControlledDynamicWebAppCluster {
@@ -337,76 +336,79 @@ public class ControlledDynamicWebAppClusterImpl extends DynamicGroupImpl impleme
try {
checkNotNull(url, "url");
checkNotNull(targetName, "targetName");
- // actually deploy
- List <Entity> cluster_members = Lists.newArrayList();
-// cluster_members.addAll((Collection<? extends Entity>) Iterables.filter(getCluster().getChildren(), JavaWebAppSoftwareProcess.class));
- for (JavaWebAppSoftwareProcess member : Iterables.filter(getCluster().getChildren(), JavaWebAppSoftwareProcess.class)) {
- Lifecycle serviceState = member.getAttribute(SERVICE_STATE);
- if (serviceState == Lifecycle.RUNNING) {
- cluster_members.add(member);
- }
- }
- Entities.invokeEffectorListWithArgs(this, cluster_members, DEPLOY, url, targetName).get();
- // Update attribute
- Set<String> deployedWars = getAttribute(DEPLOYED_WARS);
- if (deployedWars == null) {
- deployedWars = Sets.newLinkedHashSet();
+ // set it up so future nodes get the right wars
+ synchronized (this) {
+ Map<String,String> newWarsMap = MutableMap.copyOf(getConfig(WARS_BY_CONTEXT));
+ newWarsMap.put(targetName, url);
+ setConfig(WARS_BY_CONTEXT, newWarsMap);
}
+
+ // now actually deploy
+ List <Entity> clusterMembers = MutableList.copyOf(
+ Iterables.filter(getCluster().getChildren(), Predicates.and(
+ Predicates.instanceOf(JavaWebAppSoftwareProcess.class),
+ EntityPredicates.attributeEqualTo(SERVICE_STATE, Lifecycle.RUNNING)
+ )));
+ Entities.invokeEffectorListWithArgs(this, clusterMembers, DEPLOY, url, targetName).get();
+
+ // Update attribute
+ Set<String> deployedWars = MutableSet.copyOf(getAttribute(DEPLOYED_WARS));
deployedWars.add(targetName);
setAttribute(DEPLOYED_WARS, deployedWars);
- } catch (RuntimeException e) {
+
+ } catch (Exception e) {
// Log and propagate, so that log says which entity had problems...
log.warn("Error deploying '"+url+"' to "+targetName+" on "+toString()+"; rethrowing...", e);
- throw Throwables.propagate(e);
- } catch (Throwable th) {
- // Log and propagate, so that log says which entity had problems...
- log.warn("Error undeploying '"+targetName+"' on "+toString()+"; rethrowing...", th);
- throw Throwables.propagate(th);
+ throw Exceptions.propagate(e);
}
}
+
+ /*
+ * TODO
+ *
+ * - deploy to all, not just running, with a wait-for-running-or-bail-out logic
+ * - thread pool
+ * - redeploy to all (simple way, with notes)
+ * - check-in, then move down with echo here
+ */
+
/** For the DEPLOYED_WARS to be updated, the input must match the result of the call to deploy */
@Effector(description="Undeploys the given context/artifact")
- public void undeploy(
- @EffectorParam(name="targetName") String targetName) {
+ public void undeploy(@EffectorParam(name="targetName") String targetName) {
try {
+ checkNotNull(targetName, "targetName");
+
+ // set it up so future nodes get the right wars
+ synchronized (this) {
+ Map<String,String> newWarsMap = MutableMap.copyOf(getConfig(WARS_BY_CONTEXT));
+ newWarsMap.remove(targetName);
+ setConfig(WARS_BY_CONTEXT, newWarsMap);
+ }
- List <Entity> cluster_members = Lists.newArrayList();
-// cluster_members.addAll((Collection<? extends Entity>) Iterables.filter(getCluster().getChildren(), JavaWebAppSoftwareProcess.class));
- for (JavaWebAppSoftwareProcess member : Iterables.filter(getCluster().getChildren(), JavaWebAppSoftwareProcess.class)) {
- Lifecycle serviceState = member.getAttribute(SERVICE_STATE);
- if (serviceState == Lifecycle.RUNNING) {
- cluster_members.add(member);
- }
- }
- Entities.invokeEffectorListWithArgs(this, cluster_members, UNDEPLOY, targetName).get();
+ List <Entity> clusterMembers = MutableList.copyOf(
+ Iterables.filter(getCluster().getChildren(), Predicates.and(
+ Predicates.instanceOf(JavaWebAppSoftwareProcess.class),
+ EntityPredicates.attributeEqualTo(SERVICE_STATE, Lifecycle.RUNNING)
+ )));
+ Entities.invokeEffectorListWithArgs(this, clusterMembers, UNDEPLOY, targetName).get();
-
// Update attribute
- Set<String> deployedWars = getAttribute(DEPLOYED_WARS);
- if (deployedWars == null) {
- deployedWars = Sets.newLinkedHashSet();
- }
+ Set<String> deployedWars = MutableSet.copyOf(getAttribute(DEPLOYED_WARS));
deployedWars.remove( filenameToWebContextMapper.convertDeploymentTargetNameToContext(targetName) );
setAttribute(DEPLOYED_WARS, deployedWars);
- } catch (RuntimeException e) {
+
+ } catch (Exception e) {
// Log and propagate, so that log says which entity had problems...
log.warn("Error undeploying '"+targetName+"' on "+toString()+"; rethrowing...", e);
- throw Throwables.propagate(e);
- } catch (Throwable th) {
- // Log and propagate, so that log says which entity had problems...
- log.warn("Error undeploying '"+targetName+"' on "+toString()+"; rethrowing...", th);
- throw Throwables.propagate(th);
+ throw Exceptions.propagate(e);
}
+ }
+
+ @Override
+ public void redeployAll() {
+ throw new UnsupportedOperationException("TODO - support redeploying all WARs (if any of the deploy/undeploys fail)");
}
- @Effector(description="Updates the given context/artifact")
- public void update(
- @EffectorParam(name="url", description="URL of NEW WAR file") String url,
- @EffectorParam(name="targetName") String targetName) {
- // simple for now
- undeploy(targetName);
- deploy(url, targetName);
-
- }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dbf26e3a/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java b/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
index 360870f..ec942ee 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/DynamicWebAppClusterImpl.java
@@ -82,7 +82,9 @@ public class DynamicWebAppClusterImpl extends DynamicClusterImpl implements Dyna
}
for (List<? extends AttributeSensor<? extends Number>> es : averagingEnricherSetup) {
+ @SuppressWarnings("unchecked")
AttributeSensor<Number> t = (AttributeSensor<Number>) es.get(0);
+ @SuppressWarnings("unchecked")
AttributeSensor<Double> average = (AttributeSensor<Double>) es.get(1);
addEnricher(Enrichers.builder()
.aggregating(t)
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dbf26e3a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppService.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppService.java b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppService.java
index 044f49c..8561c12 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppService.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppService.java
@@ -20,9 +20,15 @@ package brooklyn.entity.webapp;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import brooklyn.config.ConfigKey;
+import brooklyn.entity.annotation.Effector;
+import brooklyn.entity.annotation.EffectorParam;
+import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.java.UsesJava;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.basic.BasicAttributeSensor;
import brooklyn.event.basic.BasicConfigKey;
import brooklyn.util.flags.SetFromFlag;
@@ -32,11 +38,71 @@ public interface JavaWebAppService extends WebAppService, UsesJava {
public static final ConfigKey<String> ROOT_WAR = new BasicConfigKey<String>(
String.class, "wars.root", "WAR file to deploy as the ROOT, as URL (supporting file: and classpath: prefixes)");
+ @SuppressWarnings({ "unchecked", "rawtypes" })
@SetFromFlag("wars")
public static final ConfigKey<List<String>> NAMED_WARS = new BasicConfigKey(
List.class, "wars.named", "Archive files to deploy, as URL strings (supporting file: and classpath: prefixes); context (path in user-facing URL) will be inferred by name");
+ @SuppressWarnings({ "unchecked", "rawtypes" })
@SetFromFlag("warsByContext")
public static final ConfigKey<Map<String,String>> WARS_BY_CONTEXT = new BasicConfigKey(
Map.class, "wars.by.context", "Map of context keys (path in user-facing URL, typically without slashes) to archives (e.g. WARs by URL) to deploy, supporting file: and classpath: prefixes)");
+
+ /** Optional marker interface for entities which support 'deploy' and 'undeploy' */
+ public interface CanDeployAndUndeploy {
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static final AttributeSensor<Set<String>> DEPLOYED_WARS = new BasicAttributeSensor(
+ Set.class, "webapp.deployedWars", "Names of archives/contexts that are currently deployed");
+
+ public static final MethodEffector<Void> DEPLOY = new MethodEffector<Void>(CanDeployAndUndeploy.class, "deploy");
+ public static final MethodEffector<Void> UNDEPLOY = new MethodEffector<Void>(CanDeployAndUndeploy.class, "undeploy");
+
+ /**
+ * Deploys the given artifact, from a source URL, to a given deployment filename/context.
+ * There is some variance in expected filename/context at various servers,
+ * so the following conventions are followed:
+ * <p>
+ * either ROOT.WAR or / denotes root context
+ * <p>
+ * anything of form FOO.?AR (ending .?AR) is copied with that name (unless copying not necessary)
+ * and is expected to be served from /FOO
+ * <p>
+ * anything of form /FOO (with leading slash) is expected to be served from /FOO
+ * (and is copied as FOO.WAR)
+ * <p>
+ * anything of form FOO (without a dot) is expected to be served from /FOO
+ * (and is copied as FOO.WAR)
+ * <p>
+ * otherwise <i>please note</i> behaviour may vary on different appservers;
+ * e.g. FOO.FOO would probably be ignored on appservers which expect a file copied across (usually),
+ * but served as /FOO.FOO on systems that take a deployment context.
+ * <p>
+ * See {@link FileNameToContextMappingTest} for definitive examples!
+ *
+ * @param url where to get the war, as a URL, either classpath://xxx or file:///home/xxx or http(s)...
+ * @param targetName where to tell the server to serve the WAR, see above
+ */
+ @Effector(description="Deploys the given artifact, from a source URL, to a given deployment filename/context")
+ public void deploy(
+ @EffectorParam(name="url", description="URL of WAR file") String url,
+ @EffectorParam(name="targetName", description="context path where WAR should be deployed (/ for ROOT)") String targetName);
+
+ /**
+ * For the DEPLOYED_WARS to be updated, the input must match the result of the call to deploy,
+ * e.g. the transformed name using
+ */
+ @Effector(description="Undeploys the given context/artifact")
+ public void undeploy(
+ @EffectorParam(name="targetName") String targetName);
+ }
+
+ /** Optional marker interface for entities which support 'redeployAll' */
+ public interface CanRedeployAll {
+ public static final MethodEffector<Void> REDEPLOY_ALL = new MethodEffector<Void>(CanRedeployAll.class, "redeployAll");
+
+ @Effector(description="Redeploys all web apps known here across the cluster (e.g. if it gets into an inconsistent state)")
+ public void redeployAll();
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/dbf26e3a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcess.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcess.java b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcess.java
index a6b43e2..5460f79 100644
--- a/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcess.java
+++ b/software/webapp/src/main/java/brooklyn/entity/webapp/JavaWebAppSoftwareProcess.java
@@ -18,57 +18,7 @@
*/
package brooklyn.entity.webapp;
-import java.util.Set;
-
-import brooklyn.entity.annotation.Effector;
-import brooklyn.entity.annotation.EffectorParam;
-import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.basic.SoftwareProcess;
-import brooklyn.event.AttributeSensor;
-import brooklyn.event.basic.BasicAttributeSensor;
-
-public interface JavaWebAppSoftwareProcess extends SoftwareProcess, JavaWebAppService {
-
- public static final AttributeSensor<Set<String>> DEPLOYED_WARS = new BasicAttributeSensor(
- Set.class, "webapp.deployedWars", "Names of archives/contexts that are currently deployed");
-
- public static final MethodEffector<Void> DEPLOY = new MethodEffector<Void>(JavaWebAppSoftwareProcess.class, "deploy");
- public static final MethodEffector<Void> UNDEPLOY = new MethodEffector<Void>(JavaWebAppSoftwareProcess.class, "undeploy");
-
- /**
- * Deploys the given artifact, from a source URL, to a given deployment filename/context.
- * There is some variance in expected filename/context at various servers,
- * so the following conventions are followed:
- * <p>
- * either ROOT.WAR or / denotes root context
- * <p>
- * anything of form FOO.?AR (ending .?AR) is copied with that name (unless copying not necessary)
- * and is expected to be served from /FOO
- * <p>
- * anything of form /FOO (with leading slash) is expected to be served from /FOO
- * (and is copied as FOO.WAR)
- * <p>
- * anything of form FOO (without a dot) is expected to be served from /FOO
- * (and is copied as FOO.WAR)
- * <p>
- * otherwise <i>please note</i> behaviour may vary on different appservers;
- * e.g. FOO.FOO would probably be ignored on appservers which expect a file copied across (usually),
- * but served as /FOO.FOO on systems that take a deployment context.
- * <p>
- * See {@link FileNameToContextMappingTest} for definitive examples!
- *
- * @param url where to get the war, as a URL, either classpath://xxx or file:///home/xxx or http(s)...
- * @param targetName where to tell the server to serve the WAR, see above
- */
- @Effector(description="Deploys the given artifact, from a source URL, to a given deployment filename/context")
- public void deploy(
- @EffectorParam(name="url", description="URL of WAR file") String url,
- @EffectorParam(name="targetName", description="context path where WAR should be deployed (/ for ROOT)") String targetName);
- /**
- * For the DEPLOYED_WARS to be updated, the input must match the result of the call to deploy
- */
- @Effector(description="Undeploys the given context/artifact")
- public void undeploy(
- @EffectorParam(name="targetName") String targetName);
+public interface JavaWebAppSoftwareProcess extends SoftwareProcess, JavaWebAppService, JavaWebAppService.CanDeployAndUndeploy {
}