Merge pull request #14 from tgerla/play
initial commit of a simple Play webapp and Ansible playbooks (Original a...pull/63/head
commit
60526841a4
@ -0,0 +1,108 @@ |
||||
# Deploying a Play/Scala-based web application with Ansible |
||||
|
||||
- Requires Ansible 1.2 |
||||
- Expects CentOS/RHEL 6 hosts (64 bit) |
||||
|
||||
### A Primer into Play Framework |
||||
---------------------------------- |
||||
|
||||
- Play Framework: Play is a pure Java and Scala framework used to develop Web |
||||
Applications, It focuses on developer productivity, modern web and mobile |
||||
applications, and predictable, minimal resource consumption (CPU, memory, |
||||
threads) resulting in highly performant, highly scalable applications, Play |
||||
compiles Java and Scala sources directly and hot-reloads them into the JVM |
||||
without the need to restart the server. |
||||
|
||||
- Akka: Akka is a toolkit and runtime for building highly concurrent, |
||||
distributed, and fault tolerant event-driven applications on the JVM. |
||||
|
||||
- Scala: Scala is a general purpose programming language designed to express |
||||
common programming patterns in a concise, elegant, and type-safe way. Scala |
||||
smoothly integrates features of object-oriented and functional languages, |
||||
enabling developers to be more productive while retaining full interoperability |
||||
with Java and taking advantage of modern multicore hardware. Scala makes it |
||||
easy to avoid shared state, so that computation can be readily distributed |
||||
across cores on a multicore server, and across servers in a datacenter. This |
||||
makes Scala an especially good match for modern multicore CPUs and distributed |
||||
cloud-computing workloads that require concurrency and parallelism. |
||||
|
||||
|
||||
## Example Deployment using Ansible |
||||
|
||||
This example deploys a very simple application which takes a hostname as a parameter |
||||
from the user and uses Ansible itself to gather and display facts from that machine. |
||||
It shows how to deploy a simple Play-based app, as well as how to call out to Ansible |
||||
from inside Scala. |
||||
|
||||
Before running the playbook, modify the inventory file 'hosts' to match your |
||||
environment. Here's an example inventory: |
||||
|
||||
[webapp_server] |
||||
play_server |
||||
|
||||
Run the playbook to deploy the app: |
||||
|
||||
ansible-playbook -i hosts site.yml |
||||
|
||||
Once the playbooks complete, you can check the deployment by logging into the |
||||
server console at http://<server-ip>:9000/. You should get a page similar to |
||||
image below. |
||||
|
||||
![Alt text](/images/play_webapp.png "webapp") |
||||
|
||||
## Fetching Facts from Hosts |
||||
|
||||
To use the example webapp and fetch facts from a host, enter the hostname of |
||||
host as shown in the figure above and press submit. Please note that the |
||||
application uses Ansible to gather facts so the hosts should have SSH keys |
||||
set up and the host entry should be available in the Ansible inventory file in |
||||
/etc/ansible/hosts. |
||||
|
||||
Upon submission, the application should return a valid json consisting the host |
||||
facts: |
||||
|
||||
localhost | success >> { |
||||
"ansible_facts": { |
||||
"ansible_all_ipv4_addresses": [ |
||||
"192.168.2.51" |
||||
], |
||||
"ansible_all_ipv6_addresses": [ |
||||
"fe80::5054:ff:fe58:776d" |
||||
], |
||||
"ansible_architecture": "x86_64", |
||||
"ansible_bios_date": "01/01/2007", |
||||
"ansible_bios_version": "0.5.1", |
||||
"ansible_cmdline": { |
||||
"KEYBOARDTYPE": "pc", |
||||
"KEYTABLE": "us", |
||||
"LANG": "en_US.UTF-8", |
||||
"SYSFONT": "latarcyrheb-sun16", |
||||
"quiet": true, |
||||
"rd_NO_DM": true, |
||||
"rd_NO_LUKS": true, |
||||
"rd_NO_LVM": true, |
||||
"rd_NO_MD": true, |
||||
"rhgb": true, |
||||
"ro": true, |
||||
"root": "UUID=5202a2bc-1a30-424f-855b-5d51a3cba8df" |
||||
}, |
||||
"ansible_date_time": { |
||||
"date": "2013-05-25", |
||||
"day": "25", |
||||
"epoch": "1369483888", |
||||
"hour": "17", |
||||
"iso8601": "2013-05-25T12:11:28Z", |
||||
"iso8601_micro": "2013-05-25T12:11:28.551538Z", |
||||
"minute": "41", |
||||
"month": "05", |
||||
"second": "28", |
||||
"time": "17:41:28", |
||||
"tz": "IST", |
||||
"year": "2013" |
||||
}, |
||||
|
||||
|
||||
The facts can also be fetched by making a GET request with following url. |
||||
|
||||
http://<serverip>:9000/inventoryID?hostname=<hostname> |
||||
|
@ -0,0 +1,2 @@ |
||||
[webapp_server] |
||||
webserver1 |
After Width: | Height: | Size: 56 KiB |
@ -0,0 +1,29 @@ |
||||
-----BEGIN PGP PUBLIC KEY BLOCK----- |
||||
Version: GnuPG v1.4.5 (GNU/Linux) |
||||
|
||||
mQINBEvSKUIBEADLGnUj24ZVKW7liFN/JA5CgtzlNnKs7sBg7fVbNWryiE3URbn1 |
||||
JXvrdwHtkKyY96/ifZ1Ld3lE2gOF61bGZ2CWwJNee76Sp9Z+isP8RQXbG5jwj/4B |
||||
M9HK7phktqFVJ8VbY2jfTjcfxRvGM8YBwXF8hx0CDZURAjvf1xRSQJ7iAo58qcHn |
||||
XtxOAvQmAbR9z6Q/h/D+Y/PhoIJp1OV4VNHCbCs9M7HUVBpgC53PDcTUQuwcgeY6 |
||||
pQgo9eT1eLNSZVrJ5Bctivl1UcD6P6CIGkkeT2gNhqindRPngUXGXW7Qzoefe+fV |
||||
QqJSm7Tq2q9oqVZ46J964waCRItRySpuW5dxZO34WM6wsw2BP2MlACbH4l3luqtp |
||||
Xo3Bvfnk+HAFH3HcMuwdaulxv7zYKXCfNoSfgrpEfo2Ex4Im/I3WdtwME/Gbnwdq |
||||
3VJzgAxLVFhczDHwNkjmIdPAlNJ9/ixRjip4dgZtW8VcBCrNoL+LhDrIfjvnLdRu |
||||
vBHy9P3sCF7FZycaHlMWP6RiLtHnEMGcbZ8QpQHi2dReU1wyr9QgguGU+jqSXYar |
||||
1yEcsdRGasppNIZ8+Qawbm/a4doT10TEtPArhSoHlwbvqTDYjtfV92lC/2iwgO6g |
||||
YgG9XrO4V8dV39Ffm7oLFfvTbg5mv4Q/E6AWo/gkjmtxkculbyAvjFtYAQARAQAB |
||||
tCFFUEVMICg2KSA8ZXBlbEBmZWRvcmFwcm9qZWN0Lm9yZz6JAjYEEwECACAFAkvS |
||||
KUICGw8GCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRA7Sd8qBgi4lR/GD/wLGPv9 |
||||
qO39eyb9NlrwfKdUEo1tHxKdrhNz+XYrO4yVDTBZRPSuvL2yaoeSIhQOKhNPfEgT |
||||
9mdsbsgcfmoHxmGVcn+lbheWsSvcgrXuz0gLt8TGGKGGROAoLXpuUsb1HNtKEOwP |
||||
Q4z1uQ2nOz5hLRyDOV0I2LwYV8BjGIjBKUMFEUxFTsL7XOZkrAg/WbTH2PW3hrfS |
||||
WtcRA7EYonI3B80d39ffws7SmyKbS5PmZjqOPuTvV2F0tMhKIhncBwoojWZPExft |
||||
HpKhzKVh8fdDO/3P1y1Fk3Cin8UbCO9MWMFNR27fVzCANlEPljsHA+3Ez4F7uboF |
||||
p0OOEov4Yyi4BEbgqZnthTG4ub9nyiupIZ3ckPHr3nVcDUGcL6lQD/nkmNVIeLYP |
||||
x1uHPOSlWfuojAYgzRH6LL7Idg4FHHBA0to7FW8dQXFIOyNiJFAOT2j8P5+tVdq8 |
||||
wB0PDSH8yRpn4HdJ9RYquau4OkjluxOWf0uRaS//SUcCZh+1/KBEOmcvBHYRZA5J |
||||
l/nakCgxGb2paQOzqqpOcHKvlyLuzO5uybMXaipLExTGJXBlXrbbASfXa/yGYSAG |
||||
iVrGz9CE6676dMlm8F+s3XXE13QZrXmjloc6jwOljnfAkjTGXjiB7OULESed96MR |
||||
XtfLk0W5Ab9pd7tKDR6QHI7rgHXfCopRnZ2VVQ== |
||||
=V/6I |
||||
-----END PGP PUBLIC KEY BLOCK----- |
@ -0,0 +1,26 @@ |
||||
[epel] |
||||
name=Extra Packages for Enterprise Linux 6 - $basearch |
||||
#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch |
||||
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch |
||||
failovermethod=priority |
||||
enabled=1 |
||||
gpgcheck=1 |
||||
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6 |
||||
|
||||
[epel-debuginfo] |
||||
name=Extra Packages for Enterprise Linux 6 - $basearch - Debug |
||||
#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch/debug |
||||
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-debug-6&arch=$basearch |
||||
failovermethod=priority |
||||
enabled=0 |
||||
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6 |
||||
gpgcheck=1 |
||||
|
||||
[epel-source] |
||||
name=Extra Packages for Enterprise Linux 6 - $basearch - Source |
||||
#baseurl=http://download.fedoraproject.org/pub/epel/6/SRPMS |
||||
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-source-6&arch=$basearch |
||||
failovermethod=priority |
||||
enabled=0 |
||||
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6 |
||||
gpgcheck=1 |
@ -0,0 +1,3 @@ |
||||
--- |
||||
- name: restart iptables |
||||
service: name=iptables state=restarted |
@ -0,0 +1,30 @@ |
||||
--- |
||||
# plays common across all servers |
||||
|
||||
- name: Copy the EPEL Repository. |
||||
copy: src=epel.repo dest=/etc/yum.repos.d/epel.repo |
||||
|
||||
- name: Create the GPG key for EPEL |
||||
copy: src=RPM-GPG-KEY-EPEL-6 dest=/etc/pki/rpm-gpg |
||||
|
||||
- name: install Java and other dependencies |
||||
yum: name={{ item }} state=installed |
||||
with_items: |
||||
- java-1.6.0-openjdk |
||||
- java-1.6.0-openjdk-devel |
||||
- libselinux-python |
||||
- ansible |
||||
- zip |
||||
- unzip |
||||
- wget |
||||
|
||||
- name: Ensure the user has a ssh key |
||||
user: name={{ ansible_ssh_user }} generate_ssh_key=yes |
||||
|
||||
- name: Make sure we have the authorized_key for local user |
||||
shell: cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys ; touch ~/.ssh/key_authorized |
||||
creates=~/.ssh/key_authorized |
||||
|
||||
- name: setup iptables rules |
||||
template: src=iptables.j2 dest=/etc/sysconfig/iptables |
||||
notify: restart iptables |
@ -0,0 +1,15 @@ |
||||
# Firewall configuration written by system-config-firewall |
||||
# Manual customization of this file is not recommended. |
||||
*filter |
||||
:INPUT ACCEPT [0:0] |
||||
:FORWARD ACCEPT [0:0] |
||||
:OUTPUT ACCEPT [0:0] |
||||
|
||||
-A INPUT -p tcp --dport 9000 -j ACCEPT |
||||
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT |
||||
-A INPUT -p icmp -j ACCEPT |
||||
-A INPUT -i lo -j ACCEPT |
||||
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT |
||||
-A INPUT -j REJECT --reject-with icmp-host-prohibited |
||||
-A FORWARD -j REJECT --reject-with icmp-host-prohibited |
||||
COMMIT |
Binary file not shown.
@ -0,0 +1,108 @@ |
||||
#!/bin/bash |
||||
# chkconfig: 345 20 80 |
||||
# description: Play start/shutdown script |
||||
# processname: play |
||||
# |
||||
# Instalation: |
||||
# copy file to /etc/init.d |
||||
# chmod +x /etc/init.d/play |
||||
# chkconfig --add /etc/init.d/play |
||||
# chkconfig play on |
||||
# |
||||
# Usage: (as root) |
||||
# service play start |
||||
# service play stop |
||||
# service play status |
||||
# |
||||
# Remember, you need python 2.6 to run the play command, it doesn't come standard with RedHat/Centos 5.5 |
||||
# Also, you may want to temporarily remove the >/dev/null for debugging purposes |
||||
|
||||
# Path to play install folder |
||||
PLAY_HOME=/opt/play |
||||
PLAY=$PLAY_HOME/play |
||||
|
||||
# Source function library. |
||||
. /etc/rc.d/init.d/functions |
||||
|
||||
# Path to the JVM |
||||
JAVA_HOME=/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/ |
||||
export JAVA_HOME |
||||
|
||||
# User running the Play process |
||||
USER=root |
||||
|
||||
# Path to the application |
||||
APPLICATION_PATH=/opt/webapp/ |
||||
APPLICATION_MODE=prod |
||||
|
||||
#APPLICATION2_PATH=/path/to/application2 |
||||
#APPLICATION_MODE=prod |
||||
|
||||
# source function library |
||||
. /etc/init.d/functions |
||||
RETVAL=0 |
||||
|
||||
start() { |
||||
echo -n "Starting Play service: " |
||||
daemon "/opt/webapp/target/start >/dev/null &" |
||||
RETVAL=$? |
||||
|
||||
# You may want to start more applications as follows |
||||
# [ $RETVAL -eq 0 ] && su -s /bin/sh $USER -c "${PLAY} start ${APPLICATION2_PATH} --%${APPLICATION_MODE} > /dev/null" |
||||
# RETVAL=$? |
||||
|
||||
if [ $RETVAL -eq 0 ]; then |
||||
echo_success |
||||
else |
||||
echo_failure |
||||
fi |
||||
echo |
||||
} |
||||
stop() { |
||||
echo -n "Shutting down Play service: " |
||||
(cd ${APPLICATION_PATH} ; ${PLAY} stop .) |
||||
|
||||
RETVAL=$? |
||||
|
||||
if [ $RETVAL -eq 0 ]; then |
||||
echo_success |
||||
else |
||||
echo_failure |
||||
fi |
||||
echo |
||||
} |
||||
status() { |
||||
test -f ${APPLICATION_PATH}/RUNNING_PID |
||||
RETVAL=$? |
||||
if [ $RETVAL -eq 0 ]; then |
||||
echo play is running as pid `cat ${APPLICATION_PATH}/RUNNING_PID` |
||||
else |
||||
echo play is not running |
||||
fi |
||||
} |
||||
clean() { |
||||
rm -f ${APPLICATION_PATH}/RUNNING_PID |
||||
} |
||||
case "$1" in |
||||
start) |
||||
clean |
||||
start |
||||
;; |
||||
stop) |
||||
stop |
||||
;; |
||||
restart|reload) |
||||
stop |
||||
sleep 10 |
||||
start |
||||
;; |
||||
status) |
||||
status |
||||
;; |
||||
clean) |
||||
clean |
||||
;; |
||||
*) |
||||
echo "Usage: $0 {start|stop|restart|status}" |
||||
esac |
||||
exit 0 |
@ -0,0 +1,3 @@ |
||||
--- |
||||
- name: restart play |
||||
service: name=play state=restarted |
@ -0,0 +1,32 @@ |
||||
--- |
||||
- name: copy the webapp |
||||
copy: src=ansible-facts-webapp.tgz dest=/opt/ |
||||
|
||||
- name: download the play framework |
||||
get_url: url=http://downloads.typesafe.com/play/2.1.1/play-2.1.1.zip dest=/opt/play-2.1.1.zip |
||||
|
||||
- name: extract the play framework |
||||
command: chdir=/opt/ unzip play-2.1.1.zip |
||||
creates=/opt/play-2.1.1 |
||||
|
||||
- name: symlink for convenience |
||||
file: src=/opt/play-2.1.1 path=/opt/play state=link |
||||
|
||||
- name: extract the webapp folder |
||||
command: chdir=/opt/ tar -xvzf ansible-facts-webapp.tgz |
||||
creates=/opt/webapp |
||||
|
||||
- name: Build and compile the webapp |
||||
shell: chdir=/opt/webapp export PATH=$PATH:/opt/play-2.1.1/; play clean compile stage |
||||
creates=/opt/webapp/target |
||||
notify: restart play |
||||
|
||||
- name: Copy the ansible hosts file |
||||
copy: src=hosts dest=/etc/ansible/hosts |
||||
|
||||
- name: Copy the webapp startup file |
||||
copy: src=play.initscript dest=/etc/init.d/play mode=0755 |
||||
notify: restart play |
||||
|
||||
- name: Start Play |
||||
service: name=play state=started enabled=yes |
@ -0,0 +1,8 @@ |
||||
--- |
||||
# Main Play webapp deployment playbook |
||||
|
||||
- hosts: webapp_server |
||||
user: root |
||||
roles: |
||||
- role: common |
||||
- role: webapp |
Reference in new issue