ansible / molecule

Molecule aids in the development and testing of Ansible content: collections, playbooks and roles
https://ansible.readthedocs.io/projects/molecule/
MIT License
3.88k stars 662 forks source link

[Feature] Create virtual machines which are not used for running tests #1203

Closed moenka closed 6 years ago

moenka commented 6 years ago

When creating roles that talk to remote endpoints I want to make sure the endpoint call is working. To test this I would normally create a vm/container that provides the endpoints by having the real application running I'm writing the role for (e.g. a running icinga on which I want to register a new host via an API call).

Atm I don't know of/find a way in the docs to create vms for providing such endpoints. It would be nice if molecule could provide something in the molecule.yml config to create such environments like specifying virtual machines that are not used to run tests on but to only exist and be reachable. I then might add an ansible playbook which configures those vm's in a way I can run tests against them.

Right now I think I'm going to create a Vagrantfile inside my repos root directory and manually start those vm's before running molecule test --all.

moenka commented 6 years ago

I tried to hack something together that might be configurable easily. The solution allows only docker containers as affiliated machines but could be extended for other providers I think. Unfortunately this doesn't work because of the config validation. En example of config, create and destroy files:

molecule.yml

---
# need to be implemented by molecule before it can be used
affiliates:
  - name: icinga
    box: jordan/icinga2
    published_ports:
      - '8080:80'
      - '5665:5665'
    env:
      ICINGA2_FEATURE_DIRECTOR_USER: director
      ICINGA2_FEATURE_DIRECTOR_PASS: director
...

create.yml

...

  tasks:
    - name: Create affiliated instance(s)
      docker_container:
        name: "{{ item.name }}"
        hostname: "{{ item.name }}"
        image: "{{ item.image }}"
        state: started
        recreate: false
        log_driver: json-file
        command: "{{ item.command | default('bash -c \"while true; do sleep 10000; done\"') }}"
        privileged: "{{ item.privileged | default(omit) }}"
        volumes: "{{ item.volumes | default(omit) }}"
        capabilities: "{{ item.capabilities | default(omit) }}"
        exposed_ports: "{{ item.exposed_ports | default(omit) }}"
        published_ports: "{{ item.published_ports | default(omit) }}"
        ulimits: "{{ item.ulimits | default(omit) }}"
        networks: "{{ item.networks | default(omit) }}"
        dns_servers: "{{ item.dns_servers | default(omit) }}"
        env: "{{ item.env | default(omit) }}"
      register: affiliates
      with_items: "{{ molecule_yml.platforms }}"
      async: 7200
      poll: 0

    - name: Wait for affiliated instance(s) creation to complete
      async_status:
        jid: "{{ item.ansible_job_id }}"
      register: docker_jobs
      until: docker_jobs.finished
      retries: 300
      with_items: "{{ affiliates.results }}"

...

destroy.yml

...

    - name: Destroy molecule instance(s)
      docker_container:
        name: "{{ item.name }}"
        state: absent
        force_kill: "{{ item.force_kill | default(true) }}"
      register: affiliates
      with_items: "{{ molecule_yml.affiliates }}"
      async: 7200
      poll: 0

    - name: Wait for instance(s) deletion to complete
      async_status:
        jid: "{{ item.ansible_job_id }}"
      register: docker_jobs
      until: docker_jobs.finished
      retries: 300
      with_items: "{{ affiliates.results }}"

...

Note: This is untested and only an example how this might be implemented. I'm open for discussion.

retr0h commented 6 years ago

Atm I don't know of/find a way in the docs to create vms for providing such endpoints. It would be nice if molecule could provide something in the molecule.yml config to create such environments like specifying virtual machines that are not used to run tests on but to only exist and be reachable.

Sure, you can create VMs in different groups.

platforms:
  - name: instance-1
    command: /sbin/init
    groups:
      - to_test
  - name: instance-2
    command: /sbin/init
    groups:
      - not_test

Inside your testinfra test, just target the 'to_test' group.

testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('to_test')
moenka commented 6 years ago

Hey, nice thanks for this information. Is there a way to specify different providers for different vm's or is it currently possible to only use the one provider specified in the molecule.yml?

This information helps me a lot. It's also stated in the documentation: https://molecule.readthedocs.io/en/latest/configuration.html#platforms

The information how to use those groups in the test_default.py I did not find anywhere so it may be useful if this is put into the documentation and linked from the page I posted. Also it may be useful to give this a own headline/topic so poeple who search for this feature but don't know to search for groups will have an easier time to find the information.

retr0h commented 6 years ago

Hey, nice thanks for this information. Is there a way to specify different providers for different vm's or is it currently possible to only use the one provider specified in the molecule.yml?

Yes

retr0h commented 6 years ago

Closing as the question has been answered. Please let us know if you have any other questions.