Testing an Ansible Collection - Part 1 - Introduction and Morpheus Test Appliance
I wrote an Ansible collection for Morpheus mainly to house the inventory plugin that sources and filters inventory targets using Morpheus as a source of truth. The inventory plugin had various issues over time, and I didn't have any sort of continuous testing in place. I also wanted to have it available in Ansible Galaxy to make it easier to install for users.
There should be an easier way to test an Ansible collection, and there may be. Unfortunately, At a certain point, you have to press forward with the knowledge you have, or you may be looking for it forever.
The initial issues that needed to be addressed were:
- Ansible Galaxy issues warnings and errors on flake8 and ansible-lint scanning, and will block your collection from importing
- If your collection successfully imports into galaxy, there is no way to alter or remove it. You need to release and import a higher version.
- Testing against an application can require a running instance of that application.
- Ansible has many versions and runs against every version of Python >=2.7. Testing against all the permutations is advised.
The most time consuming thing was getting the environment stood up. Morpheus is a large application and takes a while to spin up the first time, in contrast to a docker container for testing. I used terraform to create the infrastructure and the VM on AWS using a spare domain and a wildcard certificate I created there. After that, installation of Morpheus is very easy and works well with the playbook and role here: https://github.com/tryfan/ansible-morpheus-examples/tree/master/all-in-one Just make sure to enable the initial morpheus_setup
variable with some additional config in the group_vars
to have Morpheus ready to go before configuration.
Waiting for the appliance to come up takes a while since I am using an AWS ALB to make my life easier, but it's not very quick. All of this was done in Jenkins so I used lots of environment variables to make it portable. The Ansible role starts Morpheus, but doesn't test access through the ALB. The next script does that:
from pymorpheus import MorpheusClient
import os
import time
#print(os.environ)
# Setup vars from env
morpheusUrl = os.environ['morpheus_url']
morpheusUsername = os.environ['morpheus_user']
morpheusPassword = os.environ['morpheus_pass']
morpheusLicense = os.environ['morpheus_license']
morpheusAlive = False
while not morpheusAlive:
try:
morpheus = MorpheusClient(morpheusUrl, username=morpheusUsername, password=morpheusPassword)
result = morpheus.call("get","/ping")
print(result)
if result['success'] == True:
print("it is true")
morpheusAlive = True
except:
print("Checking...")
time.sleep(4)
licenseJson = '{"license": "%s"}' % morpheusLicense
putLicense = morpheus.call("post", "/license", jsonpayload=licenseJson)
I'm using the pymorpheus
python module to make things easier. Once this completes, the setup_ansible.sh
script runs to prepare the Ansible environment. I've already created and entered a virtualenv to install the other requirements. The AWS credentials are coming out of Jenkins. I'm using a static version of the collection just so I'm sure everything will work.
ansible-galaxy collection install -p ./collections https://github.com/tryfan/ansible-collection-morpheus-core/releases/download/v0.2.2/morpheus-core-0.2.2.tar.gz
sed -i -r "s@MORPHEUSURL@$morpheus_url@" group_vars/all
sed -i -r "s@AWSACCESSKEY@$AWS_ACCESS_KEY_ID@" group_vars/all
sed -i -r "s@AWSSECRETKEY@$AWS_SECRET_ACCESS_KEY@" group_vars/all
echo morpheus_token: $(curl -XPOST "${morpheus_url}/oauth/token?grant_type=password&scope=write&client_id=morph-api" --data-urlencode 'username=${morpheus_username}' --data-urlencode 'password=${morpheus_password} | jq -r '.access_token') >> group_vars/all
For the Morpheus configuration, I used quite a few roles from the morpheus.core
collection:
- hosts: morpheus
roles:
- morpheus.core.settings
- morpheus.core.groups
- morpheus.core.clouds
- morpheus.core.keyscerts
- morpheus.core.virtualimages
- morpheus.core.nodetypes
- morpheus.core.instancetypes
- morpheus.core.layouts
I wanted to test with CentOS, Ubuntu, and a Windows VM to verify the platforms were getting detected. CentOS and Ubuntu were fine, but I needed to add a Windows 2019 AMI to build. windowsPassword
is required to provision, but not important since I won't be logging into the instance. It ended up looking like this:
morpheus_url: MORPHEUSURL
morpheus_token: MORPHEUSTOKEN
morpheus_settings:
windowsPassword: "morphSecret2@"
morpheus_groups:
- name: maingroup
code: maingroup
morpheus_clouds:
- name: awscloud
code: awscloud
location: useast1
visibility: private
inventoryLevel: none
groupName: maingroup
zoneType:
code: amazon
config:
importExisting: "off"
isVpc: "true"
endpoint: "ec2.us-east-1.amazonaws.com"
accessKey: AWSACCESSKEY
secretKey: AWSSECRETKEY
morpheus_keyscerts:
- name: jenkinskey
publicKey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxuQdW2P1ZP6gi6gJ/EBwkDzzPQhHxAl+mPTsEuaHrQV9MZb2Hu8X/qzDT5hgIE/0R5rQDnPnwKfRVgX7WAItUQxBu06FYW22CeXB4puJa2s9tuUtKTUSVr4nsyAUUh0ZFtIUoSR8RiNAhLpUBQ6UDZRqfE1vQPZ8hoHZwm6Whw56VFQu9ki2vP401qMSV+vRtCp+d2bAegPIwpU47CnimHhKu781R2lz7r8LOTHjiOrvVLovg/6DdyUfXAayF4IciQpLhioSTXYzYYkDspjP9gw99AaVvyN2rLX+wO6voXBg1OxQkb5Cm4HKfZ6nKPL6v6sFYoRFdGXEV6R7Y/Szb
morpheus_virtualimages:
- name: "Windows 2019 AMI New"
imageType: ami
isCloudInit: "true"
installAgent: "true"
externalId: "ami-0aad84f764a2bd39a"
morpheus_nodetypes:
- name: "Win2019 Node"
shortName: win2019node
provisionTypeCode: amazon
imageType: ami
containerVersion: 2
virtual_image_name: "Windows 2019 AMI New"
morpheus_instancetypes:
- name: "New Builds"
code: newbuilds
category: OS
featured: "true"
morpheus_layouts:
- name: Win2019
instanceVersion: 1
memoryRequirement: 4096
provisionTypeCode: amazon
nodetype_name: "Win2019 Node"
instancetypecode: newbuilds
Now that all that is done, I wait 180 seconds and make the instances. I've got JSON templates which I modify because plan IDs are all dynamically generated, so there's a few substitutions in the code. The code is too long for inclusion here, so it's in the git repository. The JSON payload source files for creating the instances are also in the repository.
A note about the make_instances.py
script: At first I used the plan IDs from my first run and thought they were static. They are not. I ended up creating a m4a.16xlarge or similar and had a machine with 384GB of RAM waiting for me. That's why I rewrote for an ID lookup.
Part 2 will go into actually testing the collection against the real Morpheus test appliance, as well as preparations to submit to Ansible Galaxy.