Compare commits

..

16 Commits

Author SHA1 Message Date
Emilien Mantel d2ec2eaa28 🔧 Prepare galaxy release 2024-08-27 12:08:42 +02:00
Emilien Mantel a936b1b1a0 🔥 Remove lagacy code
- Drop Vagrant support
- Drop TravisCI
- Remove legacy tests
2024-08-27 12:08:21 +02:00
Emilien Mantel 174799ee17 🚀 Manage Galera 2024-08-27 12:08:21 +02:00
Emilien Mantel 6eeb28133e 🐛 Fix idempotence 2024-08-27 12:08:21 +02:00
Emilien Mantel 309cafcd37 📝 Update README 2024-08-27 12:08:21 +02:00
Emilien Mantel 23e385e146 👷 Fix linter 2024-08-27 12:08:21 +02:00
Emilien Mantel 35c871d873 🐛 Fix crash on non upstream calls with bad import sql file 2024-08-27 12:08:21 +02:00
Emilien Mantel 4b35bc06fc 👷 Add Github Action 2024-08-27 12:08:21 +02:00
Emilien Mantel d5ea499a4c 🎨 Cleanup vars 2024-08-27 12:08:21 +02:00
Emilien Mantel de83310be5 🎨 Modernize config files 2024-08-27 12:08:21 +02:00
Emilien Mantel 16c7e750f6 🚀 Upstream management on molecule 2024-08-27 12:08:21 +02:00
Emilien Mantel d9672a9b19 🔨 Add molecule 2024-08-27 12:08:21 +02:00
Emilien Mantel be00c762a6 🐛 Fix ansible mysql calls
due to wokes changes...
2024-08-27 12:08:21 +02:00
Emilien Mantel 5841e55a45 🚨 Fix modernized linter 2024-08-27 12:08:16 +02:00
Emilien Mantel 8a060a84ba Add collection deps 2024-08-27 11:39:14 +02:00
Emilien Mantel a03b256d05 Add ansible libs 2024-08-27 11:38:55 +02:00
25 changed files with 126 additions and 336 deletions

View File

@ -6,7 +6,6 @@ skip_list: []
exclude_paths:
- venv/
- tests/ # TODO: Remove this line when tests are migrated to molecule
- .github/
offline: false

View File

@ -14,6 +14,7 @@ jobs:
fail-fast: false
matrix:
scenario:
- debian12_galera
- debian12_master_slave
- debian12_upstream

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
.vagrant*
*.swp
*.retry
/.idea

View File

@ -7,4 +7,3 @@ rules:
ignore:
- /venv
- /tests # TODO: Remove this line when tests are migrated to molecule

View File

@ -16,9 +16,7 @@ If you need to manage previous Debian versions, please use the [latest managed v
Notes
-----
* Galera Cluster is experimental
* Due to Vagrant + Docker limitation (private network), replication/galera can't be checked with Travis
* If you need to test this role with Vagrant, you must install hostmanager plugin: `vagrant plugin install vagrant-hostmanager`
* Galera Cluster is experimental. Feel free to test it and report issues.
Requirements
------------

114
Vagrantfile vendored
View File

@ -1,114 +0,0 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# vi: set tabstop=2 :
# vi: set shiftwidth=2 :
Vagrant.configure("2") do |config|
vbox_deb_buster = 'debian/buster64'
dk_deb_buster = 'hanxhx/vagrant-ansible:debian10'
vbox_deb_bullseye = 'debian/bullseye64'
dk_deb_bullseye = 'hanxhx/vagrant-ansible:debian11'
config.hostmanager.enabled = true
config.hostmanager.manage_host = false
config.hostmanager.manage_guest = true
config.hostmanager.ignore_private_ip = false
config.hostmanager.include_offline = false
cases = [
# ========================
# Debian Buster (10)
# ========================
# Default replication
{ os_name: 'buster', vbox: vbox_deb_buster, docker: dk_deb_buster, vars: {mariadb_origin: 'default' }, groups: ['master'] },
{ os_name: 'buster', vbox: vbox_deb_buster, docker: nil, vars: {mariadb_origin: 'default' }, groups: ['slave'] },
# Upstream replication
{ os_name: 'buster', vbox: vbox_deb_buster, docker: dk_deb_buster, vars: {mariadb_origin: 'upstream' }, groups: ['master'] },
{ os_name: 'buster', vbox: vbox_deb_buster, docker: nil, vars: {mariadb_origin: 'upstream' }, groups: ['slave'] },
# Galera Debian
{ os_name: 'buster', vbox: vbox_deb_buster, docker: dk_deb_buster, vars: {mariadb_origin: 'default' }, groups: ['galera', '1'] },
{ os_name: 'buster', vbox: vbox_deb_buster, docker: nil, vars: {mariadb_origin: 'default' }, groups: ['galera', '2'] },
{ os_name: 'buster', vbox: vbox_deb_buster, docker: nil, vars: {mariadb_origin: 'default' }, groups: ['galera', '3'] },
# Galera Upstream
{ os_name: 'buster', vbox: vbox_deb_buster, docker: dk_deb_buster, vars: {mariadb_origin: 'upstream' }, groups: ['galera', '1'] },
{ os_name: 'buster', vbox: vbox_deb_buster, docker: nil, vars: {mariadb_origin: 'upstream' }, groups: ['galera', '2'] },
{ os_name: 'buster', vbox: vbox_deb_buster, docker: nil, vars: {mariadb_origin: 'upstream' }, groups: ['galera', '3'] },
# ========================
# Debian Bullseye (11)
# ========================
# Default replication
{ os_name: 'bullseye', vbox: vbox_deb_bullseye, docker: dk_deb_bullseye, vars: {mariadb_origin: 'default' }, groups: ['master'] },
{ os_name: 'bullseye', vbox: vbox_deb_bullseye, docker: nil, vars: {mariadb_origin: 'default' }, groups: ['slave'] },
# Upstream replication
{ os_name: 'bullseye', vbox: vbox_deb_bullseye, docker: dk_deb_bullseye, vars: {mariadb_origin: 'upstream' }, groups: ['master'] },
{ os_name: 'bullseye', vbox: vbox_deb_bullseye, docker: nil, vars: {mariadb_origin: 'upstream' }, groups: ['slave'] },
# Galera Debian
{ os_name: 'bullseye', vbox: vbox_deb_bullseye, docker: dk_deb_bullseye, vars: {mariadb_origin: 'default' }, groups: ['galera', '1'] },
{ os_name: 'bullseye', vbox: vbox_deb_bullseye, docker: nil, vars: {mariadb_origin: 'default' }, groups: ['galera', '2'] },
{ os_name: 'bullseye', vbox: vbox_deb_bullseye, docker: nil, vars: {mariadb_origin: 'default' }, groups: ['galera', '3'] },
# Galera Upstream
{ os_name: 'bullseye', vbox: vbox_deb_bullseye, docker: dk_deb_bullseye, vars: {mariadb_origin: 'upstream' }, groups: ['galera', '1'] },
{ os_name: 'bullseye', vbox: vbox_deb_bullseye, docker: nil, vars: {mariadb_origin: 'upstream' }, groups: ['galera', '2'] },
{ os_name: 'bullseye', vbox: vbox_deb_bullseye, docker: nil, vars: {mariadb_origin: 'upstream' }, groups: ['galera', '3'] },
]
cases.each_with_index do |opts,index|
name = 'docker-' + opts[:os_name] + '-' + opts[:vars].map{|k,v| "#{v}"}.join('-') + '-' + opts[:groups].join('-')
iplsb = 10 + index
ip = '192.168.201.' + iplsb.to_s
next if opts[:docker].nil?
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.define name do |m|
m.vm.network "private_network", ip: ip
m.vm.provider "docker" do |d|
d.image = opts[:docker]
d.remains_running = true
d.has_ssh = true
end
m.vm.provision "ansible" do |ansible|
ansible.playbook = "tests/test.yml"
ansible.verbose = 'vv'
ansible.become = true
ansible.extra_vars = opts[:vars].merge({ mariadb_debug_role: true, is_docker: true })
ansible.groups = { opts[:groups][0] => name }
end
end
end
cases.each_with_index do |opts,index|
name = 'vbox-' + opts[:os_name] + '-' + opts[:vars].map{|k,v| "#{v}"}.join('-') + '-' + opts[:groups].join('-')
iplsb = 10 + index
ip = '192.168.200.' + iplsb.to_s
config.vm.define name do |m|
m.vm.hostname = name
m.vm.box = opts[:vbox]
m.vm.network "private_network", ip: ip
m.vm.provider "virtualbox" do |v|
v.cpus = 1
v.memory = 512
end
m.vm.provision "ansible" do |ansible|
ansible.playbook = "tests/test.yml"
ansible.verbose = 'vv'
ansible.become = true
ansible.extra_vars = opts[:vars].merge({ mariadb_debug_role: true, is_docker: false })
ansible.groups = { opts[:groups][0] => name }
end
end
end
end

View File

@ -121,7 +121,7 @@ mariadb_upstream_version: '11.4'
# Galera
# -------------------------------------
mariadb_galera_resetup: false
mariadb_wsrep_node_address: false # Set primary node IP
mariadb_wsrep_node_address: '{{ ansible_default_ipv4.address if ansible_default_ipv4 is defined else "127.0.0.1" }}'
mariadb_galera_members: []
mariadb_galera_primary_node: 'change_me' # See: https://github.com/ansible/ansible/issues/17453
mariadb_wsrep_sst_method: 'rsync'

View File

@ -5,3 +5,4 @@
name: "{{ mariadb_service_name }}"
state: restarted
when: mariadb_notify_restart
throttle: 1

View File

@ -11,8 +11,7 @@ galaxy_info:
platforms:
- name: Debian
versions:
- buster
- bullseye
- bookworm
galaxy_tags:
- database
- packaging

View File

@ -10,6 +10,9 @@ scenario:
- idempotence
- verify
- destroy
dependency:
name: shell
command: "${MOLECULE_SCENARIO_DIRECTORY}/../_shared/tools/install-dependencies.sh"
driver:
name: docker
role_name_check: 1

View File

@ -2,3 +2,4 @@
mariadb_use_galera: true
mariadb_galera_members: "{{ groups['galera'] }}"
mariadb_galera_primary_node: "{{ mariadb_galera_members | first }}"

View File

@ -0,0 +1,8 @@
#!/bin/sh
if [ -z "${IS_GITHUB_ACTIONS}" ]; then
echo "This script is run in GitHub Actions."
pip install netaddr
fi
ansible-galaxy collection install -r requirements.yml

View File

@ -0,0 +1,9 @@
---
- name: Converge
hosts: all
gather_facts: true
tasks:
- name: Include role
ansible.builtin.include_role:
name: "hanxhx.mysql"

View File

@ -0,0 +1,55 @@
---
platforms:
- name: debian12-galera1
image: dokken/debian-12
command: /lib/systemd/systemd
dockerfile: ../_shared/Dockerfile.j2
capabilities:
- SYS_ADMIN
cgroupns_mode: host
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
privileged: true
groups:
- galera
networks:
- name: "00-molecule-d12-galera"
ipv4_address: '172.16.51.1'
docker_networks:
- name: "00-molecule-d12-galera"
ipam_config:
- subnet: "172.16.51.0/24"
gateway: "172.16.51.254"
- name: debian12-galera2
image: dokken/debian-12
command: /lib/systemd/systemd
dockerfile: ../_shared/Dockerfile.j2
capabilities:
- SYS_ADMIN
cgroupns_mode: host
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
privileged: true
groups:
- galera
networks:
- name: "00-molecule-d12-galera"
ipv4_address: '172.16.51.2'
- name: debian12-galera3
image: dokken/debian-12
command: /lib/systemd/systemd
dockerfile: ../_shared/Dockerfile.j2
capabilities:
- SYS_ADMIN
cgroupns_mode: host
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
privileged: true
groups:
- galera
networks:
- name: "00-molecule-d12-galera"
ipv4_address: '172.16.51.3'

View File

@ -0,0 +1,31 @@
---
- name: Verify Galera
hosts: galera
gather_facts: false
tasks:
- name: MYSQL_QUERY | Check if Galera is running
community.mysql.mysql_query:
query: "SHOW GLOBAL STATUS LIKE 'wsrep_ready'"
login_unix_socket: /run/mysqld/mysqld.sock
register: wsrep_ready
- name: ASSERT | Fail if Galera is not running
ansible.builtin.assert:
that:
- wsrep_ready.query_result.0.0.Value == "ON"
fail_msg: "Galera is not running"
success_msg: "Galera is running"
- name: MYSQL_QUERY | Check Galera status
community.mysql.mysql_query:
query: "SHOW GLOBAL STATUS LIKE 'wsrep_local_state_comment'"
login_unix_socket: /run/mysqld/mysqld.sock
register: wsrep_local_state_comment
- name: ASSERT | Fail if Galera is not on the right state
ansible.builtin.assert:
that:
- wsrep_local_state_comment.query_result.0.0.Value == "Synced"
fail_msg: "Galera is not expected state ({{ wsrep_local_state_comment.query_result.0.0.Value }})"
success_msg: "Galera is in expected state"

View File

@ -24,6 +24,8 @@
target: /tmp/import1.sql
login_unix_socket: "/run/mysqld/mysqld.sock"
loop: "{{ mariadb_databases }}"
tags:
- molecule-idempotence-notest
- name: Converge slave
hosts: slave

View File

@ -1,4 +1,5 @@
---
- name: SET_FACT | Prepare mark var
ansible.builtin.set_fact:
__mark: "{{ mariadb_datadir }}/.ansible_galera_boostrap"

View File

@ -2,31 +2,20 @@
- name: APT | Install Galera
ansible.builtin.apt:
pkg: "{{ mariadb_galera_package_name }}"
name: "{{ mariadb_galera_package_name }}"
- name: TEMPLATE | Deploy Galera configuration
ansible.builtin.template:
src: etc/mysql/mariadb.conf.d/20-galera.cnf.j2
dest: /etc/mysql/mariadb.conf.d/20-galera.cnf
src: etc/mysql/mariadb.conf.d/60-galera.cnf.j2
dest: /etc/mysql/mariadb.conf.d/60-galera.cnf
mode: 0644
owner: root
group: root
register: galeraconfig
notify: Restart mariadb
- name: INCLUDE | Bootstrap first node
ansible.builtin.import_tasks: 'bootstrap.yml'
when: inventory_hostname == mariadb_galera_primary_node
- name: INCLUDE | Configure other nodes
ansible.builtin.import_tasks: 'nodes.yml'
when: inventory_hostname != mariadb_galera_primary_node
- name: SERVICE | Restart MariaDB if needed
ansible.builtin.service:
name: "{{ mariadb_service_name }}"
state: restarted
when:
((galeraconfig or (p is defined and p.changed)) and
(bootstrap_run is not defined)) or
((inventory_hostname != mariadb_galera_primary_node) and
(mariadb_galera_resetup))
- name: META | Flush handlers
ansible.builtin.meta: flush_handlers

View File

@ -1,35 +0,0 @@
---
- name: COMMAND | GET debian.cnf from primary node
ansible.builtin.command: cat /etc/mysql/debian.cnf
register: debiancnf
delegate_to: '{{ mariadb_galera_primary_node }}'
changed_when: false
- name: COMMAND | Get current debian.cnf
ansible.builtin.command: cat /etc/mysql/debian.cnf
register: ondc
changed_when: false
- name: BLOCK | Compare debian.cnf
when: debiancnf.stdout != ondc.stdout
block:
- name: SERVICE | Stop MariaDB
ansible.builtin.service:
name: "{{ mariadb_service_name }}"
state: stopped
- name: COPY | Paste primary node's debian.cnf
ansible.builtin.copy:
content: "{{ debiancnf.stdout }}"
dest: /etc/mysql/debian.cnf
mode: 0600
owner: root
group: root
register: paste
- name: SERVICE | Start MariaDB
ansible.builtin.service:
name: "{{ mariadb_service_name }}"
state: started

View File

@ -36,6 +36,7 @@
- etc/mysql/conf.d/mysqldump.cnf.j2
- etc/mysql/mariadb.conf.d/10-extra.cnf.j2
- etc/mysql/mariadb.conf.d/50-server.cnf.j2
notify: Restart mariadb
- name: FILE | Ensure log dir exists
ansible.builtin.file:
@ -45,14 +46,8 @@
owner: mysql
group: mysql
- name: SERVICE | Restart Mariadb now one at a time (prevent bugs)
throttle: 1
ansible.builtin.service:
name: "{{ mariadb_service_name }}"
state: restarted
when:
config.changed and
not mariadb_galera_resetup
- name: META | Flush handlers
ansible.builtin.meta: flush_handlers
- name: SERVICE | Ensure service is started
ansible.builtin.service:

View File

@ -12,6 +12,7 @@
# Global
wsrep_on = ON
wsrep_provider = /usr/lib/galera/libgalera_smm.so
wsrep_cluster_address = gcomm://{{ mariadb_galera_members | join(",") }}
wsrep_sst_method = "{{ mariadb_wsrep_sst_method }}"
{% if mariadb_wsrep_cluster_name is defined %}
@ -19,7 +20,7 @@ wsrep_cluster_name = "{{ mariadb_wsrep_cluster_name }}"
{% endif %}
# Node Configuration
wsrep_node_address = "{{ mariadb_wsrep_node_address | default(ansible_default_ipv4.address if ansible_default_ipv4 is defined else '127.0.0.1') }}"
wsrep_node_address = "{{ mariadb_wsrep_node_address }}"
wsrep_node_name = "{{ mariadb_wsrep_node_name | default(ansible_fqdn) }}"
# Deps

View File

@ -1,23 +0,0 @@
About tests
===========
IMPORTANT
---------
- DO NOT `vagrant up`! My Vagrantfile provides many VMs...
- Each slave communicate to his master.
Tests
-----
- vagrant up the-master
- vagrant up the-slave
Wait master fully installed before run slave.
Example:
```
vagrant up vbox-buster-default-master
vagrant up vbox-buster-default-slave
```

View File

@ -1,6 +0,0 @@
INSERT IGNORE INTO `user` (`id`,`email`) VALUES (51,"vulputate.eu.odio@elitdictumeu.net"),(52,"Sed.eu@erosnec.edu"),(53,"magna@interdum.co.uk"),(54,"ornare.libero.at@Proin.net"),(55,"turpis@aneque.org"),(56,"ut.eros.non@Duisrisusodio.com"),(57,"Pellentesque.ultricies.dignissim@malesuada.edu"),(58,"vel.nisl@mifringilla.net"),(59,"dui@laoreet.com"),(60,"vitae@Suspendissedui.net");
INSERT IGNORE INTO `user` (`id`,`email`) VALUES (61,"turpis@Curabituregestasnunc.co.uk"),(62,"arcu@enim.co.uk"),(63,"consectetuer.rhoncus.Nullam@dolordolortempus.co.uk"),(64,"sem@felisadipiscingfringilla.net"),(65,"aliquet.metus.urna@a.net"),(66,"Fusce.fermentum.fermentum@variusNam.com"),(67,"dolor@velnisl.ca"),(68,"et.netus@Duisrisusodio.edu"),(69,"malesuada@purus.edu"),(70,"gravida.sagittis@pulvinararcuet.ca");
INSERT IGNORE INTO `user` (`id`,`email`) VALUES (71,"et.eros.Proin@Cras.co.uk"),(72,"eleifend.nunc.risus@metuseu.edu"),(73,"pede.Nunc@Phasellusnulla.net"),(74,"vitae.sodales.at@ipsumdolor.edu"),(75,"nunc.sed.pede@aliquetlobortisnisi.co.uk"),(76,"consectetuer@nonenim.ca"),(77,"ultrices@tinciduntvehicula.co.uk"),(78,"Nullam.enim.Sed@Morbiaccumsan.com"),(79,"auctor@Phasellus.net"),(80,"enim.Etiam@interdum.com");
INSERT IGNORE INTO `user` (`id`,`email`) VALUES (81,"sapien.Cras.dolor@consectetuer.com"),(82,"malesuada.fames.ac@feugiattelluslorem.edu"),(83,"risus@vestibulum.co.uk"),(84,"Nunc@Duisgravida.ca"),(85,"ornare.egestas@sitamet.edu"),(86,"Proin.ultrices@senectus.ca"),(87,"ligula@magna.edu"),(88,"orci.tincidunt.adipiscing@sed.com"),(89,"et@venenatis.edu"),(90,"leo.Cras.vehicula@eteuismod.org");
INSERT IGNORE INTO `user` (`id`,`email`) VALUES (91,"consequat.auctor.nunc@utsemNulla.net"),(92,"nec.leo@orci.com"),(93,"Nulla@atvelit.edu"),(94,"tempor.augue.ac@eleifend.edu"),(95,"fermentum.risus.at@penatibusetmagnis.edu"),(96,"id.erat.Etiam@porttitortellus.edu"),(97,"amet.metus.Aliquam@mus.co.uk"),(98,"dolor.tempus.non@risus.org"),(99,"vulputate.posuere.vulputate@purus.ca"),(100,"inceptos@pede.edu");

View File

@ -1 +0,0 @@
localhost

View File

@ -1,122 +0,0 @@
---
- hosts: all
gather_facts: false
pre_tasks:
- name: SETUP | Get facts
ansible.builtin.setup:
register: s
- name: DEBUG | Show facts
ansible.builtin.debug:
var: s
tasks:
- name: APT | Install some packages
ansible.builtin.apt:
name: "{{ p }}"
update_cache: true
cache_valid_time: 3600
vars:
p: ['ca-certificates', 'curl', 'strace', 'rsyslog', 'vim']
- name: SERVICE | Ensure rsyslog is started
ansible.builtin.service:
name: rsyslog
state: started
- hosts: master
roles:
- ../../
tasks:
- name: COPY | Deploy first dump
ansible.builtin.copy:
src: import1.sql
dest: /tmp/import1.sql
mode: 0644
owner: root
group: root
register: c
- name: MYSQL_DB | Import first dump
community.mysql.mysql_db:
name: "{{ item }}"
state: import
target: /tmp/import1.sql
login_unix_socket: "{{ mariadb_socket }}"
loop: ['testrepl', 'norepl']
when: c.changed
tags:
- skip_ansible_lint
- hosts: slave
pre_tasks:
- name: SHELL | Get master IP
ansible.builtin.shell: set -o pipefail && getent hosts {{ ansible_hostname | replace ('slave', 'master') }} | cut -d ' ' -f 1
args:
executable: /bin/bash
register: ip
changed_when: false
- name: SET_FACT | Apply some configuration
ansible.builtin.set_fact:
# MariaDB don't read /etc/hosts (from vagrant host plugin)
mariadb_replication_host: "{{ ip.stdout }}"
# Need this to use vagrant 'delegate_to'
mariadb_slave_import_from: "{{ ansible_hostname | replace ('slave', 'master') }}"
roles:
- ../../
tasks:
- block:
- name: COPY | Deploy dump
ansible.builtin.copy:
src: import2.sql
dest: /tmp/import2.sql
mode: 0644
owner: root
group: root
delegate_to: "{{ mariadb_slave_import_from }}"
register: c
- name: MYSQL_DB | Import another dump
community.mysql.mysql_db:
name: "{{ item }}"
state: import
target: /tmp/import2.sql
login_unix_socket: "{{ mariadb_socket }}"
loop: ['testrepl', 'norepl']
when: c.changed
delegate_to: "{{ mariadb_slave_import_from }}"
- name: MYSQL_REPLICATION | Get slave infos
community.mysql.mysql_replication:
mode: getslave
register: slave
- name: FAIL | if slave threads are not running
ansible.builtin.fail:
msg: "Slave issue"
when: slave.Slave_IO_Running != 'Yes' or slave.Slave_SQL_Running != 'Yes'
- hosts: galera
pre_tasks:
- name: APT_REPOSITORY | Force galera-3 on Buster + MariaDB from Debian repository (prevent crashes)
ansible.builtin.set_fact:
mariadb_galera_package_name: 'galera-3'
when: ansible_distribution_release == 'buster' and mariadb_origin == 'default'
- name: SET_FACT | Apply some configuration
ansible.builtin.set_fact:
mariadb_galera_primary_node: '{% if is_docker %}docker-{% else %}vbox-{% endif %}{{ ansible_distribution_release }}-{{ mariadb_origin }}-galera-1'
mariadb_wsrep_node_address: "{{ '127.0.0.1' if is_docker else ansible_eth1.ipv4.address }}"
roles:
- ../../