Drifter¶
Drifter is a framework to help provision developer boxes using Ansible and Vagrant.
Goals¶
- Streamline our project setups
- Ease the “entry cost” for a new squad member
- Easy to use
- Lean: small codebase, easy to maintain and extend, focus only on Debian and Ubuntu
- Be adopted by Liip as a whole
The idea behind the framework¶
The idea is to have a common ground for each project that can be improved over time, each project benefiting from the improvements.
This repository aims to contain multiples Ansible roles to manage the various part of the development stack needed to work on the various projects of Liip. If a someone need new roles, it is highly recommended that they are added to the common pool if they are deemed reusable.
Each squad can tailor its box to its need by modifying the Ansible playbook which should ultimately only contain role inclusion to maximize reuse.
When installed, Drifter creates a parameters file to hold various information about your project, a playbook file where you can choose what to install and finally a Vagrantfile where you can modify some Vagrant related parameters before the “main” Vagrantfile is included. This should offer enough flexibility for every project.
What this framework is not ?¶
This framework does not aim to provide a way to deploy staging and production servers for your project. The roles are written with a development box in mind and are thus not fit for server provisioning. There are absolutely no security issues taken into consideration.
However, if your server is using a Debian based OS based on the stable release, both configurations should be close enough so that you won’t run into issues.
Intended Public¶
This project was first and foremost created to be used inside of Liip, but you are more than welcome to use it for personal projects or anywhere else you’d like to.
Requirements¶
- Vagrant >= 1.8.4
- Git >= 1.0
You also need a virtualization solution, either one of these:
- Virtualbox >= 4.3
- LXC >= 1.0 & vagrant-lxc >= 1.0.0.alpha.2
Optional dependencies:
- vagrant-hostmanager A Vagrant plugin that manages /etc/hosts files. (will be automatically used if installed, make sure it’s at least 1.5.0 if you have it)
Install Requirements¶
Debian Stretch (testing) and Ubuntu Xenial 16.04¶
Open a terminal and run:
sudo apt-get install vagrant vagrant-lxc
vagrant plugin install vagrant-hostmanager
Older Debian and Ubuntu versions¶
Go to https://www.vagrantup.com/downloads.html to download and install the latest Vagrant version. Then open a terminal and run:
sudo apt-get install lxc redir # this is needed for LXC provider
vagrant plugin install vagrant-lxc vagrant-hostmanager
Mac OS X¶
Download and install https://www.vagrantup.com/downloads.html.
Download and install https://www.virtualbox.org/wiki/Downloads.
Then open a terminal and run:
vagrant plugin install vagrant-hostmanager
You can also use cask
to help with the installation::
brew cask install vagrant virtualbox
Windows¶
Install Virtualbox and Vagrant (>= 1.8.4) using the binaries available on their respective websites.
Also make sure that core.autocrlf
is set to input
(recommended)
or at least true
so that you don’t get issues with Windows
line-endings in the files that are in your box. You can set it by
running the following command:
git config --global core.autocrlf input
For example if you get the following error when trying to provision the box:
TASK [base : ensure base packages are installed] *******************************
failed: [default] (item=[u'locales', u'procps', u'command-not-found', u'bash-completion', u'zsh', u'bzip2', u'unzip', u'vim', u'ack-grep', u'highlight', u'libxml2-utils', u'build-essential', u'wget', u'openssh-server', u'sudo', u'imagemagick', u'iputils-ping', u'ncurses-term', u'python-pycurl']) => {"failed": true, "item": ["locales", "procps", "command-not-found", "bash-completion", "zsh", "bzip2", "unzip", "vim", "ack-grep", "highlight", "libxml2-utils", "build-essential", "wget", "openssh-server", "sudo", "imagemagick", "iputils-ping", "ncurses-term", "python-pycurl"], "module_stderr": ">>> /etc/sudoers.d/sudo-passwordless: syntax error near line 1 <<<\nsudo: parse error in /etc/sudoers.d/sudo-passwordless near line 1\nsudo: no valid sudoers sources found, quitting\nsudo: unable to initialize policy plugin\n", "module_stdout": "", "msg": "MODULE FAILURE", "parsed": false}
That’s because the sudoers file that gets copied in the box has the
wrong format. Enabling core.autocrlf
will fix the issue.
Usage¶
Drifter is going to be installed into your project as a git submodule. So if your project is not using Git as VCS, start by creating a git repo:
cd my-project && git init
Then to install Drifter, simply run the following command:
curl -sS https://raw.githubusercontent.com/liip/drifter/master/install.sh | /bin/bash
This will create a Vagrantfile
in your root and a virtualization
folder containing configuration files. You now have to follow those two
steps:
- edit
virtualization/parameters.yml
to set parameters related to your project - edit
virtualization/playbook.yml
to configure what to install in your box
You now just have to launch your Vagrant box and start hacking!:
vagrant up
Customization¶
You can customize what seems to us to be the most important options through two files:
virtualization/parameters.yml
for all project related parameters. Any value in this file will be passed to Ansible as a variable. You can override any role default values through this file. You can find details about possible parameters and values later in this documentation.virtualization/playbook.yml
for provisioning. You can control which roles are used to build your box. This allows you to control what is installed in your box.
If those two mechanisms are not enough for you, you can also modify the
Vagrantfile
, but be aware that the risk of botching things up is far
greater.
Currently you do not have a lot of control, but we will glad to add anything making sense to this file. Feel free to ask and we will comply ;)
Contributing¶
Before publishing your contributions please test your roles with the
playground. To do so, go to the playground
directory, enable any
role you need in playbook.yml
and set any parameter you want in
parameters.yml
and then run vagrant up
. The box will use the
roles of your working copy.
Please don’t commit any change to the playground, unless you’re fixing something in the playground.
System Roles¶
Base¶
This roles installs various useful software like vim, ack-grep, etc. It also put some configuration files of the vagrant user home directory.
It should always be included to have a common environment in all vagrant boxes.
Git¶
Install Git and some sane configuration and sync the username and e-mail from the host.
Fancy-diff is also
installed by default and you can opt-in to sync your git configuration
on each vagrant up
.
Parameters¶
- fancy_diff : install fancy-diff
- sync_git_with_host : sync your host git config on each
vagrant up
Supervisor¶
Install Supervisor so that you can manage long lived processes inside the box. A config file based on the parameters is also created for your service.
The service are automatically started on boot and restarted if they fail.
If you need multiple services, just include the role multiple times with the various parameters.
Parameters¶
- service_name : name of the service
- user : user to use to launch the service
- command : the command to launch
- root_directory : the base directory for the service
- environment_vars : environment vars you want to set
tmpfs¶
Configure a path to be mounted as a tmpfs (ie : in memory filesystem).
This can be used to speed up application, for example by putting their log directory in memory thus avoiding costly network transfers for shared directories.
Parameters¶
- mount_path : the path to replace with a tmpfs
SSL¶
If you set the ssl
parameter to true in your parameters.yml
file, ansible will create a Certification Authority (CA) and then create
and sign SSL certificates for all hosts configured for your project.
The CA certificate will then be copied to your project
root_directory
. If you add this certificate to your trust store, you
should be able to access your websites with HTTPS without any error
messages from most browsers.
If the role is activated, both Apache and NGinx will be configured to use the created certificates.
WARNING: if the certificate is regenerated because you did a
vagrant destroy
or the hostname changed, you will need to re import
the CA certificate into your trust store and in the meantime you might
get errors from your browser. Chrome for example produce a pretty
confusing error message about an attacker trying to steal your
credentials.
SSH¶
Disable SSH strict host key checking if ssh_no_stricthostkeychecking
is set to true in the parameters.
Also add the github and gitlab.liip.ch host key to the known_hosts
file.
Parameters¶
- ssh_no_stricthostkeychecking : if set to true, disable SSH strict host key checking
Redis¶
To be completed.
RabbitMQ¶
To be completed.
Webserver Roles¶
Apache¶
This roles installs Apache and the required virtual host configuration for your project.
Except for a static website, it should not be used directly because it is automatically included by other roles, for example PHP-Apache.
Parameters¶
- web_directory : Root directory for the virtual host, defaults to root_directory.
- ssl : Whether to activate HTTPS vhost, defaults to false. If enabled, the generated CA will be copied to the project directory.
NGinx¶
Install the NGinx web server and configure a virtual host based on the given site template. Except if you need to serve only static files, you should not have to include this role yourself, the Django or PHP-FPM roles do it automatically with the correct parameters.
The server logs are stored in
/var/log/nginx/<hostname>.(error|access).log
.
You can have your own site template in your project directory, for example virtualization/templates/nginx.j2 and extend one of the default templates provided:
{% extends "default-site.j2" %}
{% block extra %}
{{ super() }}
# Here goes your custom Nginx rules
{% endblock %}
Then set the site_template
parameter to nginx.j2
when including the nginx role (or any other that depend
on the nginx role):
roles:
- { role: nginx, site_template: nginx.j2 }
If you want to use roles that include nginx, such as php-fpm, make sure you use the right parameter name (check the docs):
roles:
- { role: php-fpm, nginx_site_template: nginx.j2 }
Parameters¶
- site_template : The virtual host template to use, defaults to “default-site.j2” for static websites only, possible values are:
default-site.j2
django-site.j2
Site template for Djangodrupal6-site.j2
Site template for Drupal6drupal7-site.j2
Site template for Drupal7drupal8-site.j2
Site template for Drupal8php-site.j2
Site template for generic PHPsilex-site.j2
Site template for Silexsymfony2-site.j2
Site template for Symfony2symfony4-site.j2
Site template for Symfony4
- index : what file do we use as an index ? defaults to ‘false’
- static_host : Which static host to use for Django projects ? defaults to “false”.
- static_dir : Which static URL dir to use for Django projects ? defaults to “false”.
- static_fs_dir : Which static filesystem dir to use for Django projects ? defaults to “”.
- expire_time : Expiration time of static files, defaults to “6h”.
- web_directory : Root directory for the virtual host, defaults to root_directory.
- ssl : Whether to activate HTTPS vhost, defaults to false. If enabled, the generated CA will be copied to the project directory.
Database Roles¶
MySQL¶
Install and set up a MySQL server and then create the configured user and database.
The database administrative user is “root” with the “root” password.
This role must be included before the Django or PHP one if both are present so that the correct extension and configuration could be made.
Parameters¶
- database_name : the name of the database to create, set in parameters.yml
- database_user: the name of the user, defaults to the database name
- database_password: the password of the user, defaults to the database name
- mysql_version: the MySQL version to install, defaults to 5.6 and supports 5.6, 5.7 and 8.0 (more info on http://dev.mysql.com/downloads/repo/apt/)
PostgreSQL¶
Install and set up a PostgreSQL server and then create the configured user and database.
This role must be included before the Django or PHP one if both are present so that the correct extension and configuration could be made.
Parameters¶
- database_name : the name of the database to create, set in parameters.yml
- database_user: the name of the user, defaults to the database name
- database_password: the password of the user, defaults to the database name
- database_template: the template to use, defaults to “template0”
- database_encoding: character encoding, defaults to UTF-8
- database_lc_collate: database collation, defaults to en_US.UTF-8
- database_lc_ctype: database ctype, defaults to en_US.UTF-8
PostGIS¶
Install and set up a PostgreSQL server with the PostGIS extension enabled.
The postgres role is declared as a dependency and does not need to be activated explicitly in playbook.yml.
For each of the supported OS, this role installs the recommended PostgreSQL/PostGIS combination package: - Debian 8 (Jessie): postgresql-9.4-postgis-2.1 - Debian 9 (Stretch): postgresql-9.6-postgis-2.3 - Ubuntu 14 (trusty): postgresql-9.3-postgis-2.1 - Ubuntu 16 (xenial): postgresql-9.5-postgis-2.2
MemCached¶
To be completed.
PHP Roles¶
PHP¶
Install PHP and various extensions : curl, intl, gd, imagemagick, …
The version can be changed and defaults to 5.6. All version are however not available on all OS versions, an error message will be displayed by Ansible if you chose an impossible combination.
Available versions are:
- Debian Stretch & Jessie: 5.6, 7.0, 7.1 and 7.2
- Ubuntu Trusty: 5.5, 5.6, 7.0, 7.1 and 7.2.
Development specific configuration options are also put into place, for example to activate error outputting.
A database driver is also installed if one of the MySQL or PostgreSQL roles was included before.
If you want to install xdebug, you’ll need to also add the specific role
: php-xdebug
.
There are also roles for some more specific extension that could be found below.
This role is automatically included by roles PHP-Apache and PHP-FPM, so you should not include it yourself.
Parameters¶
- php_sury_apt_key_id: if you’re installing PHP on Debian >= jessie, this parameter allows you to change the APT key id of the Sury repository. Defaults to B188E2B695BD4743
- php_version : version to install, defaults to 5.6
- php_error_reporting : php error reporting, defaults to “E_ALL | E_STRICT”
- php_assert_exceptions : php assert exceptions for 7.0 and above, defaults to false
- php_max_execution _time** : script max exectution time, defaults to “3600”
- php_memory_limit : memory limit, defaults to “4G”
- php_upload_max_filesize : maximal size of uploaded file, defaults to “128M”
- php_date_timezone : timezone, defaults to “Europe/Zurich”
- php_default_charset : default charset, defaults to “UTF-8”
- php_default_socket_timeout : socket timeout, defaults to 120
PHP-Apache¶
Install the PHP mod for Apache along with Apache and PHP. You only need to install this role, PHP and Apache will be automatically added as dependencies. For details about PHP config, see above.
The default vhost template from the Apache role is used.
PHP-FPM¶
Install PHP-FPM so that you can use NGinx. You only need to install this role, PHP and NGinx will be automatically added as dependencies. For details about PHP config, see above.
You can change the site template used using the parameter defined below. The templates can be found in the NGinx role.
Parameters¶
- nginx_site_template: template to use for site configuration, defaults to “php-site.j2”
- nginx_index: index in nginx configuration, defaults to “index.php”
PHP-XDebug¶
Installs the XDebug extension for PHP.
You can modify the config file /etc/php5/conf.d/20-xdebug.ini
to
change the configuration and restart your Apache or PHP-FPM. XDebug is
also configured to trigger debugging and profiling in response to the
related query string or cookie, so you should be able to install a
browser extension to make it work this way.
Parameters¶
- xdebug_idekey: value of the
xdebug.idekey
setting, defaults to XDEBUG-DRIFTER.
PHP-Redis¶
Installs the Redis extension for PHP. Redis and PHP are installed as a dependency.
Concerning Redis itself, the documentation is in the “System” section of the documentation.
PHP-MemCached¶
Installs the MemCached extension for PHP. MemCached and PHP are installed as a dependency.
Concerning MemCached itself, the documentation is in the “System” section of the documentation.
Composer¶
Installs Composer, the PHP package manager. The PHP role is defined as a
dependency. You can set the install dir, a link in /usr/local/bin
will be set up whichever the install dir is so that composer can be
accessed globally.
If composer is already installed, this role will update it instead.
Parameters¶
- composer.dir : where to install the binary, default “opt/composer”
PhiVE¶
Installs PhIVE support (Phar Installation and Verification Environment (PHIVE).
A link in /usr/local/bin
will be set up so that phive
can be accessed globally.
If PhIVE is already installed, this role will update it instead.
Parameters¶
- phive.dir : where to install the binary and the downloaded phar(s), default to “opt/phive”
Python Roles¶
Python¶
Install Pip and Virtualenv along with dev dependencies. Dependencies to build the Pillow package are also installed.
Both Python 2 and Python 3 are always installed, for example to facilitate tests on multiple python version, the parameter below only change the behavior of python related roles.
Parameters¶
- python_version: version of Python to use. Can be 2 or 3, defaults to “3”
- pip_version : the version of pip to install in the virtual environment. Defaults to 9.0.1.
- setuptools_version : the version of setuptools to install in the virtual environment. Defaults to 28.8.0.
- python3_install_from_source: whether to install Python from source (true) or use the distribution version (false). Defaults to false
- python3_source_version: Python version like 3.5.5, defaults to “3.6.5”
Virtualenv¶
Create a python virtual environment and install application requirements via pip. The environment will also get pip-tools installed.
The virtual environment is automatically activated upon box login.
- pip_requirements : filename of the requirements file, defaults to “requirements/dev.txt”
- env_root : directory where the virtual environment must be created, defaults to “~/ENV”
- pip_requirements_dir : name of the requirements directory that contain the .in files. If set, Drifter will
run
pip-compile
on these files upon provisioning. - pip_tools_version : the version of pip-tools to install in the virtual environment. Defaults to 1.8.2.
Django¶
Uses the virtualenv
or the pipenv
role (depending on the
django_use_pipenv
parameter) to create and install a virtual
environment for Django.
Configure database access via environment variable and then run migrations.
You need to include either to mysql
or postgresql
roles before
this one.
This role depends on the Virtualenv and NGinx roles. The NGinx role is configured to use the “django-site.js” site template on the port “8000”.
Parameters¶
- django_root : root directory of the Django project, default to
- the “root_directory” variable defined in parameters.yml
- django_use_pipenv: whether to use Pipenv to install requirements. Defaults to false.
Ruby Roles¶
Ruby¶
Install rbenv
along with Bundler
. Complete the installation with
the bundle install
command if a Gemfile is found in the project root
directory.
Parameters¶
- ruby_version: this should be the exact version name (such as
2.3.3). Find a list of accepted version with
rbenv install -l
. Default is 2.4.1
Rails¶
Simply add roles nodejs
and ruby
in your playbook.yml. Note that
rails will not be installed unless specified in your Gemfile.
Using mysql or postgres? then include mysql
or postgresql
role
before ruby
.
Run server¶
You have two options. First, in the box, run rails server
or puma
, then open your browser on
http://{hostname}:3000
Second option is to add the nginx role with the rails template:
- { role: nginx, web_directory: "/vagrant/public", site_template: "rails-site.j2", proxy_port: 3000 }
Then you can just open http://{hostname}
.
Java Roles¶
Java¶
Installs a Java Runtime Environment using the OpenJDK Debian package.
Parameters¶
- java_jre_version: JRE version to install, defaults to 7. Set your version according to your needs and your Linux distribution.
- java_jre_package: default is
openjdk-{{ java_jre_version }}-jre
.
JDK¶
Installs a Java Development Kit using the OpenJDK Debian package.
Parameters¶
- java_jdk_version: JDK version to install, defaults to 7. Set your version according to your needs and your Linux distribution.
- java_jdk_package: default is
openjdk-{{ java_jdk_version }}-jdk
.
Maven¶
Installs Maven via apt-get
.
Solr¶
Install solr
via the tarballs available on the Apache repository.
A specific user is created and solr
is automatically started at boot
using supervisor
.
You can choose any solr
version (compatible with Java7) via download.
However the provided start command might need some adjustment.
To create a Solr core, use both the solr_core_name
and solr_core_conf
parameter.
Parameters¶
Those parameters controls base feature for solr
. There’s also a list
below of “internal” parameters that you’ll might need to tweak if you
want to use a version different than 4.X or 5.X
- solr_version: Solr version to install, defaults to 5.3.1. You should be able to use all 5.X and 4.X version, but some tuning might be needed.
- solr_base_dir: Solr base directory, this is not directly used by the role, defaults to /opt/solr.
- solr_install_dir: Solr installation directory, defaults to
{{ solr_base_dir }}
. - solr_config_dir: Solr configuration directory, defaults to /opt/solr/server/solr.
- solr_port: defaults to 8984.
- solr_core_name: Create a new Solr core/index with such name; by
default no indexes are created. If this parameter is defined,
solr_core_conf
must be defined as well. - solr_core_conf: Specifies the Solr core/index configuration folder
to use for the index, it will be symlinked to the conf folder of the index.
Refer to the documentation for the file structure
required by Solr. Example:
solr_core_conf=/vagrant/solr/conf
.
ElasticSearch¶
To be completed
Webpack¶
Current Webpack version: 4.5.0
This role provides a pretty simple setup to handle assets (javascripts, stylesheets, images, fonts and SVG icons) through Webpack in your project.
It creates a webpack.config.js that is preconfigured to handle:
- Sass files to create stylesheets. Stylesheets are processed through Autoprefixer for browser compatibility and CSSNano for optimisations.
- JavaScript files through Babel with babel-preset-env to use next generation JavaScript today
- SVG icons through svg-sprite-loader and make a single sprite file out of it
- Images (svg, png, jp(e)g, gif, webp)
- Fonts (woff, woff2, eot, ttf, otf)
Installation¶
Once enabled, this role will create a webpack.config.js
, a babel.config.js
and a package.json
that includes all the required dependencies by default.
Existing files (webpack.config.js, babel.config.js and package.json) will not be overridden. If those files already exist, the installation will be incomplete and might not work as expected.
Parameters¶
webpack_directory: where should the webpack.config.js be created, defaults to
{{ root_directory }}/
webpack_create_config: Create the webpack.config.js & babel.config.js, defaults to
true
webpack_browserslist: Define Browserslist in
package.json
, defaults to:- "> 0.5%" - "not op_mini all" - "not dead"
Post-install¶
The default configuration expects a couple of things:
- The main JavaScript file to live at
assets/scripts/common.js
(not created by the role) - All the assets to live in
assets/…
or innode_modules
- The SVG icons to be included in the sprite to live in
assets/icons/
Other defaults:
- Built files are bundled into the
dist/
folder - Generated icons sprite is named
icons.svg
You can change all these default values by editing the webpack.config.js
file. If you need help, you should check out the Webpack config documentation.
Default tasks¶
Development¶
npm start
Starts webpack-dev-server
at example.lo:3000, compile on-the-fly and reload the browser automatically. All requests not handled by webpack will be proxified to example.lo.
Replace example.lo by the “hostname” you set in the “parameters.yml”.
Notice that webpack-dev-server does not write the files to the disk. To debug which files are being served, go to example.lo:3000/webpack-dev-server.
Production¶
npm run build
Will bundle all the assets, optimized for production, in the dist
folder by default.
Loading assets¶
The default public path for bundled assets is /
.
To load the main JavaScript file, use:
<script type="text/javascript" src="common.js"></script>
In development, CSS is automatically injected in a <style>
tag by the JavaScript file that imported it. In production, you need to include the extracted file. For example, all the CSS required by the common
bundle, would be extracted as common.css
and should be loaded like this:
<link rel="stylesheet" type="text/css" href="common.css">
If you need help to import files such as CSS, images or fonts, take a look to the Webpack asset management guide.
Gulp Role¶
Existing configuration files (Gulpfile.js, gulp.config.js, webpack.config.js, package.json) will not be overridden.
- Install
gulp
globally in the Vagrant box - Create a prefilled
Gulpfile.js
with useful tasks- Watch & live reload with BrowserSync
- Compile Sass with Autoprefixer & source-maps
- Bundle JavaScript with Webpack, preconfigured with Babel (optional)
- Lossless images optimization with ImageMin
- Create associated
gulp.config.js
andwebpack.config.js
- Add the necessary dependencies to
package.json
(only if the file doesn’t exist yet)
After the first provisioning, you should edit the gulp.config.js
and
webpack.config.js
to match your project structure.
Parameters¶
gulp_directory: where should the gulpfile be created, defaults to
<root_directory>/
gulp_create_config: Create the gulp.config.js used by the default Gulpefile.js, defaults to
true
gulp_use_webpack: Setup Webpack alongside Gulp, defaults to
true
gulp_use_purescript: Add PureScript support to Webpack, defaults to
false
gulp_browserslist: Define Browserslist in
package.json
, defaults to:- Last 2 versions - IE 11
Default tasks¶
Watch & live reload proxy¶
Run BrowserSync, watch for changes in files, compile and reload browser afterwards with:
npm start
Build for production¶
npm run build
Optimize images¶
For performance reason, this task is not included in the watch/build tasks. You should run it manually according to your needs.
Optimize jp(e)g, png, gif & svg files with:
gulp images
Browser Roles¶
Browser roles are available for frontend testing. They all depend on the role xvfb, which is a headless X server, except for Phantomjs.
Firefox¶
Install Firefox with Geckodriver to be used with selenium.
Parameters¶
- firefox_version: The version of Firefox to be installed, defaults to latest. Should be greater than 47.0. The full list of supported versions can be found on the Firefox releases page.
Chrome¶
Install Chrome with Chromedriver to be used with selenium.
There are no parameters available for this one, as they don’t really provide older versions. Therefore, always the newest Chrome browser will be installed.
PhantomJS¶
Install PhantomJS.
Parameters¶
- phantomjs_version: The version of PhantomJS to be installed, defaults to 2.1.1. The full list of supported versions can be found on the PhantomJS releases page.
Example usage with pytest and splinter¶
This is the recommended way to use those browser for testing in python with pytest. pytest-splinter is a pytest plugin that provides easy access to several webdrivers.
First, you have to install some packages via pip (see Virtualenv for instruction on how to properly do this):
- pytest
- pytest-splinter
- pytest-xvfb (When you want to use firefox or chrome)
In order to run your tests, you can simply invoke pytest. By default the Firefox webdriver will be used, but it’s possible to change this with the option –splinter-webdriver=chrome. More info available on the pytest-splinter project page.
Other Roles¶
Ruby¶
Install Ruby, Gem integration for Debian and dev dependencies.
Any Debian ruby package should then be also recognized as a Gem. You can
however continue to install Gems using the gem
utility if you need a
specific version or an unavailable package.
NodeJS¶
Install NodeJS and NPM.
Parameters¶
- nodejs_version : The version to install, currently supports 11.x, 10.x, 9.x, 8.x, 7.x, 6.x, 5.x, 4.x, 0.12 and 0.10, default being 10.x.
- nodejs_distro : Is automatically set to either ‘jessie’, ‘stretch’, etc based on available information, you can also put an Ubuntu codename here.
- nodejs_create_package_json: create a
package.json
file based on the settings below during provisioning. Defaults totrue
. - nodejs_package_json_template: template to use for the creation of the initial
package.json
file. Defaults to
package.json.j2
, orpackage.json.gulp.j2
if you’re using the gulp role. See theprovisioning/roles/nodejs/templates
directory for the list of available templates.
- nodejs_package_json_path: where should the package.json file be
created, defaults to
<root_directory>/package.json
- nodejs_package_json_author: Author that should be put in the
package.json file, defaults to
Liip AG
- nodejs_install_package_json: Run
npm install
on each provisioning. Defaults totrue
.
OpenLDAP¶
Install an OpenLDAP (slapd) server.
It will open the standard LDAP ports (389 for ldap://
, 636 for
ldaps://
), and the ldap-utils
(shipping ldapsearch
is also
installed.
Parameters¶
- ldap_organization : Fulltext organization name, defaults to ‘EvilCorp Ltd’
- ldap_organization_domain : Organization domain name, defaults
to
evilcorp.example.com
- ldap_admin_password : Password of the original cn=admin,dc=evilcorp,dc=example,dc=com user, defaults to ‘admin’
RMT - Release Management Tool¶
Install RMT in the box. Once done you must run php /home/vagrant/.config/composer/vendor/liip/rmt/RMT to init it for your project. Then for the next steps go to https://github.com/liip/RMT#usage
Redis¶
To be completed.
PHP¶
PHP Debugging with Drifter & PHPStorm¶
As said earlier, the PHP role installs php-xdebug which is configured to try to connect to any listener on the host.
If you are using Chrome and PHPStorm, debugging a script can be done by following these steps:
- Install the Xdebug helper chrome extension
- In your browser address bar, click on the little bug and select “Debug”
- In PHPStorm, open the “Run” menu and select “Start Listen for PHP Debug connection”
- Reload the page in your browser
- A dialog should open in PHPStorm to ask you which file you want to debug, choose the entry point of your application
CI¶
Integrating with Gitlab CI¶
(These instructions are specifically for the Liip Gitlab CI, but may be used on other Gitlab CI’s as well)
To make it easy to run tests on the Gitlab CI runners, this packages provides some general purpose scripts, so you don’t have to reinvent the wheel all the time.
Setup¶
Using the gitlabci role¶
The automatic way. Just uncomment/add the folloing line in your
playbook.yml
and the needed files will be created automatically on
the next provsioning (if they don’t exist already)
- { role: gitlabci }
It installs the following files (which should be added to git afterwards)
The config file for Gitlab CI, it tells the CI what exactly to run
The script called first by the gitlab runner. It updates the submodules
and then calls ./virtualization/drifter/ci/start.sh
, which does
start vagrant, provisions it and calls your actual test script.
This is where your actually test calls go. This is run within your vagrant box.
To prevent provisioning on the ci runners all the time and save lots of time, provisioning is only run, when this file changes. Therefore if you change something in your provisioning scripts, also changes this file to a different value (doesn’t matter which one, as long as it’s different, but some kind of timestamp assures that it’s different)
If you don’t add this file to your project, then provisioning will be run every time a ci build is started.
Be aware, that the CI deletes all files before each run, which are not in your git repository. This eg. means that your vendor (if you use composer) or node_modules folders are gone and not recreated, if provisioning doesn’t go through. To still keep your important directories, add this to .gitlab-ci.yml (see also https://docs.gitlab.com/ce/ci/yaml/#cache for more details)
cache:
paths:
- bin/
- vendor/
key: sharedcache
If you prefer to install those files in a different folder than scripts/
you can add the following line in your parameters.yml
, eg:
ci_scripts_folder: bin/
You can also adjust the files afterwards and uncomment the gitlabci role
in playbook.yml
again (otherwise the files will be created again
after each provisioning)
Installing it manually¶
Copy the following files to some location (we have a /scripts/ folder, but you can choose any directory)
SCRIPTS_FOLDER=./scripts/
cp virtualization/drifter/provisioning/roles/gitlabci/templates/gitlab-ci.yml .gitlab-ci.yml
cp virtualization/drifter/provisioning/roles/gitlabci/templates/gitlabci.sh $SCRIPTS_FOLDER/gitlabci.sh
cp virtualization/drifter/provisioning/roles/gitlabci/files/run_tests.sh $SCRIPTS_FOLDER/run_tests.sh
date +%Y%m%d%H%M%S > virtualization/provisionbuild.dat
And adjust .gitlab-ci.yml
and $SCRIPTS_FOLDER/gitlabci.sh
with
the corrects paths.
Add your tests¶
Put your test scripts into $SCRIPTS_FOLDER/run_tests.sh
and they
should be run the next time you push something to gitlab (also make sure
you enable one of the go-based gitlab runners for your project, the ones
labeled with “go”, “shell”, and “lxc”)
You can also use any other file, but then adjust the env variable
CI_TEST_SCRIPT
in $SCRIPTS_FOLDER/gitlabci.sh
Customization¶
Global project cache¶
On each runner, there’s a global project cache (shared with all
projects), which can be mounted, uncomment
export DO_GLOBAL_PROJECTS_CACHE=true
in
$SCRIPTS_FOLDER/gitlabci.sh
and that will be mounted into
/home/vagrant/.projects_cache
. We for example add the php composer
cache dir there into /home/vagrant/.projects_cache/composer_cache
,
so that not every project has to download the same project all over
again.
NPM would maybe be another canditate.
As this is shared with all projects, be careful where to put things there.
Running and writing tests¶
The box
pytest fixture allows you to get a full fledged Vagrant box (powered by LXC). Start by provisioning it, and then run commands in the box using the execute
method:
def test_mysql_role_installs_mysql(box):
box.provision(roles=['mysql'], parameters={'mysql_version': '5.7'})
assert '5.7' in box.execute('mysql --version')
By default boxes use a specific Debian image (refer to tests/conftest.py
for the exact distribution). You can specify the OS to use by passing the os
argument to the provision
method:
def test_mysql_role_installs_mysql_on_ubuntu(box):
box.provision(roles=['mysql'], parameters={'mysql_version': '5.7'}, os='drifter/trusty64-base')
assert '5.7' in box.execute('mysql --version')
To run the tests, start by installing the requirements:
pip3 install pytest pyyaml
And then execute the pytest
command to run the tests. Test boxes are automatically discarded when the test run is over so you don’t have to clean anything.
Running a specific test / debugging¶
When a test fails, you can either re-run only the failing tests by passing the --lf
option to pytest, or by using the -k
option, followed by a part of the name of the test (for example pytest -k mysql_role_installs
).
If you want to break at a failing test (for example to spawn a shell into the box and check what’s going on), add the --pdb
option to pytest and, once you’re into pdb, retrieve the box id:
(Pdb) p box.box.get_lxc_id()
drifter-base-boxes_default_1519465979666_71466
Then run lxc-attach -n drifter-base-boxes_default_1519465979666_71466
to get a shell to the box. Once you’re done, use the q
command to exit the debugger and destroy the box.
Passwordless tests running¶
To run the tests without any password (useful for CI integration), add the following to your sudoers (replace johndoe by your user name):
johndoe ALL=(ALL) NOPASSWD: /usr/binlxc-info -iH -n *, /usr/bin/lxc-start -n *, /usr/bin/lxc-stop -k -n *, /usr/bin/lxc-attach -n * -- *, /usr/bin/lxc-copy -s -B overlayfs -n * -N *, /usr/bin/lxc-stop -k -n *, /usr/bin/lxc-destroy -n *
The future ?¶
The framework will evolve as we use it on more projects. It is not the goal to refrain you from doing anything. It will be improved as we need it, the goal is to serve Liip teams !
What could be done if the need arise :
- Better installer with questions to automatically create the config files instead of manual editing
Create boxes¶
Current way¶
Used for the current boxes available on https://vagrantbox-public.liip.ch/
See https://gitlab.liip.ch/liip/drifter-base-boxes
Ansible¶
If you plan on using the ansible_local
provisioner, ansible
must
be installed in the box with at least a version of 1.9.0 otherwise the
roles won’t work.
Other way (older, may still work)¶
LXC¶
git clone https://github.com/team-rawbot/vagrant-lxc-base-boxes
cd vagrant-lxc-base-boxes
make jessie
If you’re getting errors when trying to install the base packages, check
your default LXC config (/etc/lxc/default.conf
) and adapt it to your
setup:
lxc.network.type = veth
lxc.network.link = lxcbr0
lxc.network.flags = up
Migration instructions¶
Version 2.0¶
Ansible version¶
This version of Drifter requires Ansible version >= 2.7 installed. If you’re
using ansible_local = true
in your Vagrantfile (which is the default),
you’ll need to make sure Ansible 2.7 is installed on the guest. To do that, open
the file virtualization/parameters.yml
in your editor and add the
following:
ansible_version: 2.7.0
Then run the provisioning using vagrant provision
, this should install the
correct Ansible version.
If you’re using ansible_local = false
, you’ll need to make sure the Ansible
version installed on the host is at least 2.7. Instructions will depend on how
you installed Ansible (OS package manager, pip, etc).
Ansible templates location¶
The new Ansible version changed the way templates are discovered. You might have
templates paths set in your application, especially if you extend a Drifter
template in one of your templates (eg. {% extends "nginx/templates/default-site.j2" %}
).
In such cases, you’ll need to replace the template path with only the template
name. For example nginx/templates/default-site.j2
would become
default-site.j2
.
Version 1.0¶
Ansible version and ansible_local
¶
Changes were made to the roles that requires to use of at least the
version 1.9.0 of ansible
. This means Debian stable users have to
install ansible
via the
Backports if they don’t
want to use the ansible_local
provisioner.
Also, the default is now ansible_local
also for LXC and the Vagrant
version was bumped to 1.8.4 in this case to get rid of the bug that
caused issues before. This is the new recommanded provisioner.
Old Vagrantfile format¶
The support for the old Vagrantfile format has been removed in this version. You should follow the steps detailed in the migration from 0.1.0 to 0.2.0 if you haven’t done it already.
Virtualbox and LXC URLs¶
It’s not possible to specify separate boxes for LXC and Virtualbox via Drifter anymore. You need to move to the new JSON box format in order to be able to do it. You can have a look at https://vagrantbox-public.liip.ch/drifter-jessie64-base.json for an example.
The lxc_box_name
, lxc_box_url
, vbox_box_name
and
vbox_box_url
have been removed in favor of box_name
and
box_url
.
Git¶
Git installation and configuration is now in its own role. It was added
to the playbook.yml.dist
file, but existing project should also add
it to their playbook if they want to have git installed.
You should also have a look at the git
role documentation inside the
System roles for the new features.
PHP roles names¶
redis-php
and memcached-php
roles have been renamed to follow
the already in place convention. You’ll now have to use php-redis
and php-memcached
Flash & Django roles¶
The flask
and django
roles now use the new virtualenv
role.
This means the parameter for the requirements is now named
pip_requirements
.
The default value for this parameter has also been changed to “requirements/dev.txt”.
Version 0.1.0 to 0.2.0¶
In order for the framework to work correctly on Windows, we removed the symlinks to the Vagrantfile stored in the submodule. The content of the VagrantfileExtra.rb is now in the Vagrantfile at your project root. This new file then loads a more complete Vagrantfile that is in the submodule.
In order to migrate, follow those steps (commands assume you are in your project root directory) :
Remove the Vagrantfile symbolic link from the root :
rm -f Vagrantfile
Copy the VagrantfileExtra.rb file to your root and rename it :
mv virtualization/VagrantfileExtra.rb Vagrantfile
Add the
get
method to yourCustomConfig
class in theVagrantfile
(copy the snippet below inside the class)Add the loading of the complete Vagrantfile to the project Vagrantfile :
echo "load 'virtualization/drifter/Vagrantfile'" >> Vagrantfile
def get(name, default = nil) if self.respond_to?(name) self.send(name) elsif default.nil? raise “[CONFIG ERROR] ‘#{name}’ cannot be found and no default provided.” else default end end