Changeset - 8278ff584984
[Not reviewed]
15 2 18
Branko Majic (branko) - 6 years ago 2017-11-26 00:28:16
branko@majic.rs
MAR-128: Upgraded tests for database role:

- Switch to new Molecule configuration.
- Updated set-up playbook to use become: yes.
- Moved some preparatory steps outside of the main playbook (eases
idempotence tests).
- Updated tests to reference the yml inventory file.
- Updated tests to use new fixture (host instead of individual ones).
- Updated backup_server and backup_client configuration in order to
make the backup testing more generic (and easier to update for
future).
21 files changed with 197 insertions and 76 deletions:
0 comments (0 inline, 0 general)
roles/database/defaults/main.yml
Show inline comments
 
---
 

	
 
enable_backup: False
 
\ No newline at end of file
 
enable_backup: False
roles/database/handlers/main.yml
Show inline comments
 
---
 
\ No newline at end of file
 
---
roles/database/molecule.yml
Show inline comments
 
deleted file
roles/database/molecule/default/create.yml
Show inline comments
 
new file 100644
 
---
 
- name: Create
 
  hosts: localhost
 
  connection: local
 
  gather_facts: False
 
  no_log: "{{ not lookup('env', 'MOLECULE_DEBUG') | bool }}"
 
  vars:
 
    molecule_file: "{{ lookup('env', 'MOLECULE_FILE') }}"
 
    molecule_instance_config: "{{ lookup('env', 'MOLECULE_INSTANCE_CONFIG') }}"
 
    molecule_yml: "{{ lookup('file', molecule_file) | molecule_from_yaml }}"
 
  tasks:
 
    - name: Create molecule instance(s)
 
      molecule_vagrant:
 
        instance_name: "{{ item.name }}"
 
        instance_interfaces: "{{ item.interfaces | default(omit) }}"
 
        instance_raw_config_args: "{{ item.instance_raw_config_args | default(omit) }}"
 

	
 
        platform_box: "{{ item.box }}"
 
        platform_box_version: "{{ item.box_version | default(omit) }}"
 
        platform_box_url: "{{ item.box_url | default(omit) }}"
 

	
 
        provider_name: "{{ molecule_yml.driver.provider.name }}"
 
        provider_memory: "{{ item.memory | default(omit) }}"
 
        provider_cpus: "{{ item.cpus | default(omit) }}"
 
        provider_raw_config_args: "{{ item.raw_config_args | default(omit) }}"
 

	
 
        state: up
 
      register: server
 
      with_items: "{{ molecule_yml.platforms }}"
 

	
 
    # Mandatory configuration for Molecule to function.
 

	
 
    - name: Populate instance config dict
 
      set_fact:
 
        instance_conf_dict: {
 
          'instance': "{{ item.Host }}",
 
          'address': "{{ item.HostName }}",
 
          'user': "{{ item.User }}",
 
          'port': "{{ item.Port }}",
 
          'identity_file': "{{ item.IdentityFile }}", }
 
      with_items: "{{ server.results }}"
 
      register: instance_config_dict
 
      when: server.changed | bool
 

	
 
    - name: Convert instance config dict to a list
 
      set_fact:
 
        instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
 
      when: server.changed | bool
 

	
 
    - name: Dump instance config
 
      copy:
 
        # NOTE(retr0h): Workaround for Ansible 2.2.
 
        #               https://github.com/ansible/ansible/issues/20885
 
        content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
 
        dest: "{{ molecule_instance_config }}"
 
      when: server.changed | bool
roles/database/molecule/default/destroy.yml
Show inline comments
 
new file 100644
 
---
 

	
 
- name: Destroy
 
  hosts: localhost
 
  connection: local
 
  gather_facts: False
 
  no_log: "{{ not lookup('env', 'MOLECULE_DEBUG') | bool }}"
 
  vars:
 
    molecule_file: "{{ lookup('env', 'MOLECULE_FILE') }}"
 
    molecule_instance_config: "{{ lookup('env',' MOLECULE_INSTANCE_CONFIG') }}"
 
    molecule_yml: "{{ lookup('file', molecule_file) | molecule_from_yaml }}"
 
  tasks:
 
    - name: Destroy molecule instance(s)
 
      molecule_vagrant:
 
        instance_name: "{{ item.name }}"
 
        platform_box: "{{ item.box }}"
 
        provider_name: "{{ molecule_yml.driver.provider.name }}"
 
        force_stop: "{{ item.force_stop | default(True) }}"
 

	
 
        state: destroy
 
      register: server
 
      with_items: "{{ molecule_yml.platforms }}"
 

	
 
    # Mandatory configuration for Molecule to function.
 

	
 
    - name: Populate instance config
 
      set_fact:
 
        instance_conf: {}
 

	
 
    - name: Dump instance config
 
      copy:
 
        # NOTE(retr0h): Workaround for Ansible 2.2.
 
        #               https://github.com/ansible/ansible/issues/20885
 
        content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
 
        dest: "{{ molecule_instance_config }}"
 
      when: server.changed | bool
roles/database/molecule/default/molecule.yml
Show inline comments
 
new file 100644
 
---
 

	
 
dependency: {}
 

	
 
driver:
 
  name: vagrant
 
  provider:
 
    name: virtualbox
 

	
 
lint:
 
  name: yamllint
 

	
 
platforms:
 

	
 
  - name: parameters-mandatory-jessie64
 
    groups:
 
      - parameters-mandatory
 
    box: debian/contrib-jessie64
 
    memory: 256
 
    cpus: 1
 

	
 
  - name: backup-jessie64
 
    groups:
 
      - backup
 
    box: debian/contrib-jessie64
 
    memory: 512
 
    cpus: 1
 

	
 
provisioner:
 
  name: ansible
 
  config_options:
 
    ssh_connection:
 
      pipelining: "True"
 
  lint:
 
    name: ansible-lint
 

	
 
scenario:
 
  name: default
 

	
 
verifier:
 
  name: testinfra
 
  lint:
 
    name: flake8
roles/database/molecule/default/playbook.yml
Show inline comments
 
file renamed from roles/database/playbook.yml to roles/database/molecule/default/playbook.yml
 
---
 

	
 
- hosts: all
 
  tasks:
 

	
 
    - name: Update all caches to avoid errors due to missing remote archives
 
      apt:
 
        update_cache: yes
 
      changed_when: False
 

	
 
- hosts: parameters-mandatory
 
  become: yes
 
  roles:
 
    - role: database
 
      db_name: testdb
 
@@ -18,19 +12,7 @@
 
      db_root_password: "root_password"
 

	
 
- hosts: backup
 
  roles:
 
    - role: backup_server
 
      backup_host_ssh_private_keys:
 
        dsa: "{{ lookup('file', 'tests/data/ssh/server_dsa') }}"
 
        rsa: "{{ lookup('file', 'tests/data/ssh/server_rsa') }}"
 
        ed25519: "{{ lookup('file', 'tests/data/ssh/server_ed25519') }}"
 
        ecdsa: "{{ lookup('file', 'tests/data/ssh/server_ecdsa') }}"
 
      backup_clients:
 
        - server: backup
 
          ip: 127.0.0.1
 
          public_key: "{{ lookup('file', 'tests/data/ssh/parameters-optional.pub') }}"
 

	
 
- hosts: backup
 
  become: yes
 
  roles:
 
    - role: database
 
      db_name: testdb
 
@@ -41,6 +23,7 @@
 
      db_root_password: "root_password"
 

	
 
      # backup_client
 
      backup_client_username: "bak-localhost"
 
      backup_encryption_key: "{{ lookup('file', 'tests/data/gnupg/parameters-optional.asc') }}"
 
      backup_server: localhost
 
      backup_server_host_ssh_public_keys:
roles/database/molecule/default/prepare.yml
Show inline comments
 
new file 100644
 
---
 

	
 
- name: Prepare
 
  hosts: all
 
  gather_facts: False
 
  tasks:
 
    - name: Install python for Ansible
 
      raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
 
      become: True
 
      changed_when: False
 

	
 
- hosts: all
 
  become: yes
 
  tasks:
 

	
 
    - name: Update all caches to avoid errors due to missing remote archives
 
      apt:
 
        update_cache: yes
 
      changed_when: False
 

	
 
- hosts: backup
 
  become: yes
 
  roles:
 
    - role: backup_server
 
      backup_host_ssh_private_keys:
 
        dsa: "{{ lookup('file', 'tests/data/ssh/server_dsa') }}"
 
        rsa: "{{ lookup('file', 'tests/data/ssh/server_rsa') }}"
 
        ed25519: "{{ lookup('file', 'tests/data/ssh/server_ed25519') }}"
 
        ecdsa: "{{ lookup('file', 'tests/data/ssh/server_ecdsa') }}"
 
      backup_clients:
 
        - server: localhost
 
          ip: 127.0.0.1
 
          public_key: "{{ lookup('file', 'tests/data/ssh/parameters-optional.pub') }}"
roles/database/molecule/default/tests/data/gnupg/parameters-optional.asc
Show inline comments
 
file renamed from roles/database/tests/data/gnupg/parameters-optional.asc to roles/database/molecule/default/tests/data/gnupg/parameters-optional.asc
roles/database/molecule/default/tests/data/ssh/parameters-optional
Show inline comments
 
file renamed from roles/database/tests/data/ssh/parameters-optional to roles/database/molecule/default/tests/data/ssh/parameters-optional
roles/database/molecule/default/tests/data/ssh/parameters-optional.pub
Show inline comments
 
file renamed from roles/database/tests/data/ssh/parameters-optional.pub to roles/database/molecule/default/tests/data/ssh/parameters-optional.pub
roles/database/molecule/default/tests/data/ssh/server_dsa
Show inline comments
 
file renamed from roles/database/tests/data/ssh/server_dsa to roles/database/molecule/default/tests/data/ssh/server_dsa
roles/database/molecule/default/tests/data/ssh/server_dsa.pub
Show inline comments
 
file renamed from roles/database/tests/data/ssh/server_dsa.pub to roles/database/molecule/default/tests/data/ssh/server_dsa.pub
roles/database/molecule/default/tests/data/ssh/server_ecdsa
Show inline comments
 
file renamed from roles/database/tests/data/ssh/server_ecdsa to roles/database/molecule/default/tests/data/ssh/server_ecdsa
roles/database/molecule/default/tests/data/ssh/server_ecdsa.pub
Show inline comments
 
file renamed from roles/database/tests/data/ssh/server_ecdsa.pub to roles/database/molecule/default/tests/data/ssh/server_ecdsa.pub
roles/database/molecule/default/tests/data/ssh/server_ed25519
Show inline comments
 
file renamed from roles/database/tests/data/ssh/server_ed25519 to roles/database/molecule/default/tests/data/ssh/server_ed25519
roles/database/molecule/default/tests/data/ssh/server_ed25519.pub
Show inline comments
 
file renamed from roles/database/tests/data/ssh/server_ed25519.pub to roles/database/molecule/default/tests/data/ssh/server_ed25519.pub
roles/database/molecule/default/tests/data/ssh/server_rsa
Show inline comments
 
file renamed from roles/database/tests/data/ssh/server_rsa to roles/database/molecule/default/tests/data/ssh/server_rsa
roles/database/molecule/default/tests/data/ssh/server_rsa.pub
Show inline comments
 
file renamed from roles/database/tests/data/ssh/server_rsa.pub to roles/database/molecule/default/tests/data/ssh/server_rsa.pub
roles/database/molecule/default/tests/test_backup.py
Show inline comments
 
file renamed from roles/database/tests/test_backup.py to roles/database/molecule/default/tests/test_backup.py
 
import testinfra.utils.ansible_runner
 

	
 
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
 
    '.molecule/ansible_inventory').get_hosts('backup')
 
    '.molecule/ansible_inventory.yml').get_hosts('backup')
 

	
 

	
 
def test_backup_directories(File, Sudo):
 
def test_backup_directories(host):
 
    """
 
    Tests if backup directories have been set-up correctly.
 
    """
 

	
 
    with Sudo():
 
    with host.sudo():
 
        directories = ["/srv/backup", "/srv/backup/mariadb"]
 

	
 
        for path in directories:
 

	
 
            directory = File(path)
 
            directory = host.file(path)
 

	
 
            assert directory.is_directory
 
            assert directory.user == 'root'
 
@@ -22,13 +22,13 @@ def test_backup_directories(File, Sudo):
 
            assert directory.mode == 0o700
 

	
 

	
 
def test_backup_script_file(File, Sudo):
 
def test_backup_script_file(host):
 
    """
 
    Tests if backup script file for dumping database has been set-up correctly.
 
    """
 

	
 
    with Sudo():
 
        script = File('/etc/duply/main/pre.d/dump_testdb.sh')
 
    with host.sudo():
 
        script = host.file('/etc/duply/main/pre.d/dump_testdb.sh')
 

	
 
        assert script.is_file
 
        assert script.user == 'root'
 
@@ -37,28 +37,28 @@ def test_backup_script_file(File, Sudo):
 
        assert "/usr/bin/mysqldump \"testdb\" > \"/srv/backup/mariadb/testdb.sql\"" in script.content
 

	
 

	
 
def test_backup_run(Command, File, Sudo):
 
def test_backup_run(host):
 
    """
 
    Tests if backup runs correctly, and if restore will included the backed-up
 
    database.
 
    """
 

	
 
    with Sudo():
 
    with host.sudo():
 

	
 
        # Remove restore directory in order to make sure restore has worked
 
        # correctly.
 
        Command("rm -rf /root/restore")
 
        host.run("rm -rf /root/restore")
 

	
 
        backup_run = Command('duply main backup')
 
        backup_run = host.run('duply main backup')
 
        assert backup_run.rc == 0
 

	
 
        database_dump = File('/srv/backup/mariadb/testdb.sql')
 
        database_dump = host.file('/srv/backup/mariadb/testdb.sql')
 
        assert database_dump.is_file
 
        assert 'Database: testdb' in database_dump.content
 

	
 
        restore_run = Command('duply main restore /root/restore')
 
        restore_run = host.run('duply main restore /root/restore')
 
        assert restore_run.rc == 0
 

	
 
        restored_database_dump = File('/root/restore/srv/backup/mariadb/testdb.sql')
 
        restored_database_dump = host.file('/root/restore/srv/backup/mariadb/testdb.sql')
 
        assert restored_database_dump.is_file
 
        assert restored_database_dump.content == database_dump.content
roles/database/molecule/default/tests/test_default.py
Show inline comments
 
file renamed from roles/database/tests/test_default.py to roles/database/molecule/default/tests/test_default.py
 
import testinfra.utils.ansible_runner
 

	
 
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
 
    '.molecule/ansible_inventory').get_hosts('all')
 
    '.molecule/ansible_inventory.yml').get_hosts('all')
 

	
 

	
 
def test_database_created(Command, Sudo):
 
def test_database_created(host):
 
    """
 
    Tests if database has been created.
 
    """
 

	
 
    with Sudo():
 
        show_databases = Command("mysql -BNe \"show databases like 'testdb'\"")
 
    with host.sudo():
 
        show_databases = host.run("mysql -BNe \"show databases like 'testdb'\"")
 

	
 
        assert show_databases.rc == 0
 
        assert show_databases.stdout == "testdb"
 

	
 

	
 
def test_database_user_login(Command):
 
def test_database_user_login(host):
 
    """
 
    Tests database user login.
 
    """
 

	
 
    login = Command("mysql -utestdb -ptestdbpassword -BNe 'show databases'")
 
    login = host.run("mysql -utestdb -ptestdbpassword -BNe 'show databases'")
 

	
 
    assert login.rc == 0
 

	
 

	
 
def test_database_user_permissions(Command, Sudo):
 
def test_database_user_permissions(host):
 
    """
 
    Tests if database user has been granted correct permissions on the database.
 
    """
 

	
 
    visible_databases = Command("mysql -utestdb -ptestdbpassword -BNe 'show databases'")
 
    visible_databases = host.run("mysql -utestdb -ptestdbpassword -BNe 'show databases'")
 

	
 
    assert visible_databases.rc == 0
 
    assert visible_databases.stdout == "information_schema\ntestdb"
 

	
 
    with Sudo():
 
        permissions = Command("mysql -BNe 'show grants for testdb@localhost'")
 
    with host.sudo():
 
        permissions = host.run("mysql -BNe 'show grants for testdb@localhost'")
 
        assert len(permissions.stdout.split("\n")) == 2
 
        assert "GRANT USAGE ON *.* TO 'testdb'@'localhost' IDENTIFIED BY PASSWORD '*676852B7FAE972722AD20D6E74781D6B1A100544'" in permissions.stdout.split("\n")
 
        assert "GRANT ALL PRIVILEGES ON `testdb`.* TO 'testdb'@'localhost'" in permissions.stdout.split("\n")
0 comments (0 inline, 0 general)