Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

e2e tests for managing vsphere virtual machines #23

Merged
merged 7 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelogs/fragments/23__e2e-manage-vm-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
major_changes:
- manage_vm - adding manage vm e2e tests using molecule testing framwork.
this includes tests for update, delete and adding a vm to the vcenter and validates the outcome of the changes.
21 changes: 21 additions & 0 deletions tests/e2e/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
VENV_DIR := .venv

.PHONY: install-python-packages
install-python-packages: $(VENV_DIR)
$(VENV_DIR)/bin/pip install -r ../integration/requirements.txt

.PHONY: install-ansible-collections
install-ansible-collections: $(VENV_DIR)
$(VENV_DIR)/bin/ansible-galaxy collection install -r ../integration/requirements.yml

.PHONY: install-molecule
install-molecule: $(VENV_DIR)
$(VENV_DIR)/bin/pip install molecule

$(VENV_DIR):
python3 -m venv $(VENV_DIR)

.PHONY: e2e-molecule
e2e-molecule: install-python-packages install-ansible-collections install-molecule
@echo "Running Molecule tests with the scenario: $(scenario)"
$(VENV_DIR)/bin/molecule test -s $(scenario)
38 changes: 38 additions & 0 deletions tests/e2e/molecule/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# cloud.vmware_ops Molecule E2E Testing

This repository contains Molecule test scenarios for the `cloud.vmware_ops` Ansible collection. Each scenario represents a feature in the collection, allowing you to test individual features in isolation.
Feel free to contribute, add new scenarios, or enhance existing ones to ensure comprehensive testing of the Ansible collection.

## Prerequisites

Before running Molecule scenarios, ensure that the following tools are installed on your system:

- [Ansible](https://www.ansible.com/)
- [Python 3](https://www.python.org/)
- [Molecule](https://molecule.readthedocs.io/)
- [ansible-junit](https://github.com/hspaans/ansible-junit) (for JUnit XML output)
- [pyvmomi](https://github.com/vmware/pyvmomi) (required for vSphere testing)

Additionally, create a password file for the vSphere credentials (vault password file). The password file should contain the vault password for the `vSphere creds` vault. The vault file should include the following variables:

```yaml
# vault.yml
vcenter_hostname: "your_vsphere_hostname"
vcenter_username: "your_vsphere_username"
vcenter_password: "your_vsphere_password"

Those should be encrypted using ansible-vault command and be placed under `vault_files/eco_vsphere_creds.yml`
The saved password should be placed under `${HOME}/vault.pass`

## Creating a New Molecule Scenario
To create a new Molecule scenario, follow these steps:

1. Create a new directory under tests/e2e/molecule/<scenario_name> for your scenario
or run `molecule init scenario <scenario_name>`
2. Define the scenario configuration in the molecule.yml file within the new scenario directory.
3. Create the necessary playbook(s) and test files for your scenario.
4. Run the scenario using `molecule test -s <new_scenario_name>`

## Running Molecule Scenarios
To run a Molecule scenario, use the following command:
molecule test -s <scenario_name>
2 changes: 2 additions & 0 deletions tests/e2e/molecule/ansible.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[defaults]
callback_whitelist = junit
21 changes: 21 additions & 0 deletions tests/e2e/molecule/converge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
- name: Run all playbooks in the scenarios directory
hosts: localhost
gather_facts: true
ignore_errors: true

tasks:
- name: Include vSphere datacenter creds
ansible.builtin.include_vars:
file: vault_files/eco_vsphere_creds.yml

- name: Run molecule scenarios
ansible.builtin.find:
paths: "{{ lookup('env', 'MOLECULE_SCENARIO_NAME') }}/scenarios"
recurse: true
patterns: "*.yml"
register: playbook_files

- name: Include and run each playbook
ansible.builtin.include_tasks:
file: "{{ item.path }}"
with_items: "{{ playbook_files.files }}"
28 changes: 28 additions & 0 deletions tests/e2e/molecule/manage_vm/destroy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
- name: Deprovision VM
hosts: localhost
gather_facts: false
tasks:
- name: Include vSphere datacenter creds
ansible.builtin.include_vars:
file: ../vault_files/eco_vsphere_creds.yml

- name: Include VM vars
ansible.builtin.include_vars:
file: vars/vars.yml

- name: Deprovision VM and run checks
loop: "{{ provision_vms + provision_vms_template + provision_vms_from_template }}"
ansible.builtin.include_tasks:
file: tasks/deprovision_vm.yml

- name: Ensure secondary network created in tests is absent
community.vmware.vmware_portgroup:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: "{{ provision_vm_validate_certs }}"
cluster_name: "{{ provision_vm_cluster }}"
switch: "{{ vswitch_name }}"
portgroup: "{{ portgroup_name }}"
state: absent
40 changes: 40 additions & 0 deletions tests/e2e/molecule/manage_vm/molecule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
dependency:
name: galaxy

# driver:
# name: podman

platforms:
- name: instance
image: ubuntu:latest
init: /lib/systemd/systemd
security_opt:
- label=disable
privileged: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
ansible_connection: ansible

provisioner:
name: ansible
lint: |
set -e
echo "Run yamllint"
yamllint .
echo "Run ansible-lint"
ansible-lint
env:
ANSIBLE_ROLES_PATH: "../../../../roles"
config_options:
defaults:
vault_password_file: ${HOME}/vault.pass
callback_whitelist: junit
playbooks:
converge: ../converge.yml
destroy: destroy.yml

verifier:
name: ansible
options:
junit-xml: ./test-results.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
- name: "Check that the following VM does not exist: {{ item.provision_vm_name }}"
community.vmware.vmware_vm_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: "{{ provision_vm_validate_certs }}"
vm_name: "{{ item.provision_vm_name }}"
register: vm_info
ignore_errors: true

- name: "Fail the task if the following VM exists: {{ item.provision_vm_name }}"
ansible.builtin.fail:
msg: "Provisioned VM {{ item.provision_vm_name }} still exists"
when: not vm_info.failed
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
- name: Get info about the VM
ansible.builtin.include_tasks:
file: ../tasks/get_vm_info.yml
vars:
vm_name: "{{ item.provision_vm_name }}"

- name: "Validate the properties of the following VM: {{ item.provision_vm_name }}"
ansible.builtin.assert:
that:
- vm_info.virtual_machines[0].guest_name == item.provision_vm_name
- vm_info.virtual_machines[0].cluster == provision_vm_cluster
- vm_info.virtual_machines[0].datacenter == provision_vm_datacenter
- vm_info.virtual_machines[0].folder == provision_vm_folder
- vm_info.virtual_machines[0].power_state | lower == item.provision_vm_state
# - vm_info.virtual_machines[0].resource_pool == item.provision_vm_resource_pool

- name: "Validate the following VM datastore when datastore was defined in provision_vm_datastore: {{ item.provision_vm_name }}"
ansible.builtin.assert:
that:
- vm_info.virtual_machines[0].datastore_url[0].name == item.provision_vm_datastore
when: "'provision_vm_datastore' in item"

- name: "Validate the following VM datastore when datastore was defined in provision_vm_disk: {{ item.provision_vm_name }}"
ansible.builtin.assert:
that:
- vm_info.virtual_machines[0].datastore_url[0].name == item.provision_vm_disk[0].datastore
when: "'provision_vm_datastore' not in item"
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
- name: Collect information about VM with ID {{ vm_moid }}
vmware.vmware_rest.vcenter_vm_info:
vcenter_hostname: "{{ vcenter_hostname }}"
vcenter_username: "{{ vcenter_username }}"
vcenter_password: "{{ vcenter_password }}"
vcenter_validate_certs: "{{ provision_vm_validate_certs }}"
vm: '{{ vm_moid }}'
register: vm_info_updated_name

- name: Print vm_info_updated_name for {{ vm_moid }}
ansible.builtin.debug:
var: vm_info_updated_name

- name: Validate name of VM with ID {{ vm_moid }}
ansible.builtin.assert:
that:
- vm_info_updated_name.value.name == vm_name
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
- name: Get info about the updated VM
ansible.builtin.include_tasks:
file: ../tasks/get_vm_info.yml
vars:
vm_name: "{{ vm_update_name }}"

- name: "Get network info about '{{ vm_update_name }}' VM"
community.vmware.vmware_guest_network:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: "{{ provision_vm_validate_certs }}"
uuid: "{{ vm_uuid }}"
gather_network_info: true
register: vm_network_info

- name: "Print vm_network_info for '{{ vm_update_name }}'"
ansible.builtin.debug:
var: vm_network_info

- name: "Validate updated network configuration of '{{ vm_update_name }}' VM"
ansible.builtin.assert:
that:
- vm_network_info.network_info[index].name == network.name
- vm_network_info.network_info[index].device_type == network.device_type
- vm_network_info.network_info[index].mac_address == network.mac
loop: "{{ vm_updated_networks }}"
loop_control:
loop_var: network
index_var: index

- name: Retrieve the CPU information from the VM
vmware.vmware_rest.vcenter_vm_hardware_cpu_info:
vcenter_hostname: "{{ vcenter_hostname }}"
vcenter_username: "{{ vcenter_username }}"
vcenter_password: "{{ vcenter_password }}"
vcenter_validate_certs: "{{ provision_vm_validate_certs }}"
vm: "{{ vm_moid }}"
register: cpu_info

- name: Retrieve the memory information from the VM
vmware.vmware_rest.vcenter_vm_hardware_memory_info:
vcenter_hostname: "{{ vcenter_hostname }}"
vcenter_username: "{{ vcenter_username }}"
vcenter_password: "{{ vcenter_password }}"
vcenter_validate_certs: "{{ provision_vm_validate_certs }}"
vm: "{{ vm_moid }}"
register: memory_info

- name: Retrieve disk information using the disk label
vmware.vmware_rest.vcenter_vm_hardware_disk_info:
vcenter_hostname: "{{ vcenter_hostname }}"
vcenter_username: "{{ vcenter_username }}"
vcenter_password: "{{ vcenter_password }}"
vcenter_validate_certs: "{{ provision_vm_validate_certs }}"
vm: "{{ vm_moid }}"
label: Hard disk 1
register: disk_info

- name: "Validate updated configuration of '{{ vm_update_name }}' VM"
ansible.builtin.assert:
that:
- vm_info.virtual_machines[0].guest_fullname == guest_fullnames[vm_updated_guest_id]
- cpu_info.value.count == vm_updated_hardware.num_cpus
- cpu_info.value.cores_per_socket == vm_updated_hardware.num_cpu_cores_per_socket
- memory_info.value.size_MiB == vm_updated_hardware.memory_mb
- disk_info.value.capacity == gib_to_bytes * ( vm_enlarge_disk[0].size_gb | int )
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
- name: Get info about the updated VM
ansible.builtin.include_tasks:
file: ../tasks/get_vm_info.yml
vars:
vm_name: "{{ vm_update_name }}"

- name: "Validate that VM is in state {{ vm_state }}"
ansible.builtin.assert:
that:
- vm_info.virtual_machines[0].power_state | lower == vm_state
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
- name: Import vars
ansible.builtin.include_vars:
file: ../vars/vars.yml

- name: Create VMs to use as template
loop: "{{ provision_vms_template }}"
ansible.builtin.include_tasks:
file: manage_vm/tasks/provision_vm.yml

- name: Turn created VMs into templates
loop: "{{ provision_vms_template }}"
community.vmware.vmware_guest:
hostname: "{{ provision_vm_hostname }}"
username: "{{ provision_vm_username }}"
password: "{{ provision_vm_password }}"
validate_certs: "{{ provision_vm_validate_certs }}"
name: "{{ item.provision_vm_name }}"
is_template: true

- name: Create VMs from template and run validations
loop: "{{ provision_vms_from_template }}"
ansible.builtin.include_tasks:
file: manage_vm/tasks/provision_vm.yml
8 changes: 8 additions & 0 deletions tests/e2e/molecule/manage_vm/scenarios/provision_vm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- name: Import vars
ansible.builtin.include_vars:
file: ../vars/vars.yml

- name: Basic Provision VM Scenario
loop: "{{ provision_vms }}"
ansible.builtin.include_tasks:
file: manage_vm/tasks/provision_vm.yml
Loading
Loading