The Elovation Ruby on Rails application was written by Christos Hrousis. It can be used to track the results of two-player games like chess, table tennis and foosball. This 14th article in this series tells us how to install the Elovation Ruby on Rails application.
The Elovation application uses the Elo rating system created by Arpad Elo, a Hungarian-born American physics professor. You can also use the Trueskill rating system for teams with multiple players and still provide rankings for individual players. Elovation requires at least Ruby on Rails 5.1 and uses the PostgreSQL database for its backend. It is free and open source software and has been released under the MIT licence.
GNU/Linux
An Ubuntu 16.04.1 LTS guest virtual machine (VM) instance using KVM/QEMU has been chosen to set up Elovation.
The host system is a Parabola GNU/Linux-libre x86_64 system, and Ansible is installed on the host system using the distribution package manager. The version of Ansible used is 2.4.3.0 as indicated below:
$ ansible --version ansible 2.4.3.0 config file = /etc/ansible/ansible.cfg configured module search path = [u’/home/shakthi/.ansible/plugins/modules’, u’/usr/share/ansible/plugins/modules’] ansible python module location = /usr/lib/python2.7/site-packages/ansible executable location = /usr/bin/ansible python version = 2.7.14 (default, Jan 5 2018, 10:41:29) [GCC 7.2.1 20171224]
You should add an entry to the /etc/hosts file for the guest ‘Ubuntu’ VM as follows:
192.168.122.244 ubuntu
On the host system, let’s create a project directory structure to store the Ansible playbooks and inventory, as follows:
ansible/inventory/kvm/ /playbooks/configuration/
The Ubuntu 16.04.1 LTS server has Python 3 by default, and hence we can use the same with Ansible. The inventory/kvm/inventory file contains the following:
[elovation-host] ubuntu ansible_host=192.168.122.244 ansible_connection=ssh ansible_user=ubuntu ansible_password=ubuntu123 [elovation-host:vars] ansible_python_interpreter=/usr/bin/python3
You should now be able to issue commands, using Ansible, to the guest OS. For example:
$ ansible -i inventory/kvm/inventory ubuntu -m ping ubuntu | SUCCESS => { “changed”: false, “ping”: “pong” }
Dependencies
The apt-daily.service runs by default on a new installation of Ubuntu 16.04.1 LTS. If we need to install software, the APT lock held by this service needs to be removed. Hence, we need to first stop this service. The APT software package repository is then updated before installing the dependencies to set up Ruby.
--- - name: Install dependencies hosts: ubuntu become: yes become_method: sudo gather_facts: true tags: [apt] tasks: - name: Stop apt-daily.service shell: systemctl kill --kill-who=all apt-daily.service - name: Update the software package repository apt: update_cache: yes - name: Install dependencies package: name: “{{ item }}” state: latest with_items: - libssl-dev - libreadline-dev - zlib1g-dev - build-essential - git
The above playbook can be executed as follows:
$ ansible-playbook -i inventory/kvm/inventory playbooks/configuration/elovation.yml --tags apt -vv -K
The -vv represents the verbosity of the Ansible output. You can use up to four ‘v’s. The -K option prompts for the sudo password for the ubuntu user.
Rbenv
Let’s use Rbenv to set up Ruby on this virtual instance. It allows the installation of multiple Ruby versions, and the version in production can be selected. The source repo of Rbenv is cloned first, and then configure and make are executed. The Rbenv PATH and initialisation are then updated in the ~/.bashrc file.
- name: Build rbenv hosts: ubuntu tags: [rbenv] tasks: - name: Get rbenv git: repo: ‘https://github.com/rbenv/rbenv.git’ dest: “/home/{{ ansible_user }}/.rbenv” - name: Build rbenv shell: “cd /home/{{ ansible_user }}/.rbenv && src/configure && make -C src” - name: Set rbenv PATH lineinfile: path: “/home/{{ ansible_user }}/.bashrc” state: present line: ‘export PATH=”$HOME/.rbenv/bin:$PATH”’ - name: rbenv init lineinfile: path: “/home/{{ ansible_user }}/.bashrc” state: present line: ‘eval “$(rbenv init -)”’
The playbook to set up Rbenv can be invoked as follows:
$ ansible-playbook -i inventory/kvm/inventory playbooks/configuration/elovation.yml --tags rbenv -K
A sample execution output is shown below for reference:
$ ansible-playbook -i inventory/kvm/inventory playbooks/configuration/elovation.yml --tags rbenv -K SUDO password: PLAY [Install dependencies] ********************************************************************************************** TASK [Gathering Facts] *************************************************************************************************** ok: [ubuntu] PLAY [Build rbenv] ******************************************************************************************************* TASK [Gathering Facts] *************************************************************************************************** ok: [ubuntu] TASK [Get rbenv] ********************************************************************************************************* ok: [ubuntu] TASK [Build rbenv] ******************************************************************************************************* changed: [ubuntu] TASK [Set rbenv PATH] **************************************************************************************************** ok: [ubuntu] TASK [rbenv init] ******************************************************************************************************** ok: [ubuntu] PLAY [Build ruby] ************************************************************************************************************************************ TASK [Gathering Facts] *************************************************************************************************** ok: [ubuntu] PLAY [Postgresql] ******************************************************************************************************** TASK [Gathering Facts] *************************************************************************************************** ok: [ubuntu] PLAY [Elovation] ********************************************************************************************************* TASK [Gathering Facts] *************************************************************************************************** ok: [ubuntu] PLAY RECAP *************************************************************************************************************** ubuntu : ok=9 changed=1 unreachable=0 failed=0
Ruby
Ruby-build is a command line utility to install Ruby. Its repository needs to be cloned into the Rbenv plugins folder. Ruby 2.4.0 is then installed using the rbenv command, and the same is set as the default global Ruby version in the following playbook:
- name: Build ruby hosts: ubuntu tags: [ruby] vars: rbenv_root: “/home/{{ ansible_user }}/.rbenv” tasks: - name: Create rbenv plugins shell: $SHELL -lc “mkdir -p {{ rbenv_root }}/plugins” - name: Get ruby-build git: repo: ‘https://github.com/rbenv/ruby-build.git’ dest: “{{ rbenv_root }}/plugins/ruby-build” - name: Install Ruby 2.4.0 shell: $SHELL -lc “{{ rbenv_root }}/bin/rbenv install 2.4.0” - name: Set Ruby 2.4.0 as Global shell: $SHELL -lc “{{ rbenv_root }}/bin/rbenv global 2.4.0”
The above playbook can be invoked with the ‘ruby’ tags option as shown below:
$ ansible-playbook -i inventory/kvm/inventory playbooks/configuration/elovation.yml --tags ruby -vv -K
PostgreSQL
Elovation uses the PostgreSQL database, by default, as its backend data store. After updating the APT software package repository, we can install the PostgreSQL server and a few other dependencies. The PostgreSQL database server is started, and the Ansible playbook waits for the database to listen on Port 5432. A separate application user account is created in the database. Although we hard-coded the password in this example, in production, it is recommended that you use Vault to encrypt and decrypt the passwords with Ansible. The local authentication is changed from peer to md5 in the PostgreSQL pg_hba.conf configuration file, and the database is restarted. The Ansible playbook again waits for the server to listen on Port 5432, as shown below:
- name: Postgresql hosts: ubuntu become: yes become_method: sudo tags: [postgresql] tasks: - name: Update the software package repository apt: update_cache: yes - name: Install dependencies package: name: “{{ item }}” state: latest with_items: - python3-psycopg2 - postgresql - postgresql-contrib - libpq-dev - name: Start database server systemd: name: postgresql state: started - wait_for: port: 5432 - name: Create application user shell: sudo -u postgres createuser -s pguser - name: Set password for application user shell: sudo -u postgres psql -c “ALTER USER pguser WITH password ‘pguser123’” - name: Replace peer auth lineinfile: path: /etc/postgresql/9.5/main/pg_hba.conf regexp: ‘^local all all peer’ line: ‘local all all md5’ - name: Restart database server systemd: name: postgresql state: restarted - wait_for: port: 5432
The above playbook to install and configure the PostgreSQL database server can be run as shown below:
$ ansible-playbook -i inventory/kvm/inventory playbooks/configuration/elovation.yml –tags postgresql -vv -K
Elovation
The final step is to set up the Elovation Ruby on Rails application. The bundler software is used to track gems and the versions required by the Rails application. It is installed first and then the Elovation repository is cloned to the HOME folder. The config/database.yml file is created and the database credentials are updated. The bundle install command is executed to fetch and install the required gems for the application. The database is created for the application and the migrations are executed to create the necessary tables. The entire playbook to set up Elovation is as follows:
- name: Elovation hosts: ubuntu tags: [elovation] vars: rbenv_root: “/home/{{ ansible_user }}/.rbenv” tasks: - name: Install bundler shell: “{{ rbenv_root }}/shims/gem install bundler” - name: Get elovation git: repo: ‘https://github.com/elovation/elovation.git’ dest: “/home/{{ ansible_user }}/elovation” - name: Create database.yml copy: src: “/home/{{ ansible_user }}/elovation/config/database.yml.example” dest: “/home/{{ ansible_user }}/elovation/config/database.yml” remote_src: yes - name: Add database credentials for development database lineinfile: path: “/home/{{ ansible_user }}/elovation/config/database.yml” insertafter: “ database: elovation_development” line: “ username: pguser\n password: pguser123” - name: Add database credentials for test database lineinfile: path: “/home/{{ ansible_user }}/elovation/config/database.yml” insertafter: “ database: elovation_test” line: “ username: pguser\n password: pguser123” - name: bundle install shell: “{{ rbenv_root }}/shims/bundle install” args: chdir: “/home/{{ ansible_user }}/elovation” - name: Create database shell: “RAILS_ENV=’development’ {{ rbenv_root }}/shims/bundle exec rake db:create” args: chdir: “/home/{{ ansible_user }}/elovation” - name: Migrate database shell: “RAILS_ENV=’development’ {{ rbenv_root }}/shims/bundle exec rake db:migrate” args: chdir: “/home/{{ ansible_user }}/elovation”
The above playbook can be executed as follows:
$ ansible-playbook -i inventory/kvm/inventory playbooks/configuration/elovation.yml --tags elovation -vv -K
You can then log in to the VM, and manually start the RAILS application using the following command:
$ cd elovation $ RAILS_ENV=”development” bundle exec rails server --binding=192.168.122.244
The application will listen on 192.168.122.244:3000, which you can open in a browser on the host system. You will see the home page, as shown in Figure 1.
You can add a player by providing the name and e-mail address, as shown in Figure 2.
You can start a new game using the Trueskill rating system, as shown in Figure 3.
You can also create a new game with the Elo rating system, as shown in Figure 4.