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/12/13 02:39:06 UTC
[1/2] incubator-brooklyn git commit: added NginxConfigFileGenerator
to pass in custom server.conf templates to NginxController
Repository: incubator-brooklyn
Updated Branches:
refs/heads/master b61dbaa18 -> 3f645fb91
added NginxConfigFileGenerator to pass in custom server.conf templates to NginxController
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/42b5e814
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/42b5e814
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/42b5e814
Branch: refs/heads/master
Commit: 42b5e814a57b8d2b4a6d73e38fe794f3c664c667
Parents: 985b351
Author: ZaidM <za...@cloudsoftcorp.com>
Authored: Fri Dec 12 15:00:52 2014 +0000
Committer: ZaidM <za...@cloudsoftcorp.com>
Committed: Fri Dec 12 16:14:00 2014 +0000
----------------------------------------------------------------------
.../proxy/nginx/NginxConfigFileGenerator.java | 250 +-----------------
.../entity/proxy/nginx/NginxConfigTemplate.java | 79 ------
.../entity/proxy/nginx/NginxController.java | 8 +-
.../entity/proxy/nginx/NginxControllerImpl.java | 13 +-
.../nginx/NginxDefaultConfigGenerator.java | 256 +++++++++++++++++++
.../nginx/NginxTemplateConfigGenerator.java | 78 ++++++
6 files changed, 353 insertions(+), 331 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/42b5e814/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigFileGenerator.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigFileGenerator.java b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigFileGenerator.java
index fa74e59..1da0ed8 100644
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigFileGenerator.java
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigFileGenerator.java
@@ -18,248 +18,16 @@
*/
package brooklyn.entity.proxy.nginx;
-import static java.lang.String.format;
-
-import java.util.Collection;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.proxy.ProxySslConfig;
-import brooklyn.util.text.Strings;
-
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Multimap;
-
/**
- * Generates a configuration file for {@link NginxController}.
+ * Generates a {@code server.conf} configuration file for an {@link NginxController}.
*/
-public class NginxConfigFileGenerator {
-
- private static final Logger LOG = LoggerFactory.getLogger(NginxConfigFileGenerator.class);
-
- private NginxDriver driver;
- private NginxController nginx;
-
- public static NginxConfigFileGenerator generator(NginxDriver driver) {
- return new NginxConfigFileGenerator(driver);
- }
-
- private NginxConfigFileGenerator(NginxDriver driver) {
- this.driver = driver;
- this.nginx = (NginxController) driver.getEntity();
- }
-
- public String configFile() {
- StringBuilder config = new StringBuilder();
- config.append("\n");
- config.append(format("pid %s;\n", driver.getPidFile()));
- config.append("events {\n");
- config.append(" worker_connections 8196;\n");
- config.append("}\n");
- config.append("http {\n");
-
- ProxySslConfig globalSslConfig = nginx.getSslConfig();
-
- if (nginx.isSsl()) {
- verifyConfig(globalSslConfig);
- appendSslConfig("global", config, " ", globalSslConfig, true, true);
- }
-
- // If no servers, then defaults to returning 404
- // TODO Give nicer page back
- if (nginx.getDomain()!=null || nginx.getServerPoolAddresses() == null || nginx.getServerPoolAddresses().isEmpty()) {
- config.append(" server {\n");
- config.append(getCodeForServerConfig());
- config.append(" listen "+nginx.getPort()+";\n");
- config.append(getCodeFor404());
- config.append(" }\n");
- }
-
- // For basic round-robin across the server-pool
- if (nginx.getServerPoolAddresses() != null && nginx.getServerPoolAddresses().size() > 0) {
- config.append(format(" upstream "+nginx.getId()+" {\n"));
- if (nginx.isSticky()){
- config.append(" sticky;\n");
- }
- for (String address : nginx.getServerPoolAddresses()) {
- config.append(" server "+address+";\n");
- }
- config.append(" }\n");
- config.append(" server {\n");
- config.append(getCodeForServerConfig());
- config.append(" listen "+nginx.getPort()+";\n");
- if (nginx.getDomain()!=null)
- config.append(" server_name "+nginx.getDomain()+";\n");
- config.append(" location / {\n");
- config.append(" proxy_pass "+(globalSslConfig != null && globalSslConfig.getTargetIsSsl() ? "https" : "http")+"://"+nginx.getId()+";\n");
- config.append(" }\n");
- config.append(" }\n");
- }
-
- // For mapping by URL
- Iterable<UrlMapping> mappings = nginx.getUrlMappings();
- Multimap<String, UrlMapping> mappingsByDomain = LinkedHashMultimap.create();
- for (UrlMapping mapping : mappings) {
- Collection<String> addrs = mapping.getAttribute(UrlMapping.TARGET_ADDRESSES);
- if (addrs != null && addrs.size() > 0) {
- mappingsByDomain.put(mapping.getDomain(), mapping);
- }
- }
-
- for (UrlMapping um : mappings) {
- Collection<String> addrs = um.getAttribute(UrlMapping.TARGET_ADDRESSES);
- if (addrs != null && addrs.size() > 0) {
- config.append(format(" upstream "+um.getUniqueLabel()+" {\n"));
- if (nginx.isSticky()){
- config.append(" sticky;\n");
- }
- for (String address: addrs) {
- config.append(" server "+address+";\n");
- }
- config.append(" }\n");
- }
- }
-
- for (String domain : mappingsByDomain.keySet()) {
- config.append(" server {\n");
- config.append(getCodeForServerConfig());
- config.append(" listen "+nginx.getPort()+";\n");
- config.append(" server_name "+domain+";\n");
- boolean hasRoot = false;
-
- // set up SSL
- ProxySslConfig localSslConfig = null;
- for (UrlMapping mappingInDomain : mappingsByDomain.get(domain)) {
- ProxySslConfig sslConfig = mappingInDomain.getConfig(UrlMapping.SSL_CONFIG);
- if (sslConfig!=null) {
- verifyConfig(sslConfig);
- if (localSslConfig!=null) {
- if (localSslConfig.equals(sslConfig)) {
- //ignore identical config specified on multiple mappings
- } else {
- LOG.warn("{} mapping {} provides SSL config for {} when a different config had already been provided by another mapping, ignoring this one",
- new Object[] {this, mappingInDomain, domain});
- }
- } else if (globalSslConfig!=null) {
- if (globalSslConfig.equals(sslConfig)) {
- //ignore identical config specified on multiple mappings
- } else {
- LOG.warn("{} mapping {} provides SSL config for {} when a different config had been provided at root nginx scope, ignoring this one",
- new Object[] {this, mappingInDomain, domain});
- }
- } else {
- //new config, is okay
- localSslConfig = sslConfig;
- }
- }
- }
- if (localSslConfig != null) {
- appendSslConfig(domain, config, " ", localSslConfig, true, true);
- }
-
- for (UrlMapping mappingInDomain : mappingsByDomain.get(domain)) {
- // TODO Currently only supports "~" for regex. Could add support for other options,
- // such as "~*", "^~", literals, etc.
- boolean isRoot = mappingInDomain.getPath()==null || mappingInDomain.getPath().length()==0 || mappingInDomain.getPath().equals("/");
- if (isRoot && hasRoot) {
- LOG.warn(""+this+" mapping "+mappingInDomain+" provides a duplicate / proxy, ignoring");
- } else {
- hasRoot |= isRoot;
- String location = isRoot ? "/" : "~ " + mappingInDomain.getPath();
- config.append(" location "+location+" {\n");
- Collection<UrlRewriteRule> rewrites = mappingInDomain.getConfig(UrlMapping.REWRITES);
- if (rewrites != null && rewrites.size() > 0) {
- for (UrlRewriteRule rule: rewrites) {
- config.append(" rewrite \"^"+rule.getFrom()+"$\" \""+rule.getTo()+"\"");
- if (rule.isBreak()) config.append(" break");
- config.append(" ;\n");
- }
- }
- config.append(" proxy_pass "+
- (localSslConfig != null && localSslConfig.getTargetIsSsl() ? "https" :
- (localSslConfig == null && globalSslConfig != null && globalSslConfig.getTargetIsSsl()) ? "https" :
- "http")+
- "://"+mappingInDomain.getUniqueLabel()+" ;\n");
- config.append(" }\n");
- }
- }
- if (!hasRoot) {
- //provide a root block giving 404 if there isn't one for this server
- config.append(" location / { \n"+getCodeFor404()+" }\n");
- }
- config.append(" }\n");
- }
-
- config.append("}\n");
-
- return config.toString();
- }
-
- protected String getCodeForServerConfig() {
- // See http://wiki.nginx.org/HttpProxyModule
- return ""+
- // this prevents nginx from reporting version number on error pages
- " server_tokens off;\n"+
-
- // this prevents nginx from using the internal proxy_pass codename as Host header passed upstream.
- // Not using $host, as that causes integration test to fail with a "connection refused" testing
- // url-mappings, at URL "http://localhost:${port}/atC0" (with a trailing slash it does work).
- " proxy_set_header Host $http_host;\n"+
-
- // following added, as recommended for wordpress in:
- // http://zeroturnaround.com/labs/wordpress-protips-go-with-a-clustered-approach/#!/
- " proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n"+
- " proxy_set_header X-Real-IP $remote_addr;\n";
- }
-
- protected String getCodeFor404() {
- return " return 404;\n";
- }
-
- protected void verifyConfig(ProxySslConfig proxySslConfig) {
- if(Strings.isEmpty(proxySslConfig.getCertificateDestination()) && Strings.isEmpty(proxySslConfig.getCertificateSourceUrl())){
- throw new IllegalStateException("ProxySslConfig can't have a null certificateDestination and null certificateSourceUrl. One or both need to be set");
- }
- }
-
- protected boolean appendSslConfig(String id, StringBuilder out, String prefix, ProxySslConfig ssl,
- boolean sslBlock, boolean certificateBlock) {
- if (ssl == null) return false;
- if (sslBlock) {
- out.append(prefix);
- out.append("ssl on;\n");
- }
- if (ssl.getReuseSessions()) {
- out.append(prefix);
- out.append("");
- }
- if (certificateBlock) {
- String cert;
- if (Strings.isEmpty(ssl.getCertificateDestination())) {
- cert = "" + id + ".crt";
- } else {
- cert = ssl.getCertificateDestination();
- }
-
- out.append(prefix);
- out.append("ssl_certificate " + cert + ";\n");
-
- String key;
- if (!Strings.isEmpty(ssl.getKeyDestination())) {
- key = ssl.getKeyDestination();
- } else if (!Strings.isEmpty(ssl.getKeySourceUrl())) {
- key = "" + id + ".key";
- } else {
- key = null;
- }
-
- if (key != null) {
- out.append(prefix);
- out.append("ssl_certificate_key " + key + ";\n");
- }
- }
- return true;
- }
+public interface NginxConfigFileGenerator {
+
+ /**
+ * Entry point for the generator.
+ *
+ * @return The contents of the {@code server.conf} file
+ */
+ String generateConfigFile(NginxDriver driver, NginxController entity);
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/42b5e814/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigTemplate.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigTemplate.java b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigTemplate.java
deleted file mode 100644
index 4c36042..0000000
--- a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxConfigTemplate.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.entity.proxy.nginx;
-
-import java.util.Collection;
-import java.util.Map;
-
-import brooklyn.entity.proxy.ProxySslConfig;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.text.Strings;
-import brooklyn.util.text.TemplateProcessor;
-
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Multimap;
-
-/**
- * Processes a FreeMarker template for an {@link NginxController} configuration file.
- */
-public class NginxConfigTemplate {
-
- private NginxDriver driver;
-
- public static NginxConfigTemplate generator(NginxDriver driver) {
- return new NginxConfigTemplate(driver);
- }
-
- private NginxConfigTemplate(NginxDriver driver) {
- this.driver = driver;
- }
-
- public String configFile() {
- // Check template URL exists
- String templateUrl = driver.getEntity().getConfig(NginxController.SERVER_CONF_TEMPLATE_URL);
- ResourceUtils.create(this).checkUrlExists(templateUrl);
-
- // Check SSL configuration
- ProxySslConfig ssl = driver.getEntity().getConfig(NginxController.SSL_CONFIG);
- if (ssl != null && Strings.isEmpty(ssl.getCertificateDestination()) && Strings.isEmpty(ssl.getCertificateSourceUrl())) {
- throw new IllegalStateException("ProxySslConfig can't have a null certificateDestination and null certificateSourceUrl. One or both need to be set");
- }
-
- // For mapping by URL
- Iterable<UrlMapping> mappings = ((NginxController) driver.getEntity()).getUrlMappings();
- Multimap<String, UrlMapping> mappingsByDomain = LinkedHashMultimap.create();
- for (UrlMapping mapping : mappings) {
- Collection<String> addrs = mapping.getAttribute(UrlMapping.TARGET_ADDRESSES);
- if (addrs != null && addrs.size() > 0) {
- mappingsByDomain.put(mapping.getDomain(), mapping);
- }
- }
- Map<String, Object> substitutions = MutableMap.<String, Object>builder()
- .putIfNotNull("ssl", ssl)
- .put("urlMappings", mappings)
- .put("domainMappings", mappingsByDomain)
- .build();
-
- // Get template contents and process
- String contents = ResourceUtils.create(driver.getEntity()).getResourceAsString(templateUrl);
- return TemplateProcessor.processTemplateContents(contents, driver, substitutions);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/42b5e814/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..c645dd2 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
@@ -37,6 +37,7 @@ import brooklyn.event.basic.Sensors;
import brooklyn.util.flags.SetFromFlag;
import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
/**
* An entity that represents an Nginx proxy (e.g. for routing requests to servers in a cluster).
@@ -104,9 +105,12 @@ public interface NginxController extends AbstractController, HasShortName {
ConfigKey<String> WITH_CC_OPT = ConfigKeys.newStringConfigKey(
"nginx.install.withCcOpt", "String to pass in with --with-cc-opt=\"<val>\"", "-I /usr/local/include");
+ @SetFromFlag("configGenerator")
+ ConfigKey<NginxConfigFileGenerator> SERVER_CONF_GENERATOR = ConfigKeys.newConfigKey(NginxConfigFileGenerator.class,
+ "nginx.config.generator", "The server.conf generator class", new NginxDefaultConfigGenerator());
+
@SetFromFlag("configTemplate")
- ConfigKey<String> SERVER_CONF_TEMPLATE_URL = ConfigKeys.newStringConfigKey(
- "nginx.config.templateUrl", "The server.conf configuration file URL (FreeMarker template)");
+ ConfigKey<String> SERVER_CONF_TEMPLATE_URL = NginxTemplateConfigGenerator.SERVER_CONF_TEMPLATE_URL;
@SetFromFlag("staticContentArchive")
ConfigKey<String> STATIC_CONTENT_ARCHIVE_URL = ConfigKeys.newStringConfigKey(
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/42b5e814/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..041b8f6 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
@@ -262,18 +262,13 @@ public class NginxControllerImpl extends AbstractControllerImpl implements Nginx
public String getConfigFile() {
NginxSshDriver driver = (NginxSshDriver) getDriver();
if (driver==null) {
- if (LOG.isDebugEnabled())
- LOG.debug("No driver for {}, so not generating config file (is entity stopping? state={})",
- this, getAttribute(NginxController.SERVICE_STATE_ACTUAL));
+ LOG.debug("No driver for {}, so not generating config file (is entity stopping? state={})",
+ this, getAttribute(NginxController.SERVICE_STATE_ACTUAL));
return null;
}
- String templateUrl = getConfig(NginxController.SERVER_CONF_TEMPLATE_URL);
- if (templateUrl != null) {
- return NginxConfigTemplate.generator(driver).configFile();
- } else {
- return NginxConfigFileGenerator.generator(driver).configFile();
- }
+ NginxConfigFileGenerator templateGenerator = getConfig(NginxController.SERVER_CONF_GENERATOR);
+ return templateGenerator.generateConfigFile(driver, this);
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/42b5e814/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxDefaultConfigGenerator.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxDefaultConfigGenerator.java b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxDefaultConfigGenerator.java
new file mode 100644
index 0000000..7ba069e
--- /dev/null
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxDefaultConfigGenerator.java
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.proxy.nginx;
+
+import static java.lang.String.format;
+
+import java.util.Collection;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Multimap;
+
+import brooklyn.entity.proxy.ProxySslConfig;
+import brooklyn.util.text.Strings;
+
+/**
+ * Generates the {@code server.conf} configuration file using sensors on an {@link NginxController}.
+ */
+public class NginxDefaultConfigGenerator implements NginxConfigFileGenerator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NginxDefaultConfigGenerator.class);
+
+ public NginxDefaultConfigGenerator() { }
+
+ @Override
+ public String generateConfigFile(NginxDriver driver, NginxController nginx) {
+ StringBuilder config = new StringBuilder();
+ config.append("\n");
+ config.append(format("pid %s;\n", driver.getPidFile()));
+ config.append("events {\n");
+ config.append(" worker_connections 8196;\n");
+ config.append("}\n");
+ config.append("http {\n");
+
+ ProxySslConfig globalSslConfig = nginx.getSslConfig();
+
+ if (nginx.isSsl()) {
+ verifyConfig(globalSslConfig);
+ appendSslConfig("global", config, " ", globalSslConfig, true, true);
+ }
+
+ // If no servers, then defaults to returning 404
+ // TODO Give nicer page back
+ if (nginx.getDomain()!=null || nginx.getServerPoolAddresses() == null || nginx.getServerPoolAddresses().isEmpty()) {
+ config.append(" server {\n");
+ config.append(getCodeForServerConfig());
+ config.append(" listen "+nginx.getPort()+";\n");
+ config.append(getCodeFor404());
+ config.append(" }\n");
+ }
+
+ // For basic round-robin across the server-pool
+ if (nginx.getServerPoolAddresses() != null && nginx.getServerPoolAddresses().size() > 0) {
+ config.append(format(" upstream "+nginx.getId()+" {\n"));
+ if (nginx.isSticky()){
+ config.append(" sticky;\n");
+ }
+ for (String address : nginx.getServerPoolAddresses()) {
+ config.append(" server "+address+";\n");
+ }
+ config.append(" }\n");
+ config.append(" server {\n");
+ config.append(getCodeForServerConfig());
+ config.append(" listen "+nginx.getPort()+";\n");
+ if (nginx.getDomain()!=null)
+ config.append(" server_name "+nginx.getDomain()+";\n");
+ config.append(" location / {\n");
+ config.append(" proxy_pass "+(globalSslConfig != null && globalSslConfig.getTargetIsSsl() ? "https" : "http")+"://"+nginx.getId()+";\n");
+ config.append(" }\n");
+ config.append(" }\n");
+ }
+
+ // For mapping by URL
+ Iterable<UrlMapping> mappings = nginx.getUrlMappings();
+ Multimap<String, UrlMapping> mappingsByDomain = LinkedHashMultimap.create();
+ for (UrlMapping mapping : mappings) {
+ Collection<String> addrs = mapping.getAttribute(UrlMapping.TARGET_ADDRESSES);
+ if (addrs != null && addrs.size() > 0) {
+ mappingsByDomain.put(mapping.getDomain(), mapping);
+ }
+ }
+
+ for (UrlMapping um : mappings) {
+ Collection<String> addrs = um.getAttribute(UrlMapping.TARGET_ADDRESSES);
+ if (addrs != null && addrs.size() > 0) {
+ config.append(format(" upstream "+um.getUniqueLabel()+" {\n"));
+ if (nginx.isSticky()){
+ config.append(" sticky;\n");
+ }
+ for (String address: addrs) {
+ config.append(" server "+address+";\n");
+ }
+ config.append(" }\n");
+ }
+ }
+
+ for (String domain : mappingsByDomain.keySet()) {
+ config.append(" server {\n");
+ config.append(getCodeForServerConfig());
+ config.append(" listen "+nginx.getPort()+";\n");
+ config.append(" server_name "+domain+";\n");
+ boolean hasRoot = false;
+
+ // set up SSL
+ ProxySslConfig localSslConfig = null;
+ for (UrlMapping mappingInDomain : mappingsByDomain.get(domain)) {
+ ProxySslConfig sslConfig = mappingInDomain.getConfig(UrlMapping.SSL_CONFIG);
+ if (sslConfig!=null) {
+ verifyConfig(sslConfig);
+ if (localSslConfig!=null) {
+ if (localSslConfig.equals(sslConfig)) {
+ //ignore identical config specified on multiple mappings
+ } else {
+ LOG.warn("{} mapping {} provides SSL config for {} when a different config had already been provided by another mapping, ignoring this one",
+ new Object[] {this, mappingInDomain, domain});
+ }
+ } else if (globalSslConfig!=null) {
+ if (globalSslConfig.equals(sslConfig)) {
+ //ignore identical config specified on multiple mappings
+ } else {
+ LOG.warn("{} mapping {} provides SSL config for {} when a different config had been provided at root nginx scope, ignoring this one",
+ new Object[] {this, mappingInDomain, domain});
+ }
+ } else {
+ //new config, is okay
+ localSslConfig = sslConfig;
+ }
+ }
+ }
+ if (localSslConfig != null) {
+ appendSslConfig(domain, config, " ", localSslConfig, true, true);
+ }
+
+ for (UrlMapping mappingInDomain : mappingsByDomain.get(domain)) {
+ // TODO Currently only supports "~" for regex. Could add support for other options,
+ // such as "~*", "^~", literals, etc.
+ boolean isRoot = mappingInDomain.getPath()==null || mappingInDomain.getPath().length()==0 || mappingInDomain.getPath().equals("/");
+ if (isRoot && hasRoot) {
+ LOG.warn(""+this+" mapping "+mappingInDomain+" provides a duplicate / proxy, ignoring");
+ } else {
+ hasRoot |= isRoot;
+ String location = isRoot ? "/" : "~ " + mappingInDomain.getPath();
+ config.append(" location "+location+" {\n");
+ Collection<UrlRewriteRule> rewrites = mappingInDomain.getConfig(UrlMapping.REWRITES);
+ if (rewrites != null && rewrites.size() > 0) {
+ for (UrlRewriteRule rule: rewrites) {
+ config.append(" rewrite \"^"+rule.getFrom()+"$\" \""+rule.getTo()+"\"");
+ if (rule.isBreak()) config.append(" break");
+ config.append(" ;\n");
+ }
+ }
+ config.append(" proxy_pass "+
+ (localSslConfig != null && localSslConfig.getTargetIsSsl() ? "https" :
+ (localSslConfig == null && globalSslConfig != null && globalSslConfig.getTargetIsSsl()) ? "https" :
+ "http")+
+ "://"+mappingInDomain.getUniqueLabel()+" ;\n");
+ config.append(" }\n");
+ }
+ }
+ if (!hasRoot) {
+ //provide a root block giving 404 if there isn't one for this server
+ config.append(" location / { \n"+getCodeFor404()+" }\n");
+ }
+ config.append(" }\n");
+ }
+
+ config.append("}\n");
+
+ return config.toString();
+ }
+
+ protected String getCodeForServerConfig() {
+ // See http://wiki.nginx.org/HttpProxyModule
+ return ""+
+ // this prevents nginx from reporting version number on error pages
+ " server_tokens off;\n"+
+
+ // this prevents nginx from using the internal proxy_pass codename as Host header passed upstream.
+ // Not using $host, as that causes integration test to fail with a "connection refused" testing
+ // url-mappings, at URL "http://localhost:${port}/atC0" (with a trailing slash it does work).
+ " proxy_set_header Host $http_host;\n"+
+
+ // following added, as recommended for wordpress in:
+ // http://zeroturnaround.com/labs/wordpress-protips-go-with-a-clustered-approach/#!/
+ " proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n"+
+ " proxy_set_header X-Real-IP $remote_addr;\n";
+ }
+
+ protected String getCodeFor404() {
+ return " return 404;\n";
+ }
+
+ protected void verifyConfig(ProxySslConfig proxySslConfig) {
+ if(Strings.isEmpty(proxySslConfig.getCertificateDestination()) && Strings.isEmpty(proxySslConfig.getCertificateSourceUrl())){
+ throw new IllegalStateException("ProxySslConfig can't have a null certificateDestination and null certificateSourceUrl. One or both need to be set");
+ }
+ }
+
+ protected boolean appendSslConfig(String id, StringBuilder out, String prefix, ProxySslConfig ssl,
+ boolean sslBlock, boolean certificateBlock) {
+ if (ssl == null) return false;
+ if (sslBlock) {
+ out.append(prefix);
+ out.append("ssl on;\n");
+ }
+ if (ssl.getReuseSessions()) {
+ out.append(prefix);
+ out.append("");
+ }
+ if (certificateBlock) {
+ String cert;
+ if (Strings.isEmpty(ssl.getCertificateDestination())) {
+ cert = "" + id + ".crt";
+ } else {
+ cert = ssl.getCertificateDestination();
+ }
+
+ out.append(prefix);
+ out.append("ssl_certificate " + cert + ";\n");
+
+ String key;
+ if (!Strings.isEmpty(ssl.getKeyDestination())) {
+ key = ssl.getKeyDestination();
+ } else if (!Strings.isEmpty(ssl.getKeySourceUrl())) {
+ key = "" + id + ".key";
+ } else {
+ key = null;
+ }
+
+ if (key != null) {
+ out.append(prefix);
+ out.append("ssl_certificate_key " + key + ";\n");
+ }
+ }
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/42b5e814/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxTemplateConfigGenerator.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxTemplateConfigGenerator.java b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxTemplateConfigGenerator.java
new file mode 100644
index 0000000..d141ecf
--- /dev/null
+++ b/software/webapp/src/main/java/brooklyn/entity/proxy/nginx/NginxTemplateConfigGenerator.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.proxy.nginx;
+
+import java.util.Collection;
+import java.util.Map;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.proxy.ProxySslConfig;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.flags.SetFromFlag;
+import brooklyn.util.text.Strings;
+import brooklyn.util.text.TemplateProcessor;
+
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Multimap;
+
+/**
+ * Processes a FreeMarker template to generate the {@code server.conf} configuration file for an {@link NginxController}.
+ */
+public class NginxTemplateConfigGenerator implements NginxConfigFileGenerator {
+
+ public static final ConfigKey<String> SERVER_CONF_TEMPLATE_URL = ConfigKeys.newStringConfigKey(
+ "nginx.config.templateUrl", "The server.conf configuration file URL (FreeMarker template)");
+
+ public NginxTemplateConfigGenerator() { }
+
+ @Override
+ public String generateConfigFile(NginxDriver driver, NginxController nginx) {
+ // Check template URL exists
+ String templateUrl = driver.getEntity().getConfig(NginxController.SERVER_CONF_TEMPLATE_URL);
+ ResourceUtils.create(this).checkUrlExists(templateUrl);
+
+ // Check SSL configuration
+ ProxySslConfig ssl = driver.getEntity().getConfig(NginxController.SSL_CONFIG);
+ if (ssl != null && Strings.isEmpty(ssl.getCertificateDestination()) && Strings.isEmpty(ssl.getCertificateSourceUrl())) {
+ throw new IllegalStateException("ProxySslConfig can't have a null certificateDestination and null certificateSourceUrl. One or both need to be set");
+ }
+
+ // For mapping by URL
+ Iterable<UrlMapping> mappings = ((NginxController) driver.getEntity()).getUrlMappings();
+ Multimap<String, UrlMapping> mappingsByDomain = LinkedHashMultimap.create();
+ for (UrlMapping mapping : mappings) {
+ Collection<String> addrs = mapping.getAttribute(UrlMapping.TARGET_ADDRESSES);
+ if (addrs != null && addrs.size() > 0) {
+ mappingsByDomain.put(mapping.getDomain(), mapping);
+ }
+ }
+ Map<String, Object> substitutions = MutableMap.<String, Object>builder()
+ .putIfNotNull("ssl", ssl)
+ .put("urlMappings", mappings)
+ .put("domainMappings", mappingsByDomain)
+ .build();
+
+ // Get template contents and process
+ String contents = ResourceUtils.create(driver.getEntity()).getResourceAsString(templateUrl);
+ return TemplateProcessor.processTemplateContents(contents, driver, substitutions);
+ }
+
+}
[2/2] incubator-brooklyn git commit: This closes #392
Posted by gr...@apache.org.
This closes #392
* github/pr/392:
added NginxConfigFileGenerator to pass in custom server.conf templates to NginxController
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/3f645fb9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/3f645fb9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/3f645fb9
Branch: refs/heads/master
Commit: 3f645fb914c30695cf0082716edb9e762e6214b3
Parents: b61dbaa 42b5e81
Author: Andrew Kennedy <gr...@apache.org>
Authored: Sat Dec 13 01:39:01 2014 +0000
Committer: Andrew Kennedy <gr...@apache.org>
Committed: Sat Dec 13 01:39:01 2014 +0000
----------------------------------------------------------------------
.../proxy/nginx/NginxConfigFileGenerator.java | 250 +-----------------
.../entity/proxy/nginx/NginxConfigTemplate.java | 79 ------
.../entity/proxy/nginx/NginxController.java | 8 +-
.../entity/proxy/nginx/NginxControllerImpl.java | 13 +-
.../nginx/NginxDefaultConfigGenerator.java | 256 +++++++++++++++++++
.../nginx/NginxTemplateConfigGenerator.java | 78 ++++++
6 files changed, 353 insertions(+), 331 deletions(-)
----------------------------------------------------------------------