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/12/15 17:57:35 UTC
[8/9] incubator-brooklyn git commit: BROOKLYN-95 - make nginx
re-configurable, to switch to ssl while live
BROOKLYN-95 - make nginx re-configurable, to switch to ssl while live
a bit sloppy, running connectSensors multiple times, but it works.
better would be a restart which does install again, or to facilitate starting at the same VM.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/a952d6b7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/a952d6b7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/a952d6b7
Branch: refs/heads/master
Commit: a952d6b7258b0d695ba7a8a591d6caf6e1faaebf
Parents: 25dccf0
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Dec 2 16:28:15 2014 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri Dec 12 13:54:55 2014 +0000
----------------------------------------------------------------------
.../brooklyn/entity/basic/EntityPredicates.java | 2 +-
.../event/feed/AttributePollHandler.java | 12 +++-
.../main/java/brooklyn/event/feed/Poller.java | 2 -
.../java/brooklyn/event/feed/http/HttpFeed.java | 2 +-
.../event/feed/http/HttpPollConfig.java | 15 +----
.../main/java/brooklyn/util/http/HttpTool.java | 17 ++++++
.../entity/proxy/AbstractController.java | 2 +-
.../entity/proxy/AbstractControllerImpl.java | 21 ++++---
.../brooklyn/entity/proxy/LoadBalancer.java | 9 ++-
.../entity/proxy/nginx/NginxController.java | 5 ++
.../entity/proxy/nginx/NginxControllerImpl.java | 41 +++++++++++--
.../entity/proxy/nginx/NginxSshDriver.java | 29 +++++++---
.../brooklyn/entity/proxy/nginx/UrlMapping.java | 1 -
.../nginx/NginxHttpsSslIntegrationTest.java | 60 ++++++++++++++++++--
.../qa/load/SimulatedNginxControllerImpl.java | 5 +-
.../java/brooklyn/rest/api/EntityConfigApi.java | 3 +-
.../main/java/brooklyn/rest/api/SensorApi.java | 3 +-
.../rest/resources/EntityConfigResource.java | 8 +--
.../brooklyn/rest/resources/SensorResource.java | 8 +--
19 files changed, 183 insertions(+), 62 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/core/src/main/java/brooklyn/entity/basic/EntityPredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityPredicates.java b/core/src/main/java/brooklyn/entity/basic/EntityPredicates.java
index 12b656d..5906d78 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityPredicates.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityPredicates.java
@@ -318,7 +318,7 @@ public class EntityPredicates {
}
@Override
public boolean apply(@Nullable Entity input) {
- return (input != null) && group.hasMember(input);
+ return (group != null) && (input != null) && group.hasMember(input);
}
@Override
public String toString() {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/core/src/main/java/brooklyn/event/feed/AttributePollHandler.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/AttributePollHandler.java b/core/src/main/java/brooklyn/event/feed/AttributePollHandler.java
index 19538b3..2029237 100644
--- a/core/src/main/java/brooklyn/event/feed/AttributePollHandler.java
+++ b/core/src/main/java/brooklyn/event/feed/AttributePollHandler.java
@@ -23,9 +23,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import brooklyn.entity.basic.Attributes;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.EntityLocal;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.Lifecycle.Transition;
import brooklyn.event.AttributeSensor;
import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.task.Tasks;
@@ -157,7 +160,7 @@ public class AttributePollHandler<V> implements PollHandler<V> {
// get a non-volatile value
Long currentProblemStartTimeCache = currentProblemStartTime;
long expiryTime =
- lastSuccessTime!=null ? lastSuccessTime+logWarningGraceTime.toMilliseconds() :
+ (lastSuccessTime!=null && !isTransitioningOrStopped()) ? lastSuccessTime+logWarningGraceTime.toMilliseconds() :
currentProblemStartTimeCache!=null ? currentProblemStartTimeCache+logWarningGraceTimeOnStartup.toMilliseconds() :
nowTime+logWarningGraceTimeOnStartup.toMilliseconds();
if (!lastWasProblem) {
@@ -194,6 +197,13 @@ public class AttributePollHandler<V> implements PollHandler<V> {
}
}
+ protected boolean isTransitioningOrStopped() {
+ if (entity==null) return false;
+ Transition expected = entity.getAttribute(Attributes.SERVICE_STATE_EXPECTED);
+ if (expected==null) return false;
+ return (expected.getState()==Lifecycle.STARTING || expected.getState()==Lifecycle.STOPPING || expected.getState()==Lifecycle.STOPPED);
+ }
+
@SuppressWarnings("unchecked")
protected void setSensor(Object v) {
if (Entities.isNoLongerManaged(entity)) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/core/src/main/java/brooklyn/event/feed/Poller.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/Poller.java b/core/src/main/java/brooklyn/event/feed/Poller.java
index 6fa9147..1bb87c9 100644
--- a/core/src/main/java/brooklyn/event/feed/Poller.java
+++ b/core/src/main/java/brooklyn/event/feed/Poller.java
@@ -79,8 +79,6 @@ public class Poller<V> {
handler.onFailure(val);
}
} catch (Exception e) {
- // 2013-12-21 AH adding add'l logging because seeing strange scheduled task abortion from here
- // even though all paths should be catching it
if (loggedPreviousException) {
if (log.isTraceEnabled()) log.trace("PollJob for {}, repeated consecutive failures, handling {} using {}", new Object[] {job, e, handler});
} else {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java b/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
index 255443a..ab9dcd1 100644
--- a/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
+++ b/core/src/main/java/brooklyn/event/feed/http/HttpFeed.java
@@ -298,7 +298,7 @@ public class HttpFeed extends AbstractFeed {
URI uri = config.buildUri(builder.baseUri, baseUriVars);
baseUriProvider = Suppliers.ofInstance(uri);
} else if (!builder.baseUriVars.isEmpty()) {
- throw new IllegalStateException("Not permitted to supply URI vars when using a URI provider");
+ throw new IllegalStateException("Not permitted to supply URI vars when using a URI provider; pass the vars to the provider instead");
}
checkNotNull(baseUriProvider);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/core/src/main/java/brooklyn/event/feed/http/HttpPollConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/feed/http/HttpPollConfig.java b/core/src/main/java/brooklyn/event/feed/http/HttpPollConfig.java
index 979e629..3476373 100644
--- a/core/src/main/java/brooklyn/event/feed/http/HttpPollConfig.java
+++ b/core/src/main/java/brooklyn/event/feed/http/HttpPollConfig.java
@@ -27,15 +27,12 @@ import brooklyn.event.AttributeSensor;
import brooklyn.event.feed.PollConfig;
import brooklyn.util.collections.MutableList;
import brooklyn.util.collections.MutableMap;
+import brooklyn.util.http.HttpTool;
import brooklyn.util.http.HttpToolResponse;
-import brooklyn.util.net.URLParamEncoder;
import brooklyn.util.time.Duration;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
public class HttpPollConfig<T> extends PollConfig<HttpToolResponse, T, HttpPollConfig<T>> {
@@ -130,15 +127,7 @@ public class HttpPollConfig<T> extends PollConfig<HttpToolResponse, T, HttpPollC
Map<String,String> allvars = concat(baseUriVars, vars);
if (allvars != null && allvars.size() > 0) {
- Iterable<String> args = Iterables.transform(allvars.entrySet(),
- new Function<Map.Entry<String,String>,String>() {
- @Override public String apply(Map.Entry<String,String> entry) {
- String k = entry.getKey();
- String v = entry.getValue();
- return URLParamEncoder.encode(k) + (v != null ? "=" + URLParamEncoder.encode(v) : "");
- }
- });
- uri += "?" + Joiner.on("&").join(args);
+ uri += "?" + HttpTool.encodeUrlParams(allvars);
}
return URI.create(uri);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/core/src/main/java/brooklyn/util/http/HttpTool.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/http/HttpTool.java b/core/src/main/java/brooklyn/util/http/HttpTool.java
index a81b928..b57c157 100644
--- a/core/src/main/java/brooklyn/util/http/HttpTool.java
+++ b/core/src/main/java/brooklyn/util/http/HttpTool.java
@@ -66,9 +66,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.net.URLParamEncoder;
+import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
public class HttpTool {
@@ -362,4 +367,16 @@ public class HttpTool {
return "Basic "+Base64.encodeBase64String( (credentials.getUserName()+":"+credentials.getPassword()).getBytes() );
}
+ public static String encodeUrlParams(Map<?,?> data) {
+ if (data==null) return "";
+ Iterable<String> args = Iterables.transform(data.entrySet(),
+ new Function<Map.Entry<?,?>,String>() {
+ @Override public String apply(Map.Entry<?,?> entry) {
+ Object k = entry.getKey();
+ Object v = entry.getValue();
+ return URLParamEncoder.encode(Strings.toString(k)) + (v != null ? "=" + URLParamEncoder.encode(Strings.toString(v)) : "");
+ }
+ });
+ return Joiner.on("&").join(args);
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractController.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractController.java b/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractController.java
index fd00924..e2ba3a1 100644
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractController.java
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractController.java
@@ -41,7 +41,7 @@ public interface AbstractController extends SoftwareProcess, LoadBalancer {
@SetFromFlag("ssl")
ConfigKey<ProxySslConfig> SSL_CONFIG = ConfigKeys.newConfigKey(ProxySslConfig.class,
- "proxy.ssl.config", "configuration (e.g. certificates) for SSL; will use SSL if set, not use SSL if not set");
+ "proxy.ssl.config", "Configuration (e.g. certificates) for SSL; causes server to run with HTTPS instead of HTTP");
@SetFromFlag("serviceUpUrlPath")
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractControllerImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractControllerImpl.java b/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractControllerImpl.java
index bf960f9..c7f518e 100644
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractControllerImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/AbstractControllerImpl.java
@@ -112,7 +112,7 @@ public abstract class AbstractControllerImpl extends SoftwareProcessImpl impleme
return; // no-op
}
if (serverPoolMemberTrackerPolicy != null) {
- LOG.warn("Call to addServerPoolMemberTrackingPolicy when serverPoolMemberTrackingPolicy already exists, in {}", this);
+ LOG.debug("Call to addServerPoolMemberTrackingPolicy when serverPoolMemberTrackingPolicy already exists, removing and re-adding, in {}", this);
removeServerPoolMemberTrackingPolicy();
}
for (Policy p: getPolicies()) {
@@ -187,6 +187,7 @@ public abstract class AbstractControllerImpl extends SoftwareProcessImpl impleme
}
}
+ @SuppressWarnings("deprecation")
@Override
public void onManagementNoLongerMaster() {
super.onManagementNoLongerMaster(); // TODO remove when deprecated method in parent removed
@@ -226,7 +227,10 @@ public abstract class AbstractControllerImpl extends SoftwareProcessImpl impleme
@Override
public Integer getPort() {
- return getAttribute(PROXY_HTTP_PORT);
+ if (isSsl())
+ return getAttribute(PROXY_HTTPS_PORT);
+ else
+ return getAttribute(PROXY_HTTP_PORT);
}
/** primary URL this controller serves, if one can / has been inferred */
@@ -254,7 +258,7 @@ public abstract class AbstractControllerImpl extends SoftwareProcessImpl impleme
public abstract void reload();
protected String inferProtocol() {
- return getConfig(SSL_CONFIG)!=null ? "https" : "http";
+ return isSsl() ? "https" : "http";
}
/** returns URL, if it can be inferred; null otherwise */
@@ -285,13 +289,17 @@ public abstract class AbstractControllerImpl extends SoftwareProcessImpl impleme
protected Collection<Integer> getRequiredOpenPorts() {
Collection<Integer> result = super.getRequiredOpenPorts();
if (groovyTruth(getAttribute(PROXY_HTTP_PORT))) result.add(getAttribute(PROXY_HTTP_PORT));
+ if (groovyTruth(getAttribute(PROXY_HTTPS_PORT))) result.add(getAttribute(PROXY_HTTPS_PORT));
return result;
}
@Override
protected void preStart() {
super.preStart();
-
+ computePortsAndUrls();
+ }
+
+ protected void computePortsAndUrls() {
AttributeSensor<String> hostAndPortSensor = getConfig(HOST_AND_PORT_SENSOR);
Maybe<Object> hostnameSensor = getConfigRaw(HOSTNAME_SENSOR, true);
Maybe<Object> portSensor = getConfigRaw(PORT_NUMBER_SENSOR, true);
@@ -312,11 +320,6 @@ public abstract class AbstractControllerImpl extends SoftwareProcessImpl impleme
@Override
protected void connectSensors() {
super.connectSensors();
- if (getUrl()==null) {
- setAttribute(MAIN_URI, URI.create(inferUrl()));
- setAttribute(ROOT_URL, inferUrl());
- }
-
// TODO when rebind policies, and rebind calls connectSensors, then this will cause problems.
// Also relying on addServerPoolMemberTrackingPolicy to set the serverPoolAddresses and serverPoolTargets.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancer.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancer.java b/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancer.java
index 0502c3f..32e2fc9 100644
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancer.java
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/LoadBalancer.java
@@ -84,8 +84,13 @@ public interface LoadBalancer extends Entity, Startable {
@SetFromFlag("port")
/** port where this controller should live */
public static final PortAttributeSensorAndConfigKey PROXY_HTTP_PORT = new PortAttributeSensorAndConfigKey(
- "proxy.http.port", "Main HTTP port where this proxy listens", ImmutableList.of(8000, "8001+"));
-
+ "proxy.http.port", "Main port where this proxy listens if using HTTP", ImmutableList.of(8000, "8001+"));
+
+ @SetFromFlag("httpsPort")
+ /** port where this controller should live */
+ public static final PortAttributeSensorAndConfigKey PROXY_HTTPS_PORT = new PortAttributeSensorAndConfigKey(
+ "proxy.https.port", "Main port where this proxy listens if using HTTPS", ImmutableList.of(8443, "8443+"));
+
@SetFromFlag("protocol")
public static final BasicAttributeSensorAndConfigKey<String> PROTOCOL = new BasicAttributeSensorAndConfigKey<String>(
String.class, "proxy.protocol", "Main URL protocol this proxy answers (typically http or https)", null);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxController.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxController.java b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxController.java
index 88d1bb9..21b3c89 100644
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxController.java
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxController.java
@@ -134,4 +134,9 @@ public interface NginxController extends AbstractController, HasShortName {
public static final AttributeSensor<Boolean> NGINX_URL_ANSWERS_NICELY = Sensors.newBooleanSensor( "nginx.url.answers.nicely");
public static final AttributeSensor<String> PID_FILE = Sensors.newStringSensor( "nginx.pid.file", "PID file");
+
+ public interface NginxControllerInternal {
+ public void doExtraConfigurationDuringStart();
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxControllerImpl.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxControllerImpl.java b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxControllerImpl.java
index 74727fb..ef5e99a 100644
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxControllerImpl.java
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxControllerImpl.java
@@ -18,9 +18,11 @@
*/
package brooklyn.entity.proxy.nginx;
+import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
@@ -36,21 +38,25 @@ import brooklyn.entity.basic.ServiceStateLogic.ServiceNotUpLogic;
import brooklyn.entity.group.AbstractMembershipTrackingPolicy;
import brooklyn.entity.proxy.AbstractControllerImpl;
import brooklyn.entity.proxy.ProxySslConfig;
+import brooklyn.entity.proxy.nginx.NginxController.NginxControllerInternal;
import brooklyn.event.SensorEvent;
import brooklyn.event.SensorEventListener;
import brooklyn.event.feed.ConfigToAttributes;
import brooklyn.event.feed.http.HttpFeed;
import brooklyn.event.feed.http.HttpPollConfig;
+import brooklyn.management.SubscriptionHandle;
import brooklyn.policy.PolicySpec;
import brooklyn.util.ResourceUtils;
import brooklyn.util.file.ArchiveUtils;
import brooklyn.util.guava.Functionals;
+import brooklyn.util.http.HttpTool;
import brooklyn.util.http.HttpToolResponse;
import brooklyn.util.stream.Streams;
import brooklyn.util.text.Strings;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@@ -58,13 +64,14 @@ import com.google.common.collect.Sets;
/**
* Implementation of the {@link NginxController} entity.
*/
-public class NginxControllerImpl extends AbstractControllerImpl implements NginxController {
+public class NginxControllerImpl extends AbstractControllerImpl implements NginxController, NginxControllerInternal {
private static final Logger LOG = LoggerFactory.getLogger(NginxControllerImpl.class);
private volatile HttpFeed httpFeed;
private final Set<String> installedKeysCache = Sets.newLinkedHashSet();
protected UrlMappingsMemberTrackerPolicy urlMappingsMemberTrackerPolicy;
+ protected SubscriptionHandle targetAddressesHandler;
@Override
public void reload() {
@@ -82,19 +89,31 @@ public class NginxControllerImpl extends AbstractControllerImpl implements Nginx
return getConfig(STICKY);
}
+ private class UrlInferencer implements Supplier<URI> {
+ private Map<String, String> parameters;
+ private UrlInferencer(Map<String,String> parameters) {
+ this.parameters = parameters;
+ }
+ @Override public URI get() {
+ String baseUrl = inferUrl(true);
+ if (parameters==null || parameters.isEmpty())
+ return URI.create(baseUrl);
+ return URI.create(baseUrl+"?"+HttpTool.encodeUrlParams(parameters));
+ }
+ }
+
@Override
public void connectSensors() {
super.connectSensors();
ConfigToAttributes.apply(this);
- String accessibleRootUrl = inferUrl(true);
// "up" is defined as returning a valid HTTP response from nginx (including a 404 etc)
httpFeed = HttpFeed.builder()
+ .uniqueTag("nginx-poll")
.entity(this)
.period(getConfig(HTTP_POLL_PERIOD))
- .baseUri(accessibleRootUrl)
- .baseUriVars(ImmutableMap.of("include-runtime", "true"))
+ .baseUri(new UrlInferencer(ImmutableMap.of("include-runtime", "true")))
.poll(new HttpPollConfig<Boolean>(NGINX_URL_ANSWERS_NICELY)
// Any response from Nginx is good.
.checkSuccess(Predicates.alwaysTrue())
@@ -115,6 +134,7 @@ public class NginxControllerImpl extends AbstractControllerImpl implements Nginx
ServiceNotUpLogic.updateNotUpIndicator(this, NGINX_URL_ANSWERS_NICELY, "No response from nginx yet");
}
addEnricher(Enrichers.builder().updatingMap(Attributes.SERVICE_NOT_UP_INDICATORS)
+ .uniqueTag("not-up-unless-url-answers")
.from(NGINX_URL_ANSWERS_NICELY)
.computing(Functionals.ifNotEquals(true).value("URL where nginx listens is not answering correctly (with expected header)") )
.build());
@@ -122,9 +142,9 @@ public class NginxControllerImpl extends AbstractControllerImpl implements Nginx
// Can guarantee that parent/managementContext has been set
Group urlMappings = getConfig(URL_MAPPINGS);
- if (urlMappings != null) {
+ if (urlMappings!=null && urlMappingsMemberTrackerPolicy==null) {
// Listen to the targets of each url-mapping changing
- subscribeToMembers(urlMappings, UrlMapping.TARGET_ADDRESSES, new SensorEventListener<Collection<String>>() {
+ targetAddressesHandler = subscribeToMembers(urlMappings, UrlMapping.TARGET_ADDRESSES, new SensorEventListener<Collection<String>>() {
@Override public void onEvent(SensorEvent<Collection<String>> event) {
updateNeeded();
}
@@ -139,6 +159,12 @@ public class NginxControllerImpl extends AbstractControllerImpl implements Nginx
protected void removeUrlMappingsMemberTrackerPolicy() {
if (urlMappingsMemberTrackerPolicy != null) {
removePolicy(urlMappingsMemberTrackerPolicy);
+ urlMappingsMemberTrackerPolicy = null;
+ }
+ Group urlMappings = getConfig(URL_MAPPINGS);
+ if (urlMappings!=null && targetAddressesHandler!=null) {
+ unsubscribe(urlMappings, targetAddressesHandler);
+ targetAddressesHandler = null;
}
}
@@ -181,7 +207,10 @@ public class NginxControllerImpl extends AbstractControllerImpl implements Nginx
}
public void doExtraConfigurationDuringStart() {
+ computePortsAndUrls();
reconfigureService();
+ // reconnect sensors if ports have changed
+ connectSensors();
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxSshDriver.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxSshDriver.java b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxSshDriver.java
index 91c69e5..1c73374 100644
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxSshDriver.java
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxSshDriver.java
@@ -33,6 +33,7 @@ import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.Lifecycle;
import brooklyn.entity.basic.lifecycle.ScriptHelper;
import brooklyn.entity.drivers.downloads.DownloadResolver;
+import brooklyn.entity.proxy.AbstractController;
import brooklyn.location.OsDetails;
import brooklyn.location.basic.SshMachineLocation;
import brooklyn.management.ManagementContext;
@@ -99,10 +100,15 @@ public class NginxSshDriver extends AbstractSoftwareProcessSshDriver implements
return format("%s/%s", getRunDir(), NGINX_PID_FILE);
}
+ @Deprecated /** @deprecated since 0.7.0 use #getPort */
public Integer getHttpPort() {
return getEntity().getPort();
}
+ public Integer getPort() {
+ return getEntity().getPort();
+ }
+
@Override
public void rebind() {
customizationCompleted = true;
@@ -111,7 +117,13 @@ public class NginxSshDriver extends AbstractSoftwareProcessSshDriver implements
@Override
public void postLaunch() {
entity.setAttribute(NginxController.PID_FILE, getRunDir() + "/" + AbstractSoftwareProcessSshDriver.PID_FILENAME);
- entity.setAttribute(Attributes.HTTP_PORT, getHttpPort());
+ if (((AbstractController)entity).isSsl()) {
+ entity.setAttribute(Attributes.HTTPS_PORT, getPort());
+ ((EntityInternal)entity).removeAttribute(Attributes.HTTP_PORT);
+ } else {
+ entity.setAttribute(Attributes.HTTP_PORT, getPort());
+ ((EntityInternal)entity).removeAttribute(Attributes.HTTPS_PORT);
+ }
super.postLaunch();
}
@@ -288,7 +300,6 @@ public class NginxSshDriver extends AbstractSoftwareProcessSshDriver implements
}
customizationCompleted = true;
- getEntity().doExtraConfigurationDuringStart();
}
@Override
@@ -301,7 +312,9 @@ public class NginxSshDriver extends AbstractSoftwareProcessSshDriver implements
// TODO if can't be root, and ports > 1024 are in the allowed port range,
// prefer that; could do this on SshMachineLocation which implements PortSupplier,
// invoked from PortAttrSensorAndConfigKey, which is invoked from MachineLifecycleTasks.preStartCustom
- Networking.checkPortsValid(MutableMap.of("httpPort", getHttpPort()));
+ Networking.checkPortsValid(MutableMap.of("port", getPort()));
+
+ getEntity().doExtraConfigurationDuringStart();
// We wait for evidence of running because, using
// brooklyn.ssh.config.tool.class=brooklyn.util.internal.ssh.cli.SshCliTool,
@@ -311,7 +324,7 @@ public class NginxSshDriver extends AbstractSoftwareProcessSshDriver implements
.body.append(
format("cd %s", getRunDir()),
BashCommands.requireExecutable("./sbin/nginx"),
- sudoBashCIfPrivilegedPort(getHttpPort(), format(
+ sudoBashCIfPrivilegedPort(getPort(), format(
"nohup ./sbin/nginx -p %s/ -c conf/server.conf > %s 2>&1 &", getRunDir(), getLogFileLocation())),
format("for i in {1..10}\n" +
"do\n" +
@@ -345,7 +358,7 @@ public class NginxSshDriver extends AbstractSoftwareProcessSshDriver implements
format("cd %s", getRunDir()),
format("export PID=`cat %s`", getPidFile()),
"test -n \"$PID\" || exit 0",
- sudoIfPrivilegedPort(getHttpPort(), "kill $PID"))
+ sudoIfPrivilegedPort(getPort(), "kill $PID"))
.execute();
}
@@ -386,8 +399,8 @@ public class NginxSshDriver extends AbstractSoftwareProcessSshDriver implements
// calling waitForEntityStart()), we can guarantee that the start-thread's call to update will happen after
// this call to reload. So we this can be a no-op, and just rely on that subsequent call to update.
- if (!isRunning()) {
- Lifecycle lifecycle = entity.getAttribute(NginxController.SERVICE_STATE_ACTUAL);
+ Lifecycle lifecycle = entity.getAttribute(NginxController.SERVICE_STATE_ACTUAL);
+ if (lifecycle==Lifecycle.STOPPING || lifecycle==Lifecycle.STOPPED || !isRunning()) {
log.debug("Ignoring reload of nginx "+entity+", because service is not running (state "+lifecycle+")");
return;
}
@@ -412,7 +425,7 @@ public class NginxSshDriver extends AbstractSoftwareProcessSshDriver implements
.body.append(
format("cd %s", getRunDir()),
format("export PID=`cat %s`", getPidFile()),
- sudoIfPrivilegedPort(getHttpPort(), "kill -HUP $PID"))
+ sudoIfPrivilegedPort(getPort(), "kill -HUP $PID"))
.execute();
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/UrlMapping.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/UrlMapping.java b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/UrlMapping.java
index 7cd7d87..d8a0377 100644
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/UrlMapping.java
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/UrlMapping.java
@@ -29,7 +29,6 @@ import brooklyn.entity.basic.MethodEffector;
import brooklyn.entity.proxy.AbstractController;
import brooklyn.entity.proxy.ProxySslConfig;
import brooklyn.entity.proxying.ImplementedBy;
-import brooklyn.entity.webapp.WebAppService;
import brooklyn.event.AttributeSensor;
import brooklyn.event.basic.Sensors;
import brooklyn.util.flags.SetFromFlag;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/software/webapp/src/test/java/brooklyn/entity/proxy/nginx/NginxHttpsSslIntegrationTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/brooklyn/entity/proxy/nginx/NginxHttpsSslIntegrationTest.java b/software/webapp/src/test/java/brooklyn/entity/proxy/nginx/NginxHttpsSslIntegrationTest.java
index 8ba88b7..a8004d7 100644
--- a/software/webapp/src/test/java/brooklyn/entity/proxy/nginx/NginxHttpsSslIntegrationTest.java
+++ b/software/webapp/src/test/java/brooklyn/entity/proxy/nginx/NginxHttpsSslIntegrationTest.java
@@ -32,24 +32,31 @@ import org.testng.annotations.Test;
import brooklyn.entity.BrooklynAppLiveTestSupport;
import brooklyn.entity.Entity;
+import brooklyn.entity.basic.EntityInternal;
import brooklyn.entity.basic.SoftwareProcess;
import brooklyn.entity.group.DynamicCluster;
+import brooklyn.entity.proxy.LoadBalancer;
import brooklyn.entity.proxy.ProxySslConfig;
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.entity.webapp.JavaWebAppService;
import brooklyn.entity.webapp.WebAppService;
import brooklyn.entity.webapp.jboss.JBoss7Server;
+import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
import brooklyn.location.Location;
+import brooklyn.location.basic.PortRanges;
import brooklyn.test.Asserts;
import brooklyn.test.HttpTestUtils;
+import brooklyn.util.exceptions.Exceptions;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
/**
* Test the operation of the {@link NginxController} class.
*/
public class NginxHttpsSslIntegrationTest extends BrooklynAppLiveTestSupport {
- @SuppressWarnings("unused")
+
private static final Logger log = LoggerFactory.getLogger(NginxHttpsSslIntegrationTest.class);
private NginxController nginx;
@@ -65,6 +72,13 @@ public class NginxHttpsSslIntegrationTest extends BrooklynAppLiveTestSupport {
super.setUp();
localLoc = mgmt.getLocationRegistry().resolve("localhost");
}
+
+ private static void urlContainsPort(NginxController nginx, PortAttributeSensorAndConfigKey sensor, String portRange) {
+ Integer port = nginx.getAttribute(sensor);
+ Assert.assertTrue(Iterables.contains(PortRanges.fromString(portRange), port), "Port "+port+" not in range "+portRange);
+ String url = Preconditions.checkNotNull(nginx.getAttribute(LoadBalancer.MAIN_URI), "main uri").toString();
+ Assert.assertTrue(url.contains(":"+port), "URL does not contain expected port; port "+port+", url "+url);
+ }
public String getTestWar() {
TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
@@ -90,12 +104,15 @@ public class NginxHttpsSslIntegrationTest extends BrooklynAppLiveTestSupport {
.configure("sticky", false)
.configure("serverPool", cluster)
.configure("domain", "localhost")
- .configure("port", "8443+")
+ .configure("httpsPort", "8453+")
.configure("ssl", ssl));
app.start(ImmutableList.of(localLoc));
+ urlContainsPort(nginx, LoadBalancer.PROXY_HTTPS_PORT, "8453+");
+
final String url = nginx.getAttribute(WebAppService.ROOT_URL);
+ log.info("URL for nginx is "+url);
if (!url.startsWith("https://")) Assert.fail("URL should be https: "+url);
Asserts.succeedsEventually(new Runnable() {
@@ -128,8 +145,8 @@ public class NginxHttpsSslIntegrationTest extends BrooklynAppLiveTestSupport {
}
private String getFile(String file) {
- return new File(getClass().getResource("/" + file).getFile()).getAbsolutePath();
- }
+ return new File(getClass().getResource("/" + file).getFile()).getAbsolutePath();
+ }
@Test(groups = "Integration")
public void testStartsWithGlobalSsl_withPreinstalledCertificateAndKey() {
@@ -183,4 +200,39 @@ public class NginxHttpsSslIntegrationTest extends BrooklynAppLiveTestSupport {
assertFalse(member.getAttribute(SoftwareProcess.SERVICE_UP));
}
}
+
+ @Test(groups = "Integration")
+ public void testStartsNonSslThenBecomesSsl() {
+ cluster = app.createAndManageChild(EntitySpec.create(DynamicCluster.class)
+ .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(JBoss7Server.class))
+ .configure("initialSize", 1)
+ .configure(JavaWebAppService.ROOT_WAR, getTestWar()));
+
+ nginx = app.createAndManageChild(EntitySpec.create(NginxController.class)
+ .configure("serverPool", cluster)
+ .configure("domain", "localhost"));
+
+ app.start(ImmutableList.of(localLoc));
+
+ urlContainsPort(nginx, LoadBalancer.PROXY_HTTP_PORT, "8000-8100");
+
+ ProxySslConfig ssl = ProxySslConfig.builder()
+ .certificateDestination(getFile("ssl/certs/localhost/server.crt"))
+ .keyDestination(getFile("ssl/certs/localhost/server.key"))
+ .build();
+ ((EntityInternal)nginx).setConfig(LoadBalancer.PROXY_HTTPS_PORT, PortRanges.fromString("8443+"));
+ ((EntityInternal)nginx).setConfig(NginxController.SSL_CONFIG, ssl);
+
+ try {
+ log.info("restarting nginx as ssl");
+ nginx.restart();
+ urlContainsPort(nginx, LoadBalancer.PROXY_HTTPS_PORT, "8443-8543");
+
+ app.stop();
+
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/usage/qa/src/main/java/brooklyn/qa/load/SimulatedNginxControllerImpl.java
----------------------------------------------------------------------
diff --git a/usage/qa/src/main/java/brooklyn/qa/load/SimulatedNginxControllerImpl.java b/usage/qa/src/main/java/brooklyn/qa/load/SimulatedNginxControllerImpl.java
index 1fc6488..e5c40c2 100644
--- a/usage/qa/src/main/java/brooklyn/qa/load/SimulatedNginxControllerImpl.java
+++ b/usage/qa/src/main/java/brooklyn/qa/load/SimulatedNginxControllerImpl.java
@@ -99,7 +99,6 @@ public class SimulatedNginxControllerImpl extends NginxControllerImpl {
.period(getConfig(HTTP_POLL_PERIOD))
.poll(new FunctionPollConfig<Boolean,Boolean>(SERVICE_UP)
.callable(new Callable<Boolean>() {
- private int counter = 0;
public Boolean call() {
return true;
}}))
@@ -158,7 +157,7 @@ public class SimulatedNginxControllerImpl extends NginxControllerImpl {
return;
}
- Networking.checkPortsValid(MutableMap.of("httpPort", getHttpPort()));
+ Networking.checkPortsValid(MutableMap.of("httpPort", getPort()));
if (entity.getConfig(SKIP_SSH_ON_START)) {
// minimal ssh, so that isRunning will subsequently work
@@ -172,7 +171,7 @@ public class SimulatedNginxControllerImpl extends NginxControllerImpl {
.body.append(
format("cd %s", getRunDir()),
"echo skipping exec of requireExecutable ./sbin/nginx",
- sudoBashCIfPrivilegedPort(getHttpPort(), format(
+ sudoBashCIfPrivilegedPort(getPort(), format(
"echo skipping exec of nohup ./sbin/nginx -p %s/ -c conf/server.conf > %s 2>&1 &", getRunDir(), getLogFileLocation())),
format("nohup sleep 100000 > %s 2>&1 < /dev/null &", getLogFileLocation()),
format("echo $! > "+getPidFile()),
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/usage/rest-api/src/main/java/brooklyn/rest/api/EntityConfigApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/EntityConfigApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/EntityConfigApi.java
index 7c576bf..75f39b3 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/api/EntityConfigApi.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/api/EntityConfigApi.java
@@ -108,6 +108,7 @@ public interface EntityConfigApi {
@ApiErrors(value = {
@ApiError(code = 404, reason = "Could not find application or entity")
})
+ @SuppressWarnings("rawtypes")
public void setFromMap(
@ApiParam(value = "Application ID or name", required = true)
@PathParam("application") final String application,
@@ -116,7 +117,7 @@ public interface EntityConfigApi {
@ApiParam(value = "Apply the config to all pre-existing descendants", required = false)
@QueryParam("recurse") @DefaultValue("false") final Boolean recurse,
@ApiParam(value = "Map of config key names to values", required = true)
- Map<?,?> newValues
+ Map newValues
) ;
@POST
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/usage/rest-api/src/main/java/brooklyn/rest/api/SensorApi.java
----------------------------------------------------------------------
diff --git a/usage/rest-api/src/main/java/brooklyn/rest/api/SensorApi.java b/usage/rest-api/src/main/java/brooklyn/rest/api/SensorApi.java
index 982aa52..9f05f52 100644
--- a/usage/rest-api/src/main/java/brooklyn/rest/api/SensorApi.java
+++ b/usage/rest-api/src/main/java/brooklyn/rest/api/SensorApi.java
@@ -113,13 +113,14 @@ public interface SensorApi {
@ApiErrors(value = {
@ApiError(code = 404, reason = "Could not find application or entity")
})
+ @SuppressWarnings("rawtypes")
public void setFromMap(
@ApiParam(value = "Application ID or name", required = true)
@PathParam("application") final String application,
@ApiParam(value = "Entity ID or name", required = true)
@PathParam("entity") final String entityToken,
@ApiParam(value = "Map of sensor names to values", required = true)
- Map<?,?> newValues
+ Map newValues
) ;
@POST
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityConfigResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityConfigResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityConfigResource.java
index 66c1ef7..efcd248 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityConfigResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityConfigResource.java
@@ -110,7 +110,7 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
- public void setFromMap(String application, String entityToken, Boolean recurse, Map<?, ?> newValues) {
+ public void setFromMap(String application, String entityToken, Boolean recurse, Map newValues) {
final EntityLocal entity = brooklyn().getEntity(application, entityToken);
if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
@@ -119,9 +119,9 @@ public class EntityConfigResource extends AbstractBrooklynRestResource implement
if (LOG.isDebugEnabled())
LOG.debug("REST user "+Entitlements.getEntitlementContext()+" setting configs "+newValues);
- for (Map.Entry<?,?> entry: newValues.entrySet()) {
- String configName = Strings.toString(entry.getKey());
- Object newValue = entry.getValue();
+ for (Object entry: newValues.entrySet()) {
+ String configName = Strings.toString(((Map.Entry)entry).getKey());
+ Object newValue = ((Map.Entry)entry).getValue();
ConfigKey ck = findConfig(entity, configName);
((EntityInternal) entity).setConfig(ck, TypeCoercions.coerce(newValue, ck.getTypeToken()));
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a952d6b7/usage/rest-server/src/main/java/brooklyn/rest/resources/SensorResource.java
----------------------------------------------------------------------
diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/SensorResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/SensorResource.java
index 987a995..8c6f3f3 100644
--- a/usage/rest-server/src/main/java/brooklyn/rest/resources/SensorResource.java
+++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/SensorResource.java
@@ -107,7 +107,7 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
- public void setFromMap(String application, String entityToken, Map<?, ?> newValues) {
+ public void setFromMap(String application, String entityToken, Map newValues) {
final EntityLocal entity = brooklyn().getEntity(application, entityToken);
if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) {
throw WebResourceUtils.unauthorized("User '%s' is not authorized to modify entity '%s'",
@@ -116,9 +116,9 @@ public class SensorResource extends AbstractBrooklynRestResource implements Sens
if (log.isDebugEnabled())
log.debug("REST user "+Entitlements.getEntitlementContext()+" setting sensors "+newValues);
- for (Map.Entry<?,?> entry: newValues.entrySet()) {
- String sensorName = Strings.toString(entry.getKey());
- Object newValue = entry.getValue();
+ for (Object entry: newValues.entrySet()) {
+ String sensorName = Strings.toString(((Map.Entry)entry).getKey());
+ Object newValue = ((Map.Entry)entry).getValue();
AttributeSensor sensor = findSensor(entity, sensorName);
entity.setAttribute(sensor, newValue);