Merge pull request #190 from algairim/nginx-multi
Introduce nginx-multi type
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxController.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxController.java
index 63cd317..d2ddd98 100644
--- a/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxController.java
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/proxy/nginx/NginxController.java
@@ -18,10 +18,7 @@
*/
package org.apache.brooklyn.entity.proxy.nginx;
-import java.util.Map;
-
import com.google.common.collect.ImmutableMap;
-
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.ImplementedBy;
import org.apache.brooklyn.api.objs.HasShortName;
@@ -38,6 +35,8 @@
import org.apache.brooklyn.entity.software.base.SoftwareProcess;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import java.util.Map;
+
/**
* An entity that represents an Nginx proxy (e.g. for routing requests to servers in a cluster).
* <p>
@@ -56,7 +55,7 @@
* or different ports if that is supported.
* see more info on Ssl in {@link ProxySslConfig}.
*/
-@Catalog(name="Nginx Server", description="A single Nginx server. Provides HTTP and reverse proxy services", iconUrl="classpath:///nginx-logo.jpeg")
+@Catalog(name="Nginx Server", description="A single Nginx server. Provides HTTP and reverse proxy services", iconUrl="classpath:///nginx-logo.png")
@ImplementedBy(NginxControllerImpl.class)
public interface NginxController extends AbstractController, HasShortName {
diff --git a/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nginx/UpstreamSyncPolicy.java b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nginx/UpstreamSyncPolicy.java
new file mode 100644
index 0000000..fc978f3
--- /dev/null
+++ b/software/webapp/src/main/java/org/apache/brooklyn/entity/webapp/nginx/UpstreamSyncPolicy.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.apache.brooklyn.entity.webapp.nginx;
+
+import com.google.common.base.Predicates;
+import org.apache.brooklyn.api.effector.Effector;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.entity.group.AbstractMembershipTrackingPolicy;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.text.Strings;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Keeps NGINX 'upstream' server addresses in sync with membership and service-up changes on a corresponding service group.
+ */
+public class UpstreamSyncPolicy extends AbstractMembershipTrackingPolicy {
+
+ public static ConfigKey<Entity> NGINX_NODE = ConfigKeys.newConfigKey(Entity.class, "nginxNode");
+ public static ConfigKey<String> GROUP_NAME = ConfigKeys.newStringConfigKey("groupName");
+
+ @Override
+ protected void onEntityEvent(EventType type, Entity entity) {
+ defaultHighlightAction(type, entity);
+
+ Entity nginx = config().get(NGINX_NODE);
+ Boolean nginxIsUp = nginx.sensors().get(Startable.SERVICE_UP);
+ if (!Boolean.TRUE.equals(nginxIsUp))
+ return;
+
+ String groupName = config().get(GROUP_NAME);
+
+ List<String> serverAddresses = getEntity().getChildren().stream().map((e) -> {
+ Boolean serviceUp = e.sensors().get(Startable.SERVICE_UP);
+ String hostName = e.sensors().get(Sensors.newStringSensor("host.name"));
+ String port = e.sensors().get(Sensors.newStringSensor("http.port"));
+ if (!Boolean.TRUE.equals(serviceUp) || hostName == null || port == null)
+ return null;
+ return hostName + ":" + port;
+ }).filter(Predicates.notNull()).collect(Collectors.toList());
+
+ Maybe<Effector<?>> renderTargets = nginx.getEntityType().getEffectorByName("render-targets");
+ Entities.invokeEffectorWithArgs(getEntity(), nginx, renderTargets.get(), groupName, Strings.join(serverAddresses, " "));
+ }
+}
diff --git a/software/webapp/src/main/resources/catalog.bom b/software/webapp/src/main/resources/catalog.bom
index bd086da..2c91da5 100644
--- a/software/webapp/src/main/resources/catalog.bom
+++ b/software/webapp/src/main/resources/catalog.bom
@@ -40,7 +40,7 @@
type: org.apache.brooklyn.entity.webapp.DynamicWebAppFabric
name: Dynamic Web App Fabric
- id: org.apache.brooklyn.entity.proxy.nginx.NginxController
- iconUrl: classpath:///nginx-logo.jpeg
+ iconUrl: classpath:///nginx-logo.png
item:
type: org.apache.brooklyn.entity.proxy.nginx.NginxController
name: Nginx Server
@@ -96,3 +96,5 @@
type: org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster
name: Controlled Dynamic Web-app Cluster
description: A cluster of load-balanced web-apps, which can be dynamically re-sized
+
+ - yaml/nginx-multi.bom
diff --git a/software/webapp/src/main/resources/nginx-logo.jpeg b/software/webapp/src/main/resources/nginx-logo.jpeg
deleted file mode 100644
index 07153a3..0000000
--- a/software/webapp/src/main/resources/nginx-logo.jpeg
+++ /dev/null
Binary files differ
diff --git a/software/webapp/src/main/resources/nginx-logo.png b/software/webapp/src/main/resources/nginx-logo.png
new file mode 100644
index 0000000..b3faf63
--- /dev/null
+++ b/software/webapp/src/main/resources/nginx-logo.png
Binary files differ
diff --git a/software/webapp/src/main/resources/scripts/nginx-render-server.sh b/software/webapp/src/main/resources/scripts/nginx-render-server.sh
new file mode 100644
index 0000000..4037b2e
--- /dev/null
+++ b/software/webapp/src/main/resources/scripts/nginx-render-server.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# 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.
+
+# TODO: verify required environment variables are set
+# TODO: emit comment block
+
+echo "server {"
+
+[[ -n "$hostName" ]] && echo " server_name ${hostName};"
+
+echo " location / { proxy_pass http://targets-${groupName}; }"
+echo "}"
diff --git a/software/webapp/src/main/resources/scripts/nginx-render-upstream.sh b/software/webapp/src/main/resources/scripts/nginx-render-upstream.sh
new file mode 100644
index 0000000..2466437
--- /dev/null
+++ b/software/webapp/src/main/resources/scripts/nginx-render-upstream.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# 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.
+
+# TODO: verify required environment variables are set
+# TODO: emit comment block
+
+echo "upstream targets-${groupName} {"
+
+# can't have an empty 'upstream' block, so add a placeholder 'server' entry if needed
+[[ -z "${serverAddresses}" ]] && echo " server 0.0.0.0;"
+
+for s in ${serverAddresses}; do
+ echo " server $s;"
+done
+
+echo "}"
diff --git a/software/webapp/src/main/resources/yaml/nginx-multi.bom b/software/webapp/src/main/resources/yaml/nginx-multi.bom
new file mode 100644
index 0000000..4c99502
--- /dev/null
+++ b/software/webapp/src/main/resources/yaml/nginx-multi.bom
@@ -0,0 +1,167 @@
+# 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.
+
+brooklyn.catalog:
+ items:
+ - id: nginx-multi
+ name: Multi-cluster NGINX
+ iconUrl: classpath:///nginx-logo.png
+ description: |
+ Create a RHEL or CentOS load balancer which can be pointed at groups of servers and routed via multiple host names.
+ Use <code>render-targets</code> to configure a unique group of servers and <code>render-routing</code> to configure a
+ unique route for the group. Use <code>delete-targets</code> and <code>delete-routing</code> to delete previously
+ configure group or route, respectively.
+ item:
+ name: NGINX (multi)
+ type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess
+
+ brooklyn.parameters:
+
+ - name: install.command
+ pinned: false
+ - name: customize.command
+ pinned: false
+ - name: launch.command
+ pinned: false
+ - name: checkRunning.command
+ pinned: false
+ - name: stop.command
+ pinned: false
+
+ #------------------------------------------------------------------------------------------
+
+ brooklyn.config:
+
+ http.port: 80
+
+ dontRequireTtyForSudo: true
+ sshMonitoring.enabled: false
+
+ shell.env:
+ NGINX_PID: /var/run/nginx.pid
+ CONF_DIR: /etc/nginx/conf.d
+ SCRIPT_DIR: $brooklyn:attributeWhenReady("install.dir")
+
+ files.install:
+ classpath://scripts/nginx-render-server.sh: nginx-render-server.sh
+ classpath://scripts/nginx-render-upstream.sh: nginx-render-upstream.sh
+
+ install.command: |
+ sudo yum install -y firewalld
+ sudo systemctl enable firewalld
+ sudo systemctl start firewalld
+ chmod +x ${SCRIPT_DIR}/*.sh
+ sudo yum install -y nginx
+ sudo firewall-cmd --permanent --zone=public --add-service=http
+ sudo firewall-cmd --reload
+
+ launch.command: |
+ sudo nginx
+
+ stop.command: |
+ # let worker processes complete processing of in-flight requests
+ sudo nginx -s quit
+
+ checkRunning.command: |
+ PID=`cat "${NGINX_PID}"`
+ sudo kill -0 $PID
+
+ #------------------------------------------------------------------------------------------
+
+ brooklyn.initializers:
+
+ - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector
+ brooklyn.config:
+ name: reload
+ description: Reload config files
+ command: |
+ sudo nginx -s reload
+
+ - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector
+ brooklyn.config:
+ name: render-targets
+ description: Create config file for 'upstream' block
+ parameters:
+ groupName:
+ description: Name of this group
+ serverAddresses:
+ description: Collection of servers separated by space, e.g. '1.2.3.4:8080 2.3.4.5'
+ command: |
+ confFile="${CONF_DIR}/targets-${groupName}.conf"
+ [[ -f "$confFile" ]] && echo "Updating ${confFile}:" || echo "Creating ${confFile}:"
+ ${SCRIPT_DIR}/nginx-render-upstream.sh | sudo tee ${confFile}
+ echo "Reloading config"
+ sudo nginx -s reload
+ echo "Done"
+
+ - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector
+ brooklyn.config:
+ name: render-routing
+ description: Create config file for 'server' block
+ parameters:
+ logicalName:
+ description: Name of this routing configuration
+ hostName: {}
+ groupName:
+ description: Name of group to render routing for
+ command: |
+ confFile="${CONF_DIR}/routing-${logicalName}.conf"
+ [[ -z "$logicalName" ]] && confFile="${CONF_DIR}/default.conf"
+ [[ -f "$confFile" ]] && echo "Updating ${confFile}:" || echo "Creating ${confFile}:"
+ ${SCRIPT_DIR}/nginx-render-server.sh | sudo tee ${confFile}
+ echo "Reloading config"
+ sudo nginx -s reload
+ echo "Done"
+
+ - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector
+ brooklyn.config:
+ name: delete-routing
+ description: Remove an existing 'server' block
+ parameters:
+ logicalName:
+ description: Name of the routing configuration to remove
+
+ command: |
+ confFile="${CONF_DIR}/routing-${logicalName}.conf"
+ [[ -z "$logicalName" ]] && confFile="${CONF_DIR}/default.conf"
+ echo "Deleting ${confFile}"
+ sudo rm -f ${confFile}
+ echo "Reloading config"
+ sudo nginx -s reload
+ echo "Done"
+
+ - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector
+ brooklyn.config:
+ name: delete-targets
+ description: Remove an existing 'upstream' block
+ parameters:
+ groupName:
+ description: Name of the group to remove
+ command: |
+ confFile="${CONF_DIR}/targets-${groupName}.conf"
+ echo "Deleting ${confFile}"
+ sudo rm -f ${confFile}
+ echo "Reloading config"
+ sudo nginx -s reload
+ echo "Done"
+
+ - id: nginx-multi-upstream-sync
+ itemType: policy
+ name: Multi-cluster NGINX config synchronizer
+ iconUrl: classpath:///nginx-logo.png
+ item:
+ type: org.apache.brooklyn.entity.webapp.nginx.UpstreamSyncPolicy
\ No newline at end of file