incus-contrib/ansible/playbooks/showcase/webapp-db.yml

149 lines
4.7 KiB
YAML

---
# showcase/webapp-db.yml — MariaDB setup for the webapp blueprint
#
# Installs MariaDB, creates webapp database and user with random password,
# configures remote access, and stores credentials in /etc/webapp-db-creds
# for the web tier to read via Incus API.
- name: Generate random database password
ansible.builtin.set_fact:
db_password: "{{ lookup('password', '/dev/null chars=ascii_letters,digits length=20') }}"
- name: Generate MariaDB setup script
ansible.builtin.set_fact:
db_setup_script: |
#!/bin/bash
set -e
echo "=== MariaDB setup starting ==="
export DEBIAN_FRONTEND=noninteractive
# Install MariaDB
apt-get install -y -qq mariadb-server 2>&1 | tail -3
echo "[OK] MariaDB installed"
# Start and enable
systemctl enable mariadb
systemctl start mariadb
echo "[OK] MariaDB started"
# Configure bind address for remote connections
sed -i 's/^bind-address.*=.*/bind-address = 0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf
systemctl restart mariadb
echo "[OK] Bind address set to 0.0.0.0"
# Create database and user
mysql -u root << 'SQL'
CREATE DATABASE IF NOT EXISTS webapp;
CREATE USER IF NOT EXISTS 'webapp'@'%' IDENTIFIED BY '{{ db_password }}';
GRANT ALL PRIVILEGES ON webapp.* TO 'webapp'@'%';
FLUSH PRIVILEGES;
-- Create sample table for the web tier to query
USE webapp;
CREATE TABLE IF NOT EXISTS visits (
id INT AUTO_INCREMENT PRIMARY KEY,
visitor_ip VARCHAR(45),
visitor_host VARCHAR(255),
visited_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO visits (visitor_ip, visitor_host) VALUES ('setup', '{{ ffsdn_instance_name }}');
SQL
echo "[OK] Database 'webapp' and user created"
# Store credentials for the web tier to read
MY_IP=$(hostname -I | awk '{print $1}')
cat > /etc/webapp-db-creds << CREDS
DB_HOST=${MY_IP}
DB_PORT=3306
DB_NAME=webapp
DB_USER=webapp
DB_PASS={{ db_password }}
CREDS
chmod 644 /etc/webapp-db-creds
echo "[OK] Credentials stored in /etc/webapp-db-creds"
echo "=== MariaDB setup complete ==="
- name: Push MariaDB setup script
ansible.builtin.uri:
url: "{{ incus_api }}/1.0/instances/{{ ffsdn_instance_name }}/files?path=/tmp/webapp-db-setup.sh"
method: POST
client_cert: "{{ incus_cert }}"
client_key: "{{ incus_key }}"
validate_certs: false
body: "{{ db_setup_script }}"
headers:
Content-Type: "application/octet-stream"
X-Incus-type: "file"
X-Incus-mode: "0755"
status_code: [200]
- name: Execute MariaDB setup script
ansible.builtin.uri:
url: "{{ incus_api }}/1.0/instances/{{ ffsdn_instance_name }}/exec"
method: POST
client_cert: "{{ incus_cert }}"
client_key: "{{ incus_key }}"
validate_certs: false
body_format: json
body:
command: ["/bin/bash", "/tmp/webapp-db-setup.sh"]
record-output: true
interactive: false
wait-for-websocket: false
environment:
DEBIAN_FRONTEND: "noninteractive"
status_code: [202]
return_content: true
register: db_setup_exec
- name: Wait for MariaDB setup to complete (up to 5 minutes)
ansible.builtin.uri:
url: "{{ incus_api }}{{ db_setup_exec.json.operation }}/wait?timeout=300"
method: GET
client_cert: "{{ incus_cert }}"
client_key: "{{ incus_key }}"
validate_certs: false
return_content: true
timeout: 320
register: db_setup_wait
failed_when: db_setup_wait.json.metadata.status != "Success"
- name: Verify MariaDB setup exit code
ansible.builtin.assert:
that:
- db_setup_wait.json.metadata.metadata.return | int == 0
fail_msg: "MariaDB setup exited with code {{ db_setup_wait.json.metadata.metadata.return }}"
success_msg: "MariaDB setup completed successfully"
- name: Verify credentials file was written
ansible.builtin.uri:
url: "{{ incus_api }}/1.0/instances/{{ ffsdn_instance_name }}/files?path=/etc/webapp-db-creds"
method: GET
client_cert: "{{ incus_cert }}"
client_key: "{{ incus_key }}"
validate_certs: false
return_content: true
register: creds_check
- name: Display MariaDB configuration
ansible.builtin.debug:
msg: "MariaDB configured: {{ creds_check.content | trim }}"
- name: Clean up setup script
ansible.builtin.uri:
url: "{{ incus_api }}/1.0/instances/{{ ffsdn_instance_name }}/exec"
method: POST
client_cert: "{{ incus_cert }}"
client_key: "{{ incus_key }}"
validate_certs: false
body_format: json
body:
command: ["/bin/rm", "-f", "/tmp/webapp-db-setup.sh"]
record-output: false
interactive: false
wait-for-websocket: false
status_code: [202]
ignore_errors: true