ansible-role-ara-api

_images/ansible-role-ara-api.png

This Ansible role provides a framework for installing one or many instances of ARA Records Ansible in a variety of opinionated deployment topologies.

It is currently tested and supported against Ubuntu 18.04 and Fedora 29.

Role Variables

See defaults/main.yaml.

# Root directory where every file for the ARA installation are located
ara_api_root_dir: "{{ ansible_user_dir }}/.ara"

# Directory where logs are written to
ara_api_log_dir: "{{ ara_api_root_dir }}/logs"

# Whether or not ara should be installed in a virtual environment.
# This defaults to true to prevent conflicting with system or distribution
# python packages.
ara_api_venv: true

# When using a virtualenv, path to where it will be installed
ara_api_venv_path: "{{ ara_api_root_dir }}/virtualenv"

# How ARA will be installed
# - source [default]: installs from a local or remote git repository
# - pypi [planned]: installs from pypi
ara_api_install_method: source

# When installing from source, the URL or filesystem path where the git source
# repository can be cloned from.
ara_api_source: "https://opendev.org/recordsansible/ara"

# When installing from source, location where the source repository will be checked out to.
ara_api_source_checkout: "{{ ara_api_root_dir }}/git/ara"

# Version of ARA to install
# When installing from source, this can be a git ref (tag, branch, commit, etc)
# When installing from PyPi, it would be a version number that has been released.
# When using "latest" as the source version, HEAD will be used
# When using "latest" as the pypi version, the latest release will be used
ara_api_version: master

# The frontend/web server for serving the ARA API
# It is recommended to specify a web server when deploying a production environment.
# - null [default]: No frontend server will be set up.
# - nginx: Nginx will be configured in front of the WSGI application server.
# - apache [planned]
ara_api_frontend_server: null

# Path to a custom vhost configuration jinja template
# The vhost configuration templates provided by the role are simple by design
# and are not sufficient to cover every use cases.
# Use this variable if you need to have your own custom nginx or apache configuration.
ara_api_frontend_vhost: null

# The WSGI server for running ARA's API server
# - null [default]: No persistent WSGI application server will be set up. Only the offline API client will work.
# - gunicorn: gunicorn will be installed and set up to run the API as a systemd service.
# - mod_wsgi [planned]
ara_api_wsgi_server: null

# Address and port on which the wsgi server will bind
# Changing this value means you might need to adjust "ara_api_allowed_hosts" and
# "ara_api_cors_origin_whitelist".
ara_api_wsgi_bind: "127.0.0.1:8000"

# When using a frontend server, the domain it will be listening on
ara_api_fqdn: "{{ ansible_default_ipv4['address'] }}"

####################################
# ara API configuration settings
# For more information, see documentation: https://ara.readthedocs.io
####################################

# ARA_BASE_DIR - Default directory for storing data and configuration
ara_api_base_dir: "{{ ara_api_root_dir }}/server"

# ARA_SETTINGS - Path to an ARA API configuration file
ara_api_settings: "{{ ara_api_base_dir }}/settings.yaml"

# ARA_ENV - Environment to load configuration for
ara_api_env: default

# ARA_READ_LOGIN_REQUIRED - Whether authentication is required for reading data
ara_api_read_login_required: false

# ARA_WRITE_LOGIN_REQUIRED - Whether authentication is required for writing data
ara_api_write_login_required: false

# ARA_PAGE_SIZE - Amount of results returned per page by the API
ara_api_page_size: 100

# ARA_LOG_LEVEL - Log level of the different components
ara_api_log_level: INFO

# ARA_LOGGING - Python logging configuration
ara_api_logging:
  disable_existing_loggers: false
  formatters:
    normal:
      format: '%(asctime)s %(levelname)s %(name)s: %(message)s'
  handlers:
    console:
      class: logging.handlers.TimedRotatingFileHandler
      formatter: normal
      level: "{{ ara_api_log_level }}"
      filename: "{{ ara_api_log_dir }}/server.log"
      when: 'midnight'
      interval: 1
      backupCount: 30
  loggers:
    ara:
      handlers:
        - console
      level: "{{ ara_api_log_level }}"
      propagate: 0
  root:
    handlers:
      - console
    level: "{{ ara_api_log_level }}"
  version: 1

# ARA_CORS_ORIGIN_ALLOW_ALL - django-cors-headers’s CORS_ORIGIN_WHITELIST_ALLOW_ALL setting
ara_api_cors_origin_allow_all: false

# ARA_CORS_ORIGIN_WHITELIST - django-cors-headers’s CORS_ORIGIN_WHITELIST setting
ara_api_cors_origin_whitelist:
  - "http://127.0.0.1:8000"
  - "http://localhost:3000"

# ARA_SERVER_ALLOWED_HOSTS - Django’s ALLOWED_HOSTS setting
ara_api_allowed_hosts:
  - "127.0.0.1"
  - "localhost"
  - "::1"
  - "{{ ansible_default_ipv4['address'] }}"

# ARA_DEBUG - Django's DEBUG setting
# It is not recommended to run with debug enabled in production.
ara_api_debug: false

# ARA_SECRET_KEY - Django's SECRET_KEY setting
# Note: If no key is provided, a random one will be generated once and persisted
ara_api_secret_key: null

# ARA_DATABASE_ENGINE - Django’s ENGINE database setting
ara_api_database_engine: django.db.backends.sqlite3

# ARA_DATABASE_NAME - Django’s NAME database setting
ara_api_database_name: "{{ ara_api_base_dir }}/ansible.sqlite"

# ARA_DATABASE_USER - Django’s USER database setting
ara_api_database_user: null

# ARA_DATABASE_PASSWORD - Django’s PASSWORD database setting
ara_api_database_password: null

# ARA_DATABASE_HOST - Django’s HOST database setting
ara_api_database_host: null

# ARA_DATABASE_PORT - Django’s PORT database setting
ara_api_database_port: null

TL;DR

Playbook that runs the role with defaults:

- name: Install ARA with default settings and no persistent API server
  hosts: all
  gather_facts: yes
  roles:
    - ara_api

What the role ends up doing by default:

  • Installs required packages (git, virtualenv, etc.) if superuser privileges are available
  • Stores everything in the home directory of the user in ~/.ara
  • Retrieves ARA from source
  • Installs ARA in a virtualenv
  • Generates a random secret key if none are already configured or provided
  • Sets up API configuration in ~/.ara/server/settings.yaml
  • Runs the API SQL migrations (ara-manage migrate)

About deployment topologies

This Ansible role is designed to support different opinionated topologies that can be selected with role variables.

For example, the following role variables are used to provide the topology from the TL;DR above:

  • ara_api_install_method: source
  • ara_api_wsgi_server: null
  • ara_api_database_engine: django.db.backends.sqlite3
  • ara_api_web_server: null

The intent is that as the role gains support for other install methods, wsgi servers, database engines or web servers, it will be possible to mix and match according to preference or requirements.

Perhaps ARA could be installed from pypi and run with gunicorn, nginx and mysql. Or maybe it could be installed from distribution packages and set up to run with apache, mod_wsgi and postgresql. Or any combination of any of those.

Example playbooks

Install ARA and set up the API to be served by a persistent gunicorn service:

- name: Install ARA and set up the API to be served by gunicorn
  hosts: all
  gather_facts: yes
  vars:
    ara_api_wsgi_server: gunicorn
  roles:
    - ara_api

Install ARA and set up the API to be served by nginx in front of gunicorn:

# Requires superuser privileges to set up nginx and the ara-api service
# The API will be reachable at http://api.ara.example.org
- name: Install ARA and set up the API to be served by nginx in front of gunicorn
  hosts: all
  gather_facts: yes
  vars:
     ara_api_frontend_server: nginx
     ara_api_wsgi_server: gunicorn
     ara_api_fqdn: api.ara.example.org
     ara_api_allowed_hosts:
       - api.ara.example.org
     ara_api_frontend_vhost: custom_vhost.conf.j2
   roles:
     - ara_api