Import role for deploying ara-web

The ara_web role is intended as a way to deploy and install the
ara-web project in different ways.

The commit also adds integration test jobs for the role.
The integration job names and general layout will be cleaned up
in a future patch.

Change-Id: Ib59c455bb38f107fef3d5aca3dff42b6f7eac8a7
This commit is contained in:
David Moreau Simard 2019-03-07 18:11:41 -05:00
parent cf49034673
commit 064b87b54f
No known key found for this signature in database
GPG Key ID: CBEB466764A9E621
18 changed files with 630 additions and 26 deletions

View File

@ -76,6 +76,37 @@
parent: ara-1.0-role-integration-base
nodeset: fedora-latest
- job:
name: ara-web-role-integration-base
parent: base
vars:
ara_web_source: "{{ ansible_user_dir }}/src/git.openstack.org/openstack/ara-web"
ara_web_api_server: "https://api.demo.recordsansible.org"
files:
- playbooks/*
- roles/ara_frontend_nginx/*
- roles/ara_web/*
- src/.*
- public/.*
- package.json
- package-lock.json
- .zuul.d/*
required-projects:
- openstack/ara-web
- openstack/ara-infra
run: playbooks/ara_web.yaml
post-run: tests/role-ara-web-post.yaml
- job:
name: ara-web-role-integration-ubuntu
parent: ara-web-role-integration-base
nodeset: ubuntu-bionic
- job:
name: ara-web-role-integration-fedora
parent: ara-web-role-integration-base
nodeset: fedora-latest
- project:
vars:
rtd_webhook_id: '49230'
@ -89,6 +120,8 @@
- ara-1.0-integration-ubuntu-2.6
- ara-1.0-role-integration-ubuntu
- ara-1.0-role-integration-fedora
- ara-web-role-integration-ubuntu
- ara-web-role-integration-fedora
- ara-tox-linters
- ara-tox-py3
gate:
@ -97,5 +130,7 @@
- ara-1.0-integration-ubuntu-2.6
- ara-1.0-role-integration-ubuntu
- ara-1.0-role-integration-fedora
- ara-web-role-integration-ubuntu
- ara-web-role-integration-fedora
- ara-tox-linters
- ara-tox-py3

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -0,0 +1,4 @@
.. _ansible-role-ara-web:
.. include:: ../../roles/ara_web/README.rst
:end-before: include_delimiter_end

View File

@ -18,3 +18,4 @@ Table of Contents
:maxdepth: 1
ansible-role-ara-api <ansible-role-ara-api>
ansible-role-ara-web <ansible-role-ara-web>

View File

@ -17,9 +17,10 @@ in order to avoid conflicts with your Linux distribution python packages::
# Install ARA 1.0 from source
~/.ara/venv/bin/pip install git+https://git.openstack.org/openstack/ara@feature/1.0
Using ansible-role-ara-api
---------------------------
Using Ansible roles
-------------------
An Ansible role is available to install and configure ARA.
Two roles are built-in to help users configure their API and web deployments:
For more details, refer to the role documentation: :ref:`ansible-role-ara-api`.
- :ref:`ansible-role-ara-api` to install the python parts (Ansible plugins, API server)
- :ref:`ansible-role-ara-web` to install the web client (nodejs, react+patternfly)

5
playbooks/ara_web.yaml Normal file
View File

@ -0,0 +1,5 @@
- name: Install ara-web with default settings
hosts: all
gather_facts: yes
roles:
- ara_web

View File

@ -13,27 +13,36 @@ Role Variables
--------------
- ``ara_api_frontend_vhost``: Path to a custom nginx vhost configuration file for ara-api.
- ``ara_web_frontend_vhost``: Path to a custom nginx vhost configuration file for ara-web.
Example playbook
----------------
Example playbooks
-----------------
Install ARA and set up the API to be served by nginx with a custom vhost configuration
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
# The web interface will be reachable at http://web.ara.example.org
# The web interface will be set up to query api.ara.example.org.
- name: Deploy ARA API server and web interface
hosts: all
gather_facts: yes
vars:
# ara_api
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
ara_api_frontend_vhost: custom_api_vhost.conf.j2
# ara_web
ara_web_fqdn: web.ara.example.org
ara_web_api_endpoint: "http://api.ara.example.org"
ara_web_frontend_server: nginx
ara_web_frontend_vhost: custom_web_vhost.conf.j2
roles:
- ara_api
- ara_web
Copyright
---------

View File

@ -36,24 +36,41 @@
persistent: yes
when: ansible_os_family == "RedHat"
- name: Set up the ARA API nginx vhost
template:
src: "{{ ara_api_frontend_vhost | default('ara-api.conf.j2') }}"
dest: "{{ ara_nginx_config_path }}/ara-api.conf"
notify:
- restart nginx
when:
- ara_api_fqdn is defined
- ara_api_wsgi_bind is defined
- when: ara_api_fqdn is defined
block:
- name: Set up the ARA API nginx vhost
template:
src: "{{ ara_api_frontend_vhost | default('ara-api.conf.j2') }}"
dest: "{{ ara_nginx_config_path }}/ara-api.conf"
notify:
- restart nginx
- name: Enable the nginx configuration on Debian-like systems
file:
src: "{{ ara_nginx_config_path }}/ara-api.conf"
dest: /etc/nginx/sites-enabled/ara-api.conf
state: link
when: ansible_os_family == 'Debian'
notify:
- restart nginx
- name: Enable the API nginx configuration on Debian-like systems
file:
src: "{{ ara_nginx_config_path }}/ara-api.conf"
dest: /etc/nginx/sites-enabled/ara-api.conf
state: link
when: ansible_os_family == 'Debian'
notify:
- restart nginx
- when: ara_web_fqdn is defined
block:
- name: Set up the ARA API nginx vhost
template:
src: "{{ ara_web_frontend_vhost | default('ara-web.conf.j2') }}"
dest: "{{ ara_nginx_config_path }}/ara-web.conf"
notify:
- restart nginx
- name: Enable the web nginx configuration on Debian-like systems
file:
src: "{{ ara_nginx_config_path }}/ara-web.conf"
dest: /etc/nginx/sites-enabled/ara-web.conf
state: link
when: ansible_os_family == 'Debian'
notify:
- restart nginx
- name: Enable and start nginx
service:

View File

@ -0,0 +1,33 @@
{% if ara_web_dev_server %}
upstream ara_web {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response
server {{ ara_web_dev_server_bind_address }}:{{ ara_web_dev_server_bind_port }} fail_timeout=0;
}
{% endif %}
server {
listen 80;
keepalive_timeout 5;
server_name {{ ara_web_fqdn }};
root {{ ara_web_static_dir }};
access_log /var/log/nginx/{{ ara_web_fqdn }}_access.log;
error_log /var/log/nginx/{{ ara_web_fqdn }}_error.log;
{% if ara_web_dev_server %}
location / {
# checks if the file exists, if not found proxy to app
try_files $uri @proxy_to_app;
}
location @proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://ara_web;
}
{% endif %}
}

111
roles/ara_web/README.rst Normal file
View File

@ -0,0 +1,111 @@
ansible-role-ara-web
====================
.. image:: ../../doc/source/_static/ansible-role-ara-web.png
This Ansible role provides a framework for installing one or many instances of
`ara-web <https://github.com/openstack/ara-web>`_ 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 <https://github.com/openstack/ara/blob/feature/1.0/roles/ara_web/defaults/main.yaml>`_.
.. literalinclude:: ../../roles/ara_web/defaults/main.yaml
:language: yaml+jinja
:start-after: www.gnu.org
TL;DR
------
This is what the role does by default out of the box:
- Retrieves ara-web from source
- Installs nodejs LTS (v10)
- Installs ara-web dependencies with npm
- Configures an ara-server API endpoint in ara-web's ``public/config.json`` file
- Sets up a systemd unit file for running ara-web with the embedded development server
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 defaults used to provide the
topology from the ``TL;DR`` above:
- ``ara_web_install_method: source``
- ``ara_web_dev_server: true``
- ``ara_web_frontend_server: null``
The intent is that as the role gains support for other install methods or
frontend servers, it will be possible to mix and match according to preference
or requirements.
Example playbooks
-----------------
Deploy the ARA API and web client on the same machine with defaults:
.. code-block:: yaml+jinja
- name: Deploy ARA API and web client
hosts: all
gather_facts: yes
vars:
# ara_api
ara_api_fqdn: api.ara.example.org
ara_api_wsgi_server: gunicorn
ara_api_allowed_hosts:
- api.ara.example.org
ara_api_cors_origin_whitelist:
- web.ara.example.org
# ara_web
ara_web_fqdn: web.ara.example.org
ara_web_api_endpoint: "http://api.ara.example.org"
roles:
- ara_api
- ara_web
Deploy only ara-web behind nginx and point it to a remote API endpoint:
.. code-block:: yaml+jinja
# Note: Don't forget to add the web fqdn in the remote cors_origin_whitelist.
# Otherwise, the web client might not be authorized to query the API.
- name: Deploy ara-web for remote API endpoint
hosts: all
gather_facts: yes
vars:
ara_web_fqdn: web.ara.example.org
ara_web_api_endpoint: "http://api.remoteara.example.org"
ara_web_frontend_server: nginx
ara_web_frontend_vhost: custom-web-vhost.conf.j2
roles:
- ara_web
.. _include_delimiter_end:
Copyright
---------
::
Copyright (c) 2019 Red Hat, Inc.
ARA Records Ansible is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ARA Records Ansible is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARA Records Ansible. If not, see <http://www.gnu.org/licenses/>.

View File

@ -0,0 +1,71 @@
---
# Copyright (c) 2019 Red Hat, Inc.
#
# This file is part of ARA Records Ansible.
#
# ARA Records Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ARA Records Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ARA Records Ansible. If not, see <http://www.gnu.org/licenses/>.
# Root of where files will be stored for ara-web
ara_web_root_dir: "{{ ansible_user_dir }}/.ara"
# When using static builds without the dev server, path to ara-web static assets
ara_web_static_dir: "{{ ara_web_root_dir }}/www/ara-web"
# How ara-web will be installed
# - source (default): installs from a local or remote git repository specified by ara_web_source
# - npm (planned): installs from npm
ara_web_install_method: source
# When installing from source, the location of the remote or local git repository
ara_web_source: "https://git.openstack.org/openstack/ara-web"
# Location where ara-web will be checked out
ara_web_source_checkout: "{{ ara_web_root_dir }}/git/ara-web"
# Location where node_modules will be installed
ara_web_node_modules_dir: "{{ ara_web_source_checkout }}"
# Version of ara-web to install
# This can be a git ref (tag, branch, commit) when installed from source
# When using "latest" as the source version, HEAD will be used
ara_web_version: latest
# Whether to use the embedded react web server or not
# Setting this to false means ara-web will be statically built instead
ara_web_dev_server: true
# When the development server is enabled, the address it will be listening on
ara_web_dev_server_bind_address: 127.0.0.1
# When the development server is enabled, the port it will be listening on
ara_web_dev_server_bind_port: 3000
# Version of nodesource nodejs repositories to install
ara_web_nodejs_version: 10
# ara-server API endpoint to use
ara_web_api_endpoint: "http://127.0.0.1:8000"
# The frontend server for serving ara-web
# - null (default): none, users are expected to use the development server directly or deploy their own web server
# - nginx: when performance of the development server is an issue
# - apache (planned)
ara_web_frontend_server: null
# When using a frontend server, you can override the default vhost configuration
# template by specifying the path to your own template file.
ara_web_frontend_vhost: null
# When using a frontend server, the hostname to listen on
ara_web_fqdn: "{{ ansible_default_ipv4['address'] }}"

View File

@ -0,0 +1,31 @@
---
# Copyright (c) 2019 Red Hat, Inc.
#
# This file is part of ARA Records Ansible.
#
# ARA Records Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ARA Records Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ARA Records Ansible. If not, see <http://www.gnu.org/licenses/>.
# Is there a better way ? Static files are not created with the httpd context
- name: restore selinux context for static files
become: "{{ (ansible_user_dir in ara_web_static_dir) | ternary(false, true) }}"
command: "restorecon -Rv {{ ara_web_static_dir }}"
when: ansible_os_family == "RedHat"
- name: restart ara-web
become: true
service:
name: ara-web
state: restarted
when:
- ara_web_service_enabled is not changed

View File

@ -0,0 +1,36 @@
---
# Copyright (c) 2019 Red Hat, Inc.
#
# This file is part of ARA Records Ansible.
#
# ARA Records Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ARA Records Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ARA Records Ansible. If not, see <http://www.gnu.org/licenses/>.
galaxy_info:
author: David Moreau-Simard
description: Role to set up ara-web
license: GPLv3
min_ansible_version: 2.7
platforms:
- name: Fedora
versions:
- 29
- name: Ubuntu
versions:
- bionic
galaxy_tags:
- ansible
- ara
- ara-web
dependencies: []

View File

@ -0,0 +1,107 @@
---
# Copyright (c) 2019 Red Hat, Inc.
#
# This file is part of ARA Records Ansible.
#
# ARA Records Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ARA Records Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ARA Records Ansible. If not, see <http://www.gnu.org/licenses/>.
- name: Ensure libselinux-python is installed for Red Hat derivatives
become: yes
package:
name: libselinux-python
state: present
when: ansible_os_family == "RedHat"
- name: Ensure git is installed
become: yes
package:
name: git
state: present
# TODO: node_modules and public/config.json are local to the git repository so this is not idempotent
- name: Prepare git repository for ara-web
git:
repo: "{{ ara_web_source }}"
dest: "{{ ara_web_source_checkout }}"
version: "{{ (ara_web_version == 'latest') | ternary('HEAD', ara_web_version) }}"
force: yes
- name: Install ara-web npm dependencies
npm:
path: "{{ ara_web_source_checkout }}"
global: no
production: yes
state: present
notify:
- restart ara-web
- name: Configure ara-server API endpoint for ara-web
vars:
web_config:
apiURL: "{{ ara_web_api_endpoint }}"
copy:
content: "{{ web_config | to_nice_json(indent=2) }}"
dest: "{{ ara_web_source_checkout }}/public/config.json"
mode: 0644
notify:
- restart ara-web
- when: ara_web_dev_server | bool
become: yes
block:
- name: Set up systemd unit file for ara-web
template:
src: ara-web.service.j2
dest: /etc/systemd/system/ara-web.service
owner: root
group: root
mode: 0644
notify:
- restart ara-web
- name: Enable and start ara-web
service:
name: ara-web
state: started
enabled: yes
daemon_reload: yes
register: ara_web_service_enabled
- when: not ara_web_dev_server | bool
block:
- name: Stop and disable ara-web
become: yes
service:
name: ara-web
state: stopped
enabled: no
- name: Ensure systemd unit file is not configured
become: yes
file:
path: /etc/systemd/system/ara-web.service
state: absent
- name: Run a production build of ara-web
command: npm run build
args:
chdir: "{{ ara_web_source_checkout }}"
creates: "{{ ara_web_source_checkout }}/build"
- name: Synchronize build to web directory
become: "{{ (ansible_user_dir in ara_web_static_dir) | ternary(false, true) }}"
command: |
rsync -rlog --delete-delay {{ ara_web_source_checkout }}/build/ {{ ara_web_static_dir }}
notify:
- restore selinux context for static files

View File

@ -0,0 +1,28 @@
---
# Copyright (c) 2019 Red Hat, Inc.
#
# This file is part of ARA Records Ansible.
#
# ARA Records Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ARA Records Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ARA Records Ansible. If not, see <http://www.gnu.org/licenses/>.
- name: Install nodejs
include_tasks: nodejs.yaml
- name: Include ara-web installation
include_tasks: install/{{ ara_web_install_method }}.yaml
- name: Include frontend server installation
include_role:
name: "ara_frontend_{{ ara_web_frontend_server }}"
when: ara_web_frontend_server is not none

View File

@ -0,0 +1,53 @@
---
# Copyright (c) 2019 Red Hat, Inc.
#
# This file is part of ARA Records Ansible.
#
# ARA Records Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ARA Records Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ARA Records Ansible. If not, see <http://www.gnu.org/licenses/>.
- when: ansible_os_family == "Debian"
become: yes
block:
- name: Install apt-transport-https
package:
name: apt-transport-https
state: present
- name: Install nodesource repository key
apt_key:
url: "https://deb.nodesource.com/gpgkey/nodesource.gpg.key"
- name: Install nodesource apt source repository
apt_repository:
repo: "deb-src https://deb.nodesource.com/node_{{ ara_web_nodejs_version }}.x {{ ansible_distribution_release }} main"
state: present
- name: Install nodesource apt repository
apt_repository:
repo: "deb https://deb.nodesource.com/node_{{ ara_web_nodejs_version }}.x {{ ansible_distribution_release }} main"
state: present
update_cache: yes
- name: Install Nodesource yum repository
become: yes
package:
name: "https://rpm.nodesource.com/pub_{{ ara_web_nodejs_version }}.x/fc/{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/nodesource-release-fc{{ ansible_distribution_major_version }}-1.noarch.rpm"
state: present
when: ansible_os_family == "RedHat"
- name: Install nodejs
become: yes
package:
name: nodejs
state: present

View File

@ -0,0 +1,16 @@
[Unit]
Description=ARA Records Ansible web client
After=network.target
[Service]
PIDFile=/run/ara-web/pid
User={{ ansible_user_id }}
RuntimeDirectory=ara-web
WorkingDirectory={{ ara_web_source_checkout }}
ExecStart=/usr/bin/npm start --host {{ ara_web_dev_server_bind_address }} --port {{ ara_web_dev_server_bind_port }}
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,46 @@
- name: Deploy ara-web
hosts: all
gather_facts: yes
vars:
ara_web_source_checkout: "{{ ansible_user_dir }}/.ara/git/ara-web"
config:
apiURL: "https://api.demo.recordsansible.org"
tasks:
# Before building the application, we need to set the homepage argument
# from package.json to use the URL where logs will be uploaded.
- name: Resolve Zuul log path
include_role:
name: set-zuul-log-path-fact
- name: Read package.json
command: "cat {{ ara_web_source_checkout }}/package.json"
register: package_json
- name: Set homepage parameter
vars:
build_url: "http://logs.openstack.org/{{ zuul_log_path }}/build"
set_fact:
package_json: "{{ package_json.stdout | from_json | combine({'homepage': build_url}) }}"
- name: Write package.json
copy:
content: "{{ package_json | to_nice_json }}"
dest: "{{ ara_web_source_checkout }}/package.json"
- name: Set config.json to use api.demo.recordsansible.org
copy:
content: "{{ config | to_nice_json }}"
dest: "{{ ara_web_source_checkout }}/public/config.json"
- name: Run a production build of ara-web
command: npm run build
args:
chdir: "{{ ara_web_source_checkout }}"
creates: "{{ ara_web_source_checkout }}/build"
- name: Upload build to log server
synchronize:
src: "{{ ara_web_source_checkout }}/build"
dest: "{{ zuul.executor.log_root }}"
mode: pull
verify_host: true