Seite wählen

NETWAYS Blog

Ansible – Testing roles with Molecule

Ansible is a widely used and a powerful open-source configuration and deployment management tool. It can be used for simple repetitive daily tasks or complex application deployments, therefore Ansible is able to cover mostly any situation.

If used in complex or heterogene environments it is necessary to test the code to reduce time to fix code in production. To test Ansible code it is suggested to use Molecule.

Molecule is a useful tool to run automated tests on Ansible roles or collections. It helps with unit tests to ensure properly working code on different systems. Whether using the role internally or provide it to the public, it is useful to test many cases your role can be used. In addition Molecule is easily integrated into known CI/CD tools, like Github Actions or Gitlab CI/CD.

In this short introduction I’ll try get your first Molecule tests configured and running!

Please make sure you installed Molecule beforehand. On most distributions it’s easily installed via PIP.
The fastest and most common way to test roles would be in container. Due to a version problem with systemd currently it’s not possible to start services over systemd in containers. For this reason you can easily start with a vagrant instance and later migrate to docker or podman easily.


pip install molecule molecule-vagrant

If you have a role you can change into the role directory and create a default scenario.


cd ~/Documents/netways/git/thilo.my_config/
molecule init scenario -r thilo.my_config default
INFO     Initializing new scenario default...
INFO     Initialized scenario in /Users/thilo/Documents/netways/git/thilo.my_config/molecule/default successfully.

Below the molecule folder all scenarios are listed. Edit the default/molecule.yml to add the vagrant options.

Add a dependency file with your collections as with newer Ansible versions only the core is available. If needed you can add sudo privileges to your tests.

molecule/default/molecule.yml


---
dependency:
  name: galaxy
  options:
    requirements-file: collections.yml
driver:
  name: vagrant
platforms:
  - name: instance
    box: bento/centos-7
provisioner:
  name: ansible
verifier:
  name: testinfra
  options:
    sudo: true

The converge.yml is basically the playbook to run on your instance. In the playbook you define which variables should be used or if some pre-tasks should be run.

molecule/default/converge.yml


---
- name: Converge
  hosts: all
  become: true
  tasks:
    - name: "Include thilo.my_config"
      include_role:
        name: "thilo.my_config"

Now you can run your playbook with molecule. If you want to deploy and not delete your instance use converge. Otherwise you can use test, then the instance will be created, tested and destroyed afterwards.


python3 -m molecule converge -s default
or 
python3 -m molecule test -s default

Finally we can define some tests, the right tool is testinfra. Testinfra provides different modules to gather informations and check them if they have specific attributes.

Your scenario creates a tests folder with the following file: molecule/default/tests/test_default.py

In this example I’ll test the resources my role should create.


"""Role testing files using testinfra."""


def test_user(host):
    """Validate created user"""
    u = host.user("thilo")

    assert u.exists

def test_authorized_keys(host):
    """Validate pub key deployment"""
    f = host.file("/home/thilo/.ssh/authorized_keys")

    assert f.exists
    assert f.content_string == "ssh-rsa AAAA[...] \n"

And if we already converged our instance, we can verify these definitions against our deployment.


python3 -m molecule verify
INFO     default scenario test matrix: verify
INFO     Performing prerun with role_name_check=0...
[...]
INFO     Running default > verify
INFO     Executing Testinfra tests found in /Users/thilo/Documents/netways/git/thilo.my_config/molecule/default/tests/...
============================= test session starts ==============================
platform darwin -- Python 3.9.12, pytest-6.2.5, py-1.11.0, pluggy-0.13.1
rootdir: /
plugins: testinfra-6.4.0
collected 2 items

molecule/default/tests/test_default.py ..                                [100%]

============================== 2 passed in 1.79s ===============================
INFO     Verifier completed successfully.

With those easy steps you can easily test your roles for any scenario and your deployments can run without any hassle or at least you will be more relaxed during it 😉

Check out our Blog for more awesome posts and if you need help with Ansible send us a message or sign up for one of our trainings!

Thilo Wening
Thilo Wening
Manager Consulting

Thilo hat bei NETWAYS mit der Ausbildung zum Fachinformatiker, Schwerpunkt Systemadministration begonnen und unterstützt nun nach erfolgreich bestandener Prüfung tatkräftig die Kollegen im Consulting. In seiner Freizeit ist er athletisch in der Senkrechten unterwegs und stählt seine Muskeln beim Bouldern. Als richtiger Profi macht er das natürlich am liebsten in der Natur und geht nur noch in Ausnahmefällen in die Kletterhalle.

Zeit ist einzigartig


Einige haben erst am 12. Dezember 2012 gemerkt, dass die Zeit einzigartig ist. CAs hingegen wissen das schon seit Längerem und wissen dies auch effektiv zu nutzen. Bei meinem letzten Setup bin ich wieder über diese Falle gestolpert: Die Einrichtung der externen CA und des Puppetmasters ging wie immer ohne Probleme, nur jegliche Zertifikate wollten nicht akzeptiert werden. Wer Puppet einsetzt wird diese Fehlermeldung sofort erkennen:
err: Could not retrieve catalog from remote server: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed: [certificate signature failure for /CN=puppet ]
Wir können in diesem Fall zum einen prüfen, ob unsere CA die selbe ist.
Mit OpenSSL können Zertifikate lesbar dargestellt werden.
openssl x509 -text -noout -in /path/to/ssl/certs/ca.pem | grep Issuer
In dem Output sollte dann eine Zeile mit dem Issuer zu sehen sein und wenn dieser mit der Puppet CA nicht übereinstimmt, müssen deren Einstellungen überprüft werden. Dabei können diese Befehle hilfreich sein.
sudo puppet master --configprint certname
sudo puppet master --configprint ca
Sobald aber hier alles richtig konfiguriert wurde, ist es zum anderen gut ein Auge auf die Zeit zu werfen.
Wenn die Zeit nicht stimmt kann es dazu kommen, dass Zertifikate in der Zukunft ausgestellt werden und diese für die CA keine Gültigkeit besitzen.
Ein einheitlicher Zeitserver kommt diesem Problem entgegen, denn mit ihm vermeiden wir Zertifikate in der Zukunft auszustellen. Wenn dieser nicht vorhanden ist, reicht ein einfaches:
sudo apt-get install ntp
und eventuell ein kurzer Neustart. Danach muss der Puppet Agent neu signiert werden. Dazu müssen alle Zertifikate gelöscht werden.
Auf dem Puppetmaster:
sudo puppet cert clean yourserver.localdomain
Auf dem Client:
sudo rm -rf /path/to/puppet/ssl/*  #Default ist /var/lib/puppet/ssl/
Anschließend kann ein neuer Testlauf auf dem Agent ausgeführt werden, der dann ein neues Zertifikat generiert
sudo puppet agent --test
und durch den Puppetmaster validieren lässt.
sudo puppet cert sign yourserver.localdomain
P.S.: Achtet bei eurer Icinga2 HA Installation auch auf die Zeit, hier werden ebenfalls SSL Zertifikate benutzt und unterschiedliche Zeitserver können zu Zeitverschiebungen (im Projekt) führen. 😉

Thilo Wening
Thilo Wening
Manager Consulting

Thilo hat bei NETWAYS mit der Ausbildung zum Fachinformatiker, Schwerpunkt Systemadministration begonnen und unterstützt nun nach erfolgreich bestandener Prüfung tatkräftig die Kollegen im Consulting. In seiner Freizeit ist er athletisch in der Senkrechten unterwegs und stählt seine Muskeln beim Bouldern. Als richtiger Profi macht er das natürlich am liebsten in der Natur und geht nur noch in Ausnahmefällen in die Kletterhalle.