# ansible-clever
Ansible role for clever cloud deployment
+=======
+Clever deploy
+=========
+
+This roles deploy an haskell app on clever cloud (https://www.clever-cloud.com).
+
+Requirements
+------------
+
+
+Role Variables
+--------------
+
+Variables for the application
+- `clever_token`: clever_cloud token, mandatory.
+- `clever_secret`: clever_cloud secret, mandatory.
+- `clever_app`: the id of the app to link, mandatory.
+- `clever_env`: a dict of environment variables for the application (without add_ons one already available), optional.
+- `clever_addons`: a list of dict describing addons enabled for the application from which we would use information during deploy, optional.<br/>
+ Example: `{ name: pg, env_prefix: POSTGRESQL_ADDON }`
+- `clever_app_role`: role to be executed after environment and addons variables where gathered. Specific to an app, should be use to run migrations. Optional.
+- `domain`: the domain from which the application should be reachable, optional
+- `syslog_server`: UDP Syslog server to be used as UDPSyslog drain for the application, optional. Example: `udp://198.51.100.51:12345`.
+
+Variables specific to deployment, default should be fine:
+- `clever_cli_version`: Version of clever cli tools, default to `0.9.3`.
+- `clever_user_path`: Path relative to ansible_user home dir where cli tools and helpers are installed default to `.local/bin`.
+- `clever_app_root`: Path of the application to deploy, default to `"{{ playbook_dir }}/.."`, ie ansible directory in the root of the application.
+- `clever_app_confdir`: Path where to store clever cloud data specific to this application, default to `"{{ clever_app_root }}/.clever_cloud"`
+- `clever_login_file`: Path to store login information. Default to `"{{ clever_app_confdir }}/login"`.
+
+
+Dependencies
+------------
+
+None
+
+Example Playbook
+----------------
+
+Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
+
+ - hosts: servers
+ roles:
+ - { role: fretlink.clever, clever_app: 42, clever_token: "{{ vault_clever_token }}", clever_secret: "{{ vault_clever_secret}}" }
+
+
+TODO
+----
+
+Add some tests and Travis integration
+
+License
+-------
+
+BSD
+
+Author Information
+------------------
+
+Developped at Fretlink (https://www.fretlink.com) for our
--- /dev/null
+---
+# defaults file for clever
+clever_cli_version: 0.9.3
+clever_user_path: .local/bin
+clever_app_root: "{{ playbook_dir }}/.."
+clever_app_confdir: "{{ clever_app_root }}/.clever_cloud"
+clever_login_file: "{{ clever_app_confdir }}/login"
+
+clever_env: {}
+
+clever_addons: []
+# example
+# clever_addons:
+# - name: pg
+# - env_prefix: POSTGRESQL_ADDON
--- /dev/null
+#!/bin/bash -e
+
+function checkDomain {
+ clever domain | grep "${DOMAIN}"
+}
+
+function setDomain {
+ clever domain add "${DOMAIN}"
+}
+
+checkDomain || setDomain
--- /dev/null
+#!/bin/bash -e
+
+function checkDrain {
+ clever drain | grep "${SYSLOG_UDP_SERVER}"
+}
+
+function setDrain {
+ clever drain create UDPSyslog "udp://${SYSLOG_UDP_SERVER}"
+}
+
+checkDrain || setDrain
--- /dev/null
+#!/bin/bash -e
+
+function deploying {
+ checkStatus "$1" "IN PROGRESS"
+}
+
+function deployed {
+ checkStatus "$1" "OK"
+}
+
+function inactive {
+ local commit="$1"
+ [[ "$(clever activity | grep "$commit" | grep "DEPLOY" | wc -l)" == "0" ]]
+}
+
+function checkStatus {
+ local commit="$1"
+ local status="$2"
+ [[ "$(clever activity | grep "$commit" | grep "${status}\s\+DEPLOY" | wc -l)" == "1" ]]
+}
+
+function check {
+ local timeout=600 # 10 minutes
+ local commit="$1"
+ local samplingTime=5
+
+ echo "Waiting for deployment start..."
+ while inactive "$commit" -a $timeout -gt 0
+ do
+ sleep $samplingTime
+ let "timeout-=$samplingTime"
+ done
+
+ # Wait for completion
+ echo "Deployement in progress..."
+ while deploying "$commit" -a $timeout -gt 0
+ do
+ sleep $samplingTime
+ let "timeout-=$samplingTime"
+ done
+
+ if [ $samplingTime -eq 0 ]
+ then
+ echo "Timeout"
+ fi
+
+ deployed "$commit"
+}
+
+check "$(git rev-parse HEAD)"
--- /dev/null
+---
+# handlers file for clever
\ No newline at end of file
--- /dev/null
+galaxy_info:
+ author: Fretlink
+ description: Love and trucks
+ company: Fretlink
+
+ # If the issue tracker for your role is not on github, uncomment the
+ # next line and provide a value
+ # issue_tracker_url: http://example.com/issue/tracker
+
+ # Some suggested licenses:
+ # - BSD (default)
+ # - MIT
+ # - GPLv2
+ # - GPLv3
+ # - Apache
+ # - CC-BY
+ license: BSD
+
+ min_ansible_version: 2.4
+
+ # If this a Container Enabled role, provide the minimum Ansible Container version.
+ # min_ansible_container_version:
+
+ # Optionally specify the branch Galaxy will use when accessing the GitHub
+ # repo for this role. During role install, if no tags are available,
+ # Galaxy will use this branch. During import Galaxy will access files on
+ # this branch. If Travis integration is configured, only notifications for this
+ # branch will be accepted. Otherwise, in all cases, the repo's default branch
+ # (usually master) will be used.
+ github_branch: master
+
+ #
+ # platforms is a list of platforms, and each platform has a name and a list of versions.
+ #
+ # platforms:
+ # - name: Fedora
+ # versions:
+ # - all
+ # - 25
+ # - name: SomePlatform
+ # versions:
+ # - all
+ # - 1.0
+ # - 7
+ # - 99.99
+
+ galaxy_tags:
+ - clevercloud
+ - deployment
+ - cd
+ # List tags for your role here, one per line. A tag is a keyword that describes
+ # and categorizes the role. Users find roles by searching for tags. Be sure to
+ # remove the '[]' above, if you add tags to this list.
+ #
+ # NOTE: A tag is limited to a single word comprised of alphanumeric characters.
+ # Maximum 20 tags per role.
+
+dependencies: []
+ # List your role dependencies here, one per line. Be sure to remove the '[]' above,
+ # if you add dependencies to this list.
--- /dev/null
+- name: Gather addon information for {{ addon.name }}
+ shell: "clever env | grep {{ addon.env_prefix }} | sed -e 's/{{ addon.env_prefix }}_//' -e 's/=/: \"/' -e 's/$/\"/' > .clever-cloud/{{ addon.name }}_env.yml"
+ environment:
+ CONFIGURATION_FILE: "{{ clever_login_file }}"
+
+- name: Include addon var for {{ addon.name }}
+ include_vars:
+ file: "{{ addon.name }}_env.yml"
+ name: "{{ addon.name }}"
--- /dev/null
+- name: Configure Drain
+ when: syslog_server is defined
+ command: clever-set-drain.sh
+ environment:
+ SYSLOG_UDP_SERVER: "{{ syslog_server }}"
+ CONFIGURATION_FILE: "{{ clever_login_file }}"
+
+- name: Configure Domain
+ when: domain is defined
+ command: clever-set-domain.sh
+ environment:
+ DOMAIN: "{{ domain }}"
+ CONFIGURATION_FILE: "{{ clever_login_file }}"
+
+- name: Push Environment
+ shell: "clever env import < {{ clever_app_confdir }}/env"
+ environment:
+ CONFIGURATION_FILE: "{{ clever_login_file }}"
+
+#TODO: Improve ssh-key validation
+- name: Accept Clever-Cloud servers
+ shell: "ssh-keyscan -H push-par-clevercloud-customers.services.clever-cloud.com >> ~/.ssh/known_hosts"
+
+- name: Push to Clever-Cloud to trigger deployment
+ command: "git push --force git+ssh://git@push-par-clevercloud-customers.services.clever-cloud.com/{{ clever_app }}.git HEAD:refs/heads/master"
+
+- name: Wait until deployment completion
+ command: clever-wait-deploy.sh
+ environment:
+ CONFIGURATION_FILE: "{{ clever_login_file }}"
--- /dev/null
+- name: Create environment file
+ template:
+ src: env.j2
+ dest: "{{ clever_app_confdir }}/env"
+ no_log: true
+
+- name: Create add_ons variable file
+ include_tasks: addon.yml
+ vars:
+ addon: "{{ item }}"
+ with_items: "{{ clever_addons }}"
--- /dev/null
+- name: Create .clever-cloud directory
+ file:
+ path: "{{ clever_app_confdir }}"
+ state: directory
+
+- name: Fill the login file
+ template:
+ src: cleverlogin.j2
+ dest: "{{ clever_login_file }}"
+ no_log: true
+
+- name: Link app
+ shell: clever link {{ clever_app }}
+ environment:
+ CONFIGURATION_FILE: "{{ clever_login_file }}"
--- /dev/null
+---
+# tasks file for clever
+- name: Setup environment for clever
+ include_tasks: setup.yml
+ tags:
+ - clever
+ - clever-setup
+
+- name: Login to clever
+ include_tasks: login.yml
+ tags:
+ - clever
+ - clever-login
+
+- name: Manage environment
+ include_tasks: environment.yml
+ tags:
+ - clever
+ - clever-env
+
+- name: Include specific role
+ include_role: "{{ clever_app_role }}"
+ when: clever_app_role
+ tags:
+ - clever
+ - clever-specific-role
+
+- name: Deploy app
+ include_tasks: deploy.yml
+ tags:
+ - clever
+ - clever-deploy
--- /dev/null
+- name: Check if clever command is available in path and version
+ command: clever --version
+ register: clever_returned_version
+ ignore_error: true
+
+- name: Ensure user path exists
+ file:
+ path: "{{ ansible_env.HOME }}/{{ clever_user_path }}"
+ state: directory
+
+- name: Download and install clever cli tools if necessary
+ unarchive:
+ remote_src: yes
+ src: https://clever-tools.cellar.services.clever-cloud.com/releases/{{ clever_cli_version }}/clever-tools-{{ clever_cli_version }}_linux.tar.gz
+ dest: "{{ ansible_env.HOME }}/{{ clever_user_path }}"
+ when: clever_returned_version|failed or clever_returned_version.stdout != clever_cli_version
+
+- name: Install helper scripts
+ copy:
+ src: "{{ item }}"
+ dest: "{{ ansible_env.HOME }}/{{ clever_user_path }}/{{ item }}"
+ with_items:
+ - clever-set-domain.sh
+ - clever-set-drain.sh
+ - clever-wait-deploy.sh
--- /dev/null
+{
+ "token": "{{ clever_token }}",
+ "secret": "{{ clever_secret }}"
+}
--- /dev/null
+{% for key, value in clever_env.iteritems() %}
+{{ key }}={{ value }}
+{% endfor %}
--- /dev/null
+localhost
+
--- /dev/null
+---
+- hosts: localhost
+ remote_user: root
+ roles:
+ - clever
\ No newline at end of file
--- /dev/null
+---
+# vars file for clever
\ No newline at end of file