Skip to content
This repository has been archived by the owner on May 7, 2018. It is now read-only.

Commit

Permalink
Merge pull request #1 from cloudify-examples/CFY-3574-Ansible-Nodecellar
Browse files Browse the repository at this point in the history
Cfy 3574 ansible nodecellar
  • Loading branch information
EarthmanT committed Jul 5, 2016
2 parents 14077bf + f65a70d commit cda2e7f
Show file tree
Hide file tree
Showing 13 changed files with 367 additions and 0 deletions.
35 changes: 35 additions & 0 deletions README.md
@@ -1,2 +1,37 @@
# cloudify-nodecellar-example-ansible
A spin on the Cloudify-Nodecellar-Example using Ansible instead of bash scripts.

## Notes

* This is a community contributed example.
* Tested only with Cloudify 3.3m4

## Instructions

Download the Vagrant Box from GetCloudify.org: http://getcloudify.org/guide/3.2/quickstart.html#important-before-you-begin.

These simple commands should start the deployment on your vagrant machine:

`
cd /vagrant
`
`
git clone https://github.com/cloudify-examples/cloudify-nodecellar-example-ansible.git
`

`
cd cloudify-nodecellar-example-ansible
`

`
git checkout {branch or tag id}
`

`
cfy local init --install-plugins -p local-ansible-blueprint.yaml -i inputs/local.yaml.template
`

`
cfy local execute -w install
`

5 changes: 5 additions & 0 deletions inputs/local.yaml.template
@@ -0,0 +1,5 @@
# If you are using the vagrant box

host_ip: 10.10.1.10
agent_user: vagrant
agent_private_key_path: ~/.ssh/agent_key.pem
83 changes: 83 additions & 0 deletions local-ansible-blueprint.yaml
@@ -0,0 +1,83 @@
###########################################################
# This Blueprint installs the nodecellar application
# on an existing host.
###########################################################

tosca_definitions_version: cloudify_dsl_1_3

imports:
- http://www.getcloudify.org/spec/cloudify/3.4/types.yaml
- http://www.getcloudify.org/spec/diamond-plugin/1.3.3/plugin.yaml
- types/ansible-types.yaml

#####################################################################################
# inputs section allows the user to use same
# blueprint for creating different deployments, each one
# with its own parameters.
# to specify deployment inputs run:
# - cfy deployments create -b <blueprint_id> -d <deployment_id> -i inputs.json
#####################################################################################

inputs:

host_ip:
description: >
The ip of the host the application will be deployed on
agent_user:
description: >
The agent user on the machine.
agent_private_key_path:
description: >
The path to the ssh key on the machine.
node_templates:

ansible:
type: ansible.nodes.Ansible
properties:
playbook_file_name: main.yaml
relationships:
- type: ansible.relationships.contained_in
target: host

mongod:
type: ansible.nodes.MongoDatabase
relationships:
- type: cloudify.relationships.contained_in
target: host
- type: ansible.relationships.provisioned_by
target: ansible

nodejs:
type: ansible.nodes.NodecellarApplicationModule
relationships:
- type: cloudify.relationships.contained_in
target: host
- type: ansible.relationships.provisioned_by
target: ansible
- type: node_connected_to_mongo
target: mongod

host:
type: cloudify.nodes.Compute
properties:
install_agent: false
ip: { get_input: host_ip }
cloudify_agent:
user: { get_input: agent_user }
key: { get_input: agent_private_key_path }

###########################################################
# This outputs section exposes the application endpoint.
# You can access it by running:
# - cfy deployments -d <deployment_id> outputs
###########################################################

outputs:
endpoint:
description: Web application endpoint
value:
ip_address: { get_property: [ host, ip ] }
port: 8080
5 changes: 5 additions & 0 deletions resources/ansible.cfg
@@ -0,0 +1,5 @@
[defaults]
host_key_checking=False
private_key_file={{ ctx.instance.runtime_properties['agentkey'] }}
inventory=/tmp/{{ ctx.execution_id }}/ansible/inventory
log_path=/tmp/{{ ctx.execution_id }}/ansible/ansible.log
7 changes: 7 additions & 0 deletions resources/dbservers.yaml
@@ -0,0 +1,7 @@
# /tmp/deployment/ansible/dbservers.yaml

- hosts: {{ ctx.source.node.name }}
roles:
- Stouts.mongodb
vars:
mongodb_conf_port: {{ ctx.source.node.properties.port }}
15 changes: 15 additions & 0 deletions resources/main.yaml
@@ -0,0 +1,15 @@

- hosts: {{ ctx.node.name }}
tasks:
- name: downloading Stouts.mongodb archive
get_url: url=https://github.com/Stouts/Stouts.mongodb/archive/2.1.0.tar.gz dest=/tmp/{{ ctx.execution_id }}/Stouts.mongodb.tar.gz
- name: Unarchiving Stouts.mongodb Package
unarchive: src=/tmp/{{ ctx.execution_id }}/Stouts.mongodb.tar.gz dest=/tmp/{{ ctx.execution_id }}/ansible/roles
- name: renaming roles
command: mv /tmp/{{ ctx.execution_id }}/ansible/roles/Stouts.mongodb-2.1.0 /tmp/{{ ctx.execution_id }}/ansible/roles/Stouts.mongodb
- name: downloading ansible-role-nodejs archive
get_url: url=https://github.com/geerlingguy/ansible-role-nodejs/archive/1.2.0.tar.gz dest=/tmp/{{ ctx.execution_id }}/ansible-role-nodejs.tar.gz
- name: Unarchiving ansible-role-nodejs Package
unarchive: src=/tmp/{{ ctx.execution_id }}/ansible-role-nodejs.tar.gz dest=/tmp/{{ ctx.execution_id }}/ansible/roles
- name: renaming roles
command: mv /tmp/{{ ctx.execution_id }}/ansible/roles/ansible-role-nodejs-1.2.0 /tmp/{{ ctx.execution_id }}/ansible/roles/ansible-role-nodejs
19 changes: 19 additions & 0 deletions resources/webservers.yaml
@@ -0,0 +1,19 @@

- hosts: {{ ctx.source.node.name }}
# remote_user: root
tasks:
- name: downloading nodecellar archive
get_url: url=https://github.com/cloudify-cosmo/nodecellar/archive/master.tar.gz dest=/tmp/{{ ctx.execution_id }}/master.tar.gz
- name: Unarchiving Nodecellar Package
unarchive: src=/tmp/{{ ctx.execution_id }}/master.tar.gz dest=/tmp/{{ ctx.execution_id }}/
- name: installing nodecellar dependencies
npm: path=/tmp/{{ ctx.execution_id }}/nodecellar-master/
- name: running nodecellar
command: forever start /tmp/{{ ctx.execution_id }}/nodecellar-master/server.js
environment:
NODECELLAR_PORT: {{ ctx.source.node.properties.port }}
MONGO_HOST: {{ ctx.source.instance.runtime_properties.mongo_host }}
MONGO_PORT: {{ ctx.source.instance.runtime_properties.mongo_port }}
poll: 0
roles:
- ansible-role-nodejs
9 changes: 9 additions & 0 deletions scripts/ansible/establish.sh
@@ -0,0 +1,9 @@
#!/bin/bash

TEMP_DIR='/tmp'
ANSIBLE_DIRECTORY=${TEMP_DIR}/$(ctx execution-id)/ansible
FILENAME=$(ctx source node properties playbook_file_name)
PLAYBOOK_PATH=${ANSIBLE_DIRECTORY}/${FILENAME}
export ANSIBLE_CONFIG=$(ctx target instance runtime-properties confpath)
ansible-playbook ${PLAYBOOK_PATH} --sudo --connection=paramiko -vvvv > ${ANSIBLE_DIRECTORY}/output.log 2>&1
ctx logger info "executed ${PLAYBOOK_PATH}"
34 changes: 34 additions & 0 deletions scripts/ansible/post.sh
@@ -0,0 +1,34 @@
#!/bin/bash -e

TEMP_DIR='/tmp'
ANSIBLE_DIRECTORY=${TEMP_DIR}/$(ctx execution-id)/ansible
FILENAME=$(ctx source node properties playbook_file_name)
PLAYBOOK_PATH=${ANSIBLE_DIRECTORY}/${FILENAME}

NODE_HOSTNAME=$(ctx source node name)
NODE_ADDRESS=$(ctx source instance host_ip)

set -e
if ! ping -c 1 ${NODE_HOSTNAME} > /dev/null; then
echo "${NODE_ADDRESS} ${NODE_HOSTNAME}" | sudo tee -a /etc/hosts
ctx logger info "added hostname ${NODE_HOSTNAME}"
fi
set +e

cat <<EOF > ${ANSIBLE_DIRECTORY}/inventory
$NODE_HOSTNAME
EOF
ctx logger info "added ${NODE_HOSTNAME} to inventory"

PLAYBOOK=$(ctx download-resource-and-render resources/${FILENAME})
cp $PLAYBOOK $PLAYBOOK_PATH
set -e
if stat $PLAYBOOK; then
ctx logger info "downloaded resource to ${PLAYBOOK_PATH}"
else ctx logger info "resource not downloaded."
fi
if stat $PLAYBOOK_PATH; then
ctx logger info "copied to ${PLAYBOOK_PATH}"
else ctx logger info "resource not copied."
fi
set e
3 changes: 3 additions & 0 deletions scripts/ansible/pre.sh
@@ -0,0 +1,3 @@
#!/bin/bash

ctx source instance runtime-properties agentkey $(ctx target node properties cloudify_agent.key)
49 changes: 49 additions & 0 deletions scripts/ansible/start.sh
@@ -0,0 +1,49 @@
#!/bin/bash -e

ctx logger info "installing ansible"

# Make sure that ansible exists in the virtualenv
set -e
if ! type ansible > /dev/null; then
pip install ansible
ctx logger info "installed ansible"
fi
set +e

TEMP_DIR='/tmp'
ANSIBLE_DIRECTORY=${TEMP_DIR}/$(ctx execution-id)/ansible
FILENAME=$(ctx node properties playbook_file_name)
PLAYBOOK_PATH=${ANSIBLE_DIRECTORY}/${FILENAME}

mkdir -p ${ANSIBLE_DIRECTORY}/roles

# Download and Move the Default Ansible Config in place
TEMP_CONF_PATH=$(ctx download-resource-and-render resources/ansible.cfg)
ctx logger info "downloaded resource to ${TEMP_CONF_PATH}"
CONF_PATH=$ANSIBLE_DIRECTORY/ansible.cfg
cp $TEMP_CONF_PATH $CONF_PATH
ctx logger info "copied ${TEMP_CONF_PATH} ${CONF_PATH}"
export ANSIBLE_CONFIG=${CONF_PATH}
ctx instance runtime-properties confpath ${CONF_PATH}

# Add the ansible hostname name to the inventory and to etc hosts
NODE_HOSTNAME=$(ctx node name)
NODE_ADDRESS=$(ctx instance host_ip)

cat <<EOF > ${ANSIBLE_DIRECTORY}/inventory
$NODE_HOSTNAME
EOF

set -e
if ! ping -c 1 ${NODE_HOSTNAME} > /dev/null; then
echo "${NODE_ADDRESS} ${NODE_HOSTNAME}" | sudo tee -a /etc/hosts
ctx logger info "added hostname ${NODE_HOSTNAME}"
fi
set +e

# Download the playbook that will download the roles for the other modules
PLAYBOOK=$(ctx download-resource-and-render resources/${FILENAME})
cp $PLAYBOOK $PLAYBOOK_PATH
ctx logger info "downloaded resource to ${PLAYBOOK_PATH}"
ansible-playbook ${PLAYBOOK_PATH} --connection=paramiko -vvvv > ${ANSIBLE_DIRECTORY}/output.log 2>&1
ctx logger info "executed ${PLAYBOOK_PATH}"
4 changes: 4 additions & 0 deletions scripts/mongo/assign-mongo-environment.sh
@@ -0,0 +1,4 @@
#!/bin/bash -e

ctx source instance runtime_properties mongo_host $(ctx target node name)
ctx source instance runtime_properties mongo_port $(ctx target node properties port)
99 changes: 99 additions & 0 deletions types/ansible-types.yaml
@@ -0,0 +1,99 @@
################################################################
# Blueprint node types.
#
# specific new types for the nodecellar app.
# these types are mapped to scripts that are resposible
# for the lifecycle operation.
################################################################

node_types:

ansible.nodes.Ansible:
derived_from: cloudify.nodes.SoftwareComponent
properties:
playbook_file_name:
description: >
The name of a playbook needed to execute this nodes requirements.
Also, this is the name of the same file under ./resources.
type: string
interfaces:
cloudify.interfaces.lifecycle:
start: scripts/ansible/start.sh

ansible.nodes.AnsibleModule:
derived_from: ansible.nodes.Ansible
properties:
port:
default: 65536
interfaces:
cloudify.interfaces.lifecycle:
create: {}
start: {}

###########################################################
# Mongo Database.
#
# Used the data backend for the nodecellar application.
# configurable properties:
# - port
###########################################################

ansible.nodes.MongoDatabase:
derived_from: ansible.nodes.AnsibleModule
properties:
port:
default: 27017
playbook_file_name:
default: dbservers.yaml

###########################################################
# Nodecellar application.
#
# This is the actual application source files.
# configurable properties:
# - port
# - application url
# - startup script
###########################################################

ansible.nodes.NodecellarApplicationModule:
derived_from: ansible.nodes.AnsibleModule
properties:
port:
default: 8080
playbook_file_name:
default: webservers.yaml

################################################################
# Blueprint relationships.
#
# specific new relationships for the nodecellar app.
# these relationships are mapped to scripts that are resposible
# for the relationship operation.
################################################################

relationships:

ansible.relationships.contained_in:
derived_from: cloudify.relationships.contained_in
target_interfaces:
cloudify.interfaces.relationship_lifecycle:
preconfigure:
implementation: scripts/ansible/pre.sh

ansible.relationships.provisioned_by:
derived_from: cloudify.relationships.depends_on
properties:
connection_type:
default: all_to_one
target_interfaces:
cloudify.interfaces.relationship_lifecycle:
postconfigure: scripts/ansible/post.sh
establish: scripts/ansible/establish.sh

node_connected_to_mongo:
derived_from: cloudify.relationships.connected_to
target_interfaces:
cloudify.interfaces.relationship_lifecycle:
preconfigure: scripts/mongo/assign-mongo-environment.sh

0 comments on commit cda2e7f

Please sign in to comment.