How to register the result of a mysql query with Ansible

When you run a query on mysql you normally have a output like:

+-----------+
| USERNAME  |
+-----------+
| rcastells |
+-----------+
1 row in set (0.00 sec)

If you need to register only ‘rcastells’, how can you register the result of query above with ansible? You need to add following args to your mysql query:

  • -N, –skip-column-names: Don’t write column names in results.
  • -s, –silent: Be more silent. Print results with a tab as separator, each row on new line.

So your task will look like:

- name:  Get username
  command: mysql -u {{ username }} -p {{ mysql_root_password }} {{ database }} -Ns -e "<your_query>"
  register: username

- debug: msg="{{ username.stdout_lines }}"

 

Advertisements

Jinja2: How to gather_facts from other hosts

If you have this content in your inventory file:

[loadbalancers]
ha01 ansible_host=ec2-52-50-164-246.eu-west-1.compute.amazonaws.com
ha02 ansible_host=ec2-52-48-101-228.eu-west-1.compute.amazonaws.com

[webservers]
web01 ansible_host=ec2-52-50-143-215.eu-west-1.compute.amazonaws.com
web02 ansible_host=ec2-52-31-14-253.eu-west-1.compute.amazonaws.com

And you want to create a template inside your loadbalancers with information from webservers, like for example following haproxy configuration:

{% for host in groups['webservers'] %}
server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_default_ipv4']['address'] }}:80
{% endfor %}

You first need to connect to webservers. No need to do anything. So, your playbook will look like:

---
# No need to run a task for webservers. This will gather their facts.
- hosts: webservers
  become: yes

- hosts: loadbalancers
  become: yes
  roles:
- haproxy-ha

This will connect first to your webservers and gather their facts that will be used in haproxy.cfg.j2 template file.

Role: HAProxy in HA with Keepalived in Ubuntu

https://github.com/rcastells/ansible

This role is created to work with:

  • 2 LoadBalancers
  • 1 or more WebServers

First of all review your inventory file and create a group for loadbalancers and another one for webservers:

[loadbalancers]
 ha01 ansible_host=ec2-52-50-164-246.eu-west-1.compute.amazonaws.com
 ha02 ansible_host=ec2-52-48-101-228.eu-west-1.compute.amazonaws.com

[webservers]
 web01 ansible_host=ec2-52-50-143-215.eu-west-1.compute.amazonaws.com
 web02 ansible_host=ec2-52-31-14-253.eu-west-1.compute.amazonaws.com

Then, take a look at host_vars directory and inside the role at default vars:

host_vars

You must define for ha01 and ha02 which one will be the master and the VIP between servers:

keepalived_interval: 2
keepalived_debug: 2
keepalived_interface: eth0
keepalived_MASTER_SLAVE: MASTER (or SLAVE)
keepalived_priority: 101 (or 100)
keepalived_virtualip: 172.31.39.157 (your VIP)

default vars

You could need to change these vars.

---
# Set default haproxy installation package if not defined at host_vars
haproxy_url: http://www.haproxy.org/download/1.6/src/haproxy-1.6.7.tar.gz
haproxy_version: 1.6.7

Finally take a look at the initial playbook (haproxy-ha.yml):

---
# HAProxy servers
- hosts: webservers
become: yes

- hosts: loadbalancers
become: yes
roles:
- haproxy-ha

We want to connect to webservers just to gather their facts and then use them in haproxy.cfg template file.

To run the playbook you must run:

ansible-playbook -i <inventory_file>  haproxy-ha.yml -k -K -u <username>

As an example if you have ssh key connection to all servers you could run:

ansible-playbook -i inventory/production haproxy-ha.yml

 

Using vars_prompt to create menu with options

Normally I prefer to reduce the probability that a user does mistakes. So sometimes is better if you ask through a menu what do you want to do when running a playbook. For example, if you’re using the same playbook to perform deployments of different applications is a good idea to create a menu with options. So you can reuse the same playbook for different actions. If you have following menu created by using vars_prompt:

vars_prompt:
 - name: "application"
   prompt: "Which application do you want to deploy?\n1- Web\n2- Wiki\n"
   private: no

You will have following prompt when running the playbook:

Which application do you want to deploy?
1- Web
2- Wiki

Then inside your playbook you can work with this condition.

For example you can define variables using set_fact:

 - set_fact: app=web
 when: ( application == "1" )
 
 - set_fact: app=wiki
 when: ( application == "2" )

Or perform actions taking into account which option you have chosen:

 - name: Build the war for website
   shell: /opt/builds/buildwebwar.sh
   when: ( application == "1" ) 


- name: Build the war for wiki
   shell: /opt/builds/buildwikiwar.sh
   when: ( application == "2" )

In that way you can be sure that user can do only one mistake: press the wrong number 🙂

Using variables in hosts declaration inside playbooks

When you declare in which hosts do you want to run a playbook you usually do it like this:

- hosts: databases

But let’s say that you want to be more flexible and you want to have some variable inside your hosts declaration. How can you do that? One possible solution is using extra vars.

If we decide to call our variable ‘env’ we should define our hosts inside the playbook like:

- hosts: "{{ env }}_master"

And then run the playbook as follows:

ansible-playbook -i inventory/databases binlogs.yml --extra-vars "env=database01"

Obviously inside your inventory file, these hosts must exist:

database01_master ansible_host=db01
database02_master ansible_host=db03
database03_master ansible_host=db05